]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
PR target/55445
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
2d05dfad 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
934a1e72 4;; Free Software Foundation, Inc.
b11cae9e 5;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 6;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 7;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 8
acf6ed70 9;; This file is part of GCC.
b11cae9e 10
acf6ed70 11;; GCC is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published
038d1e19 13;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 14;; option) any later version.
b11cae9e 15
acf6ed70 16;; GCC is distributed in the hope that it will be useful, but WITHOUT
17;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19;; License for more details.
b11cae9e 20
21;; You should have received a copy of the GNU General Public License
038d1e19 22;; along with GCC; see the file COPYING3. If not see
23;; <http://www.gnu.org/licenses/>.
b11cae9e 24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
9c08d1fa 27\f
e1159bbe 28;;---------------------------------------------------------------------------
29;; Constants
30
bffbb863 31;; Register numbers -- All machine registers should be defined here
e1159bbe 32(define_constants
bffbb863 33 [(R0_REGNUM 0) ; First CORE register
34 (R1_REGNUM 1) ; Second CORE register
35 (IP_REGNUM 12) ; Scratch register
36 (SP_REGNUM 13) ; Stack pointer
37 (LR_REGNUM 14) ; Return address register
38 (PC_REGNUM 15) ; Program counter
39 (LAST_ARM_REGNUM 15) ;
40 (CC_REGNUM 100) ; Condition code pseudo register
41 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
2ff91fec 51;; conditional compare combination
52(define_constants
53 [(CMP_CMP 0)
54 (CMN_CMP 1)
55 (CMP_CMN 2)
56 (CMN_CMN 3)
57 (NUM_OF_COND_CMP 4)
58 ]
59)
e1159bbe 60
9c08d1fa 61;; UNSPEC Usage:
8a18b90c 62;; Note: sin and cos are no-longer used.
e7d6d136 63;; Unspec enumerators for Neon are defined in neon.md.
6b8f7c28 64;; Unspec enumerators for iwmmxt2 are defined in iwmmxt2.md
e1159bbe 65
e7d6d136 66(define_c_enum "unspec" [
e7d6d136 67 UNSPEC_PUSH_MULT ; `push multiple' operation:
68 ; operand 0 is the first register,
69 ; subsequent registers are in parallel (use ...)
70 ; expressions.
71 UNSPEC_PIC_SYM ; A symbol that has been treated properly for pic
72 ; usage, that is, we will add the pic_register
73 ; value to it before trying to dereference it.
74 UNSPEC_PIC_BASE ; Add PC and all but the last operand together,
75 ; The last operand is the number of a PIC_LABEL
76 ; that points at the containing instruction.
77 UNSPEC_PRLG_STK ; A special barrier that prevents frame accesses
78 ; being scheduled before the stack adjustment insn.
fb94f18b 79 UNSPEC_REGISTER_USE ; As USE insns are not meaningful after reload,
e7d6d136 80 ; this unspec is used to prevent the deletion of
81 ; instructions setting registers for EH handling
82 ; and stack frame generation. Operand 0 is the
83 ; register to "use".
84 UNSPEC_CHECK_ARCH ; Set CCs to indicate 26-bit or 32-bit mode.
85 UNSPEC_WSHUFH ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
86 UNSPEC_WACC ; Used by the intrinsic form of the iWMMXt WACC instruction.
87 UNSPEC_TMOVMSK ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
88 UNSPEC_WSAD ; Used by the intrinsic form of the iWMMXt WSAD instruction.
89 UNSPEC_WSADZ ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
90 UNSPEC_WMACS ; Used by the intrinsic form of the iWMMXt WMACS instruction.
91 UNSPEC_WMACU ; Used by the intrinsic form of the iWMMXt WMACU instruction.
92 UNSPEC_WMACSZ ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
93 UNSPEC_WMACUZ ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
94 UNSPEC_CLRDI ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
6b8f7c28 95 UNSPEC_WALIGNI ; Used by the intrinsic form of the iWMMXt WALIGN instruction.
e7d6d136 96 UNSPEC_TLS ; A symbol that has been treated properly for TLS usage.
97 UNSPEC_PIC_LABEL ; A label used for PIC access that does not appear in the
98 ; instruction stream.
e7d6d136 99 UNSPEC_PIC_OFFSET ; A symbolic 12-bit OFFSET that has been treated
100 ; correctly for PIC usage.
851d9296 101 UNSPEC_GOTSYM_OFF ; The offset of the start of the GOT from a
e7d6d136 102 ; a given symbolic address.
103 UNSPEC_THUMB1_CASESI ; A Thumb1 compressed dispatch-table call.
104 UNSPEC_RBIT ; rbit operation.
105 UNSPEC_SYMBOL_OFFSET ; The offset of the start of the symbol from
106 ; another symbolic address.
107 UNSPEC_MEMORY_BARRIER ; Represent a memory barrier.
eb04cafb 108 UNSPEC_UNALIGNED_LOAD ; Used to represent ldr/ldrh instructions that access
109 ; unaligned locations, on architectures which support
110 ; that.
111 UNSPEC_UNALIGNED_STORE ; Same for str/strh.
350ccca5 112 UNSPEC_PIC_UNIFIED ; Create a common pic addressing form.
ab1e18de 113 UNSPEC_LL ; Represent an unpaired load-register-exclusive.
2d391553 114 UNSPEC_VRINTZ ; Represent a float to integral float rounding
115 ; towards zero.
116 UNSPEC_VRINTP ; Represent a float to integral float rounding
117 ; towards +Inf.
118 UNSPEC_VRINTM ; Represent a float to integral float rounding
119 ; towards -Inf.
120 UNSPEC_VRINTR ; Represent a float to integral float rounding
121 ; FPSCR rounding mode.
122 UNSPEC_VRINTX ; Represent a float to integral float rounding
123 ; FPSCR rounding mode and signal inexactness.
124 UNSPEC_VRINTA ; Represent a float to integral float rounding
125 ; towards nearest, ties away from zero.
e7d6d136 126])
e1159bbe 127
215b30b3 128;; UNSPEC_VOLATILE Usage:
e1159bbe 129
e7d6d136 130(define_c_enum "unspecv" [
131 VUNSPEC_BLOCKAGE ; `blockage' insn to prevent scheduling across an
132 ; insn in the code.
133 VUNSPEC_EPILOGUE ; `epilogue' insn, used to represent any part of the
134 ; instruction epilogue sequence that isn't expanded
135 ; into normal RTL. Used for both normal and sibcall
136 ; epilogues.
7571d3f7 137 VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
138 ; modes from arm to thumb.
e7d6d136 139 VUNSPEC_ALIGN ; `align' insn. Used at the head of a minipool table
140 ; for inlined constants.
141 VUNSPEC_POOL_END ; `end-of-table'. Used to mark the end of a minipool
142 ; table.
143 VUNSPEC_POOL_1 ; `pool-entry(1)'. An entry in the constant pool for
144 ; an 8-bit object.
145 VUNSPEC_POOL_2 ; `pool-entry(2)'. An entry in the constant pool for
146 ; a 16-bit object.
147 VUNSPEC_POOL_4 ; `pool-entry(4)'. An entry in the constant pool for
148 ; a 32-bit object.
149 VUNSPEC_POOL_8 ; `pool-entry(8)'. An entry in the constant pool for
150 ; a 64-bit object.
151 VUNSPEC_POOL_16 ; `pool-entry(16)'. An entry in the constant pool for
152 ; a 128-bit object.
153 VUNSPEC_TMRC ; Used by the iWMMXt TMRC instruction.
154 VUNSPEC_TMCR ; Used by the iWMMXt TMCR instruction.
155 VUNSPEC_ALIGN8 ; 8-byte alignment version of VUNSPEC_ALIGN
156 VUNSPEC_WCMP_EQ ; Used by the iWMMXt WCMPEQ instructions
157 VUNSPEC_WCMP_GTU ; Used by the iWMMXt WCMPGTU instructions
158 VUNSPEC_WCMP_GT ; Used by the iwMMXT WCMPGT instructions
159 VUNSPEC_EH_RETURN ; Use to override the return address for exception
160 ; handling.
e1b93706 161 VUNSPEC_ATOMIC_CAS ; Represent an atomic compare swap.
162 VUNSPEC_ATOMIC_XCHG ; Represent an atomic exchange.
163 VUNSPEC_ATOMIC_OP ; Represent an atomic operation.
164 VUNSPEC_LL ; Represent a load-register-exclusive.
165 VUNSPEC_SC ; Represent a store-register-exclusive.
e7d6d136 166])
b11cae9e 167\f
e1159bbe 168;;---------------------------------------------------------------------------
9c08d1fa 169;; Attributes
170
a651f34d 171;; Processor type. This is created automatically from arm-cores.def.
172(include "arm-tune.md")
173
215b30b3 174; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
175; generating ARM code. This is used to control the length of some insn
176; patterns that share the same RTL in both ARM and Thumb code.
1c494086 177(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 178
ef51b8e1 179; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
180(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
181
747b7458 182; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
183(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
184
331beb1a 185;; Operand number of an input operand that is shifted. Zero if the
186;; given instruction does not shift one of its input operands.
331beb1a 187(define_attr "shift" "" (const_int 0))
188
3d91c5d6 189; Floating Point Unit. If we only have floating point emulation, then there
190; is no point in scheduling the floating point insns. (Well, for best
191; performance we should try and group them together).
bffbb863 192(define_attr "fpu" "none,vfp"
c7f506fd 193 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 194
094e994f 195; LENGTH of an instruction (in bytes)
06df6b17 196(define_attr "length" ""
e1b93706 197 (const_int 4))
9c08d1fa 198
d5d4dc8d 199; The architecture which supports the instruction (or alternative).
200; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
201; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
202; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
203; arm_arch6. This attribute is used to compute attribute "enabled",
204; use type "any" to enable an alternative in all cases.
6b8f7c28 205(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,neon_onlya8,nota8,neon_nota8,iwmmxt,iwmmxt2"
d5d4dc8d 206 (const_string "any"))
207
208(define_attr "arch_enabled" "no,yes"
209 (cond [(eq_attr "arch" "any")
210 (const_string "yes")
211
212 (and (eq_attr "arch" "a")
0bf497f5 213 (match_test "TARGET_ARM"))
d5d4dc8d 214 (const_string "yes")
215
216 (and (eq_attr "arch" "t")
0bf497f5 217 (match_test "TARGET_THUMB"))
d5d4dc8d 218 (const_string "yes")
219
220 (and (eq_attr "arch" "t1")
0bf497f5 221 (match_test "TARGET_THUMB1"))
d5d4dc8d 222 (const_string "yes")
223
224 (and (eq_attr "arch" "t2")
0bf497f5 225 (match_test "TARGET_THUMB2"))
d5d4dc8d 226 (const_string "yes")
227
228 (and (eq_attr "arch" "32")
0bf497f5 229 (match_test "TARGET_32BIT"))
d5d4dc8d 230 (const_string "yes")
231
232 (and (eq_attr "arch" "v6")
0bf497f5 233 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 234 (const_string "yes")
235
236 (and (eq_attr "arch" "nov6")
0bf497f5 237 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 238 (const_string "yes")
239
240 (and (eq_attr "arch" "onlya8")
241 (eq_attr "tune" "cortexa8"))
242 (const_string "yes")
243
10efb95f 244 (and (eq_attr "arch" "neon_onlya8")
245 (eq_attr "tune" "cortexa8")
246 (match_test "TARGET_NEON"))
247 (const_string "yes")
248
a651f34d 249 (and (eq_attr "arch" "nota8")
250 (not (eq_attr "tune" "cortexa8")))
10efb95f 251 (const_string "yes")
252
253 (and (eq_attr "arch" "neon_nota8")
254 (not (eq_attr "tune" "cortexa8"))
255 (match_test "TARGET_NEON"))
6b8f7c28 256 (const_string "yes")
257
258 (and (eq_attr "arch" "iwmmxt2")
259 (match_test "TARGET_REALLY_IWMMXT2"))
d5d4dc8d 260 (const_string "yes")]
6b8f7c28 261
d5d4dc8d 262 (const_string "no")))
263
aa06c51c 264(define_attr "opt" "any,speed,size"
265 (const_string "any"))
266
267(define_attr "opt_enabled" "no,yes"
268 (cond [(eq_attr "opt" "any")
269 (const_string "yes")
270
271 (and (eq_attr "opt" "speed")
272 (match_test "optimize_function_for_speed_p (cfun)"))
273 (const_string "yes")
274
275 (and (eq_attr "opt" "size")
276 (match_test "optimize_function_for_size_p (cfun)"))
277 (const_string "yes")]
278 (const_string "no")))
279
d5d4dc8d 280; Allows an insn to disable certain alternatives for reasons other than
281; arch support.
282(define_attr "insn_enabled" "no,yes"
283 (const_string "yes"))
284
285; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 286 (define_attr "enabled" "no,yes"
aa06c51c 287 (cond [(eq_attr "insn_enabled" "no")
288 (const_string "no")
289
290 (eq_attr "arch_enabled" "no")
291 (const_string "no")
292
293 (eq_attr "opt_enabled" "no")
294 (const_string "no")]
295 (const_string "yes")))
d5d4dc8d 296
56d27660 297; POOL_RANGE is how far away from a constant pool entry that this insn
298; can be placed. If the distance is zero, then this insn will never
299; reference the pool.
cffb2a26 300; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 301; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 302(define_attr "arm_pool_range" "" (const_int 0))
303(define_attr "thumb2_pool_range" "" (const_int 0))
304(define_attr "arm_neg_pool_range" "" (const_int 0))
305(define_attr "thumb2_neg_pool_range" "" (const_int 0))
306
307(define_attr "pool_range" ""
308 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
309 (attr "arm_pool_range")))
310(define_attr "neg_pool_range" ""
311 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
312 (attr "arm_neg_pool_range")))
56d27660 313
215b30b3 314; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 315; If such an insn references the pool, then we have no way of knowing how,
316; so use the most conservative value for pool_range.
9c08d1fa 317(define_asm_attributes
4d7a8451 318 [(set_attr "conds" "clob")
319 (set_attr "length" "4")
320 (set_attr "pool_range" "250")])
9c08d1fa 321
a2cd141b 322;; The instruction used to implement a particular pattern. This
323;; information is used by pipeline descriptions to provide accurate
324;; scheduling information.
325
326(define_attr "insn"
b49e3742 327 "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,sat,other"
a2cd141b 328 (const_string "other"))
329
9c08d1fa 330; TYPE attribute is used to detect floating point instructions which, if
331; running on a co-processor can run in parallel with other, basic instructions
332; If write-buffer scheduling is enabled then it can also be used in the
333; scheduling of writes.
334
335; Classification of each insn
607978a1 336; Note: vfp.md has different meanings for some of these, and some further
337; types as well. See that file for details.
a2cd141b 338; alu any alu instruction that doesn't hit memory or fp
339; regs or have a shifted source operand
340; alu_shift any data instruction that doesn't hit memory or fp
341; regs, but has a source operand shifted by a constant
342; alu_shift_reg any data instruction that doesn't hit memory or fp
343; regs, but has a source operand shifted by a register value
f7fbdd4a 344; mult a multiply instruction
9c08d1fa 345; block blockage insn, this blocks all functional units
346; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 347; fdivd DFmode floating point division
348; fdivs SFmode floating point division
013b9671 349; f_load[sd] A single/double load from memory. Used for VFP unit.
350; f_store[sd] A single/double store to memory. Used for VFP unit.
c0e1af52 351; f_flag a transfer of co-processor flags to the CPSR
96854199 352; f_2_r transfer float to core (no memory needed)
353; r_2_f transfer core to float
c0e1af52 354; f_cvt convert floating<->integral
a2cd141b 355; branch a branch
9c08d1fa 356; call a subroutine call
a2cd141b 357; load_byte load byte(s) from memory to arm registers
358; load1 load 1 word from memory to arm registers
359; load2 load 2 words from memory to arm registers
360; load3 load 3 words from memory to arm registers
361; load4 load 4 words from memory to arm registers
362; store store 1 word to memory from arm registers
9c08d1fa 363; store2 store 2 words
364; store3 store 3 words
a2cd141b 365; store4 store 4 (or more) words
9c08d1fa 366;
bcaec148 367
9c08d1fa 368(define_attr "type"
96854199 369 "alu,\
370 alu_shift,\
371 alu_shift_reg,\
372 mult,\
373 block,\
374 float,\
375 fdivd,\
376 fdivs,\
377 fmuls,\
378 fmuld,\
379 fmacs,\
380 fmacd,\
2d391553 381 f_rints,\
382 f_rintd,\
96854199 383 f_flag,\
384 f_loads,\
385 f_loadd,\
386 f_stores,\
387 f_stored,\
388 f_2_r,\
389 r_2_f,\
390 f_cvt,\
391 branch,\
392 call,\
393 load_byte,\
394 load1,\
395 load2,\
396 load3,\
397 load4,\
398 store1,\
399 store2,\
400 store3,\
401 store4,\
402 fconsts,\
403 fconstd,\
404 fadds,\
405 faddd,\
406 ffariths,\
407 ffarithd,\
408 fcmps,\
409 fcmpd,\
410 fcpys"
411 (if_then_else
412 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,\
413 umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
414 (const_string "mult")
415 (const_string "alu")))
9c08d1fa 416
65f2f758 417; Is this an (integer side) multiply with a 64-bit result?
418(define_attr "mul64" "no,yes"
96854199 419 (if_then_else
420 (eq_attr "insn"
421 "smlalxy,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
422 (const_string "yes")
423 (const_string "no")))
65f2f758 424
6b8f7c28 425; wtype for WMMX insn scheduling purposes.
426(define_attr "wtype"
427 "none,wor,wxor,wand,wandn,wmov,tmcrr,tmrrc,wldr,wstr,tmcr,tmrc,wadd,wsub,wmul,wmac,wavg2,tinsr,textrm,wshufh,wcmpeq,wcmpgt,wmax,wmin,wpack,wunpckih,wunpckil,wunpckeh,wunpckel,wror,wsra,wsrl,wsll,wmadd,tmia,tmiaph,tmiaxy,tbcst,tmovmsk,wacc,waligni,walignr,tandc,textrc,torc,torvsc,wsad,wabs,wabsdiff,waddsubhx,wsubaddhx,wavg4,wmulw,wqmulm,wqmulwm,waddbhus,wqmiaxy,wmiaxy,wmiawxy,wmerge" (const_string "none"))
428
9888ad6d 429; Load scheduling, set from the arm_ld_sched variable
4c834714 430; initialized by arm_option_override()
9888ad6d 431(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 432
c52acdd2 433;; Classification of NEON instructions for scheduling purposes.
c52acdd2 434(define_attr "neon_type"
435 "neon_int_1,\
436 neon_int_2,\
437 neon_int_3,\
438 neon_int_4,\
439 neon_int_5,\
440 neon_vqneg_vqabs,\
441 neon_vmov,\
442 neon_vaba,\
443 neon_vsma,\
444 neon_vaba_qqq,\
445 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
446 neon_mul_qqq_8_16_32_ddd_32,\
447 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
448 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
449 neon_mla_qqq_8_16,\
450 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
451 neon_mla_qqq_32_qqd_32_scalar,\
452 neon_mul_ddd_16_scalar_32_16_long_scalar,\
453 neon_mul_qqd_32_scalar,\
454 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
455 neon_shift_1,\
456 neon_shift_2,\
457 neon_shift_3,\
458 neon_vshl_ddd,\
459 neon_vqshl_vrshl_vqrshl_qqq,\
460 neon_vsra_vrsra,\
461 neon_fp_vadd_ddd_vabs_dd,\
462 neon_fp_vadd_qqq_vabs_qq,\
463 neon_fp_vsum,\
464 neon_fp_vmul_ddd,\
465 neon_fp_vmul_qqd,\
466 neon_fp_vmla_ddd,\
467 neon_fp_vmla_qqq,\
468 neon_fp_vmla_ddd_scalar,\
469 neon_fp_vmla_qqq_scalar,\
470 neon_fp_vrecps_vrsqrts_ddd,\
471 neon_fp_vrecps_vrsqrts_qqq,\
472 neon_bp_simple,\
473 neon_bp_2cycle,\
474 neon_bp_3cycle,\
475 neon_ldr,\
476 neon_str,\
477 neon_vld1_1_2_regs,\
478 neon_vld1_3_4_regs,\
479 neon_vld2_2_regs_vld1_vld2_all_lanes,\
480 neon_vld2_4_regs,\
481 neon_vld3_vld4,\
482 neon_vst1_1_2_regs_vst2_2_regs,\
483 neon_vst1_3_4_regs,\
484 neon_vst2_4_regs_vst3_vst4,\
485 neon_vst3_vst4,\
486 neon_vld1_vld2_lane,\
487 neon_vld3_vld4_lane,\
488 neon_vst1_vst2_lane,\
489 neon_vst3_vst4_lane,\
490 neon_vld3_vld4_all_lanes,\
491 neon_mcr,\
492 neon_mcr_2_mcrr,\
493 neon_mrc,\
494 neon_mrrc,\
495 neon_ldm_2,\
496 neon_stm_2,\
497 none"
498 (const_string "none"))
499
f7fbdd4a 500; condition codes: this one is used by final_prescan_insn to speed up
501; conditionalizing instructions. It saves having to scan the rtl to see if
502; it uses or alters the condition codes.
215b30b3 503;
f7fbdd4a 504; USE means that the condition codes are used by the insn in the process of
215b30b3 505; outputting code, this means (at present) that we can't use the insn in
506; inlined branches
507;
f7fbdd4a 508; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 509; well defined manner.
510;
f7fbdd4a 511; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 512; they are altered at all
513;
ad6d3e2a 514; UNCONDITIONAL means the instruction can not be conditionally executed and
515; that the instruction does not use or alter the condition codes.
c52acdd2 516;
ad6d3e2a 517; NOCOND means that the instruction does not use or alter the condition
518; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 519
b0694be0 520(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 521 (if_then_else
522 (ior (eq_attr "is_thumb1" "yes")
523 (eq_attr "type" "call"))
c1a66faf 524 (const_string "clob")
c52acdd2 525 (if_then_else (eq_attr "neon_type" "none")
526 (const_string "nocond")
527 (const_string "unconditional"))))
f7fbdd4a 528
215b30b3 529; Predicable means that the insn can be conditionally executed based on
530; an automatically added predicate (additional patterns are generated by
531; gen...). We default to 'no' because no Thumb patterns match this rule
532; and not all ARM patterns do.
0d66636f 533(define_attr "predicable" "no,yes" (const_string "no"))
534
129a2fe4 535; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
536; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 537; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 538; affect the schedule).
74a71f7d 539(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 540
215b30b3 541; WRITE_CONFLICT implies that a read following an unrelated write is likely
542; to stall the processor. Used with model_wbuf above.
9c08d1fa 543(define_attr "write_conflict" "no,yes"
544 (if_then_else (eq_attr "type"
96854199 545 "block,call,load1")
9c08d1fa 546 (const_string "yes")
547 (const_string "no")))
548
215b30b3 549; Classify the insns into those that take one cycle and those that take more
550; than one on the main cpu execution unit.
f7fbdd4a 551(define_attr "core_cycles" "single,multi"
552 (if_then_else (eq_attr "type"
96854199 553 "alu,alu_shift,float,fdivd,fdivs")
f7fbdd4a 554 (const_string "single")
555 (const_string "multi")))
556
cffb2a26 557;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 558;; distant label. Only applicable to Thumb code.
cffb2a26 559(define_attr "far_jump" "yes,no" (const_string "no"))
560
d51f92df 561
25f905c2 562;; The number of machine instructions this pattern expands to.
563;; Used for Thumb-2 conditional execution.
564(define_attr "ce_count" "" (const_int 1))
565
d51f92df 566;;---------------------------------------------------------------------------
fd781bb2 567;; Mode iterators
d51f92df 568
3de0dec6 569(include "iterators.md")
03770691 570
d51f92df 571;;---------------------------------------------------------------------------
572;; Predicates
573
9c9db025 574(include "predicates.md")
234f6557 575(include "constraints.md")
9c9db025 576
a2cd141b 577;;---------------------------------------------------------------------------
578;; Pipeline descriptions
215b30b3 579
e3879fd0 580(define_attr "tune_cortexr4" "yes,no"
581 (const (if_then_else
7d3cda8c 582 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 583 (const_string "yes")
584 (const_string "no"))))
585
a2cd141b 586;; True if the generic scheduling description should be used.
587
588(define_attr "generic_sched" "yes,no"
2546d93a 589 (const (if_then_else
65f2f758 590 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexa15,cortexm4")
2546d93a 591 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 592 (const_string "no")
593 (const_string "yes"))))
594
c0e1af52 595(define_attr "generic_vfp" "yes,no"
596 (const (if_then_else
597 (and (eq_attr "fpu" "vfp")
2546d93a 598 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 599 (eq_attr "tune_cortexr4" "no"))
c0e1af52 600 (const_string "yes")
601 (const_string "no"))))
602
6b8f7c28 603(include "marvell-f-iwmmxt.md")
a2cd141b 604(include "arm-generic.md")
605(include "arm926ejs.md")
c0e1af52 606(include "arm1020e.md")
a2cd141b 607(include "arm1026ejs.md")
608(include "arm1136jfs.md")
0e266d06 609(include "fa526.md")
610(include "fa606te.md")
611(include "fa626te.md")
612(include "fmp626.md")
613(include "fa726te.md")
3f1e069f 614(include "cortex-a5.md")
bcaec148 615(include "cortex-a8.md")
036068af 616(include "cortex-a9.md")
65f2f758 617(include "cortex-a15.md")
934a1e72 618(include "cortex-r4.md")
e3879fd0 619(include "cortex-r4f.md")
2546d93a 620(include "cortex-m4.md")
621(include "cortex-m4-fpu.md")
55e3ada8 622(include "vfp11.md")
3586df96 623
9c08d1fa 624\f
215b30b3 625;;---------------------------------------------------------------------------
e1159bbe 626;; Insn patterns
627;;
a0f94409 628;; Addition insns.
215b30b3 629
9c08d1fa 630;; Note: For DImode insns, there is normally no reason why operands should
631;; not be in the same register, what we don't want is for something being
632;; written to partially overlap something that is an input.
633
cffb2a26 634(define_expand "adddi3"
635 [(parallel
215b30b3 636 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 637 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 638 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 639 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 640 "TARGET_EITHER"
641 "
25f905c2 642 if (TARGET_THUMB1)
cffb2a26 643 {
0438d37f 644 if (!REG_P (operands[1]))
bc5a93af 645 operands[1] = force_reg (DImode, operands[1]);
0438d37f 646 if (!REG_P (operands[2]))
bc5a93af 647 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 648 }
649 "
650)
651
25f905c2 652(define_insn "*thumb1_adddi3"
cffb2a26 653 [(set (match_operand:DI 0 "register_operand" "=l")
654 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 655 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 656 (clobber (reg:CC CC_REGNUM))
cffb2a26 657 ]
25f905c2 658 "TARGET_THUMB1"
cffb2a26 659 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
660 [(set_attr "length" "4")]
661)
662
a0f94409 663(define_insn_and_split "*arm_adddi3"
10e5ccd5 664 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
665 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
666 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 667 (clobber (reg:CC CC_REGNUM))]
b805622c 668 "TARGET_32BIT && !TARGET_NEON"
33782ec7 669 "#"
94829feb 670 "TARGET_32BIT && reload_completed
671 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 672 [(parallel [(set (reg:CC_C CC_REGNUM)
673 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
674 (match_dup 1)))
675 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 676 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
677 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 678 "
679 {
680 operands[3] = gen_highpart (SImode, operands[0]);
681 operands[0] = gen_lowpart (SImode, operands[0]);
682 operands[4] = gen_highpart (SImode, operands[1]);
683 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 684 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 685 operands[2] = gen_lowpart (SImode, operands[2]);
686 }"
cffb2a26 687 [(set_attr "conds" "clob")
688 (set_attr "length" "8")]
689)
9c08d1fa 690
a0f94409 691(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 692 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
693 (plus:DI (sign_extend:DI
97499065 694 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 695 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 696 (clobber (reg:CC CC_REGNUM))]
b805622c 697 "TARGET_32BIT"
33782ec7 698 "#"
25f905c2 699 "TARGET_32BIT && reload_completed"
a0f94409 700 [(parallel [(set (reg:CC_C CC_REGNUM)
701 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
702 (match_dup 1)))
703 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 704 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 705 (const_int 31))
080c0b9a 706 (match_dup 4))
707 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 708 "
709 {
710 operands[3] = gen_highpart (SImode, operands[0]);
711 operands[0] = gen_lowpart (SImode, operands[0]);
712 operands[4] = gen_highpart (SImode, operands[1]);
713 operands[1] = gen_lowpart (SImode, operands[1]);
714 operands[2] = gen_lowpart (SImode, operands[2]);
715 }"
215b30b3 716 [(set_attr "conds" "clob")
717 (set_attr "length" "8")]
718)
9c08d1fa 719
a0f94409 720(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 721 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
722 (plus:DI (zero_extend:DI
97499065 723 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 724 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 725 (clobber (reg:CC CC_REGNUM))]
b805622c 726 "TARGET_32BIT"
33782ec7 727 "#"
25f905c2 728 "TARGET_32BIT && reload_completed"
a0f94409 729 [(parallel [(set (reg:CC_C CC_REGNUM)
730 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
731 (match_dup 1)))
732 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 733 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
734 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 735 "
736 {
737 operands[3] = gen_highpart (SImode, operands[0]);
738 operands[0] = gen_lowpart (SImode, operands[0]);
739 operands[4] = gen_highpart (SImode, operands[1]);
740 operands[1] = gen_lowpart (SImode, operands[1]);
741 operands[2] = gen_lowpart (SImode, operands[2]);
742 }"
cffb2a26 743 [(set_attr "conds" "clob")
744 (set_attr "length" "8")]
745)
b11cae9e 746
87b22bf7 747(define_expand "addsi3"
cffb2a26 748 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 749 (plus:SI (match_operand:SI 1 "s_register_operand" "")
750 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 751 "TARGET_EITHER"
87b22bf7 752 "
0438d37f 753 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 754 {
96f57e36 755 arm_split_constant (PLUS, SImode, NULL_RTX,
756 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 757 optimize && can_create_pseudo_p ());
87b22bf7 758 DONE;
759 }
cffb2a26 760 "
761)
87b22bf7 762
5bd751ff 763; If there is a scratch available, this will be faster than synthesizing the
a0f94409 764; addition.
765(define_peephole2
766 [(match_scratch:SI 3 "r")
372575c7 767 (set (match_operand:SI 0 "arm_general_register_operand" "")
768 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 769 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 770 "TARGET_32BIT &&
a0f94409 771 !(const_ok_for_arm (INTVAL (operands[2]))
772 || const_ok_for_arm (-INTVAL (operands[2])))
773 && const_ok_for_arm (~INTVAL (operands[2]))"
774 [(set (match_dup 3) (match_dup 2))
775 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
776 ""
777)
87b22bf7 778
2f02c19f 779;; The r/r/k alternative is required when reloading the address
780;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
781;; put the duplicated register first, and not try the commutative version.
a0f94409 782(define_insn_and_split "*arm_addsi3"
c24d855d 783 [(set (match_operand:SI 0 "s_register_operand" "=rk, r,k, r,r, k, r, k,k,r, k, r")
784 (plus:SI (match_operand:SI 1 "s_register_operand" "%0, rk,k, r,rk,k, rk,k,r,rk,k, rk")
785 (match_operand:SI 2 "reg_or_int_operand" "rk, rI,rI,k,Pj,Pj,L, L,L,PJ,PJ,?n")))]
25f905c2 786 "TARGET_32BIT"
5565501b 787 "@
c24d855d 788 add%?\\t%0, %0, %2
5565501b 789 add%?\\t%0, %1, %2
aaa37ad6 790 add%?\\t%0, %1, %2
2f02c19f 791 add%?\\t%0, %2, %1
d5cbae34 792 addw%?\\t%0, %1, %2
793 addw%?\\t%0, %1, %2
aaa37ad6 794 sub%?\\t%0, %1, #%n2
87b22bf7 795 sub%?\\t%0, %1, #%n2
d7757711 796 sub%?\\t%0, %1, #%n2
d5cbae34 797 subw%?\\t%0, %1, #%n2
798 subw%?\\t%0, %1, #%n2
87b22bf7 799 #"
a3ffc315 800 "TARGET_32BIT
0438d37f 801 && CONST_INT_P (operands[2])
d5cbae34 802 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 803 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 804 [(clobber (const_int 0))]
805 "
96f57e36 806 arm_split_constant (PLUS, SImode, curr_insn,
807 INTVAL (operands[2]), operands[0],
a0f94409 808 operands[1], 0);
809 DONE;
810 "
c24d855d 811 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 812 (set_attr "predicable" "yes")
c24d855d 813 (set_attr "arch" "t2,*,*,*,t2,t2,*,*,a,t2,t2,*")]
cffb2a26 814)
815
0bdb6455 816(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 817 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
818 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
819 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 820 "TARGET_THUMB1"
cffb2a26 821 "*
0d66636f 822 static const char * const asms[] =
cffb2a26 823 {
824 \"add\\t%0, %0, %2\",
825 \"sub\\t%0, %0, #%n2\",
826 \"add\\t%0, %1, %2\",
827 \"add\\t%0, %0, %2\",
828 \"add\\t%0, %0, %2\",
829 \"add\\t%0, %1, %2\",
0bdb6455 830 \"add\\t%0, %1, %2\",
831 \"#\",
bf7bc2f6 832 \"#\",
0bdb6455 833 \"#\"
cffb2a26 834 };
835 if ((which_alternative == 2 || which_alternative == 6)
0438d37f 836 && CONST_INT_P (operands[2])
cffb2a26 837 && INTVAL (operands[2]) < 0)
838 return \"sub\\t%0, %1, #%n2\";
839 return asms[which_alternative];
840 "
0bdb6455 841 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 842 && ((operands[1] != stack_pointer_rtx
843 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
844 || (operands[1] == stack_pointer_rtx
845 && INTVAL (operands[2]) > 1020))"
0bdb6455 846 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
847 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
848 {
849 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 850 if (operands[1] == stack_pointer_rtx)
851 offset -= 1020;
852 else
853 {
854 if (offset > 255)
855 offset = 255;
856 else if (offset < -255)
857 offset = -255;
858 }
0bdb6455 859 operands[3] = GEN_INT (offset);
860 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
861 }
bf7bc2f6 862 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 863)
864
865;; Reloading and elimination of the frame pointer can
866;; sometimes cause this optimization to be missed.
a0f94409 867(define_peephole2
372575c7 868 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 869 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 870 (set (match_dup 0)
372575c7 871 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 872 "TARGET_THUMB1
cffb2a26 873 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
874 && (INTVAL (operands[1]) & 3) == 0"
372575c7 875 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 876 ""
cffb2a26 877)
b11cae9e 878
90c2bcf0 879(define_insn "addsi3_compare0"
bd5b4116 880 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 881 (compare:CC_NOOV
215b30b3 882 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
883 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 884 (const_int 0)))
885 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 886 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 887 "TARGET_ARM"
5565501b 888 "@
25f905c2 889 add%.\\t%0, %1, %2
890 sub%.\\t%0, %1, #%n2"
cffb2a26 891 [(set_attr "conds" "set")]
892)
9c08d1fa 893
aea4c774 894(define_insn "*addsi3_compare0_scratch"
bd5b4116 895 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 896 (compare:CC_NOOV
215b30b3 897 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
898 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 899 (const_int 0)))]
ec792a7b 900 "TARGET_ARM"
cffb2a26 901 "@
902 cmn%?\\t%0, %1
903 cmp%?\\t%0, #%n1"
596e5e8f 904 [(set_attr "conds" "set")
905 (set_attr "predicable" "yes")]
0d66636f 906)
cffb2a26 907
aed179ae 908(define_insn "*compare_negsi_si"
909 [(set (reg:CC_Z CC_REGNUM)
910 (compare:CC_Z
911 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
912 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 913 "TARGET_32BIT"
aed179ae 914 "cmn%?\\t%1, %0"
596e5e8f 915 [(set_attr "conds" "set")
916 (set_attr "predicable" "yes")]
0d66636f 917)
aea4c774 918
203c488f 919;; This is the canonicalization of addsi3_compare0_for_combiner when the
920;; addend is a constant.
921(define_insn "*cmpsi2_addneg"
922 [(set (reg:CC CC_REGNUM)
923 (compare:CC
924 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 925 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 926 (set (match_operand:SI 0 "s_register_operand" "=r,r")
927 (plus:SI (match_dup 1)
2a977b78 928 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 929 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 930 "@
2a977b78 931 add%.\\t%0, %1, %3
932 sub%.\\t%0, %1, #%n3"
203c488f 933 [(set_attr "conds" "set")]
934)
935
936;; Convert the sequence
937;; sub rd, rn, #1
938;; cmn rd, #1 (equivalent to cmp rd, #-1)
939;; bne dest
940;; into
941;; subs rd, rn, #1
942;; bcs dest ((unsigned)rn >= 1)
943;; similarly for the beq variant using bcc.
944;; This is a common looping idiom (while (n--))
945(define_peephole2
372575c7 946 [(set (match_operand:SI 0 "arm_general_register_operand" "")
947 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 948 (const_int -1)))
949 (set (match_operand 2 "cc_register" "")
950 (compare (match_dup 0) (const_int -1)))
951 (set (pc)
952 (if_then_else (match_operator 3 "equality_operator"
953 [(match_dup 2) (const_int 0)])
954 (match_operand 4 "" "")
955 (match_operand 5 "" "")))]
25f905c2 956 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 957 [(parallel[
958 (set (match_dup 2)
959 (compare:CC
960 (match_dup 1) (const_int 1)))
961 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
962 (set (pc)
963 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
964 (match_dup 4)
965 (match_dup 5)))]
966 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
967 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
968 ? GEU : LTU),
969 VOIDmode,
970 operands[2], const0_rtx);"
971)
972
ebcc79bc 973;; The next four insns work because they compare the result with one of
974;; the operands, and we know that the use of the condition code is
975;; either GEU or LTU, so we can use the carry flag from the addition
976;; instead of doing the compare a second time.
977(define_insn "*addsi3_compare_op1"
bd5b4116 978 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 979 (compare:CC_C
980 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
981 (match_operand:SI 2 "arm_add_operand" "rI,L"))
982 (match_dup 1)))
983 (set (match_operand:SI 0 "s_register_operand" "=r,r")
984 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 985 "TARGET_32BIT"
ebcc79bc 986 "@
25f905c2 987 add%.\\t%0, %1, %2
988 sub%.\\t%0, %1, #%n2"
0d66636f 989 [(set_attr "conds" "set")]
990)
ebcc79bc 991
992(define_insn "*addsi3_compare_op2"
bd5b4116 993 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 994 (compare:CC_C
995 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
996 (match_operand:SI 2 "arm_add_operand" "rI,L"))
997 (match_dup 2)))
5565501b 998 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 999 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1000 "TARGET_32BIT"
5565501b 1001 "@
25f905c2 1002 add%.\\t%0, %1, %2
1003 sub%.\\t%0, %1, #%n2"
0d66636f 1004 [(set_attr "conds" "set")]
1005)
9c08d1fa 1006
ebcc79bc 1007(define_insn "*compare_addsi2_op0"
bd5b4116 1008 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 1009 (compare:CC_C
1010 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
1011 (match_operand:SI 1 "arm_add_operand" "rI,L"))
1012 (match_dup 0)))]
25f905c2 1013 "TARGET_32BIT"
ebcc79bc 1014 "@
1015 cmn%?\\t%0, %1
1016 cmp%?\\t%0, #%n1"
596e5e8f 1017 [(set_attr "conds" "set")
1018 (set_attr "predicable" "yes")]
0d66636f 1019)
ebcc79bc 1020
1021(define_insn "*compare_addsi2_op1"
bd5b4116 1022 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 1023 (compare:CC_C
1024 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
1025 (match_operand:SI 1 "arm_add_operand" "rI,L"))
1026 (match_dup 1)))]
25f905c2 1027 "TARGET_32BIT"
ebcc79bc 1028 "@
1029 cmn%?\\t%0, %1
1030 cmp%?\\t%0, #%n1"
596e5e8f 1031 [(set_attr "conds" "set")
1032 (set_attr "predicable" "yes")]
0d66636f 1033)
ebcc79bc 1034
080c0b9a 1035(define_insn "*addsi3_carryin_<optab>"
10e5ccd5 1036 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1037 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r")
1038 (match_operand:SI 2 "arm_not_operand" "rI,K"))
080c0b9a 1039 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1040 "TARGET_32BIT"
10e5ccd5 1041 "@
1042 adc%?\\t%0, %1, %2
1043 sbc%?\\t%0, %1, #%B2"
cffb2a26 1044 [(set_attr "conds" "use")]
1045)
ebcc79bc 1046
080c0b9a 1047(define_insn "*addsi3_carryin_alt2_<optab>"
10e5ccd5 1048 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
080c0b9a 1049 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
10e5ccd5 1050 (match_operand:SI 1 "s_register_operand" "%r,r"))
1051 (match_operand:SI 2 "arm_rhs_operand" "rI,K")))]
25f905c2 1052 "TARGET_32BIT"
10e5ccd5 1053 "@
1054 adc%?\\t%0, %1, %2
1055 sbc%?\\t%0, %1, #%B2"
0d66636f 1056 [(set_attr "conds" "use")]
1057)
ebcc79bc 1058
080c0b9a 1059(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1060 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1061 (plus:SI (plus:SI
1062 (match_operator:SI 2 "shift_operator"
1063 [(match_operand:SI 3 "s_register_operand" "r")
1064 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1065 (match_operand:SI 1 "s_register_operand" "r"))
1066 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1067 "TARGET_32BIT"
080c0b9a 1068 "adc%?\\t%0, %1, %3%S2"
1069 [(set_attr "conds" "use")
1070 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1071 (const_string "alu_shift")
1072 (const_string "alu_shift_reg")))]
cffb2a26 1073)
ebcc79bc 1074
922b6913 1075(define_insn "*addsi3_carryin_clobercc_<optab>"
1076 [(set (match_operand:SI 0 "s_register_operand" "=r")
1077 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1078 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1079 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1080 (clobber (reg:CC CC_REGNUM))]
1081 "TARGET_32BIT"
1082 "adc%.\\t%0, %1, %2"
1083 [(set_attr "conds" "set")]
1084)
1085
25f905c2 1086(define_expand "incscc"
1087 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1088 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1089 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1090 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1091 "TARGET_32BIT"
1092 ""
1093)
1094
1095(define_insn "*arm_incscc"
9c08d1fa 1096 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 1097 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1098 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 1099 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 1100 "TARGET_ARM"
5565501b 1101 "@
1102 add%d2\\t%0, %1, #1
1103 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 1104 [(set_attr "conds" "use")
215b30b3 1105 (set_attr "length" "4,8")]
1106)
9c08d1fa 1107
d795fb69 1108; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1109(define_split
1110 [(set (match_operand:SI 0 "s_register_operand" "")
1111 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1112 (match_operand:SI 2 "s_register_operand" ""))
1113 (const_int -1)))
1114 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1115 "TARGET_32BIT"
d795fb69 1116 [(set (match_dup 3) (match_dup 1))
1117 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1118 "
1119 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1120")
1121
604f3a0a 1122(define_expand "addsf3"
1123 [(set (match_operand:SF 0 "s_register_operand" "")
1124 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1125 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1126 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1127 "
604f3a0a 1128")
1129
604f3a0a 1130(define_expand "adddf3"
1131 [(set (match_operand:DF 0 "s_register_operand" "")
1132 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1133 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1134 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1135 "
604f3a0a 1136")
1137
cffb2a26 1138(define_expand "subdi3"
1139 [(parallel
1140 [(set (match_operand:DI 0 "s_register_operand" "")
1141 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1142 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1143 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1144 "TARGET_EITHER"
1145 "
25f905c2 1146 if (TARGET_THUMB1)
cffb2a26 1147 {
0438d37f 1148 if (!REG_P (operands[1]))
5aa8c5f0 1149 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1150 if (!REG_P (operands[2]))
5aa8c5f0 1151 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1152 }
1153 "
1154)
1155
1156(define_insn "*arm_subdi3"
1157 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1158 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1159 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1160 (clobber (reg:CC CC_REGNUM))]
94829feb 1161 "TARGET_32BIT && !TARGET_NEON"
97499065 1162 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1163 [(set_attr "conds" "clob")
1164 (set_attr "length" "8")]
1165)
1166
1167(define_insn "*thumb_subdi3"
1168 [(set (match_operand:DI 0 "register_operand" "=l")
1169 (minus:DI (match_operand:DI 1 "register_operand" "0")
1170 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1171 (clobber (reg:CC CC_REGNUM))]
25f905c2 1172 "TARGET_THUMB1"
cffb2a26 1173 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1174 [(set_attr "length" "4")]
1175)
9c08d1fa 1176
f7fbdd4a 1177(define_insn "*subdi_di_zesidi"
cffb2a26 1178 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1179 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1180 (zero_extend:DI
cffb2a26 1181 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1182 (clobber (reg:CC CC_REGNUM))]
25f905c2 1183 "TARGET_32BIT"
97499065 1184 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1185 [(set_attr "conds" "clob")
1186 (set_attr "length" "8")]
1187)
9c08d1fa 1188
f7fbdd4a 1189(define_insn "*subdi_di_sesidi"
cffb2a26 1190 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1191 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1192 (sign_extend:DI
cffb2a26 1193 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1194 (clobber (reg:CC CC_REGNUM))]
25f905c2 1195 "TARGET_32BIT"
97499065 1196 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1197 [(set_attr "conds" "clob")
1198 (set_attr "length" "8")]
1199)
9c08d1fa 1200
f7fbdd4a 1201(define_insn "*subdi_zesidi_di"
cffb2a26 1202 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1203 (minus:DI (zero_extend:DI
cffb2a26 1204 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1205 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1206 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1207 "TARGET_ARM"
97499065 1208 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1209 [(set_attr "conds" "clob")
1210 (set_attr "length" "8")]
1211)
9c08d1fa 1212
f7fbdd4a 1213(define_insn "*subdi_sesidi_di"
cffb2a26 1214 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1215 (minus:DI (sign_extend:DI
cffb2a26 1216 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1217 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1218 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1219 "TARGET_ARM"
97499065 1220 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1221 [(set_attr "conds" "clob")
1222 (set_attr "length" "8")]
1223)
9c08d1fa 1224
f7fbdd4a 1225(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1226 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1227 (minus:DI (zero_extend:DI
cffb2a26 1228 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1229 (zero_extend:DI
cffb2a26 1230 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1231 (clobber (reg:CC CC_REGNUM))]
25f905c2 1232 "TARGET_32BIT"
1233 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1234 [(set_attr "conds" "clob")
1235 (set_attr "length" "8")]
1236)
b11cae9e 1237
87b22bf7 1238(define_expand "subsi3"
cffb2a26 1239 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1240 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1241 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1242 "TARGET_EITHER"
87b22bf7 1243 "
0438d37f 1244 if (CONST_INT_P (operands[1]))
87b22bf7 1245 {
25f905c2 1246 if (TARGET_32BIT)
cffb2a26 1247 {
96f57e36 1248 arm_split_constant (MINUS, SImode, NULL_RTX,
1249 INTVAL (operands[1]), operands[0],
e1ba4a27 1250 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1251 DONE;
1252 }
25f905c2 1253 else /* TARGET_THUMB1 */
cffb2a26 1254 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1255 }
cffb2a26 1256 "
1257)
87b22bf7 1258
747b7458 1259(define_insn "thumb1_subsi3_insn"
cffb2a26 1260 [(set (match_operand:SI 0 "register_operand" "=l")
1261 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1262 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1263 "TARGET_THUMB1"
cffb2a26 1264 "sub\\t%0, %1, %2"
747b7458 1265 [(set_attr "length" "2")
1266 (set_attr "conds" "set")])
cffb2a26 1267
25f905c2 1268; ??? Check Thumb-2 split length
a0f94409 1269(define_insn_and_split "*arm_subsi3_insn"
91a5e339 1270 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r")
1271 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n")
1272 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r")))]
25f905c2 1273 "TARGET_32BIT"
e2348bcb 1274 "@
87b22bf7 1275 rsb%?\\t%0, %2, %1
aaa37ad6 1276 sub%?\\t%0, %1, %2
080c0b9a 1277 sub%?\\t%0, %1, %2
87b22bf7 1278 #"
0438d37f 1279 "&& (CONST_INT_P (operands[1])
91a5e339 1280 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1281 [(clobber (const_int 0))]
1282 "
96f57e36 1283 arm_split_constant (MINUS, SImode, curr_insn,
1284 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1285 DONE;
cffb2a26 1286 "
91a5e339 1287 [(set_attr "length" "4,4,4,16")
a0f94409 1288 (set_attr "predicable" "yes")]
1289)
1290
1291(define_peephole2
1292 [(match_scratch:SI 3 "r")
372575c7 1293 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1294 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1295 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1296 "TARGET_32BIT
a0f94409 1297 && !const_ok_for_arm (INTVAL (operands[1]))
1298 && const_ok_for_arm (~INTVAL (operands[1]))"
1299 [(set (match_dup 3) (match_dup 1))
1300 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1301 ""
cffb2a26 1302)
b11cae9e 1303
f7fbdd4a 1304(define_insn "*subsi3_compare0"
bd5b4116 1305 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1306 (compare:CC_NOOV
1307 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1308 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1309 (const_int 0)))
9c08d1fa 1310 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1311 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1312 "TARGET_32BIT"
e2348bcb 1313 "@
25f905c2 1314 sub%.\\t%0, %1, %2
1315 rsb%.\\t%0, %2, %1"
cffb2a26 1316 [(set_attr "conds" "set")]
1317)
9c08d1fa 1318
080c0b9a 1319(define_insn "*subsi3_compare"
1320 [(set (reg:CC CC_REGNUM)
1321 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1322 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1323 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1324 (minus:SI (match_dup 1) (match_dup 2)))]
1325 "TARGET_32BIT"
1326 "@
1327 sub%.\\t%0, %1, %2
1328 rsb%.\\t%0, %2, %1"
1329 [(set_attr "conds" "set")]
1330)
1331
25f905c2 1332(define_expand "decscc"
1333 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1334 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1335 (match_operator:SI 2 "arm_comparison_operator"
1336 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1337 "TARGET_32BIT"
1338 ""
1339)
1340
1341(define_insn "*arm_decscc"
cffb2a26 1342 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1343 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1344 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1345 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1346 "TARGET_ARM"
e2348bcb 1347 "@
215b30b3 1348 sub%d2\\t%0, %1, #1
1349 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1350 [(set_attr "conds" "use")
1351 (set_attr "length" "*,8")]
1352)
9c08d1fa 1353
604f3a0a 1354(define_expand "subsf3"
1355 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1356 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1357 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1358 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1359 "
604f3a0a 1360")
1361
604f3a0a 1362(define_expand "subdf3"
1363 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1364 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1365 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1366 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1367 "
604f3a0a 1368")
1369
b11cae9e 1370\f
1371;; Multiplication insns
1372
cffb2a26 1373(define_expand "mulsi3"
1374 [(set (match_operand:SI 0 "s_register_operand" "")
1375 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1376 (match_operand:SI 1 "s_register_operand" "")))]
1377 "TARGET_EITHER"
1378 ""
1379)
1380
9c08d1fa 1381;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1382(define_insn "*arm_mulsi3"
1383 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1384 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1385 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1386 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1387 "mul%?\\t%0, %2, %1"
a2cd141b 1388 [(set_attr "insn" "mul")
0d66636f 1389 (set_attr "predicable" "yes")]
cffb2a26 1390)
1391
58d7d654 1392(define_insn "*arm_mulsi3_v6"
1393 [(set (match_operand:SI 0 "s_register_operand" "=r")
1394 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1395 (match_operand:SI 2 "s_register_operand" "r")))]
1396 "TARGET_32BIT && arm_arch6"
1397 "mul%?\\t%0, %1, %2"
1398 [(set_attr "insn" "mul")
1399 (set_attr "predicable" "yes")]
1400)
1401
215b30b3 1402; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1403; 1 and 2; are the same, because reload will make operand 0 match
1404; operand 1 without realizing that this conflicts with operand 2. We fix
1405; this by adding another alternative to match this case, and then `reload'
1406; it ourselves. This alternative must come first.
cffb2a26 1407(define_insn "*thumb_mulsi3"
1408 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1409 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1410 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1411 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1412 "*
1413 if (which_alternative < 2)
20c4e896 1414 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1415 else
20c4e896 1416 return \"mul\\t%0, %2\";
cffb2a26 1417 "
1418 [(set_attr "length" "4,4,2")
a2cd141b 1419 (set_attr "insn" "mul")]
cffb2a26 1420)
b11cae9e 1421
58d7d654 1422(define_insn "*thumb_mulsi3_v6"
1423 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1424 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1425 (match_operand:SI 2 "register_operand" "l,0,0")))]
1426 "TARGET_THUMB1 && arm_arch6"
1427 "@
1490694c 1428 mul\\t%0, %2
1429 mul\\t%0, %1
58d7d654 1430 mul\\t%0, %1"
1431 [(set_attr "length" "2")
1432 (set_attr "insn" "mul")]
1433)
1434
f7fbdd4a 1435(define_insn "*mulsi3_compare0"
bd5b4116 1436 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1437 (compare:CC_NOOV (mult:SI
1438 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1439 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1440 (const_int 0)))
1441 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1442 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1443 "TARGET_ARM && !arm_arch6"
1444 "mul%.\\t%0, %2, %1"
1445 [(set_attr "conds" "set")
1446 (set_attr "insn" "muls")]
1447)
1448
1449(define_insn "*mulsi3_compare0_v6"
1450 [(set (reg:CC_NOOV CC_REGNUM)
1451 (compare:CC_NOOV (mult:SI
1452 (match_operand:SI 2 "s_register_operand" "r")
1453 (match_operand:SI 1 "s_register_operand" "r"))
1454 (const_int 0)))
1455 (set (match_operand:SI 0 "s_register_operand" "=r")
1456 (mult:SI (match_dup 2) (match_dup 1)))]
1457 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1458 "mul%.\\t%0, %2, %1"
cffb2a26 1459 [(set_attr "conds" "set")
a2cd141b 1460 (set_attr "insn" "muls")]
cffb2a26 1461)
9c08d1fa 1462
f7fbdd4a 1463(define_insn "*mulsi_compare0_scratch"
bd5b4116 1464 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1465 (compare:CC_NOOV (mult:SI
1466 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1467 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1468 (const_int 0)))
1469 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1470 "TARGET_ARM && !arm_arch6"
1471 "mul%.\\t%0, %2, %1"
1472 [(set_attr "conds" "set")
1473 (set_attr "insn" "muls")]
1474)
1475
1476(define_insn "*mulsi_compare0_scratch_v6"
1477 [(set (reg:CC_NOOV CC_REGNUM)
1478 (compare:CC_NOOV (mult:SI
1479 (match_operand:SI 2 "s_register_operand" "r")
1480 (match_operand:SI 1 "s_register_operand" "r"))
1481 (const_int 0)))
1482 (clobber (match_scratch:SI 0 "=r"))]
1483 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1484 "mul%.\\t%0, %2, %1"
cffb2a26 1485 [(set_attr "conds" "set")
a2cd141b 1486 (set_attr "insn" "muls")]
cffb2a26 1487)
9c08d1fa 1488
b11cae9e 1489;; Unnamed templates to match MLA instruction.
1490
f7fbdd4a 1491(define_insn "*mulsi3addsi"
9c08d1fa 1492 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1493 (plus:SI
9c08d1fa 1494 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1495 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1496 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1497 "TARGET_32BIT && !arm_arch6"
1498 "mla%?\\t%0, %2, %1, %3"
1499 [(set_attr "insn" "mla")
1500 (set_attr "predicable" "yes")]
1501)
1502
1503(define_insn "*mulsi3addsi_v6"
1504 [(set (match_operand:SI 0 "s_register_operand" "=r")
1505 (plus:SI
1506 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1507 (match_operand:SI 1 "s_register_operand" "r"))
1508 (match_operand:SI 3 "s_register_operand" "r")))]
1509 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1510 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1511 [(set_attr "insn" "mla")
0d66636f 1512 (set_attr "predicable" "yes")]
1513)
b11cae9e 1514
f7fbdd4a 1515(define_insn "*mulsi3addsi_compare0"
bd5b4116 1516 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1517 (compare:CC_NOOV
1518 (plus:SI (mult:SI
1519 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1520 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1521 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1522 (const_int 0)))
9c08d1fa 1523 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1524 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1525 (match_dup 3)))]
58d7d654 1526 "TARGET_ARM && arm_arch6"
1527 "mla%.\\t%0, %2, %1, %3"
1528 [(set_attr "conds" "set")
1529 (set_attr "insn" "mlas")]
1530)
1531
1532(define_insn "*mulsi3addsi_compare0_v6"
1533 [(set (reg:CC_NOOV CC_REGNUM)
1534 (compare:CC_NOOV
1535 (plus:SI (mult:SI
1536 (match_operand:SI 2 "s_register_operand" "r")
1537 (match_operand:SI 1 "s_register_operand" "r"))
1538 (match_operand:SI 3 "s_register_operand" "r"))
1539 (const_int 0)))
1540 (set (match_operand:SI 0 "s_register_operand" "=r")
1541 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1542 (match_dup 3)))]
1543 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1544 "mla%.\\t%0, %2, %1, %3"
0d66636f 1545 [(set_attr "conds" "set")
a2cd141b 1546 (set_attr "insn" "mlas")]
0d66636f 1547)
9c08d1fa 1548
f7fbdd4a 1549(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1550 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1551 (compare:CC_NOOV
1552 (plus:SI (mult:SI
1553 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1554 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1555 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1556 (const_int 0)))
9c08d1fa 1557 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1558 "TARGET_ARM && !arm_arch6"
1559 "mla%.\\t%0, %2, %1, %3"
1560 [(set_attr "conds" "set")
1561 (set_attr "insn" "mlas")]
1562)
1563
1564(define_insn "*mulsi3addsi_compare0_scratch_v6"
1565 [(set (reg:CC_NOOV CC_REGNUM)
1566 (compare:CC_NOOV
1567 (plus:SI (mult:SI
1568 (match_operand:SI 2 "s_register_operand" "r")
1569 (match_operand:SI 1 "s_register_operand" "r"))
1570 (match_operand:SI 3 "s_register_operand" "r"))
1571 (const_int 0)))
1572 (clobber (match_scratch:SI 0 "=r"))]
1573 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1574 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1575 [(set_attr "conds" "set")
a2cd141b 1576 (set_attr "insn" "mlas")]
cffb2a26 1577)
f7fbdd4a 1578
89545238 1579(define_insn "*mulsi3subsi"
1580 [(set (match_operand:SI 0 "s_register_operand" "=r")
1581 (minus:SI
1582 (match_operand:SI 3 "s_register_operand" "r")
1583 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1584 (match_operand:SI 1 "s_register_operand" "r"))))]
1585 "TARGET_32BIT && arm_arch_thumb2"
1586 "mls%?\\t%0, %2, %1, %3"
1587 [(set_attr "insn" "mla")
1588 (set_attr "predicable" "yes")]
1589)
1590
5cdca009 1591(define_expand "maddsidi4"
1592 [(set (match_operand:DI 0 "s_register_operand" "")
1593 (plus:DI
1594 (mult:DI
1595 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1596 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1597 (match_operand:DI 3 "s_register_operand" "")))]
1598 "TARGET_32BIT && arm_arch3m"
1599 "")
82b85d08 1600
1601(define_insn "*mulsidi3adddi"
fe8dbf85 1602 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1603 (plus:DI
215b30b3 1604 (mult:DI
fe8dbf85 1605 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1606 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1607 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1608 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1609 "smlal%?\\t%Q0, %R0, %3, %2"
1610 [(set_attr "insn" "smlal")
1611 (set_attr "predicable" "yes")]
1612)
1613
1614(define_insn "*mulsidi3adddi_v6"
1615 [(set (match_operand:DI 0 "s_register_operand" "=r")
1616 (plus:DI
1617 (mult:DI
1618 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1619 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1620 (match_operand:DI 1 "s_register_operand" "0")))]
1621 "TARGET_32BIT && arm_arch6"
fe8dbf85 1622 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1623 [(set_attr "insn" "smlal")
0d66636f 1624 (set_attr "predicable" "yes")]
1625)
82b85d08 1626
957788b0 1627;; 32x32->64 widening multiply.
1628;; As with mulsi3, the only difference between the v3-5 and v6+
1629;; versions of these patterns is the requirement that the output not
1630;; overlap the inputs, but that still means we have to have a named
1631;; expander and two different starred insns.
1632
1633(define_expand "mulsidi3"
1634 [(set (match_operand:DI 0 "s_register_operand" "")
1635 (mult:DI
1636 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1637 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1638 "TARGET_32BIT && arm_arch3m"
1639 ""
1640)
1641
1642(define_insn "*mulsidi3_nov6"
f7fbdd4a 1643 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1644 (mult:DI
1645 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1646 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1647 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1648 "smull%?\\t%Q0, %R0, %1, %2"
1649 [(set_attr "insn" "smull")
1650 (set_attr "predicable" "yes")]
1651)
1652
957788b0 1653(define_insn "*mulsidi3_v6"
58d7d654 1654 [(set (match_operand:DI 0 "s_register_operand" "=r")
1655 (mult:DI
1656 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1657 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1658 "TARGET_32BIT && arm_arch6"
97499065 1659 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1660 [(set_attr "insn" "smull")
0d66636f 1661 (set_attr "predicable" "yes")]
1662)
f7fbdd4a 1663
957788b0 1664(define_expand "umulsidi3"
1665 [(set (match_operand:DI 0 "s_register_operand" "")
1666 (mult:DI
1667 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1668 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1669 "TARGET_32BIT && arm_arch3m"
1670 ""
1671)
1672
1673(define_insn "*umulsidi3_nov6"
f7fbdd4a 1674 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1675 (mult:DI
1676 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1677 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1678 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1679 "umull%?\\t%Q0, %R0, %1, %2"
1680 [(set_attr "insn" "umull")
1681 (set_attr "predicable" "yes")]
1682)
1683
957788b0 1684(define_insn "*umulsidi3_v6"
58d7d654 1685 [(set (match_operand:DI 0 "s_register_operand" "=r")
1686 (mult:DI
1687 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1688 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1689 "TARGET_32BIT && arm_arch6"
97499065 1690 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1691 [(set_attr "insn" "umull")
0d66636f 1692 (set_attr "predicable" "yes")]
1693)
b11cae9e 1694
5cdca009 1695(define_expand "umaddsidi4"
1696 [(set (match_operand:DI 0 "s_register_operand" "")
1697 (plus:DI
1698 (mult:DI
1699 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1700 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1701 (match_operand:DI 3 "s_register_operand" "")))]
1702 "TARGET_32BIT && arm_arch3m"
1703 "")
82b85d08 1704
1705(define_insn "*umulsidi3adddi"
8ead09f9 1706 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1707 (plus:DI
215b30b3 1708 (mult:DI
fe8dbf85 1709 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1710 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1711 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1712 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1713 "umlal%?\\t%Q0, %R0, %3, %2"
1714 [(set_attr "insn" "umlal")
1715 (set_attr "predicable" "yes")]
1716)
1717
1718(define_insn "*umulsidi3adddi_v6"
1719 [(set (match_operand:DI 0 "s_register_operand" "=r")
1720 (plus:DI
1721 (mult:DI
1722 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1723 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1724 (match_operand:DI 1 "s_register_operand" "0")))]
1725 "TARGET_32BIT && arm_arch6"
fe8dbf85 1726 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1727 [(set_attr "insn" "umlal")
0d66636f 1728 (set_attr "predicable" "yes")]
1729)
82b85d08 1730
957788b0 1731(define_expand "smulsi3_highpart"
1732 [(parallel
1733 [(set (match_operand:SI 0 "s_register_operand" "")
1734 (truncate:SI
1735 (lshiftrt:DI
1736 (mult:DI
1737 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1738 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1739 (const_int 32))))
1740 (clobber (match_scratch:SI 3 ""))])]
1741 "TARGET_32BIT && arm_arch3m"
1742 ""
1743)
1744
1745(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1746 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1747 (truncate:SI
1748 (lshiftrt:DI
215b30b3 1749 (mult:DI
e5fea38e 1750 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1751 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1752 (const_int 32))))
1753 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1754 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1755 "smull%?\\t%3, %0, %2, %1"
1756 [(set_attr "insn" "smull")
1757 (set_attr "predicable" "yes")]
1758)
1759
957788b0 1760(define_insn "*smulsi3_highpart_v6"
58d7d654 1761 [(set (match_operand:SI 0 "s_register_operand" "=r")
1762 (truncate:SI
1763 (lshiftrt:DI
1764 (mult:DI
1765 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1766 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1767 (const_int 32))))
1768 (clobber (match_scratch:SI 3 "=r"))]
1769 "TARGET_32BIT && arm_arch6"
f082f1c4 1770 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1771 [(set_attr "insn" "smull")
0d66636f 1772 (set_attr "predicable" "yes")]
cffb2a26 1773)
f082f1c4 1774
957788b0 1775(define_expand "umulsi3_highpart"
1776 [(parallel
1777 [(set (match_operand:SI 0 "s_register_operand" "")
1778 (truncate:SI
1779 (lshiftrt:DI
1780 (mult:DI
1781 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1782 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1783 (const_int 32))))
1784 (clobber (match_scratch:SI 3 ""))])]
1785 "TARGET_32BIT && arm_arch3m"
1786 ""
1787)
1788
1789(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1790 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1791 (truncate:SI
1792 (lshiftrt:DI
215b30b3 1793 (mult:DI
e5fea38e 1794 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1795 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1796 (const_int 32))))
1797 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1798 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1799 "umull%?\\t%3, %0, %2, %1"
1800 [(set_attr "insn" "umull")
1801 (set_attr "predicable" "yes")]
1802)
1803
957788b0 1804(define_insn "*umulsi3_highpart_v6"
58d7d654 1805 [(set (match_operand:SI 0 "s_register_operand" "=r")
1806 (truncate:SI
1807 (lshiftrt:DI
1808 (mult:DI
1809 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1810 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1811 (const_int 32))))
1812 (clobber (match_scratch:SI 3 "=r"))]
1813 "TARGET_32BIT && arm_arch6"
f082f1c4 1814 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1815 [(set_attr "insn" "umull")
0d66636f 1816 (set_attr "predicable" "yes")]
cffb2a26 1817)
f082f1c4 1818
331beb1a 1819(define_insn "mulhisi3"
1820 [(set (match_operand:SI 0 "s_register_operand" "=r")
1821 (mult:SI (sign_extend:SI
1822 (match_operand:HI 1 "s_register_operand" "%r"))
1823 (sign_extend:SI
1824 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1825 "TARGET_DSP_MULTIPLY"
61a2d04c 1826 "smulbb%?\\t%0, %1, %2"
a2cd141b 1827 [(set_attr "insn" "smulxy")
fec538d9 1828 (set_attr "predicable" "yes")]
1829)
1830
1831(define_insn "*mulhisi3tb"
1832 [(set (match_operand:SI 0 "s_register_operand" "=r")
1833 (mult:SI (ashiftrt:SI
1834 (match_operand:SI 1 "s_register_operand" "r")
1835 (const_int 16))
1836 (sign_extend:SI
1837 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1838 "TARGET_DSP_MULTIPLY"
fec538d9 1839 "smultb%?\\t%0, %1, %2"
a2cd141b 1840 [(set_attr "insn" "smulxy")
fec538d9 1841 (set_attr "predicable" "yes")]
1842)
1843
1844(define_insn "*mulhisi3bt"
1845 [(set (match_operand:SI 0 "s_register_operand" "=r")
1846 (mult:SI (sign_extend:SI
1847 (match_operand:HI 1 "s_register_operand" "r"))
1848 (ashiftrt:SI
1849 (match_operand:SI 2 "s_register_operand" "r")
1850 (const_int 16))))]
25f905c2 1851 "TARGET_DSP_MULTIPLY"
fec538d9 1852 "smulbt%?\\t%0, %1, %2"
a2cd141b 1853 [(set_attr "insn" "smulxy")
fec538d9 1854 (set_attr "predicable" "yes")]
1855)
1856
1857(define_insn "*mulhisi3tt"
1858 [(set (match_operand:SI 0 "s_register_operand" "=r")
1859 (mult:SI (ashiftrt:SI
1860 (match_operand:SI 1 "s_register_operand" "r")
1861 (const_int 16))
1862 (ashiftrt:SI
1863 (match_operand:SI 2 "s_register_operand" "r")
1864 (const_int 16))))]
25f905c2 1865 "TARGET_DSP_MULTIPLY"
fec538d9 1866 "smultt%?\\t%0, %1, %2"
a2cd141b 1867 [(set_attr "insn" "smulxy")
fec538d9 1868 (set_attr "predicable" "yes")]
331beb1a 1869)
1870
5cdca009 1871(define_insn "maddhisi4"
331beb1a 1872 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1873 (plus:SI (mult:SI (sign_extend:SI
1874 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1875 (sign_extend:SI
cfa6c608 1876 (match_operand:HI 2 "s_register_operand" "r")))
1877 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1878 "TARGET_DSP_MULTIPLY"
5cdca009 1879 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1880 [(set_attr "insn" "smlaxy")
fec538d9 1881 (set_attr "predicable" "yes")]
331beb1a 1882)
1883
9a92f368 1884;; Note: there is no maddhisi4ibt because this one is canonical form
1885(define_insn "*maddhisi4tb"
1886 [(set (match_operand:SI 0 "s_register_operand" "=r")
1887 (plus:SI (mult:SI (ashiftrt:SI
1888 (match_operand:SI 1 "s_register_operand" "r")
1889 (const_int 16))
1890 (sign_extend:SI
1891 (match_operand:HI 2 "s_register_operand" "r")))
1892 (match_operand:SI 3 "s_register_operand" "r")))]
1893 "TARGET_DSP_MULTIPLY"
1894 "smlatb%?\\t%0, %1, %2, %3"
1895 [(set_attr "insn" "smlaxy")
1896 (set_attr "predicable" "yes")]
1897)
1898
1899(define_insn "*maddhisi4tt"
1900 [(set (match_operand:SI 0 "s_register_operand" "=r")
1901 (plus:SI (mult:SI (ashiftrt:SI
1902 (match_operand:SI 1 "s_register_operand" "r")
1903 (const_int 16))
1904 (ashiftrt:SI
1905 (match_operand:SI 2 "s_register_operand" "r")
1906 (const_int 16)))
1907 (match_operand:SI 3 "s_register_operand" "r")))]
1908 "TARGET_DSP_MULTIPLY"
1909 "smlatt%?\\t%0, %1, %2, %3"
1910 [(set_attr "insn" "smlaxy")
1911 (set_attr "predicable" "yes")]
1912)
1913
aff5fb4d 1914(define_insn "maddhidi4"
331beb1a 1915 [(set (match_operand:DI 0 "s_register_operand" "=r")
1916 (plus:DI
331beb1a 1917 (mult:DI (sign_extend:DI
cfa6c608 1918 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1919 (sign_extend:DI
cfa6c608 1920 (match_operand:HI 2 "s_register_operand" "r")))
1921 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1922 "TARGET_DSP_MULTIPLY"
5cdca009 1923 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1924 [(set_attr "insn" "smlalxy")
fec538d9 1925 (set_attr "predicable" "yes")])
331beb1a 1926
9a92f368 1927;; Note: there is no maddhidi4ibt because this one is canonical form
1928(define_insn "*maddhidi4tb"
1929 [(set (match_operand:DI 0 "s_register_operand" "=r")
1930 (plus:DI
1931 (mult:DI (sign_extend:DI
1932 (ashiftrt:SI
1933 (match_operand:SI 1 "s_register_operand" "r")
1934 (const_int 16)))
1935 (sign_extend:DI
1936 (match_operand:HI 2 "s_register_operand" "r")))
1937 (match_operand:DI 3 "s_register_operand" "0")))]
1938 "TARGET_DSP_MULTIPLY"
1939 "smlaltb%?\\t%Q0, %R0, %1, %2"
1940 [(set_attr "insn" "smlalxy")
1941 (set_attr "predicable" "yes")])
1942
1943(define_insn "*maddhidi4tt"
1944 [(set (match_operand:DI 0 "s_register_operand" "=r")
1945 (plus:DI
1946 (mult:DI (sign_extend:DI
1947 (ashiftrt:SI
1948 (match_operand:SI 1 "s_register_operand" "r")
1949 (const_int 16)))
1950 (sign_extend:DI
1951 (ashiftrt:SI
1952 (match_operand:SI 2 "s_register_operand" "r")
1953 (const_int 16))))
1954 (match_operand:DI 3 "s_register_operand" "0")))]
1955 "TARGET_DSP_MULTIPLY"
1956 "smlaltt%?\\t%Q0, %R0, %1, %2"
1957 [(set_attr "insn" "smlalxy")
1958 (set_attr "predicable" "yes")])
1959
604f3a0a 1960(define_expand "mulsf3"
1961 [(set (match_operand:SF 0 "s_register_operand" "")
1962 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1963 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1964 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1965 "
604f3a0a 1966")
1967
604f3a0a 1968(define_expand "muldf3"
1969 [(set (match_operand:DF 0 "s_register_operand" "")
1970 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1971 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1972 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1973 "
604f3a0a 1974")
b11cae9e 1975\f
1976;; Division insns
1977
7db9af5d 1978(define_expand "divsf3"
1979 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1980 (div:SF (match_operand:SF 1 "s_register_operand" "")
1981 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 1982 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 1983 "")
9c08d1fa 1984
7db9af5d 1985(define_expand "divdf3"
1986 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1987 (div:DF (match_operand:DF 1 "s_register_operand" "")
1988 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 1989 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1990 "")
b11cae9e 1991\f
1992;; Boolean and,ior,xor insns
1993
f6ebffac 1994;; Split up double word logical operations
1995
1996;; Split up simple DImode logical operations. Simply perform the logical
1997;; operation on the upper and lower halves of the registers.
1998(define_split
1999 [(set (match_operand:DI 0 "s_register_operand" "")
2000 (match_operator:DI 6 "logical_binary_operator"
2001 [(match_operand:DI 1 "s_register_operand" "")
2002 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2003 "TARGET_32BIT && reload_completed
e2669ea7 2004 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2005 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2006 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2007 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2008 "
215b30b3 2009 {
2010 operands[3] = gen_highpart (SImode, operands[0]);
2011 operands[0] = gen_lowpart (SImode, operands[0]);
2012 operands[4] = gen_highpart (SImode, operands[1]);
2013 operands[1] = gen_lowpart (SImode, operands[1]);
2014 operands[5] = gen_highpart (SImode, operands[2]);
2015 operands[2] = gen_lowpart (SImode, operands[2]);
2016 }"
2017)
f6ebffac 2018
f6ebffac 2019(define_split
2020 [(set (match_operand:DI 0 "s_register_operand" "")
2021 (match_operator:DI 6 "logical_binary_operator"
2022 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2023 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2024 "TARGET_32BIT && reload_completed"
f6ebffac 2025 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2026 (set (match_dup 3) (match_op_dup:SI 6
2027 [(ashiftrt:SI (match_dup 2) (const_int 31))
2028 (match_dup 4)]))]
2029 "
215b30b3 2030 {
2031 operands[3] = gen_highpart (SImode, operands[0]);
2032 operands[0] = gen_lowpart (SImode, operands[0]);
2033 operands[4] = gen_highpart (SImode, operands[1]);
2034 operands[1] = gen_lowpart (SImode, operands[1]);
2035 operands[5] = gen_highpart (SImode, operands[2]);
2036 operands[2] = gen_lowpart (SImode, operands[2]);
2037 }"
2038)
f6ebffac 2039
f6ebffac 2040;; The zero extend of operand 2 means we can just copy the high part of
2041;; operand1 into operand0.
2042(define_split
2043 [(set (match_operand:DI 0 "s_register_operand" "")
2044 (ior:DI
2045 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2046 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2047 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2048 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2049 (set (match_dup 3) (match_dup 4))]
2050 "
215b30b3 2051 {
2052 operands[4] = gen_highpart (SImode, operands[1]);
2053 operands[3] = gen_highpart (SImode, operands[0]);
2054 operands[0] = gen_lowpart (SImode, operands[0]);
2055 operands[1] = gen_lowpart (SImode, operands[1]);
2056 }"
2057)
f6ebffac 2058
2059;; The zero extend of operand 2 means we can just copy the high part of
2060;; operand1 into operand0.
2061(define_split
2062 [(set (match_operand:DI 0 "s_register_operand" "")
2063 (xor:DI
2064 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2065 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2066 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2067 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2068 (set (match_dup 3) (match_dup 4))]
2069 "
215b30b3 2070 {
2071 operands[4] = gen_highpart (SImode, operands[1]);
2072 operands[3] = gen_highpart (SImode, operands[0]);
2073 operands[0] = gen_lowpart (SImode, operands[0]);
2074 operands[1] = gen_lowpart (SImode, operands[1]);
2075 }"
2076)
f6ebffac 2077
e2669ea7 2078(define_expand "anddi3"
2079 [(set (match_operand:DI 0 "s_register_operand" "")
2080 (and:DI (match_operand:DI 1 "s_register_operand" "")
2081 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2082 "TARGET_32BIT"
2083 ""
2084)
2085
2086(define_insn "*anddi3_insn"
cffb2a26 2087 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2088 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2089 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2090 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2091 "#"
215b30b3 2092 [(set_attr "length" "8")]
2093)
b11cae9e 2094
a0f94409 2095(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2096 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2097 (and:DI (zero_extend:DI
2098 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2099 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2100 "TARGET_32BIT"
f6ebffac 2101 "#"
25f905c2 2102 "TARGET_32BIT && reload_completed"
a0f94409 2103 ; The zero extend of operand 2 clears the high word of the output
2104 ; operand.
2105 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2106 (set (match_dup 3) (const_int 0))]
2107 "
2108 {
2109 operands[3] = gen_highpart (SImode, operands[0]);
2110 operands[0] = gen_lowpart (SImode, operands[0]);
2111 operands[1] = gen_lowpart (SImode, operands[1]);
2112 }"
215b30b3 2113 [(set_attr "length" "8")]
2114)
b11cae9e 2115
f7fbdd4a 2116(define_insn "*anddi_sesdi_di"
cffb2a26 2117 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2118 (and:DI (sign_extend:DI
2119 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2120 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2121 "TARGET_32BIT"
f6ebffac 2122 "#"
cffb2a26 2123 [(set_attr "length" "8")]
2124)
b11cae9e 2125
87b22bf7 2126(define_expand "andsi3"
cffb2a26 2127 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2128 (and:SI (match_operand:SI 1 "s_register_operand" "")
2129 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2130 "TARGET_EITHER"
87b22bf7 2131 "
25f905c2 2132 if (TARGET_32BIT)
87b22bf7 2133 {
0438d37f 2134 if (CONST_INT_P (operands[2]))
cffb2a26 2135 {
47b5b27b 2136 if (INTVAL (operands[2]) == 255 && arm_arch6)
2137 {
2138 operands[1] = convert_to_mode (QImode, operands[1], 1);
2139 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2140 operands[1]));
2141 }
2142 else
2143 arm_split_constant (AND, SImode, NULL_RTX,
2144 INTVAL (operands[2]), operands[0],
2145 operands[1],
2146 optimize && can_create_pseudo_p ());
615caa51 2147
cffb2a26 2148 DONE;
2149 }
87b22bf7 2150 }
25f905c2 2151 else /* TARGET_THUMB1 */
cffb2a26 2152 {
0438d37f 2153 if (!CONST_INT_P (operands[2]))
923ffadb 2154 {
2155 rtx tmp = force_reg (SImode, operands[2]);
2156 if (rtx_equal_p (operands[0], operands[1]))
2157 operands[2] = tmp;
2158 else
2159 {
2160 operands[2] = operands[1];
2161 operands[1] = tmp;
2162 }
2163 }
cffb2a26 2164 else
2165 {
2166 int i;
2167
215b30b3 2168 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2169 {
215b30b3 2170 operands[2] = force_reg (SImode,
2171 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2172
747b7458 2173 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2174
2175 DONE;
2176 }
87b22bf7 2177
cffb2a26 2178 for (i = 9; i <= 31; i++)
2179 {
2180 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2181 {
2182 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2183 const0_rtx));
2184 DONE;
2185 }
215b30b3 2186 else if ((((HOST_WIDE_INT) 1) << i) - 1
2187 == ~INTVAL (operands[2]))
cffb2a26 2188 {
2189 rtx shift = GEN_INT (i);
2190 rtx reg = gen_reg_rtx (SImode);
2191
2192 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2193 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2194
2195 DONE;
2196 }
2197 }
2198
2199 operands[2] = force_reg (SImode, operands[2]);
2200 }
215b30b3 2201 }
2202 "
cffb2a26 2203)
2204
25f905c2 2205; ??? Check split length for Thumb-2
a0f94409 2206(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2207 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2208 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2209 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2210 "TARGET_32BIT"
5565501b 2211 "@
2212 and%?\\t%0, %1, %2
87b22bf7 2213 bic%?\\t%0, %1, #%B2
2214 #"
25f905c2 2215 "TARGET_32BIT
0438d37f 2216 && CONST_INT_P (operands[2])
a0f94409 2217 && !(const_ok_for_arm (INTVAL (operands[2]))
2218 || const_ok_for_arm (~INTVAL (operands[2])))"
2219 [(clobber (const_int 0))]
2220 "
96f57e36 2221 arm_split_constant (AND, SImode, curr_insn,
2222 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2223 DONE;
2224 "
0d66636f 2225 [(set_attr "length" "4,4,16")
2226 (set_attr "predicable" "yes")]
cffb2a26 2227)
2228
25f905c2 2229(define_insn "*thumb1_andsi3_insn"
cffb2a26 2230 [(set (match_operand:SI 0 "register_operand" "=l")
2231 (and:SI (match_operand:SI 1 "register_operand" "%0")
2232 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2233 "TARGET_THUMB1"
747b7458 2234 "and\\t%0, %2"
2235 [(set_attr "length" "2")
2236 (set_attr "conds" "set")])
87b22bf7 2237
f7fbdd4a 2238(define_insn "*andsi3_compare0"
bd5b4116 2239 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2240 (compare:CC_NOOV
2241 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2242 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2243 (const_int 0)))
cffb2a26 2244 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2245 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2246 "TARGET_32BIT"
5565501b 2247 "@
25f905c2 2248 and%.\\t%0, %1, %2
2249 bic%.\\t%0, %1, #%B2"
cffb2a26 2250 [(set_attr "conds" "set")]
2251)
9c08d1fa 2252
f7fbdd4a 2253(define_insn "*andsi3_compare0_scratch"
bd5b4116 2254 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2255 (compare:CC_NOOV
2256 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2257 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2258 (const_int 0)))
dd193d7c 2259 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2260 "TARGET_32BIT"
5565501b 2261 "@
2262 tst%?\\t%0, %1
25f905c2 2263 bic%.\\t%2, %0, #%B1"
0d66636f 2264 [(set_attr "conds" "set")]
2265)
9c08d1fa 2266
f7fbdd4a 2267(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2268 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2269 (compare:CC_NOOV (zero_extract:SI
2270 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2271 (match_operand 1 "const_int_operand" "n")
2272 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2273 (const_int 0)))]
25f905c2 2274 "TARGET_32BIT
cffb2a26 2275 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2276 && INTVAL (operands[1]) > 0
2277 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2278 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2279 "*
5c49a439 2280 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2281 << INTVAL (operands[2]));
40dbec34 2282 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2283 return \"\";
0d66636f 2284 "
596e5e8f 2285 [(set_attr "conds" "set")
2286 (set_attr "predicable" "yes")]
0d66636f 2287)
9c08d1fa 2288
f4462328 2289(define_insn_and_split "*ne_zeroextractsi"
c4034607 2290 [(set (match_operand:SI 0 "s_register_operand" "=r")
2291 (ne:SI (zero_extract:SI
2292 (match_operand:SI 1 "s_register_operand" "r")
2293 (match_operand:SI 2 "const_int_operand" "n")
2294 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2295 (const_int 0)))
2296 (clobber (reg:CC CC_REGNUM))]
25f905c2 2297 "TARGET_32BIT
cffb2a26 2298 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2299 && INTVAL (operands[2]) > 0
2300 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2301 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2302 "#"
25f905c2 2303 "TARGET_32BIT
f4462328 2304 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2305 && INTVAL (operands[2]) > 0
2306 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2307 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2308 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2309 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2310 (const_int 0)))
2311 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2312 (set (match_dup 0)
2313 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2314 (match_dup 0) (const_int 1)))]
2315 "
2316 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2317 << INTVAL (operands[3]));
2318 "
2319 [(set_attr "conds" "clob")
25f905c2 2320 (set (attr "length")
2321 (if_then_else (eq_attr "is_thumb" "yes")
2322 (const_int 12)
2323 (const_int 8)))]
f4462328 2324)
2325
2326(define_insn_and_split "*ne_zeroextractsi_shifted"
2327 [(set (match_operand:SI 0 "s_register_operand" "=r")
2328 (ne:SI (zero_extract:SI
2329 (match_operand:SI 1 "s_register_operand" "r")
2330 (match_operand:SI 2 "const_int_operand" "n")
2331 (const_int 0))
2332 (const_int 0)))
2333 (clobber (reg:CC CC_REGNUM))]
2334 "TARGET_ARM"
2335 "#"
2336 "TARGET_ARM"
2337 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2338 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2339 (const_int 0)))
2340 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2341 (set (match_dup 0)
2342 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2343 (match_dup 0) (const_int 1)))]
2344 "
2345 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2346 "
2347 [(set_attr "conds" "clob")
2348 (set_attr "length" "8")]
2349)
2350
2351(define_insn_and_split "*ite_ne_zeroextractsi"
2352 [(set (match_operand:SI 0 "s_register_operand" "=r")
2353 (if_then_else:SI (ne (zero_extract:SI
2354 (match_operand:SI 1 "s_register_operand" "r")
2355 (match_operand:SI 2 "const_int_operand" "n")
2356 (match_operand:SI 3 "const_int_operand" "n"))
2357 (const_int 0))
2358 (match_operand:SI 4 "arm_not_operand" "rIK")
2359 (const_int 0)))
2360 (clobber (reg:CC CC_REGNUM))]
2361 "TARGET_ARM
2362 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2363 && INTVAL (operands[2]) > 0
2364 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2365 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2366 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2367 "#"
2368 "TARGET_ARM
2369 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2370 && INTVAL (operands[2]) > 0
2371 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2372 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2373 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2374 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2375 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2376 (const_int 0)))
2377 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2378 (set (match_dup 0)
2379 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2380 (match_dup 0) (match_dup 4)))]
2381 "
c4034607 2382 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2383 << INTVAL (operands[3]));
2384 "
2385 [(set_attr "conds" "clob")
2386 (set_attr "length" "8")]
2387)
2388
2389(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2390 [(set (match_operand:SI 0 "s_register_operand" "=r")
2391 (if_then_else:SI (ne (zero_extract:SI
2392 (match_operand:SI 1 "s_register_operand" "r")
2393 (match_operand:SI 2 "const_int_operand" "n")
2394 (const_int 0))
2395 (const_int 0))
2396 (match_operand:SI 3 "arm_not_operand" "rIK")
2397 (const_int 0)))
2398 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2399 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2400 "#"
f8d7bf2f 2401 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2402 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2403 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2404 (const_int 0)))
2405 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2406 (set (match_dup 0)
2407 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2408 (match_dup 0) (match_dup 3)))]
2409 "
2410 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2411 "
2412 [(set_attr "conds" "clob")
215b30b3 2413 (set_attr "length" "8")]
2414)
9c08d1fa 2415
58d6528b 2416(define_split
2417 [(set (match_operand:SI 0 "s_register_operand" "")
2418 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2419 (match_operand:SI 2 "const_int_operand" "")
2420 (match_operand:SI 3 "const_int_operand" "")))
2421 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2422 "TARGET_THUMB1"
58d6528b 2423 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2424 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2425 "{
2426 HOST_WIDE_INT temp = INTVAL (operands[2]);
2427
2428 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2429 operands[3] = GEN_INT (32 - temp);
2430 }"
2431)
2432
25f905c2 2433;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2434(define_split
2435 [(set (match_operand:SI 0 "s_register_operand" "")
2436 (match_operator:SI 1 "shiftable_operator"
2437 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2438 (match_operand:SI 3 "const_int_operand" "")
2439 (match_operand:SI 4 "const_int_operand" ""))
2440 (match_operand:SI 5 "s_register_operand" "")]))
2441 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2442 "TARGET_ARM"
2443 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2444 (set (match_dup 0)
2445 (match_op_dup 1
2446 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2447 (match_dup 5)]))]
2448 "{
2449 HOST_WIDE_INT temp = INTVAL (operands[3]);
2450
2451 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2452 operands[4] = GEN_INT (32 - temp);
2453 }"
2454)
2455
58d6528b 2456(define_split
2457 [(set (match_operand:SI 0 "s_register_operand" "")
2458 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2459 (match_operand:SI 2 "const_int_operand" "")
2460 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2461 "TARGET_THUMB1"
58d6528b 2462 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2463 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2464 "{
2465 HOST_WIDE_INT temp = INTVAL (operands[2]);
2466
2467 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2468 operands[3] = GEN_INT (32 - temp);
2469 }"
2470)
2471
d7863cfe 2472(define_split
2473 [(set (match_operand:SI 0 "s_register_operand" "")
2474 (match_operator:SI 1 "shiftable_operator"
2475 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2476 (match_operand:SI 3 "const_int_operand" "")
2477 (match_operand:SI 4 "const_int_operand" ""))
2478 (match_operand:SI 5 "s_register_operand" "")]))
2479 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2480 "TARGET_ARM"
2481 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2482 (set (match_dup 0)
2483 (match_op_dup 1
2484 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2485 (match_dup 5)]))]
2486 "{
2487 HOST_WIDE_INT temp = INTVAL (operands[3]);
2488
2489 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2490 operands[4] = GEN_INT (32 - temp);
2491 }"
2492)
2493
a42059fd 2494;;; ??? This pattern is bogus. If operand3 has bits outside the range
2495;;; represented by the bitfield, then this will produce incorrect results.
2496;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2497;;; which have a real bit-field insert instruction, the truncation happens
2498;;; in the bit-field insert instruction itself. Since arm does not have a
2499;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2500;;; the value before we insert. This loses some of the advantage of having
2501;;; this insv pattern, so this pattern needs to be reevalutated.
2502
8a18b90c 2503(define_expand "insv"
eb04cafb 2504 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2505 (match_operand 1 "general_operand" "")
2506 (match_operand 2 "general_operand" ""))
2507 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2508 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2509 "
215b30b3 2510 {
2511 int start_bit = INTVAL (operands[2]);
2512 int width = INTVAL (operands[1]);
2513 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2514 rtx target, subtarget;
2515
8b054d5a 2516 if (arm_arch_thumb2)
2517 {
eb04cafb 2518 if (unaligned_access && MEM_P (operands[0])
2519 && s_register_operand (operands[3], GET_MODE (operands[3]))
2520 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2521 {
eb04cafb 2522 rtx base_addr;
2523
2524 if (BYTES_BIG_ENDIAN)
2525 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2526 - start_bit;
8b054d5a 2527
eb04cafb 2528 if (width == 32)
8b054d5a 2529 {
eb04cafb 2530 base_addr = adjust_address (operands[0], SImode,
2531 start_bit / BITS_PER_UNIT);
2532 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2533 }
eb04cafb 2534 else
2535 {
2536 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2537
eb04cafb 2538 base_addr = adjust_address (operands[0], HImode,
2539 start_bit / BITS_PER_UNIT);
2540 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2541 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2542 }
2543 DONE;
8b054d5a 2544 }
eb04cafb 2545 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2546 {
eb04cafb 2547 bool use_bfi = TRUE;
8b054d5a 2548
0438d37f 2549 if (CONST_INT_P (operands[3]))
eb04cafb 2550 {
2551 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2552
2553 if (val == 0)
2554 {
2555 emit_insn (gen_insv_zero (operands[0], operands[1],
2556 operands[2]));
2557 DONE;
2558 }
2559
2560 /* See if the set can be done with a single orr instruction. */
2561 if (val == mask && const_ok_for_arm (val << start_bit))
2562 use_bfi = FALSE;
2563 }
2564
2565 if (use_bfi)
2566 {
0438d37f 2567 if (!REG_P (operands[3]))
eb04cafb 2568 operands[3] = force_reg (SImode, operands[3]);
2569
2570 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2571 operands[3]));
2572 DONE;
2573 }
8b054d5a 2574 }
eb04cafb 2575 else
2576 FAIL;
8b054d5a 2577 }
2578
eb04cafb 2579 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2580 FAIL;
2581
3f8fde42 2582 target = copy_rtx (operands[0]);
215b30b3 2583 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2584 subreg as the final target. */
2585 if (GET_CODE (target) == SUBREG)
2586 {
2587 subtarget = gen_reg_rtx (SImode);
2588 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2589 < GET_MODE_SIZE (SImode))
2590 target = SUBREG_REG (target);
2591 }
2592 else
2593 subtarget = target;
8a18b90c 2594
0438d37f 2595 if (CONST_INT_P (operands[3]))
215b30b3 2596 {
2597 /* Since we are inserting a known constant, we may be able to
2598 reduce the number of bits that we have to clear so that
2599 the mask becomes simple. */
2600 /* ??? This code does not check to see if the new mask is actually
2601 simpler. It may not be. */
2602 rtx op1 = gen_reg_rtx (SImode);
2603 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2604 start of this pattern. */
2605 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2606 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2607
c5b3a71b 2608 emit_insn (gen_andsi3 (op1, operands[0],
2609 gen_int_mode (~mask2, SImode)));
215b30b3 2610 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2611 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2612 }
2613 else if (start_bit == 0
2614 && !(const_ok_for_arm (mask)
2615 || const_ok_for_arm (~mask)))
2616 {
2617 /* A Trick, since we are setting the bottom bits in the word,
2618 we can shift operand[3] up, operand[0] down, OR them together
2619 and rotate the result back again. This takes 3 insns, and
5910bb95 2620 the third might be mergeable into another op. */
215b30b3 2621 /* The shift up copes with the possibility that operand[3] is
2622 wider than the bitfield. */
2623 rtx op0 = gen_reg_rtx (SImode);
2624 rtx op1 = gen_reg_rtx (SImode);
2625
2626 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2627 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2628 emit_insn (gen_iorsi3 (op1, op1, op0));
2629 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2630 }
2631 else if ((width + start_bit == 32)
2632 && !(const_ok_for_arm (mask)
2633 || const_ok_for_arm (~mask)))
2634 {
2635 /* Similar trick, but slightly less efficient. */
8a18b90c 2636
215b30b3 2637 rtx op0 = gen_reg_rtx (SImode);
2638 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2639
215b30b3 2640 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2641 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2642 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2643 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2644 }
2645 else
2646 {
c5b3a71b 2647 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2648 rtx op1 = gen_reg_rtx (SImode);
2649 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2650
215b30b3 2651 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2652 {
2653 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2654
215b30b3 2655 emit_insn (gen_movsi (tmp, op0));
2656 op0 = tmp;
2657 }
8a18b90c 2658
215b30b3 2659 /* Mask out any bits in operand[3] that are not needed. */
2660 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2661
0438d37f 2662 if (CONST_INT_P (op0)
215b30b3 2663 && (const_ok_for_arm (mask << start_bit)
2664 || const_ok_for_arm (~(mask << start_bit))))
2665 {
c5b3a71b 2666 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2667 emit_insn (gen_andsi3 (op2, operands[0], op0));
2668 }
2669 else
2670 {
0438d37f 2671 if (CONST_INT_P (op0))
215b30b3 2672 {
2673 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2674
215b30b3 2675 emit_insn (gen_movsi (tmp, op0));
2676 op0 = tmp;
2677 }
2678
2679 if (start_bit != 0)
2680 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2681
215b30b3 2682 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2683 }
8a18b90c 2684
215b30b3 2685 if (start_bit != 0)
2686 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2687
215b30b3 2688 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2689 }
f082f1c4 2690
215b30b3 2691 if (subtarget != target)
2692 {
2693 /* If TARGET is still a SUBREG, then it must be wider than a word,
2694 so we must be careful only to set the subword we were asked to. */
2695 if (GET_CODE (target) == SUBREG)
2696 emit_move_insn (target, subtarget);
2697 else
2698 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2699 }
8a18b90c 2700
215b30b3 2701 DONE;
2702 }"
2703)
8a18b90c 2704
8b054d5a 2705(define_insn "insv_zero"
2706 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2707 (match_operand:SI 1 "const_int_operand" "M")
2708 (match_operand:SI 2 "const_int_operand" "M"))
2709 (const_int 0))]
2710 "arm_arch_thumb2"
2711 "bfc%?\t%0, %2, %1"
2712 [(set_attr "length" "4")
2713 (set_attr "predicable" "yes")]
2714)
2715
2716(define_insn "insv_t2"
2717 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2718 (match_operand:SI 1 "const_int_operand" "M")
2719 (match_operand:SI 2 "const_int_operand" "M"))
2720 (match_operand:SI 3 "s_register_operand" "r"))]
2721 "arm_arch_thumb2"
2722 "bfi%?\t%0, %3, %2, %1"
2723 [(set_attr "length" "4")
2724 (set_attr "predicable" "yes")]
2725)
2726
215b30b3 2727; constants for op 2 will never be given to these patterns.
a0f94409 2728(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2729 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2730 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2731 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2732 "TARGET_32BIT"
f6ebffac 2733 "#"
e2669ea7 2734 "TARGET_32BIT && reload_completed
2735 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2736 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2737 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2738 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2739 "
2740 {
2741 operands[3] = gen_highpart (SImode, operands[0]);
2742 operands[0] = gen_lowpart (SImode, operands[0]);
2743 operands[4] = gen_highpart (SImode, operands[1]);
2744 operands[1] = gen_lowpart (SImode, operands[1]);
2745 operands[5] = gen_highpart (SImode, operands[2]);
2746 operands[2] = gen_lowpart (SImode, operands[2]);
2747 }"
0d66636f 2748 [(set_attr "length" "8")
2749 (set_attr "predicable" "yes")]
2750)
9c08d1fa 2751
a0f94409 2752(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2753 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2754 (and:DI (not:DI (zero_extend:DI
2755 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2756 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2757 "TARGET_32BIT"
e2348bcb 2758 "@
97499065 2759 bic%?\\t%Q0, %Q1, %2
f6ebffac 2760 #"
a0f94409 2761 ; (not (zero_extend ...)) allows us to just copy the high word from
2762 ; operand1 to operand0.
25f905c2 2763 "TARGET_32BIT
a0f94409 2764 && reload_completed
2765 && operands[0] != operands[1]"
5a097f7d 2766 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2767 (set (match_dup 3) (match_dup 4))]
2768 "
2769 {
2770 operands[3] = gen_highpart (SImode, operands[0]);
2771 operands[0] = gen_lowpart (SImode, operands[0]);
2772 operands[4] = gen_highpart (SImode, operands[1]);
2773 operands[1] = gen_lowpart (SImode, operands[1]);
2774 }"
0d66636f 2775 [(set_attr "length" "4,8")
2776 (set_attr "predicable" "yes")]
2777)
9c08d1fa 2778
a0f94409 2779(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2780 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2781 (and:DI (not:DI (sign_extend:DI
2782 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2783 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2784 "TARGET_32BIT"
f6ebffac 2785 "#"
25f905c2 2786 "TARGET_32BIT && reload_completed"
5a097f7d 2787 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2788 (set (match_dup 3) (and:SI (not:SI
2789 (ashiftrt:SI (match_dup 2) (const_int 31)))
2790 (match_dup 4)))]
2791 "
2792 {
2793 operands[3] = gen_highpart (SImode, operands[0]);
2794 operands[0] = gen_lowpart (SImode, operands[0]);
2795 operands[4] = gen_highpart (SImode, operands[1]);
2796 operands[1] = gen_lowpart (SImode, operands[1]);
2797 }"
0d66636f 2798 [(set_attr "length" "8")
2799 (set_attr "predicable" "yes")]
2800)
9c08d1fa 2801
8a18b90c 2802(define_insn "andsi_notsi_si"
9c08d1fa 2803 [(set (match_operand:SI 0 "s_register_operand" "=r")
2804 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2805 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2806 "TARGET_32BIT"
0d66636f 2807 "bic%?\\t%0, %1, %2"
2808 [(set_attr "predicable" "yes")]
2809)
b11cae9e 2810
747b7458 2811(define_insn "thumb1_bicsi3"
cffb2a26 2812 [(set (match_operand:SI 0 "register_operand" "=l")
2813 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2814 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2815 "TARGET_THUMB1"
747b7458 2816 "bic\\t%0, %1"
2817 [(set_attr "length" "2")
2818 (set_attr "conds" "set")])
cffb2a26 2819
8a18b90c 2820(define_insn "andsi_not_shiftsi_si"
a2cd141b 2821 [(set (match_operand:SI 0 "s_register_operand" "=r")
2822 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2823 [(match_operand:SI 2 "s_register_operand" "r")
2824 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2825 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2826 "TARGET_ARM"
6c4c2133 2827 "bic%?\\t%0, %1, %2%S4"
344495ea 2828 [(set_attr "predicable" "yes")
331beb1a 2829 (set_attr "shift" "2")
a2cd141b 2830 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2831 (const_string "alu_shift")
2832 (const_string "alu_shift_reg")))]
6c4c2133 2833)
8a18b90c 2834
f7fbdd4a 2835(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2836 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2837 (compare:CC_NOOV
2838 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2839 (match_operand:SI 1 "s_register_operand" "r"))
2840 (const_int 0)))
9c08d1fa 2841 (set (match_operand:SI 0 "s_register_operand" "=r")
2842 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2843 "TARGET_32BIT"
2844 "bic%.\\t%0, %1, %2"
0d66636f 2845 [(set_attr "conds" "set")]
2846)
9c08d1fa 2847
f7fbdd4a 2848(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2849 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2850 (compare:CC_NOOV
2851 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2852 (match_operand:SI 1 "s_register_operand" "r"))
2853 (const_int 0)))
9c08d1fa 2854 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2855 "TARGET_32BIT"
2856 "bic%.\\t%0, %1, %2"
0d66636f 2857 [(set_attr "conds" "set")]
2858)
9c08d1fa 2859
e2669ea7 2860(define_expand "iordi3"
2861 [(set (match_operand:DI 0 "s_register_operand" "")
2862 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2863 (match_operand:DI 2 "neon_logic_op2" "")))]
2864 "TARGET_32BIT"
2865 ""
2866)
2867
2868(define_insn "*iordi3_insn"
cffb2a26 2869 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2870 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2871 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2872 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2873 "#"
0d66636f 2874 [(set_attr "length" "8")
2875 (set_attr "predicable" "yes")]
cffb2a26 2876)
9c08d1fa 2877
f7fbdd4a 2878(define_insn "*iordi_zesidi_di"
9c08d1fa 2879 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2880 (ior:DI (zero_extend:DI
2881 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2882 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2883 "TARGET_32BIT"
e2348bcb 2884 "@
97499065 2885 orr%?\\t%Q0, %Q1, %2
f6ebffac 2886 #"
0d66636f 2887 [(set_attr "length" "4,8")
2888 (set_attr "predicable" "yes")]
cffb2a26 2889)
9c08d1fa 2890
f7fbdd4a 2891(define_insn "*iordi_sesidi_di"
9c08d1fa 2892 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2893 (ior:DI (sign_extend:DI
2894 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2895 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2896 "TARGET_32BIT"
f6ebffac 2897 "#"
0d66636f 2898 [(set_attr "length" "8")
2899 (set_attr "predicable" "yes")]
cffb2a26 2900)
9c08d1fa 2901
87b22bf7 2902(define_expand "iorsi3"
cffb2a26 2903 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2904 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2905 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2906 "TARGET_EITHER"
87b22bf7 2907 "
0438d37f 2908 if (CONST_INT_P (operands[2]))
87b22bf7 2909 {
25f905c2 2910 if (TARGET_32BIT)
cffb2a26 2911 {
96f57e36 2912 arm_split_constant (IOR, SImode, NULL_RTX,
2913 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2914 optimize && can_create_pseudo_p ());
cffb2a26 2915 DONE;
2916 }
25f905c2 2917 else /* TARGET_THUMB1 */
923ffadb 2918 {
2919 rtx tmp = force_reg (SImode, operands[2]);
2920 if (rtx_equal_p (operands[0], operands[1]))
2921 operands[2] = tmp;
2922 else
2923 {
2924 operands[2] = operands[1];
2925 operands[1] = tmp;
2926 }
2927 }
87b22bf7 2928 }
cffb2a26 2929 "
2930)
87b22bf7 2931
d5d4dc8d 2932(define_insn_and_split "*iorsi3_insn"
2933 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2934 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2935 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2936 "TARGET_32BIT"
87b22bf7 2937 "@
2938 orr%?\\t%0, %1, %2
d5d4dc8d 2939 orn%?\\t%0, %1, #%B2
87b22bf7 2940 #"
d5d4dc8d 2941 "TARGET_32BIT
0438d37f 2942 && CONST_INT_P (operands[2])
d5d4dc8d 2943 && !(const_ok_for_arm (INTVAL (operands[2]))
2944 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2945 [(clobber (const_int 0))]
d5d4dc8d 2946{
96f57e36 2947 arm_split_constant (IOR, SImode, curr_insn,
2948 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2949 DONE;
d5d4dc8d 2950}
2951 [(set_attr "length" "4,4,16")
2952 (set_attr "arch" "32,t2,32")
2953 (set_attr "predicable" "yes")])
cffb2a26 2954
747b7458 2955(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2956 [(set (match_operand:SI 0 "register_operand" "=l")
2957 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2958 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2959 "TARGET_THUMB1"
747b7458 2960 "orr\\t%0, %2"
2961 [(set_attr "length" "2")
2962 (set_attr "conds" "set")])
9c08d1fa 2963
a0f94409 2964(define_peephole2
2965 [(match_scratch:SI 3 "r")
372575c7 2966 (set (match_operand:SI 0 "arm_general_register_operand" "")
2967 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2968 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2969 "TARGET_ARM
a0f94409 2970 && !const_ok_for_arm (INTVAL (operands[2]))
2971 && const_ok_for_arm (~INTVAL (operands[2]))"
2972 [(set (match_dup 3) (match_dup 2))
2973 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2974 ""
215b30b3 2975)
a0f94409 2976
f7fbdd4a 2977(define_insn "*iorsi3_compare0"
bd5b4116 2978 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2979 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2980 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2981 (const_int 0)))
2982 (set (match_operand:SI 0 "s_register_operand" "=r")
2983 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2984 "TARGET_32BIT"
2985 "orr%.\\t%0, %1, %2"
cffb2a26 2986 [(set_attr "conds" "set")]
2987)
9c08d1fa 2988
f7fbdd4a 2989(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2990 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2991 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2992 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2993 (const_int 0)))
2994 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2995 "TARGET_32BIT"
2996 "orr%.\\t%0, %1, %2"
0d66636f 2997 [(set_attr "conds" "set")]
2998)
9c08d1fa 2999
e2669ea7 3000(define_expand "xordi3"
3001 [(set (match_operand:DI 0 "s_register_operand" "")
3002 (xor:DI (match_operand:DI 1 "s_register_operand" "")
3003 (match_operand:DI 2 "s_register_operand" "")))]
3004 "TARGET_32BIT"
3005 ""
3006)
3007
3008(define_insn "*xordi3_insn"
cffb2a26 3009 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3010 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
3011 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 3012 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 3013 "#"
0d66636f 3014 [(set_attr "length" "8")
3015 (set_attr "predicable" "yes")]
cffb2a26 3016)
9c08d1fa 3017
f7fbdd4a 3018(define_insn "*xordi_zesidi_di"
9c08d1fa 3019 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3020 (xor:DI (zero_extend:DI
3021 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3022 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3023 "TARGET_32BIT"
e2348bcb 3024 "@
97499065 3025 eor%?\\t%Q0, %Q1, %2
f6ebffac 3026 #"
0d66636f 3027 [(set_attr "length" "4,8")
3028 (set_attr "predicable" "yes")]
cffb2a26 3029)
9c08d1fa 3030
f7fbdd4a 3031(define_insn "*xordi_sesidi_di"
9c08d1fa 3032 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3033 (xor:DI (sign_extend:DI
3034 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3035 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3036 "TARGET_32BIT"
f6ebffac 3037 "#"
0d66636f 3038 [(set_attr "length" "8")
3039 (set_attr "predicable" "yes")]
cffb2a26 3040)
9c08d1fa 3041
cffb2a26 3042(define_expand "xorsi3"
3043 [(set (match_operand:SI 0 "s_register_operand" "")
3044 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3045 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3046 "TARGET_EITHER"
0438d37f 3047 "if (CONST_INT_P (operands[2]))
923ffadb 3048 {
3049 if (TARGET_32BIT)
3050 {
3051 arm_split_constant (XOR, SImode, NULL_RTX,
3052 INTVAL (operands[2]), operands[0], operands[1],
3053 optimize && can_create_pseudo_p ());
3054 DONE;
3055 }
3056 else /* TARGET_THUMB1 */
3057 {
3058 rtx tmp = force_reg (SImode, operands[2]);
3059 if (rtx_equal_p (operands[0], operands[1]))
3060 operands[2] = tmp;
3061 else
3062 {
3063 operands[2] = operands[1];
3064 operands[1] = tmp;
3065 }
3066 }
3067 }"
cffb2a26 3068)
3069
5dcb35d9 3070(define_insn_and_split "*arm_xorsi3"
3071 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3072 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3073 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
25f905c2 3074 "TARGET_32BIT"
5dcb35d9 3075 "@
3076 eor%?\\t%0, %1, %2
3077 #"
3078 "TARGET_32BIT
0438d37f 3079 && CONST_INT_P (operands[2])
5dcb35d9 3080 && !const_ok_for_arm (INTVAL (operands[2]))"
3081 [(clobber (const_int 0))]
3082{
3083 arm_split_constant (XOR, SImode, curr_insn,
3084 INTVAL (operands[2]), operands[0], operands[1], 0);
3085 DONE;
3086}
3087 [(set_attr "length" "4,16")
3088 (set_attr "predicable" "yes")]
cffb2a26 3089)
3090
747b7458 3091(define_insn "*thumb1_xorsi3_insn"
cffb2a26 3092 [(set (match_operand:SI 0 "register_operand" "=l")
3093 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3094 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3095 "TARGET_THUMB1"
747b7458 3096 "eor\\t%0, %2"
3097 [(set_attr "length" "2")
3098 (set_attr "conds" "set")])
9c08d1fa 3099
f7fbdd4a 3100(define_insn "*xorsi3_compare0"
bd5b4116 3101 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3102 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3103 (match_operand:SI 2 "arm_rhs_operand" "rI"))
3104 (const_int 0)))
3105 (set (match_operand:SI 0 "s_register_operand" "=r")
3106 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3107 "TARGET_32BIT"
3108 "eor%.\\t%0, %1, %2"
0d66636f 3109 [(set_attr "conds" "set")]
3110)
9c08d1fa 3111
f7fbdd4a 3112(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3113 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3114 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
3115 (match_operand:SI 1 "arm_rhs_operand" "rI"))
3116 (const_int 0)))]
25f905c2 3117 "TARGET_32BIT"
40dbec34 3118 "teq%?\\t%0, %1"
cffb2a26 3119 [(set_attr "conds" "set")]
3120)
9c08d1fa 3121
215b30b3 3122; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3123; (NOT D) we can sometimes merge the final NOT into one of the following
3124; insns.
9c08d1fa 3125
3126(define_split
a058e94a 3127 [(set (match_operand:SI 0 "s_register_operand" "")
3128 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3129 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3130 (match_operand:SI 3 "arm_rhs_operand" "")))
3131 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3132 "TARGET_32BIT"
9c08d1fa 3133 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3134 (not:SI (match_dup 3))))
3135 (set (match_dup 0) (not:SI (match_dup 4)))]
3136 ""
3137)
3138
f7fbdd4a 3139(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 3140 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3141 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3142 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3143 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3144 "TARGET_32BIT"
40dbec34 3145 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 3146 [(set_attr "length" "8")
25f905c2 3147 (set_attr "ce_count" "2")
0d66636f 3148 (set_attr "predicable" "yes")]
cffb2a26 3149)
9c08d1fa 3150
25f905c2 3151; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3152; insns are available?
d7863cfe 3153(define_split
3154 [(set (match_operand:SI 0 "s_register_operand" "")
3155 (match_operator:SI 1 "logical_binary_operator"
3156 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3157 (match_operand:SI 3 "const_int_operand" "")
3158 (match_operand:SI 4 "const_int_operand" ""))
3159 (match_operator:SI 9 "logical_binary_operator"
3160 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3161 (match_operand:SI 6 "const_int_operand" ""))
3162 (match_operand:SI 7 "s_register_operand" "")])]))
3163 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3164 "TARGET_32BIT
d7863cfe 3165 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3166 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3167 [(set (match_dup 8)
3168 (match_op_dup 1
3169 [(ashift:SI (match_dup 2) (match_dup 4))
3170 (match_dup 5)]))
3171 (set (match_dup 0)
3172 (match_op_dup 1
3173 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3174 (match_dup 7)]))]
3175 "
3176 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3177")
3178
3179(define_split
3180 [(set (match_operand:SI 0 "s_register_operand" "")
3181 (match_operator:SI 1 "logical_binary_operator"
3182 [(match_operator:SI 9 "logical_binary_operator"
3183 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3184 (match_operand:SI 6 "const_int_operand" ""))
3185 (match_operand:SI 7 "s_register_operand" "")])
3186 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3187 (match_operand:SI 3 "const_int_operand" "")
3188 (match_operand:SI 4 "const_int_operand" ""))]))
3189 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3190 "TARGET_32BIT
d7863cfe 3191 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3192 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3193 [(set (match_dup 8)
3194 (match_op_dup 1
3195 [(ashift:SI (match_dup 2) (match_dup 4))
3196 (match_dup 5)]))
3197 (set (match_dup 0)
3198 (match_op_dup 1
3199 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3200 (match_dup 7)]))]
3201 "
3202 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3203")
3204
3205(define_split
3206 [(set (match_operand:SI 0 "s_register_operand" "")
3207 (match_operator:SI 1 "logical_binary_operator"
3208 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3209 (match_operand:SI 3 "const_int_operand" "")
3210 (match_operand:SI 4 "const_int_operand" ""))
3211 (match_operator:SI 9 "logical_binary_operator"
3212 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3213 (match_operand:SI 6 "const_int_operand" ""))
3214 (match_operand:SI 7 "s_register_operand" "")])]))
3215 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3216 "TARGET_32BIT
d7863cfe 3217 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3218 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3219 [(set (match_dup 8)
3220 (match_op_dup 1
3221 [(ashift:SI (match_dup 2) (match_dup 4))
3222 (match_dup 5)]))
3223 (set (match_dup 0)
3224 (match_op_dup 1
3225 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3226 (match_dup 7)]))]
3227 "
3228 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3229")
3230
3231(define_split
3232 [(set (match_operand:SI 0 "s_register_operand" "")
3233 (match_operator:SI 1 "logical_binary_operator"
3234 [(match_operator:SI 9 "logical_binary_operator"
3235 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3236 (match_operand:SI 6 "const_int_operand" ""))
3237 (match_operand:SI 7 "s_register_operand" "")])
3238 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3239 (match_operand:SI 3 "const_int_operand" "")
3240 (match_operand:SI 4 "const_int_operand" ""))]))
3241 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3242 "TARGET_32BIT
d7863cfe 3243 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3244 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3245 [(set (match_dup 8)
3246 (match_op_dup 1
3247 [(ashift:SI (match_dup 2) (match_dup 4))
3248 (match_dup 5)]))
3249 (set (match_dup 0)
3250 (match_op_dup 1
3251 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3252 (match_dup 7)]))]
3253 "
3254 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3255")
9c08d1fa 3256\f
3257
3258;; Minimum and maximum insns
3259
8b9dc177 3260(define_expand "smaxsi3"
3261 [(parallel [
3262 (set (match_operand:SI 0 "s_register_operand" "")
3263 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3264 (match_operand:SI 2 "arm_rhs_operand" "")))
3265 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3266 "TARGET_32BIT"
8b9dc177 3267 "
8774928b 3268 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3269 {
3270 /* No need for a clobber of the condition code register here. */
3271 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3272 gen_rtx_SMAX (SImode, operands[1],
3273 operands[2])));
3274 DONE;
3275 }
3276")
3277
3278(define_insn "*smax_0"
3279 [(set (match_operand:SI 0 "s_register_operand" "=r")
3280 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3281 (const_int 0)))]
25f905c2 3282 "TARGET_32BIT"
8b9dc177 3283 "bic%?\\t%0, %1, %1, asr #31"
3284 [(set_attr "predicable" "yes")]
3285)
3286
8774928b 3287(define_insn "*smax_m1"
3288 [(set (match_operand:SI 0 "s_register_operand" "=r")
3289 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3290 (const_int -1)))]
25f905c2 3291 "TARGET_32BIT"
8774928b 3292 "orr%?\\t%0, %1, %1, asr #31"
3293 [(set_attr "predicable" "yes")]
3294)
3295
25f905c2 3296(define_insn "*arm_smax_insn"
8b9dc177 3297 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3298 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3299 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3300 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3301 "TARGET_ARM"
e2348bcb 3302 "@
3303 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3304 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3305 [(set_attr "conds" "clob")
8b9dc177 3306 (set_attr "length" "8,12")]
cffb2a26 3307)
9c08d1fa 3308
8b9dc177 3309(define_expand "sminsi3"
3310 [(parallel [
3311 (set (match_operand:SI 0 "s_register_operand" "")
3312 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3313 (match_operand:SI 2 "arm_rhs_operand" "")))
3314 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3315 "TARGET_32BIT"
8b9dc177 3316 "
3317 if (operands[2] == const0_rtx)
3318 {
3319 /* No need for a clobber of the condition code register here. */
3320 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3321 gen_rtx_SMIN (SImode, operands[1],
3322 operands[2])));
3323 DONE;
3324 }
3325")
3326
3327(define_insn "*smin_0"
3328 [(set (match_operand:SI 0 "s_register_operand" "=r")
3329 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3330 (const_int 0)))]
25f905c2 3331 "TARGET_32BIT"
8b9dc177 3332 "and%?\\t%0, %1, %1, asr #31"
3333 [(set_attr "predicable" "yes")]
3334)
3335
25f905c2 3336(define_insn "*arm_smin_insn"
8b9dc177 3337 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3338 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3339 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3340 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3341 "TARGET_ARM"
e2348bcb 3342 "@
3343 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3344 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3345 [(set_attr "conds" "clob")
8b9dc177 3346 (set_attr "length" "8,12")]
0d66636f 3347)
9c08d1fa 3348
25f905c2 3349(define_expand "umaxsi3"
3350 [(parallel [
3351 (set (match_operand:SI 0 "s_register_operand" "")
3352 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3353 (match_operand:SI 2 "arm_rhs_operand" "")))
3354 (clobber (reg:CC CC_REGNUM))])]
3355 "TARGET_32BIT"
3356 ""
3357)
3358
3359(define_insn "*arm_umaxsi3"
9c08d1fa 3360 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3361 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3362 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3363 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3364 "TARGET_ARM"
e2348bcb 3365 "@
3366 cmp\\t%1, %2\;movcc\\t%0, %2
3367 cmp\\t%1, %2\;movcs\\t%0, %1
3368 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3369 [(set_attr "conds" "clob")
3370 (set_attr "length" "8,8,12")]
3371)
9c08d1fa 3372
25f905c2 3373(define_expand "uminsi3"
3374 [(parallel [
3375 (set (match_operand:SI 0 "s_register_operand" "")
3376 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3377 (match_operand:SI 2 "arm_rhs_operand" "")))
3378 (clobber (reg:CC CC_REGNUM))])]
3379 "TARGET_32BIT"
3380 ""
3381)
3382
3383(define_insn "*arm_uminsi3"
9c08d1fa 3384 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3385 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3386 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3387 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3388 "TARGET_ARM"
e2348bcb 3389 "@
3390 cmp\\t%1, %2\;movcs\\t%0, %2
3391 cmp\\t%1, %2\;movcc\\t%0, %1
3392 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3393 [(set_attr "conds" "clob")
3394 (set_attr "length" "8,8,12")]
3395)
9c08d1fa 3396
8a18b90c 3397(define_insn "*store_minmaxsi"
9c08d1fa 3398 [(set (match_operand:SI 0 "memory_operand" "=m")
3399 (match_operator:SI 3 "minmax_operator"
3400 [(match_operand:SI 1 "s_register_operand" "r")
3401 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3402 (clobber (reg:CC CC_REGNUM))]
25f905c2 3403 "TARGET_32BIT"
9c08d1fa 3404 "*
dc55b8a9 3405 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3406 operands[1], operands[2]);
e2348bcb 3407 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3408 if (TARGET_THUMB2)
3409 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3410 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3411 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3412 return \"\";
0d66636f 3413 "
3414 [(set_attr "conds" "clob")
25f905c2 3415 (set (attr "length")
3416 (if_then_else (eq_attr "is_thumb" "yes")
3417 (const_int 14)
3418 (const_int 12)))
0d66636f 3419 (set_attr "type" "store1")]
3420)
9c08d1fa 3421
8a18b90c 3422; Reject the frame pointer in operand[1], since reloading this after
3423; it has been eliminated can cause carnage.
f7fbdd4a 3424(define_insn "*minmax_arithsi"
9c08d1fa 3425 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3426 (match_operator:SI 4 "shiftable_operator"
3427 [(match_operator:SI 5 "minmax_operator"
3428 [(match_operand:SI 2 "s_register_operand" "r,r")
3429 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3430 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3431 (clobber (reg:CC CC_REGNUM))]
25f905c2 3432 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3433 "*
0d66636f 3434 {
3435 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3436 bool need_else;
3437
3438 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3439 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3440 need_else = true;
3441 else
3442 need_else = false;
0d66636f 3443
dc55b8a9 3444 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3445 operands[2], operands[3]);
0d66636f 3446 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3447 if (TARGET_THUMB2)
3448 {
3449 if (need_else)
3450 output_asm_insn (\"ite\\t%d5\", operands);
3451 else
3452 output_asm_insn (\"it\\t%d5\", operands);
3453 }
0d66636f 3454 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3455 if (need_else)
0d66636f 3456 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3457 return \"\";
215b30b3 3458 }"
0d66636f 3459 [(set_attr "conds" "clob")
25f905c2 3460 (set (attr "length")
3461 (if_then_else (eq_attr "is_thumb" "yes")
3462 (const_int 14)
3463 (const_int 12)))]
0d66636f 3464)
9c08d1fa 3465
b49e3742 3466(define_code_iterator SAT [smin smax])
3467(define_code_iterator SATrev [smin smax])
3468(define_code_attr SATlo [(smin "1") (smax "2")])
3469(define_code_attr SAThi [(smin "2") (smax "1")])
3470
3471(define_insn "*satsi_<SAT:code>"
3472 [(set (match_operand:SI 0 "s_register_operand" "=r")
3473 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3474 (match_operand:SI 1 "const_int_operand" "i"))
3475 (match_operand:SI 2 "const_int_operand" "i")))]
3476 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3477 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3478{
3479 int mask;
3480 bool signed_sat;
3481 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3482 &mask, &signed_sat))
3483 gcc_unreachable ();
3484
3485 operands[1] = GEN_INT (mask);
3486 if (signed_sat)
3487 return "ssat%?\t%0, %1, %3";
3488 else
3489 return "usat%?\t%0, %1, %3";
3490}
3491 [(set_attr "predicable" "yes")
3492 (set_attr "insn" "sat")])
3493
3494(define_insn "*satsi_<SAT:code>_shift"
3495 [(set (match_operand:SI 0 "s_register_operand" "=r")
3496 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3497 [(match_operand:SI 4 "s_register_operand" "r")
3498 (match_operand:SI 5 "const_int_operand" "i")])
3499 (match_operand:SI 1 "const_int_operand" "i"))
3500 (match_operand:SI 2 "const_int_operand" "i")))]
3501 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3502 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3503{
3504 int mask;
3505 bool signed_sat;
3506 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3507 &mask, &signed_sat))
3508 gcc_unreachable ();
3509
3510 operands[1] = GEN_INT (mask);
3511 if (signed_sat)
3512 return "ssat%?\t%0, %1, %4%S3";
3513 else
3514 return "usat%?\t%0, %1, %4%S3";
3515}
3516 [(set_attr "predicable" "yes")
3517 (set_attr "insn" "sat")
3518 (set_attr "shift" "3")
3519 (set_attr "type" "alu_shift")])
b11cae9e 3520\f
3521;; Shift and rotation insns
3522
a2cd141b 3523(define_expand "ashldi3"
3524 [(set (match_operand:DI 0 "s_register_operand" "")
3525 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3526 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3527 "TARGET_32BIT"
a2cd141b 3528 "
aa06c51c 3529 if (TARGET_NEON)
3530 {
3531 /* Delay the decision whether to use NEON or core-regs until
3532 register allocation. */
3533 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3534 DONE;
3535 }
3536 else
3537 {
3538 /* Only the NEON case can handle in-memory shift counts. */
3539 if (!reg_or_int_operand (operands[2], SImode))
3540 operands[2] = force_reg (SImode, operands[2]);
3541 }
3542
b805622c 3543 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3544 ; /* No special preparation statements; expand pattern as above. */
3545 else
a2cd141b 3546 {
ffcc986d 3547 rtx scratch1, scratch2;
3548
3549 if (CONST_INT_P (operands[2])
3550 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3551 {
3552 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3553 DONE;
3554 }
ffcc986d 3555
3556 /* Ideally we should use iwmmxt here if we could know that operands[1]
3557 ends up already living in an iwmmxt register. Otherwise it's
3558 cheaper to have the alternate code being generated than moving
3559 values to iwmmxt regs and back. */
3560
3561 /* If we're optimizing for size, we prefer the libgcc calls. */
3562 if (optimize_function_for_size_p (cfun))
3563 FAIL;
3564
3565 /* Expand operation using core-registers.
3566 'FAIL' would achieve the same thing, but this is a bit smarter. */
3567 scratch1 = gen_reg_rtx (SImode);
3568 scratch2 = gen_reg_rtx (SImode);
3569 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3570 operands[2], scratch1, scratch2);
3571 DONE;
a2cd141b 3572 }
a2cd141b 3573 "
3574)
3575
3576(define_insn "arm_ashldi3_1bit"
50ad1bf9 3577 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3578 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3579 (const_int 1)))
3580 (clobber (reg:CC CC_REGNUM))]
25f905c2 3581 "TARGET_32BIT"
a2cd141b 3582 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3583 [(set_attr "conds" "clob")
3584 (set_attr "length" "8")]
3585)
3586
87b22bf7 3587(define_expand "ashlsi3"
cffb2a26 3588 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3589 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3590 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3591 "TARGET_EITHER"
87b22bf7 3592 "
0438d37f 3593 if (CONST_INT_P (operands[2])
87b22bf7 3594 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3595 {
3596 emit_insn (gen_movsi (operands[0], const0_rtx));
3597 DONE;
3598 }
cffb2a26 3599 "
3600)
3601
25f905c2 3602(define_insn "*thumb1_ashlsi3"
cffb2a26 3603 [(set (match_operand:SI 0 "register_operand" "=l,l")
3604 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3605 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3606 "TARGET_THUMB1"
cffb2a26 3607 "lsl\\t%0, %1, %2"
747b7458 3608 [(set_attr "length" "2")
3609 (set_attr "conds" "set")])
b11cae9e 3610
a2cd141b 3611(define_expand "ashrdi3"
3612 [(set (match_operand:DI 0 "s_register_operand" "")
3613 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3614 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3615 "TARGET_32BIT"
a2cd141b 3616 "
aa06c51c 3617 if (TARGET_NEON)
3618 {
3619 /* Delay the decision whether to use NEON or core-regs until
3620 register allocation. */
3621 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3622 DONE;
3623 }
3624
b805622c 3625 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3626 ; /* No special preparation statements; expand pattern as above. */
3627 else
a2cd141b 3628 {
ffcc986d 3629 rtx scratch1, scratch2;
3630
3631 if (CONST_INT_P (operands[2])
3632 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3633 {
3634 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3635 DONE;
3636 }
ffcc986d 3637
3638 /* Ideally we should use iwmmxt here if we could know that operands[1]
3639 ends up already living in an iwmmxt register. Otherwise it's
3640 cheaper to have the alternate code being generated than moving
3641 values to iwmmxt regs and back. */
3642
3643 /* If we're optimizing for size, we prefer the libgcc calls. */
3644 if (optimize_function_for_size_p (cfun))
3645 FAIL;
3646
3647 /* Expand operation using core-registers.
3648 'FAIL' would achieve the same thing, but this is a bit smarter. */
3649 scratch1 = gen_reg_rtx (SImode);
3650 scratch2 = gen_reg_rtx (SImode);
3651 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3652 operands[2], scratch1, scratch2);
3653 DONE;
a2cd141b 3654 }
a2cd141b 3655 "
3656)
3657
3658(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3659 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3660 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3661 (const_int 1)))
3662 (clobber (reg:CC CC_REGNUM))]
25f905c2 3663 "TARGET_32BIT"
a2cd141b 3664 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3665 [(set_attr "conds" "clob")
d2a518d1 3666 (set_attr "insn" "mov")
a2cd141b 3667 (set_attr "length" "8")]
3668)
3669
87b22bf7 3670(define_expand "ashrsi3"
cffb2a26 3671 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3672 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3673 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3674 "TARGET_EITHER"
87b22bf7 3675 "
0438d37f 3676 if (CONST_INT_P (operands[2])
87b22bf7 3677 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3678 operands[2] = GEN_INT (31);
cffb2a26 3679 "
3680)
3681
25f905c2 3682(define_insn "*thumb1_ashrsi3"
cffb2a26 3683 [(set (match_operand:SI 0 "register_operand" "=l,l")
3684 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3685 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3686 "TARGET_THUMB1"
cffb2a26 3687 "asr\\t%0, %1, %2"
747b7458 3688 [(set_attr "length" "2")
3689 (set_attr "conds" "set")])
b11cae9e 3690
a2cd141b 3691(define_expand "lshrdi3"
3692 [(set (match_operand:DI 0 "s_register_operand" "")
3693 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3694 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3695 "TARGET_32BIT"
a2cd141b 3696 "
aa06c51c 3697 if (TARGET_NEON)
3698 {
3699 /* Delay the decision whether to use NEON or core-regs until
3700 register allocation. */
3701 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3702 DONE;
3703 }
3704
b805622c 3705 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3706 ; /* No special preparation statements; expand pattern as above. */
3707 else
a2cd141b 3708 {
ffcc986d 3709 rtx scratch1, scratch2;
3710
3711 if (CONST_INT_P (operands[2])
3712 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3713 {
3714 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3715 DONE;
3716 }
ffcc986d 3717
3718 /* Ideally we should use iwmmxt here if we could know that operands[1]
3719 ends up already living in an iwmmxt register. Otherwise it's
3720 cheaper to have the alternate code being generated than moving
3721 values to iwmmxt regs and back. */
3722
3723 /* If we're optimizing for size, we prefer the libgcc calls. */
3724 if (optimize_function_for_size_p (cfun))
3725 FAIL;
3726
3727 /* Expand operation using core-registers.
3728 'FAIL' would achieve the same thing, but this is a bit smarter. */
3729 scratch1 = gen_reg_rtx (SImode);
3730 scratch2 = gen_reg_rtx (SImode);
3731 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3732 operands[2], scratch1, scratch2);
3733 DONE;
a2cd141b 3734 }
a2cd141b 3735 "
3736)
3737
3738(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3739 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3740 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3741 (const_int 1)))
3742 (clobber (reg:CC CC_REGNUM))]
25f905c2 3743 "TARGET_32BIT"
a2cd141b 3744 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3745 [(set_attr "conds" "clob")
d2a518d1 3746 (set_attr "insn" "mov")
a2cd141b 3747 (set_attr "length" "8")]
3748)
3749
87b22bf7 3750(define_expand "lshrsi3"
cffb2a26 3751 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3752 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3753 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3754 "TARGET_EITHER"
87b22bf7 3755 "
0438d37f 3756 if (CONST_INT_P (operands[2])
87b22bf7 3757 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3758 {
3759 emit_insn (gen_movsi (operands[0], const0_rtx));
3760 DONE;
3761 }
cffb2a26 3762 "
3763)
3764
25f905c2 3765(define_insn "*thumb1_lshrsi3"
cffb2a26 3766 [(set (match_operand:SI 0 "register_operand" "=l,l")
3767 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3768 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3769 "TARGET_THUMB1"
cffb2a26 3770 "lsr\\t%0, %1, %2"
747b7458 3771 [(set_attr "length" "2")
3772 (set_attr "conds" "set")])
b11cae9e 3773
87b22bf7 3774(define_expand "rotlsi3"
cffb2a26 3775 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3776 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3777 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3778 "TARGET_32BIT"
87b22bf7 3779 "
0438d37f 3780 if (CONST_INT_P (operands[2]))
87b22bf7 3781 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3782 else
b11cae9e 3783 {
87b22bf7 3784 rtx reg = gen_reg_rtx (SImode);
3785 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3786 operands[2] = reg;
b11cae9e 3787 }
cffb2a26 3788 "
3789)
9c08d1fa 3790
87b22bf7 3791(define_expand "rotrsi3"
cffb2a26 3792 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3793 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3794 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3795 "TARGET_EITHER"
87b22bf7 3796 "
25f905c2 3797 if (TARGET_32BIT)
cffb2a26 3798 {
0438d37f 3799 if (CONST_INT_P (operands[2])
cffb2a26 3800 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3801 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3802 }
25f905c2 3803 else /* TARGET_THUMB1 */
cffb2a26 3804 {
0438d37f 3805 if (CONST_INT_P (operands [2]))
cffb2a26 3806 operands [2] = force_reg (SImode, operands[2]);
3807 }
3808 "
3809)
87b22bf7 3810
25f905c2 3811(define_insn "*thumb1_rotrsi3"
cffb2a26 3812 [(set (match_operand:SI 0 "register_operand" "=l")
3813 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3814 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3815 "TARGET_THUMB1"
cffb2a26 3816 "ror\\t%0, %0, %2"
3817 [(set_attr "length" "2")]
3818)
3819
3820(define_insn "*arm_shiftsi3"
3821 [(set (match_operand:SI 0 "s_register_operand" "=r")
3822 (match_operator:SI 3 "shift_operator"
3823 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3824 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3825 "TARGET_32BIT"
3826 "* return arm_output_shift(operands, 0);"
344495ea 3827 [(set_attr "predicable" "yes")
331beb1a 3828 (set_attr "shift" "1")
a2cd141b 3829 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3830 (const_string "alu_shift")
3831 (const_string "alu_shift_reg")))]
6c4c2133 3832)
87b22bf7 3833
f7fbdd4a 3834(define_insn "*shiftsi3_compare0"
bd5b4116 3835 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3836 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3837 [(match_operand:SI 1 "s_register_operand" "r")
3838 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3839 (const_int 0)))
3840 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3841 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3842 "TARGET_32BIT"
3843 "* return arm_output_shift(operands, 1);"
344495ea 3844 [(set_attr "conds" "set")
331beb1a 3845 (set_attr "shift" "1")
a2cd141b 3846 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3847 (const_string "alu_shift")
3848 (const_string "alu_shift_reg")))]
0d66636f 3849)
9c08d1fa 3850
f7fbdd4a 3851(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3852 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3853 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3854 [(match_operand:SI 1 "s_register_operand" "r")
3855 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3856 (const_int 0)))
3857 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3858 "TARGET_32BIT"
3859 "* return arm_output_shift(operands, 1);"
344495ea 3860 [(set_attr "conds" "set")
a2cd141b 3861 (set_attr "shift" "1")]
0d66636f 3862)
9c08d1fa 3863
d5d4dc8d 3864(define_insn "*not_shiftsi"
3865 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3866 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3867 [(match_operand:SI 1 "s_register_operand" "r,r")
3868 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3869 "TARGET_32BIT"
6c4c2133 3870 "mvn%?\\t%0, %1%S3"
344495ea 3871 [(set_attr "predicable" "yes")
331beb1a 3872 (set_attr "shift" "1")
d2a518d1 3873 (set_attr "insn" "mvn")
d5d4dc8d 3874 (set_attr "arch" "32,a")
3875 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3876
d5d4dc8d 3877(define_insn "*not_shiftsi_compare0"
bd5b4116 3878 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3879 (compare:CC_NOOV
3880 (not:SI (match_operator:SI 3 "shift_operator"
3881 [(match_operand:SI 1 "s_register_operand" "r,r")
3882 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3883 (const_int 0)))
3884 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3885 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3886 "TARGET_32BIT"
25f905c2 3887 "mvn%.\\t%0, %1%S3"
344495ea 3888 [(set_attr "conds" "set")
331beb1a 3889 (set_attr "shift" "1")
d2a518d1 3890 (set_attr "insn" "mvn")
d5d4dc8d 3891 (set_attr "arch" "32,a")
3892 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3893
d5d4dc8d 3894(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3895 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3896 (compare:CC_NOOV
3897 (not:SI (match_operator:SI 3 "shift_operator"
3898 [(match_operand:SI 1 "s_register_operand" "r,r")
3899 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3900 (const_int 0)))
3901 (clobber (match_scratch:SI 0 "=r,r"))]
3902 "TARGET_32BIT"
25f905c2 3903 "mvn%.\\t%0, %1%S3"
344495ea 3904 [(set_attr "conds" "set")
331beb1a 3905 (set_attr "shift" "1")
d2a518d1 3906 (set_attr "insn" "mvn")
d5d4dc8d 3907 (set_attr "arch" "32,a")
3908 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3909
cffb2a26 3910;; We don't really have extzv, but defining this using shifts helps
3911;; to reduce register pressure later on.
3912
3913(define_expand "extzv"
eb04cafb 3914 [(set (match_operand 0 "s_register_operand" "")
3915 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3916 (match_operand 2 "const_int_operand" "")
3917 (match_operand 3 "const_int_operand" "")))]
8b054d5a 3918 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3919 "
3920 {
3921 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3922 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3923
8b054d5a 3924 if (arm_arch_thumb2)
3925 {
eb04cafb 3926 HOST_WIDE_INT width = INTVAL (operands[2]);
3927 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3928
3929 if (unaligned_access && MEM_P (operands[1])
3930 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3931 {
3932 rtx base_addr;
3933
3934 if (BYTES_BIG_ENDIAN)
3935 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3936 - bitpos;
3937
3938 if (width == 32)
3939 {
3940 base_addr = adjust_address (operands[1], SImode,
3941 bitpos / BITS_PER_UNIT);
3942 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3943 }
3944 else
3945 {
3946 rtx dest = operands[0];
3947 rtx tmp = gen_reg_rtx (SImode);
3948
3949 /* We may get a paradoxical subreg here. Strip it off. */
3950 if (GET_CODE (dest) == SUBREG
3951 && GET_MODE (dest) == SImode
3952 && GET_MODE (SUBREG_REG (dest)) == HImode)
3953 dest = SUBREG_REG (dest);
3954
3955 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3956 FAIL;
3957
3958 base_addr = adjust_address (operands[1], HImode,
3959 bitpos / BITS_PER_UNIT);
3960 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3961 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3962 }
3963 DONE;
3964 }
3965 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3966 {
3967 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3968 operands[3]));
3969 DONE;
3970 }
3971 else
3972 FAIL;
8b054d5a 3973 }
eb04cafb 3974
3975 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3976 FAIL;
8b054d5a 3977
cffb2a26 3978 operands[3] = GEN_INT (rshift);
3979
3980 if (lshift == 0)
3981 {
3982 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3983 DONE;
3984 }
3985
eb04cafb 3986 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3987 operands[3], gen_reg_rtx (SImode)));
3988 DONE;
215b30b3 3989 }"
cffb2a26 3990)
3991
eb04cafb 3992;; Helper for extzv, for the Thumb-1 register-shifts case.
3993
3994(define_expand "extzv_t1"
3995 [(set (match_operand:SI 4 "s_register_operand" "")
3996 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
3997 (match_operand:SI 2 "const_int_operand" "")))
3998 (set (match_operand:SI 0 "s_register_operand" "")
3999 (lshiftrt:SI (match_dup 4)
4000 (match_operand:SI 3 "const_int_operand" "")))]
4001 "TARGET_THUMB1"
4002 "")
4003
4004(define_expand "extv"
4005 [(set (match_operand 0 "s_register_operand" "")
4006 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4007 (match_operand 2 "const_int_operand" "")
4008 (match_operand 3 "const_int_operand" "")))]
4009 "arm_arch_thumb2"
4010{
4011 HOST_WIDE_INT width = INTVAL (operands[2]);
4012 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4013
4014 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4015 && (bitpos % BITS_PER_UNIT) == 0)
4016 {
4017 rtx base_addr;
4018
4019 if (BYTES_BIG_ENDIAN)
4020 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4021
4022 if (width == 32)
4023 {
4024 base_addr = adjust_address (operands[1], SImode,
4025 bitpos / BITS_PER_UNIT);
4026 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4027 }
4028 else
4029 {
4030 rtx dest = operands[0];
4031 rtx tmp = gen_reg_rtx (SImode);
4032
4033 /* We may get a paradoxical subreg here. Strip it off. */
4034 if (GET_CODE (dest) == SUBREG
4035 && GET_MODE (dest) == SImode
4036 && GET_MODE (SUBREG_REG (dest)) == HImode)
4037 dest = SUBREG_REG (dest);
4038
4039 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4040 FAIL;
4041
4042 base_addr = adjust_address (operands[1], HImode,
4043 bitpos / BITS_PER_UNIT);
4044 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4045 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4046 }
4047
4048 DONE;
4049 }
4050 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4051 FAIL;
4052 else if (GET_MODE (operands[0]) == SImode
4053 && GET_MODE (operands[1]) == SImode)
4054 {
4055 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4056 operands[3]));
4057 DONE;
4058 }
4059
4060 FAIL;
4061})
4062
4063; Helper to expand register forms of extv with the proper modes.
4064
4065(define_expand "extv_regsi"
4066 [(set (match_operand:SI 0 "s_register_operand" "")
4067 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4068 (match_operand 2 "const_int_operand" "")
4069 (match_operand 3 "const_int_operand" "")))]
4070 ""
4071{
4072})
4073
4074; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4075
4076(define_insn "unaligned_loadsi"
4077 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4078 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4079 UNSPEC_UNALIGNED_LOAD))]
4080 "unaligned_access && TARGET_32BIT"
4081 "ldr%?\t%0, %1\t@ unaligned"
4082 [(set_attr "arch" "t2,any")
4083 (set_attr "length" "2,4")
4084 (set_attr "predicable" "yes")
4085 (set_attr "type" "load1")])
4086
4087(define_insn "unaligned_loadhis"
4088 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4089 (sign_extend:SI
4090 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4091 UNSPEC_UNALIGNED_LOAD)))]
4092 "unaligned_access && TARGET_32BIT"
4093 "ldr%(sh%)\t%0, %1\t@ unaligned"
4094 [(set_attr "arch" "t2,any")
4095 (set_attr "length" "2,4")
4096 (set_attr "predicable" "yes")
4097 (set_attr "type" "load_byte")])
4098
4099(define_insn "unaligned_loadhiu"
4100 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4101 (zero_extend:SI
4102 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4103 UNSPEC_UNALIGNED_LOAD)))]
4104 "unaligned_access && TARGET_32BIT"
4105 "ldr%(h%)\t%0, %1\t@ unaligned"
4106 [(set_attr "arch" "t2,any")
4107 (set_attr "length" "2,4")
4108 (set_attr "predicable" "yes")
4109 (set_attr "type" "load_byte")])
4110
4111(define_insn "unaligned_storesi"
4112 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4113 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4114 UNSPEC_UNALIGNED_STORE))]
4115 "unaligned_access && TARGET_32BIT"
4116 "str%?\t%1, %0\t@ unaligned"
4117 [(set_attr "arch" "t2,any")
4118 (set_attr "length" "2,4")
4119 (set_attr "predicable" "yes")
4120 (set_attr "type" "store1")])
4121
4122(define_insn "unaligned_storehi"
4123 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4124 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4125 UNSPEC_UNALIGNED_STORE))]
4126 "unaligned_access && TARGET_32BIT"
4127 "str%(h%)\t%1, %0\t@ unaligned"
4128 [(set_attr "arch" "t2,any")
4129 (set_attr "length" "2,4")
4130 (set_attr "predicable" "yes")
4131 (set_attr "type" "store1")])
4132
4133(define_insn "*extv_reg"
8b054d5a 4134 [(set (match_operand:SI 0 "s_register_operand" "=r")
4135 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4136 (match_operand:SI 2 "const_int_operand" "M")
4137 (match_operand:SI 3 "const_int_operand" "M")))]
4138 "arm_arch_thumb2"
4139 "sbfx%?\t%0, %1, %3, %2"
4140 [(set_attr "length" "4")
4141 (set_attr "predicable" "yes")]
4142)
4143
4144(define_insn "extzv_t2"
4145 [(set (match_operand:SI 0 "s_register_operand" "=r")
4146 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4147 (match_operand:SI 2 "const_int_operand" "M")
4148 (match_operand:SI 3 "const_int_operand" "M")))]
4149 "arm_arch_thumb2"
4150 "ubfx%?\t%0, %1, %3, %2"
4151 [(set_attr "length" "4")
4152 (set_attr "predicable" "yes")]
4153)
4154
7d3cda8c 4155
4156;; Division instructions
4157(define_insn "divsi3"
4158 [(set (match_operand:SI 0 "s_register_operand" "=r")
4159 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4160 (match_operand:SI 2 "s_register_operand" "r")))]
4161 "TARGET_IDIV"
4162 "sdiv%?\t%0, %1, %2"
4163 [(set_attr "predicable" "yes")
4164 (set_attr "insn" "sdiv")]
4165)
4166
4167(define_insn "udivsi3"
4168 [(set (match_operand:SI 0 "s_register_operand" "=r")
4169 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4170 (match_operand:SI 2 "s_register_operand" "r")))]
4171 "TARGET_IDIV"
4172 "udiv%?\t%0, %1, %2"
4173 [(set_attr "predicable" "yes")
4174 (set_attr "insn" "udiv")]
4175)
4176
b11cae9e 4177\f
4178;; Unary arithmetic insns
4179
cffb2a26 4180(define_expand "negdi2"
4181 [(parallel
8135a42b 4182 [(set (match_operand:DI 0 "s_register_operand" "")
4183 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4184 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4185 "TARGET_EITHER"
774d2fbb 4186 {
4187 if (TARGET_NEON)
4188 {
4189 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4190 DONE;
4191 }
4192 }
cffb2a26 4193)
4194
4195;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4196;; The first alternative allows the common case of a *full* overlap.
cffb2a26 4197(define_insn "*arm_negdi2"
458a8706 4198 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4199 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4200 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4201 "TARGET_ARM"
97499065 4202 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 4203 [(set_attr "conds" "clob")
4204 (set_attr "length" "8")]
4205)
b11cae9e 4206
25f905c2 4207(define_insn "*thumb1_negdi2"
8135a42b 4208 [(set (match_operand:DI 0 "register_operand" "=&l")
4209 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 4210 (clobber (reg:CC CC_REGNUM))]
25f905c2 4211 "TARGET_THUMB1"
cffb2a26 4212 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
4213 [(set_attr "length" "6")]
4214)
4215
4216(define_expand "negsi2"
4217 [(set (match_operand:SI 0 "s_register_operand" "")
4218 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4219 "TARGET_EITHER"
b11cae9e 4220 ""
cffb2a26 4221)
4222
4223(define_insn "*arm_negsi2"
4224 [(set (match_operand:SI 0 "s_register_operand" "=r")
4225 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4226 "TARGET_32BIT"
cffb2a26 4227 "rsb%?\\t%0, %1, #0"
0d66636f 4228 [(set_attr "predicable" "yes")]
cffb2a26 4229)
4230
25f905c2 4231(define_insn "*thumb1_negsi2"
cffb2a26 4232 [(set (match_operand:SI 0 "register_operand" "=l")
4233 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4234 "TARGET_THUMB1"
cffb2a26 4235 "neg\\t%0, %1"
4236 [(set_attr "length" "2")]
4237)
b11cae9e 4238
604f3a0a 4239(define_expand "negsf2"
4240 [(set (match_operand:SF 0 "s_register_operand" "")
4241 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4242 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4243 ""
4244)
4245
4246(define_expand "negdf2"
4247 [(set (match_operand:DF 0 "s_register_operand" "")
4248 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4249 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4250 "")
4251
9c08d1fa 4252;; abssi2 doesn't really clobber the condition codes if a different register
4253;; is being set. To keep things simple, assume during rtl manipulations that
4254;; it does, but tell the final scan operator the truth. Similarly for
4255;; (neg (abs...))
4256
604f3a0a 4257(define_expand "abssi2"
4258 [(parallel
4259 [(set (match_operand:SI 0 "s_register_operand" "")
4260 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4261 (clobber (match_dup 2))])]
4262 "TARGET_EITHER"
4263 "
25f905c2 4264 if (TARGET_THUMB1)
ba156559 4265 operands[2] = gen_rtx_SCRATCH (SImode);
4266 else
4267 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4268")
604f3a0a 4269
7d57ec45 4270(define_insn "*arm_abssi2"
ba156559 4271 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4272 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4273 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4274 "TARGET_ARM"
e2348bcb 4275 "@
4276 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 4277 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 4278 [(set_attr "conds" "clob,*")
331beb1a 4279 (set_attr "shift" "1")
2ad08b65 4280 (set_attr "predicable" "no, yes")
cffb2a26 4281 (set_attr "length" "8")]
4282)
9c08d1fa 4283
25f905c2 4284(define_insn_and_split "*thumb1_abssi2"
ba156559 4285 [(set (match_operand:SI 0 "s_register_operand" "=l")
4286 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
4287 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4288 "TARGET_THUMB1"
ba156559 4289 "#"
25f905c2 4290 "TARGET_THUMB1 && reload_completed"
ba156559 4291 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4292 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
4293 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4294 ""
4295 [(set_attr "length" "6")]
4296)
4297
4298(define_insn "*arm_neg_abssi2"
9c08d1fa 4299 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4300 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4301 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4302 "TARGET_ARM"
e2348bcb 4303 "@
4304 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 4305 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 4306 [(set_attr "conds" "clob,*")
331beb1a 4307 (set_attr "shift" "1")
2ad08b65 4308 (set_attr "predicable" "no, yes")
cffb2a26 4309 (set_attr "length" "8")]
4310)
b11cae9e 4311
25f905c2 4312(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 4313 [(set (match_operand:SI 0 "s_register_operand" "=l")
4314 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
4315 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4316 "TARGET_THUMB1"
ba156559 4317 "#"
25f905c2 4318 "TARGET_THUMB1 && reload_completed"
ba156559 4319 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4320 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
4321 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4322 ""
4323 [(set_attr "length" "6")]
4324)
4325
604f3a0a 4326(define_expand "abssf2"
4327 [(set (match_operand:SF 0 "s_register_operand" "")
4328 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4329 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4330 "")
4331
604f3a0a 4332(define_expand "absdf2"
4333 [(set (match_operand:DF 0 "s_register_operand" "")
4334 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4335 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4336 "")
4337
7db9af5d 4338(define_expand "sqrtsf2"
4339 [(set (match_operand:SF 0 "s_register_operand" "")
4340 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4341 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4342 "")
9c08d1fa 4343
7db9af5d 4344(define_expand "sqrtdf2"
4345 [(set (match_operand:DF 0 "s_register_operand" "")
4346 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4347 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4348 "")
9c08d1fa 4349
a0f94409 4350(define_insn_and_split "one_cmpldi2"
10efb95f 4351 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4352 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4353 "TARGET_32BIT"
10efb95f 4354 "@
4355 vmvn\t%P0, %P1
4356 #
4357 #
4358 vmvn\t%P0, %P1"
4359 "TARGET_32BIT && reload_completed
4360 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4361 [(set (match_dup 0) (not:SI (match_dup 1)))
4362 (set (match_dup 2) (not:SI (match_dup 3)))]
4363 "
4364 {
4365 operands[2] = gen_highpart (SImode, operands[0]);
4366 operands[0] = gen_lowpart (SImode, operands[0]);
4367 operands[3] = gen_highpart (SImode, operands[1]);
4368 operands[1] = gen_lowpart (SImode, operands[1]);
4369 }"
10efb95f 4370 [(set_attr "length" "*,8,8,*")
4371 (set_attr "predicable" "no,yes,yes,no")
4372 (set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
4373 (set_attr "arch" "neon_nota8,*,*,neon_onlya8")]
cffb2a26 4374)
b11cae9e 4375
cffb2a26 4376(define_expand "one_cmplsi2"
4377 [(set (match_operand:SI 0 "s_register_operand" "")
4378 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4379 "TARGET_EITHER"
b11cae9e 4380 ""
cffb2a26 4381)
4382
4383(define_insn "*arm_one_cmplsi2"
4384 [(set (match_operand:SI 0 "s_register_operand" "=r")
4385 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4386 "TARGET_32BIT"
cffb2a26 4387 "mvn%?\\t%0, %1"
d2a518d1 4388 [(set_attr "predicable" "yes")
4389 (set_attr "insn" "mvn")]
cffb2a26 4390)
4391
25f905c2 4392(define_insn "*thumb1_one_cmplsi2"
cffb2a26 4393 [(set (match_operand:SI 0 "register_operand" "=l")
4394 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4395 "TARGET_THUMB1"
cffb2a26 4396 "mvn\\t%0, %1"
d2a518d1 4397 [(set_attr "length" "2")
4398 (set_attr "insn" "mvn")]
cffb2a26 4399)
9c08d1fa 4400
f7fbdd4a 4401(define_insn "*notsi_compare0"
bd5b4116 4402 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4403 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4404 (const_int 0)))
4405 (set (match_operand:SI 0 "s_register_operand" "=r")
4406 (not:SI (match_dup 1)))]
25f905c2 4407 "TARGET_32BIT"
4408 "mvn%.\\t%0, %1"
d2a518d1 4409 [(set_attr "conds" "set")
4410 (set_attr "insn" "mvn")]
cffb2a26 4411)
9c08d1fa 4412
f7fbdd4a 4413(define_insn "*notsi_compare0_scratch"
bd5b4116 4414 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4415 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4416 (const_int 0)))
4417 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4418 "TARGET_32BIT"
4419 "mvn%.\\t%0, %1"
d2a518d1 4420 [(set_attr "conds" "set")
4421 (set_attr "insn" "mvn")]
cffb2a26 4422)
b11cae9e 4423\f
4424;; Fixed <--> Floating conversion insns
4425
9b8516be 4426(define_expand "floatsihf2"
4427 [(set (match_operand:HF 0 "general_operand" "")
4428 (float:HF (match_operand:SI 1 "general_operand" "")))]
4429 "TARGET_EITHER"
4430 "
4431 {
4432 rtx op1 = gen_reg_rtx (SFmode);
4433 expand_float (op1, operands[1], 0);
4434 op1 = convert_to_mode (HFmode, op1, 0);
4435 emit_move_insn (operands[0], op1);
4436 DONE;
4437 }"
4438)
4439
4440(define_expand "floatdihf2"
4441 [(set (match_operand:HF 0 "general_operand" "")
4442 (float:HF (match_operand:DI 1 "general_operand" "")))]
4443 "TARGET_EITHER"
4444 "
4445 {
4446 rtx op1 = gen_reg_rtx (SFmode);
4447 expand_float (op1, operands[1], 0);
4448 op1 = convert_to_mode (HFmode, op1, 0);
4449 emit_move_insn (operands[0], op1);
4450 DONE;
4451 }"
4452)
4453
604f3a0a 4454(define_expand "floatsisf2"
4455 [(set (match_operand:SF 0 "s_register_operand" "")
4456 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4457 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4458 "
604f3a0a 4459")
4460
604f3a0a 4461(define_expand "floatsidf2"
4462 [(set (match_operand:DF 0 "s_register_operand" "")
4463 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4464 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4465 "
604f3a0a 4466")
4467
9b8516be 4468(define_expand "fix_trunchfsi2"
4469 [(set (match_operand:SI 0 "general_operand" "")
4470 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4471 "TARGET_EITHER"
4472 "
4473 {
4474 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4475 expand_fix (operands[0], op1, 0);
4476 DONE;
4477 }"
4478)
4479
4480(define_expand "fix_trunchfdi2"
4481 [(set (match_operand:DI 0 "general_operand" "")
4482 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4483 "TARGET_EITHER"
4484 "
4485 {
4486 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4487 expand_fix (operands[0], op1, 0);
4488 DONE;
4489 }"
4490)
4491
604f3a0a 4492(define_expand "fix_truncsfsi2"
4493 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4494 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4495 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4496 "
604f3a0a 4497")
4498
604f3a0a 4499(define_expand "fix_truncdfsi2"
4500 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4501 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4502 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4503 "
604f3a0a 4504")
4505
f544c6d2 4506;; Truncation insns
b11cae9e 4507
604f3a0a 4508(define_expand "truncdfsf2"
4509 [(set (match_operand:SF 0 "s_register_operand" "")
4510 (float_truncate:SF
4511 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4512 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4513 ""
4514)
9b8516be 4515
4516/* DFmode -> HFmode conversions have to go through SFmode. */
4517(define_expand "truncdfhf2"
4518 [(set (match_operand:HF 0 "general_operand" "")
4519 (float_truncate:HF
4520 (match_operand:DF 1 "general_operand" "")))]
4521 "TARGET_EITHER"
4522 "
4523 {
4524 rtx op1;
4525 op1 = convert_to_mode (SFmode, operands[1], 0);
4526 op1 = convert_to_mode (HFmode, op1, 0);
4527 emit_move_insn (operands[0], op1);
4528 DONE;
4529 }"
4530)
b11cae9e 4531\f
9c08d1fa 4532;; Zero and sign extension instructions.
b11cae9e 4533
848e66ac 4534(define_insn "zero_extend<mode>di2"
4535 [(set (match_operand:DI 0 "s_register_operand" "=r")
6d97728e 4536 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4537 "<qhs_zextenddi_cstr>")))]
848e66ac 4538 "TARGET_32BIT <qhs_zextenddi_cond>"
4539 "#"
4540 [(set_attr "length" "8")
4541 (set_attr "ce_count" "2")
4542 (set_attr "predicable" "yes")]
25f905c2 4543)
4544
848e66ac 4545(define_insn "extend<mode>di2"
9c08d1fa 4546 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4547 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4548 "<qhs_extenddi_cstr>")))]
848e66ac 4549 "TARGET_32BIT <qhs_sextenddi_cond>"
4550 "#"
0d66636f 4551 [(set_attr "length" "8")
848e66ac 4552 (set_attr "ce_count" "2")
4553 (set_attr "shift" "1")
0d66636f 4554 (set_attr "predicable" "yes")]
4555)
9c08d1fa 4556
848e66ac 4557;; Splits for all extensions to DImode
4558(define_split
4559 [(set (match_operand:DI 0 "s_register_operand" "")
4560 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4561 "TARGET_32BIT"
848e66ac 4562 [(set (match_dup 0) (match_dup 1))]
4563{
848e66ac 4564 rtx lo_part = gen_lowpart (SImode, operands[0]);
4565 enum machine_mode src_mode = GET_MODE (operands[1]);
4566
4567 if (REG_P (operands[0])
4568 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4569 emit_clobber (operands[0]);
4570 if (!REG_P (lo_part) || src_mode != SImode
4571 || !rtx_equal_p (lo_part, operands[1]))
4572 {
4573 if (src_mode == SImode)
4574 emit_move_insn (lo_part, operands[1]);
4575 else
4576 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4577 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4578 operands[1] = lo_part;
4579 }
4580 operands[0] = gen_highpart (SImode, operands[0]);
4581 operands[1] = const0_rtx;
4582})
9c08d1fa 4583
848e66ac 4584(define_split
25f905c2 4585 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4586 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4587 "TARGET_32BIT"
848e66ac 4588 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4589{
4590 rtx lo_part = gen_lowpart (SImode, operands[0]);
4591 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4592
848e66ac 4593 if (REG_P (operands[0])
4594 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4595 emit_clobber (operands[0]);
4596
4597 if (!REG_P (lo_part) || src_mode != SImode
4598 || !rtx_equal_p (lo_part, operands[1]))
4599 {
4600 if (src_mode == SImode)
4601 emit_move_insn (lo_part, operands[1]);
4602 else
4603 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4604 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4605 operands[1] = lo_part;
4606 }
4607 operands[0] = gen_highpart (SImode, operands[0]);
4608})
9c08d1fa 4609
4610(define_expand "zero_extendhisi2"
ef51b8e1 4611 [(set (match_operand:SI 0 "s_register_operand" "")
4612 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4613 "TARGET_EITHER"
ef51b8e1 4614{
4615 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4616 {
ef51b8e1 4617 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4618 DONE;
25f7a26e 4619 }
ef51b8e1 4620 if (!arm_arch6 && !MEM_P (operands[1]))
4621 {
4622 rtx t = gen_lowpart (SImode, operands[1]);
4623 rtx tmp = gen_reg_rtx (SImode);
4624 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4625 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4626 DONE;
4627 }
4628})
9c08d1fa 4629
ef51b8e1 4630(define_split
b146458f 4631 [(set (match_operand:SI 0 "s_register_operand" "")
4632 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4633 "!TARGET_THUMB2 && !arm_arch6"
4634 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4635 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4636{
4637 operands[2] = gen_lowpart (SImode, operands[1]);
4638})
4639
4640(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4641 [(set (match_operand:SI 0 "register_operand" "=l,l")
4642 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4643 "TARGET_THUMB1"
848e66ac 4644{
a2cd141b 4645 rtx mem;
4646
ef51b8e1 4647 if (which_alternative == 0 && arm_arch6)
848e66ac 4648 return "uxth\t%0, %1";
ef51b8e1 4649 if (which_alternative == 0)
848e66ac 4650 return "#";
a2cd141b 4651
4652 mem = XEXP (operands[1], 0);
4653
4654 if (GET_CODE (mem) == CONST)
4655 mem = XEXP (mem, 0);
4656
a2cd141b 4657 if (GET_CODE (mem) == PLUS)
4658 {
4659 rtx a = XEXP (mem, 0);
a2cd141b 4660
4661 /* This can happen due to bugs in reload. */
0438d37f 4662 if (REG_P (a) && REGNO (a) == SP_REGNUM)
a2cd141b 4663 {
4664 rtx ops[2];
4665 ops[0] = operands[0];
4666 ops[1] = a;
4667
848e66ac 4668 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4669
4670 XEXP (mem, 0) = operands[0];
4671 }
a2cd141b 4672 }
4673
848e66ac 4674 return "ldrh\t%0, %1";
4675}
ef51b8e1 4676 [(set_attr_alternative "length"
4677 [(if_then_else (eq_attr "is_arch6" "yes")
4678 (const_int 2) (const_int 4))
4679 (const_int 4)])
848e66ac 4680 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4681)
4682
cffb2a26 4683(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4684 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4685 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4686 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4687 "@
4688 #
4689 ldr%(h%)\\t%0, %1"
4690 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4691 (set_attr "predicable" "yes")]
cffb2a26 4692)
f7fbdd4a 4693
a2cd141b 4694(define_insn "*arm_zero_extendhisi2_v6"
4695 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4696 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4697 "TARGET_ARM && arm_arch6"
4698 "@
4699 uxth%?\\t%0, %1
25f905c2 4700 ldr%(h%)\\t%0, %1"
a2cd141b 4701 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4702 (set_attr "predicable" "yes")]
a2cd141b 4703)
4704
4705(define_insn "*arm_zero_extendhisi2addsi"
4706 [(set (match_operand:SI 0 "s_register_operand" "=r")
4707 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4708 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4709 "TARGET_INT_SIMD"
a2cd141b 4710 "uxtah%?\\t%0, %2, %1"
4711 [(set_attr "type" "alu_shift")
4712 (set_attr "predicable" "yes")]
4713)
4714
87b22bf7 4715(define_expand "zero_extendqisi2"
cffb2a26 4716 [(set (match_operand:SI 0 "s_register_operand" "")
4717 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4718 "TARGET_EITHER"
ef51b8e1 4719{
0438d37f 4720 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 4721 {
ef51b8e1 4722 emit_insn (gen_andsi3 (operands[0],
4723 gen_lowpart (SImode, operands[1]),
4724 GEN_INT (255)));
4725 DONE;
4726 }
4727 if (!arm_arch6 && !MEM_P (operands[1]))
4728 {
4729 rtx t = gen_lowpart (SImode, operands[1]);
4730 rtx tmp = gen_reg_rtx (SImode);
4731 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4732 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4733 DONE;
4734 }
4735})
cffb2a26 4736
ef51b8e1 4737(define_split
b146458f 4738 [(set (match_operand:SI 0 "s_register_operand" "")
4739 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4740 "!arm_arch6"
4741 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4742 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4743{
4744 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4745 if (TARGET_ARM)
4746 {
4747 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4748 DONE;
4749 }
ef51b8e1 4750})
9c08d1fa 4751
25f905c2 4752(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4753 [(set (match_operand:SI 0 "register_operand" "=l,l")
4754 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4755 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4756 "@
4757 #
4758 ldrb\\t%0, %1"
4759 [(set_attr "length" "4,2")
4760 (set_attr "type" "alu_shift,load_byte")
4761 (set_attr "pool_range" "*,32")]
cffb2a26 4762)
4763
25f905c2 4764(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4765 [(set (match_operand:SI 0 "register_operand" "=l,l")
4766 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4767 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4768 "@
4769 uxtb\\t%0, %1
4770 ldrb\\t%0, %1"
848e66ac 4771 [(set_attr "length" "2")
4772 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4773)
4774
cffb2a26 4775(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4776 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4777 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4778 "TARGET_ARM && !arm_arch6"
ef51b8e1 4779 "@
4780 #
4781 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4782 [(set_attr "length" "8,4")
4783 (set_attr "type" "alu_shift,load_byte")
848e66ac 4784 (set_attr "predicable" "yes")]
cffb2a26 4785)
87b22bf7 4786
a2cd141b 4787(define_insn "*arm_zero_extendqisi2_v6"
4788 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4789 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4790 "TARGET_ARM && arm_arch6"
4791 "@
25f905c2 4792 uxtb%(%)\\t%0, %1
4793 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4794 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4795 (set_attr "predicable" "yes")]
a2cd141b 4796)
4797
4798(define_insn "*arm_zero_extendqisi2addsi"
4799 [(set (match_operand:SI 0 "s_register_operand" "=r")
4800 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4801 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4802 "TARGET_INT_SIMD"
a2cd141b 4803 "uxtab%?\\t%0, %2, %1"
4804 [(set_attr "predicable" "yes")
bcaec148 4805 (set_attr "insn" "xtab")
a2cd141b 4806 (set_attr "type" "alu_shift")]
4807)
4808
87b22bf7 4809(define_split
4810 [(set (match_operand:SI 0 "s_register_operand" "")
4811 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4812 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4813 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 4814 [(set (match_dup 2) (match_dup 1))
4815 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4816 ""
4817)
9c08d1fa 4818
8a4d25d6 4819(define_split
4820 [(set (match_operand:SI 0 "s_register_operand" "")
4821 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4822 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4823 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 4824 [(set (match_dup 2) (match_dup 1))
4825 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4826 ""
4827)
4828
1c274529 4829
4830(define_split
4831 [(set (match_operand:SI 0 "s_register_operand" "")
4832 (ior_xor:SI (and:SI (ashift:SI
4833 (match_operand:SI 1 "s_register_operand" "")
4834 (match_operand:SI 2 "const_int_operand" ""))
4835 (match_operand:SI 3 "const_int_operand" ""))
4836 (zero_extend:SI
4837 (match_operator 5 "subreg_lowpart_operator"
4838 [(match_operand:SI 4 "s_register_operand" "")]))))]
4839 "TARGET_32BIT
63787642 4840 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4841 == (GET_MODE_MASK (GET_MODE (operands[5]))
4842 & (GET_MODE_MASK (GET_MODE (operands[5]))
4843 << (INTVAL (operands[2])))))"
4844 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4845 (match_dup 4)))
4846 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4847 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4848)
4849
f7fbdd4a 4850(define_insn "*compareqi_eq0"
bd5b4116 4851 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4852 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4853 (const_int 0)))]
25f905c2 4854 "TARGET_32BIT"
596e5e8f 4855 "tst%?\\t%0, #255"
4856 [(set_attr "conds" "set")
4857 (set_attr "predicable" "yes")]
cffb2a26 4858)
b11cae9e 4859
b11cae9e 4860(define_expand "extendhisi2"
ef51b8e1 4861 [(set (match_operand:SI 0 "s_register_operand" "")
4862 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4863 "TARGET_EITHER"
ef51b8e1 4864{
4865 if (TARGET_THUMB1)
4866 {
4867 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4868 DONE;
4869 }
4870 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4871 {
4872 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4873 DONE;
4874 }
ed29c566 4875
ef51b8e1 4876 if (!arm_arch6 && !MEM_P (operands[1]))
4877 {
4878 rtx t = gen_lowpart (SImode, operands[1]);
4879 rtx tmp = gen_reg_rtx (SImode);
4880 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4881 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4882 DONE;
4883 }
4884})
cffb2a26 4885
ef51b8e1 4886(define_split
4887 [(parallel
4888 [(set (match_operand:SI 0 "register_operand" "")
4889 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4890 (clobber (match_scratch:SI 2 ""))])]
4891 "!arm_arch6"
4892 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4893 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4894{
4895 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4896})
25f7a26e 4897
a2cd141b 4898;; We used to have an early-clobber on the scratch register here.
4899;; However, there's a bug somewhere in reload which means that this
4900;; can be partially ignored during spill allocation if the memory
ed29c566 4901;; address also needs reloading; this causes us to die later on when
a2cd141b 4902;; we try to verify the operands. Fortunately, we don't really need
4903;; the early-clobber: we can always use operand 0 if operand 2
4904;; overlaps the address.
ef51b8e1 4905(define_insn "thumb1_extendhisi2"
a2cd141b 4906 [(set (match_operand:SI 0 "register_operand" "=l,l")
4907 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4908 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4909 "TARGET_THUMB1"
a2cd141b 4910 "*
4911 {
4912 rtx ops[4];
4913 rtx mem;
4914
ef51b8e1 4915 if (which_alternative == 0 && !arm_arch6)
4916 return \"#\";
a2cd141b 4917 if (which_alternative == 0)
4918 return \"sxth\\t%0, %1\";
4919
4920 mem = XEXP (operands[1], 0);
4921
4922 /* This code used to try to use 'V', and fix the address only if it was
4923 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4924 range of QImode offsets, and offsettable_address_p does a QImode
4925 address check. */
4926
4927 if (GET_CODE (mem) == CONST)
4928 mem = XEXP (mem, 0);
4929
4930 if (GET_CODE (mem) == LABEL_REF)
4931 return \"ldr\\t%0, %1\";
4932
4933 if (GET_CODE (mem) == PLUS)
4934 {
4935 rtx a = XEXP (mem, 0);
4936 rtx b = XEXP (mem, 1);
4937
4938 if (GET_CODE (a) == LABEL_REF
0438d37f 4939 && CONST_INT_P (b))
a2cd141b 4940 return \"ldr\\t%0, %1\";
4941
0438d37f 4942 if (REG_P (b))
a2cd141b 4943 return \"ldrsh\\t%0, %1\";
4944
4945 ops[1] = a;
4946 ops[2] = b;
4947 }
4948 else
4949 {
4950 ops[1] = mem;
4951 ops[2] = const0_rtx;
4952 }
4953
0438d37f 4954 gcc_assert (REG_P (ops[1]));
a2cd141b 4955
4956 ops[0] = operands[0];
4957 if (reg_mentioned_p (operands[2], ops[1]))
4958 ops[3] = ops[0];
4959 else
4960 ops[3] = operands[2];
4961 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4962 return \"\";
4963 }"
ef51b8e1 4964 [(set_attr_alternative "length"
4965 [(if_then_else (eq_attr "is_arch6" "yes")
4966 (const_int 2) (const_int 4))
4967 (const_int 4)])
a2cd141b 4968 (set_attr "type" "alu_shift,load_byte")
4969 (set_attr "pool_range" "*,1020")]
4970)
4971
25f905c2 4972;; This pattern will only be used when ldsh is not available
25f7a26e 4973(define_expand "extendhisi2_mem"
eab14235 4974 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4975 (set (match_dup 3)
eab14235 4976 (zero_extend:SI (match_dup 7)))
25f7a26e 4977 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4978 (set (match_operand:SI 0 "" "")
4979 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4980 "TARGET_ARM"
25f7a26e 4981 "
215b30b3 4982 {
4983 rtx mem1, mem2;
4984 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4985
788fcce0 4986 mem1 = change_address (operands[1], QImode, addr);
29c05e22 4987 mem2 = change_address (operands[1], QImode,
4988 plus_constant (Pmode, addr, 1));
215b30b3 4989 operands[0] = gen_lowpart (SImode, operands[0]);
4990 operands[1] = mem1;
4991 operands[2] = gen_reg_rtx (SImode);
4992 operands[3] = gen_reg_rtx (SImode);
4993 operands[6] = gen_reg_rtx (SImode);
4994 operands[7] = mem2;
25f7a26e 4995
215b30b3 4996 if (BYTES_BIG_ENDIAN)
4997 {
4998 operands[4] = operands[2];
4999 operands[5] = operands[3];
5000 }
5001 else
5002 {
5003 operands[4] = operands[3];
5004 operands[5] = operands[2];
5005 }
5006 }"
5007)
b11cae9e 5008
ef51b8e1 5009(define_split
5010 [(set (match_operand:SI 0 "register_operand" "")
5011 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5012 "!arm_arch6"
5013 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5014 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5015{
5016 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5017})
5018
a2cd141b 5019(define_insn "*arm_extendhisi2"
ef51b8e1 5020 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5021 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5022 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5023 "@
5024 #
5025 ldr%(sh%)\\t%0, %1"
5026 [(set_attr "length" "8,4")
5027 (set_attr "type" "alu_shift,load_byte")
0d66636f 5028 (set_attr "predicable" "yes")
ef51b8e1 5029 (set_attr "pool_range" "*,256")
5030 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5031)
f7fbdd4a 5032
25f905c2 5033;; ??? Check Thumb-2 pool range
a2cd141b 5034(define_insn "*arm_extendhisi2_v6"
5035 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5036 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 5037 "TARGET_32BIT && arm_arch6"
a2cd141b 5038 "@
5039 sxth%?\\t%0, %1
25f905c2 5040 ldr%(sh%)\\t%0, %1"
a2cd141b 5041 [(set_attr "type" "alu_shift,load_byte")
5042 (set_attr "predicable" "yes")
5043 (set_attr "pool_range" "*,256")
5044 (set_attr "neg_pool_range" "*,244")]
5045)
5046
5047(define_insn "*arm_extendhisi2addsi"
5048 [(set (match_operand:SI 0 "s_register_operand" "=r")
5049 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5050 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5051 "TARGET_INT_SIMD"
a2cd141b 5052 "sxtah%?\\t%0, %2, %1"
5053)
5054
c8f69309 5055(define_expand "extendqihi2"
5056 [(set (match_dup 2)
bed7d9a5 5057 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5058 (const_int 24)))
9c08d1fa 5059 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5060 (ashiftrt:SI (match_dup 2)
5061 (const_int 24)))]
cffb2a26 5062 "TARGET_ARM"
c8f69309 5063 "
215b30b3 5064 {
0438d37f 5065 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5066 {
5067 emit_insn (gen_rtx_SET (VOIDmode,
5068 operands[0],
5069 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5070 DONE;
5071 }
5072 if (!s_register_operand (operands[1], QImode))
5073 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5074 operands[0] = gen_lowpart (SImode, operands[0]);
5075 operands[1] = gen_lowpart (SImode, operands[1]);
5076 operands[2] = gen_reg_rtx (SImode);
5077 }"
5078)
f7fbdd4a 5079
25f905c2 5080(define_insn "*arm_extendqihi_insn"
b4e8a300 5081 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5082 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5083 "TARGET_ARM && arm_arch4"
25f905c2 5084 "ldr%(sb%)\\t%0, %1"
a2cd141b 5085 [(set_attr "type" "load_byte")
0d66636f 5086 (set_attr "predicable" "yes")
cffb2a26 5087 (set_attr "pool_range" "256")
5088 (set_attr "neg_pool_range" "244")]
5089)
3fc2009e 5090
b11cae9e 5091(define_expand "extendqisi2"
ef51b8e1 5092 [(set (match_operand:SI 0 "s_register_operand" "")
5093 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5094 "TARGET_EITHER"
ef51b8e1 5095{
5096 if (!arm_arch4 && MEM_P (operands[1]))
5097 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5098
ef51b8e1 5099 if (!arm_arch6 && !MEM_P (operands[1]))
5100 {
5101 rtx t = gen_lowpart (SImode, operands[1]);
5102 rtx tmp = gen_reg_rtx (SImode);
5103 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5104 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5105 DONE;
5106 }
5107})
a2cd141b 5108
ef51b8e1 5109(define_split
5110 [(set (match_operand:SI 0 "register_operand" "")
5111 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5112 "!arm_arch6"
5113 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5114 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5115{
5116 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5117})
f7fbdd4a 5118
a2cd141b 5119(define_insn "*arm_extendqisi"
ef51b8e1 5120 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5121 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5122 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5123 "@
5124 #
5125 ldr%(sb%)\\t%0, %1"
5126 [(set_attr "length" "8,4")
5127 (set_attr "type" "alu_shift,load_byte")
0d66636f 5128 (set_attr "predicable" "yes")
ef51b8e1 5129 (set_attr "pool_range" "*,256")
5130 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5131)
3fc2009e 5132
a2cd141b 5133(define_insn "*arm_extendqisi_v6"
5134 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5135 (sign_extend:SI
5136 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5137 "TARGET_ARM && arm_arch6"
b4e8a300 5138 "@
5139 sxtb%?\\t%0, %1
25f905c2 5140 ldr%(sb%)\\t%0, %1"
a2cd141b 5141 [(set_attr "type" "alu_shift,load_byte")
5142 (set_attr "predicable" "yes")
a2cd141b 5143 (set_attr "pool_range" "*,256")
5144 (set_attr "neg_pool_range" "*,244")]
5145)
5146
5147(define_insn "*arm_extendqisi2addsi"
5148 [(set (match_operand:SI 0 "s_register_operand" "=r")
5149 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5150 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5151 "TARGET_INT_SIMD"
a2cd141b 5152 "sxtab%?\\t%0, %2, %1"
5153 [(set_attr "type" "alu_shift")
bcaec148 5154 (set_attr "insn" "xtab")
a2cd141b 5155 (set_attr "predicable" "yes")]
5156)
5157
ef51b8e1 5158(define_split
5159 [(set (match_operand:SI 0 "register_operand" "")
5160 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
5161 "TARGET_THUMB1 && reload_completed"
5162 [(set (match_dup 0) (match_dup 2))
5163 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
5164{
5165 rtx addr = XEXP (operands[1], 0);
cffb2a26 5166
ef51b8e1 5167 if (GET_CODE (addr) == CONST)
5168 addr = XEXP (addr, 0);
cffb2a26 5169
ef51b8e1 5170 if (GET_CODE (addr) == PLUS
5171 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5172 /* No split necessary. */
5173 FAIL;
5174
5175 if (GET_CODE (addr) == PLUS
5176 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
5177 FAIL;
5178
5179 if (reg_overlap_mentioned_p (operands[0], addr))
5180 {
5181 rtx t = gen_lowpart (QImode, operands[0]);
5182 emit_move_insn (t, operands[1]);
5183 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
5184 DONE;
5185 }
5186
5187 if (REG_P (addr))
5188 {
5189 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
5190 operands[2] = const0_rtx;
5191 }
5192 else if (GET_CODE (addr) != PLUS)
5193 FAIL;
5194 else if (REG_P (XEXP (addr, 0)))
5195 {
5196 operands[2] = XEXP (addr, 1);
5197 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
5198 }
5199 else
5200 {
5201 operands[2] = XEXP (addr, 0);
5202 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
5203 }
cffb2a26 5204
ef51b8e1 5205 operands[3] = change_address (operands[1], QImode, addr);
5206})
5207
8a3b73a1 5208(define_peephole2
5209 [(set (match_operand:SI 0 "register_operand" "")
5210 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
5211 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
5212 (set (match_operand:SI 3 "register_operand" "")
5213 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
5214 "TARGET_THUMB1
5215 && GET_CODE (XEXP (operands[4], 0)) == PLUS
5216 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
5217 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
5218 && (peep2_reg_dead_p (3, operands[0])
5219 || rtx_equal_p (operands[0], operands[3]))
5220 && (peep2_reg_dead_p (3, operands[2])
5221 || rtx_equal_p (operands[2], operands[3]))"
5222 [(set (match_dup 2) (match_dup 1))
5223 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
5224{
5225 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
5226 operands[4] = change_address (operands[4], QImode, addr);
5227})
5228
ef51b8e1 5229(define_insn "thumb1_extendqisi2"
a2cd141b 5230 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5231 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 5232 "TARGET_THUMB1"
5233{
5234 rtx addr;
a2cd141b 5235
ef51b8e1 5236 if (which_alternative == 0 && arm_arch6)
5237 return "sxtb\\t%0, %1";
5238 if (which_alternative == 0)
5239 return "#";
a2cd141b 5240
ef51b8e1 5241 addr = XEXP (operands[1], 0);
5242 if (GET_CODE (addr) == PLUS
5243 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5244 return "ldrsb\\t%0, %1";
a2cd141b 5245
ef51b8e1 5246 return "#";
5247}
5248 [(set_attr_alternative "length"
5249 [(if_then_else (eq_attr "is_arch6" "yes")
5250 (const_int 2) (const_int 4))
5251 (const_int 2)
5252 (if_then_else (eq_attr "is_arch6" "yes")
5253 (const_int 4) (const_int 6))])
5254 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 5255)
5256
caedf871 5257(define_expand "extendsfdf2"
5258 [(set (match_operand:DF 0 "s_register_operand" "")
5259 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5260 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5261 ""
5262)
9b8516be 5263
5264/* HFmode -> DFmode conversions have to go through SFmode. */
5265(define_expand "extendhfdf2"
5266 [(set (match_operand:DF 0 "general_operand" "")
5267 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5268 "TARGET_EITHER"
5269 "
5270 {
5271 rtx op1;
5272 op1 = convert_to_mode (SFmode, operands[1], 0);
5273 op1 = convert_to_mode (DFmode, op1, 0);
5274 emit_insn (gen_movdf (operands[0], op1));
5275 DONE;
5276 }"
5277)
b11cae9e 5278\f
5279;; Move insns (including loads and stores)
5280
5281;; XXX Just some ideas about movti.
9c08d1fa 5282;; I don't think these are a good idea on the arm, there just aren't enough
5283;; registers
b11cae9e 5284;;(define_expand "loadti"
9c08d1fa 5285;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5286;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5287;; "" "")
5288
5289;;(define_expand "storeti"
5290;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5291;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5292;; "" "")
5293
5294;;(define_expand "movti"
5295;; [(set (match_operand:TI 0 "general_operand" "")
5296;; (match_operand:TI 1 "general_operand" ""))]
5297;; ""
5298;; "
5299;;{
5300;; rtx insn;
5301;;
0438d37f 5302;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5303;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5304;; if (MEM_P (operands[0]))
b11cae9e 5305;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5306;; else if (MEM_P (operands[1]))
b11cae9e 5307;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5308;; else
5309;; FAIL;
5310;;
5311;; emit_insn (insn);
5312;; DONE;
5313;;}")
5314
a2f10574 5315;; Recognize garbage generated above.
b11cae9e 5316
5317;;(define_insn ""
5318;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5319;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5320;; ""
5321;; "*
5322;; {
5323;; register mem = (which_alternative < 3);
0d66636f 5324;; register const char *template;
b11cae9e 5325;;
5326;; operands[mem] = XEXP (operands[mem], 0);
5327;; switch (which_alternative)
5328;; {
5329;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5330;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5331;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5332;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5333;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5334;; case 5: template = \"stmia\\t%0, %M1\"; break;
5335;; }
e2348bcb 5336;; output_asm_insn (template, operands);
5337;; return \"\";
b11cae9e 5338;; }")
5339
cffb2a26 5340(define_expand "movdi"
5341 [(set (match_operand:DI 0 "general_operand" "")
5342 (match_operand:DI 1 "general_operand" ""))]
5343 "TARGET_EITHER"
5344 "
e1ba4a27 5345 if (can_create_pseudo_p ())
cffb2a26 5346 {
0438d37f 5347 if (!REG_P (operands[0]))
b2778788 5348 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5349 }
5350 "
5351)
b11cae9e 5352
cffb2a26 5353(define_insn "*arm_movdi"
d51f92df 5354 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5355 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 5356 "TARGET_32BIT
b805622c 5357 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5358 && !TARGET_IWMMXT
5359 && ( register_operand (operands[0], DImode)
5360 || register_operand (operands[1], DImode))"
b11cae9e 5361 "*
d51f92df 5362 switch (which_alternative)
5363 {
5364 case 0:
5365 case 1:
5366 case 2:
5367 return \"#\";
5368 default:
26ff80c0 5369 return output_move_double (operands, true, NULL);
d51f92df 5370 }
cffb2a26 5371 "
359a6e9f 5372 [(set_attr "length" "8,12,16,8,8")
5373 (set_attr "type" "*,*,*,load2,store2")
cde1623a 5374 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5375 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 5376 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
5377 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5378)
5379
d51f92df 5380(define_split
5381 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5382 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 5383 "TARGET_32BIT
d51f92df 5384 && reload_completed
5385 && (arm_const_double_inline_cost (operands[1])
5386 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
5387 [(const_int 0)]
5388 "
5389 arm_split_constant (SET, SImode, curr_insn,
5390 INTVAL (gen_lowpart (SImode, operands[1])),
5391 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5392 arm_split_constant (SET, SImode, curr_insn,
5393 INTVAL (gen_highpart_mode (SImode,
5394 GET_MODE (operands[0]),
5395 operands[1])),
5396 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5397 DONE;
5398 "
5399)
5400
e5ba9289 5401; If optimizing for size, or if we have load delay slots, then
5402; we want to split the constant into two separate operations.
5403; In both cases this may split a trivial part into a single data op
5404; leaving a single complex constant to load. We can also get longer
5405; offsets in a LDR which means we get better chances of sharing the pool
5406; entries. Finally, we can normally do a better job of scheduling
5407; LDR instructions than we can with LDM.
5408; This pattern will only match if the one above did not.
5409(define_split
5410 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5411 (match_operand:ANY64 1 "const_double_operand" ""))]
5412 "TARGET_ARM && reload_completed
5413 && arm_const_double_by_parts (operands[1])"
5414 [(set (match_dup 0) (match_dup 1))
5415 (set (match_dup 2) (match_dup 3))]
5416 "
5417 operands[2] = gen_highpart (SImode, operands[0]);
5418 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5419 operands[1]);
5420 operands[0] = gen_lowpart (SImode, operands[0]);
5421 operands[1] = gen_lowpart (SImode, operands[1]);
5422 "
5423)
5424
d51f92df 5425(define_split
5426 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5427 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5428 "TARGET_EITHER && reload_completed"
5429 [(set (match_dup 0) (match_dup 1))
5430 (set (match_dup 2) (match_dup 3))]
5431 "
5432 operands[2] = gen_highpart (SImode, operands[0]);
5433 operands[3] = gen_highpart (SImode, operands[1]);
5434 operands[0] = gen_lowpart (SImode, operands[0]);
5435 operands[1] = gen_lowpart (SImode, operands[1]);
5436
5437 /* Handle a partial overlap. */
5438 if (rtx_equal_p (operands[0], operands[3]))
5439 {
5440 rtx tmp0 = operands[0];
5441 rtx tmp1 = operands[1];
5442
5443 operands[0] = operands[2];
5444 operands[1] = operands[3];
5445 operands[2] = tmp0;
5446 operands[3] = tmp1;
5447 }
5448 "
5449)
5450
a8a3b539 5451;; We can't actually do base+index doubleword loads if the index and
5452;; destination overlap. Split here so that we at least have chance to
5453;; schedule.
5454(define_split
5455 [(set (match_operand:DI 0 "s_register_operand" "")
5456 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5457 (match_operand:SI 2 "s_register_operand" ""))))]
5458 "TARGET_LDRD
5459 && reg_overlap_mentioned_p (operands[0], operands[1])
5460 && reg_overlap_mentioned_p (operands[0], operands[2])"
5461 [(set (match_dup 4)
5462 (plus:SI (match_dup 1)
5463 (match_dup 2)))
5464 (set (match_dup 0)
5465 (mem:DI (match_dup 4)))]
5466 "
5467 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5468 "
5469)
5470
cffb2a26 5471;;; ??? This should have alternatives for constants.
5472;;; ??? This was originally identical to the movdf_insn pattern.
5473;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5474;;; thumb_reorg with a memory reference.
25f905c2 5475(define_insn "*thumb1_movdi_insn"
215b30b3 5476 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5477 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 5478 "TARGET_THUMB1
cffb2a26 5479 && ( register_operand (operands[0], DImode)
5480 || register_operand (operands[1], DImode))"
5481 "*
5482 {
5483 switch (which_alternative)
5484 {
5485 default:
5486 case 0:
5487 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5488 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5489 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5490 case 1:
5491 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5492 case 2:
5493 operands[1] = GEN_INT (- INTVAL (operands[1]));
5494 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5495 case 3:
5496 return \"ldmia\\t%1, {%0, %H0}\";
5497 case 4:
5498 return \"stmia\\t%0, {%1, %H1}\";
5499 case 5:
5500 return thumb_load_double_from_address (operands);
5501 case 6:
1a83b3ff 5502 operands[2] = gen_rtx_MEM (SImode,
29c05e22 5503 plus_constant (Pmode, XEXP (operands[0], 0), 4));
cffb2a26 5504 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5505 return \"\";
5506 case 7:
5507 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5508 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5509 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5510 }
5511 }"
5512 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5513 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5514 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5515 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5516)
b11cae9e 5517
9c08d1fa 5518(define_expand "movsi"
5519 [(set (match_operand:SI 0 "general_operand" "")
5520 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5521 "TARGET_EITHER"
9c08d1fa 5522 "
befb0bac 5523 {
e348ff3e 5524 rtx base, offset, tmp;
5525
25f905c2 5526 if (TARGET_32BIT)
9c08d1fa 5527 {
674a8f0b 5528 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5529 if (MEM_P (operands[0]))
cffb2a26 5530 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5531 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5532 && CONST_INT_P (operands[1])
cffb2a26 5533 && !(const_ok_for_arm (INTVAL (operands[1]))
5534 || const_ok_for_arm (~INTVAL (operands[1]))))
5535 {
96f57e36 5536 arm_split_constant (SET, SImode, NULL_RTX,
5537 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5538 optimize && can_create_pseudo_p ());
cffb2a26 5539 DONE;
5540 }
5541 }
25f905c2 5542 else /* TARGET_THUMB1... */
cffb2a26 5543 {
e1ba4a27 5544 if (can_create_pseudo_p ())
cffb2a26 5545 {
0438d37f 5546 if (!REG_P (operands[0]))
cffb2a26 5547 operands[1] = force_reg (SImode, operands[1]);
5548 }
9c08d1fa 5549 }
f655717d 5550
e348ff3e 5551 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5552 {
5553 split_const (operands[1], &base, &offset);
5554 if (GET_CODE (base) == SYMBOL_REF
5555 && !offset_within_block_p (base, INTVAL (offset)))
5556 {
b308ddcf 5557 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5558 emit_move_insn (tmp, base);
5559 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5560 DONE;
5561 }
5562 }
5563
f655717d 5564 /* Recognize the case where operand[1] is a reference to thread-local
5565 data and load its address to a register. */
5566 if (arm_tls_referenced_p (operands[1]))
5567 {
5568 rtx tmp = operands[1];
5569 rtx addend = NULL;
5570
5571 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5572 {
5573 addend = XEXP (XEXP (tmp, 0), 1);
5574 tmp = XEXP (XEXP (tmp, 0), 0);
5575 }
5576
5577 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5578 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5579
e1ba4a27 5580 tmp = legitimize_tls_address (tmp,
5581 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5582 if (addend)
5583 {
5584 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5585 tmp = force_operand (tmp, operands[0]);
5586 }
5587 operands[1] = tmp;
5588 }
5589 else if (flag_pic
5590 && (CONSTANT_P (operands[1])
5591 || symbol_mentioned_p (operands[1])
5592 || label_mentioned_p (operands[1])))
5593 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5594 (!can_create_pseudo_p ()
5595 ? operands[0]
5596 : 0));
befb0bac 5597 }
215b30b3 5598 "
5599)
9c08d1fa 5600
d0e6a121 5601;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5602;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5603;; so this does not matter.
5604(define_insn "*arm_movt"
5605 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5606 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5607 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5608 "arm_arch_thumb2"
d0e6a121 5609 "movt%?\t%0, #:upper16:%c2"
5610 [(set_attr "predicable" "yes")
5611 (set_attr "length" "4")]
5612)
5613
cffb2a26 5614(define_insn "*arm_movsi_insn"
aaa37ad6 5615 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5616 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5617 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5618 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5619 && ( register_operand (operands[0], SImode)
5620 || register_operand (operands[1], SImode))"
f7fbdd4a 5621 "@
aaa37ad6 5622 mov%?\\t%0, %1
f7fbdd4a 5623 mov%?\\t%0, %1
5624 mvn%?\\t%0, #%B1
25f905c2 5625 movw%?\\t%0, %1
f7fbdd4a 5626 ldr%?\\t%0, %1
5627 str%?\\t%1, %0"
aaa37ad6 5628 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5629 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5630 (set_attr "predicable" "yes")
aaa37ad6 5631 (set_attr "pool_range" "*,*,*,*,4096,*")
5632 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5633)
87b22bf7 5634
5635(define_split
a2cd141b 5636 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5637 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5638 "TARGET_32BIT
215b30b3 5639 && (!(const_ok_for_arm (INTVAL (operands[1]))
5640 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5641 [(clobber (const_int 0))]
5642 "
96f57e36 5643 arm_split_constant (SET, SImode, NULL_RTX,
5644 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5645 DONE;
215b30b3 5646 "
5647)
9c08d1fa 5648
b8d5d078 5649;; Split symbol_refs at the later stage (after cprop), instead of generating
5650;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5651;; and lo_sum would be merged back into memory load at cprop. However,
5652;; if the default is to prefer movt/movw rather than a load from the constant
5653;; pool, the performance is better.
5654(define_split
5655 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5656 (match_operand:SI 1 "general_operand" ""))]
5657 "TARGET_32BIT
5658 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5659 && !flag_pic && !target_word_relocations
5660 && !arm_tls_referenced_p (operands[1])"
5661 [(clobber (const_int 0))]
5662{
5663 arm_emit_movpair (operands[0], operands[1]);
5664 DONE;
5665})
5666
25f905c2 5667(define_insn "*thumb1_movsi_insn"
55a0d64c 5668 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5669 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 5670 "TARGET_THUMB1
cffb2a26 5671 && ( register_operand (operands[0], SImode)
5672 || register_operand (operands[1], SImode))"
5673 "@
5674 mov %0, %1
5675 mov %0, %1
5676 #
5677 #
5678 ldmia\\t%1, {%0}
5679 stmia\\t%0, {%1}
5680 ldr\\t%0, %1
5681 str\\t%1, %0
5682 mov\\t%0, %1"
5683 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5684 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5685 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5686 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5687
5688(define_split
5689 [(set (match_operand:SI 0 "register_operand" "")
5690 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5691 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5692 [(set (match_dup 2) (match_dup 1))
5693 (set (match_dup 0) (neg:SI (match_dup 2)))]
5694 "
5695 {
5696 operands[1] = GEN_INT (- INTVAL (operands[1]));
5697 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5698 }"
cffb2a26 5699)
5700
5701(define_split
5702 [(set (match_operand:SI 0 "register_operand" "")
5703 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5704 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5705 [(set (match_dup 2) (match_dup 1))
5706 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5707 "
5708 {
e4aeee53 5709 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5710 unsigned HOST_WIDE_INT mask = 0xff;
5711 int i;
5712
5713 for (i = 0; i < 25; i++)
5714 if ((val & (mask << i)) == val)
5715 break;
5716
1276f1b8 5717 /* Don't split if the shift is zero. */
cffb2a26 5718 if (i == 0)
5719 FAIL;
5720
5721 operands[1] = GEN_INT (val >> i);
1276f1b8 5722 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5723 operands[3] = GEN_INT (i);
cffb2a26 5724 }"
5725)
5726
c5b75283 5727;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
5728(define_split
5729 [(set (match_operand:SI 0 "register_operand" "")
5730 (match_operand:SI 1 "const_int_operand" ""))]
5731 "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
5732 [(set (match_dup 2) (match_dup 1))
5733 (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
5734 "
5735 {
5736 operands[1] = GEN_INT (INTVAL (operands[1]) - 255);
5737 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5738 operands[3] = GEN_INT (255);
5739 }"
5740)
5741
67336bcf 5742;; When generating pic, we need to load the symbol offset into a register.
5743;; So that the optimizer does not confuse this with a normal symbol load
5744;; we use an unspec. The offset will be loaded from a constant pool entry,
5745;; since that is the only type of relocation we can use.
5746
94f8caca 5747;; Wrap calculation of the whole PIC address in a single pattern for the
5748;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5749;; a PIC address involves two loads from memory, so we want to CSE it
5750;; as often as possible.
5751;; This pattern will be split into one of the pic_load_addr_* patterns
5752;; and a move after GCSE optimizations.
5753;;
5754;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5755(define_expand "calculate_pic_address"
5756 [(set (match_operand:SI 0 "register_operand" "")
5757 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5758 (unspec:SI [(match_operand:SI 2 "" "")]
5759 UNSPEC_PIC_SYM))))]
5760 "flag_pic"
5761)
5762
5763;; Split calculate_pic_address into pic_load_addr_* and a move.
5764(define_split
5765 [(set (match_operand:SI 0 "register_operand" "")
5766 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5767 (unspec:SI [(match_operand:SI 2 "" "")]
5768 UNSPEC_PIC_SYM))))]
5769 "flag_pic"
5770 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5771 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5772 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5773)
5774
350ccca5 5775;; operand1 is the memory address to go into
5776;; pic_load_addr_32bit.
5777;; operand2 is the PIC label to be emitted
5778;; from pic_add_dot_plus_eight.
5779;; We do this to allow hoisting of the entire insn.
5780(define_insn_and_split "pic_load_addr_unified"
5781 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5782 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5783 (match_operand:SI 2 "" "")]
5784 UNSPEC_PIC_UNIFIED))]
5785 "flag_pic"
5786 "#"
5787 "&& reload_completed"
5788 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5789 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5790 (match_dup 2)] UNSPEC_PIC_BASE))]
5791 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5792 [(set_attr "type" "load1,load1,load1")
5793 (set_attr "pool_range" "4096,4096,1024")
5794 (set_attr "neg_pool_range" "4084,0,0")
5795 (set_attr "arch" "a,t2,t1")
5796 (set_attr "length" "8,6,4")]
5797)
5798
67336bcf 5799;; The rather odd constraints on the following are to force reload to leave
5800;; the insn alone, and to force the minipool generation pass to then move
5801;; the GOT symbol to memory.
849170fd 5802
b3cd5f55 5803(define_insn "pic_load_addr_32bit"
849170fd 5804 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5805 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5806 "TARGET_32BIT && flag_pic"
67336bcf 5807 "ldr%?\\t%0, %1"
a2cd141b 5808 [(set_attr "type" "load1")
b3cd5f55 5809 (set_attr "pool_range" "4096")
5810 (set (attr "neg_pool_range")
5811 (if_then_else (eq_attr "is_thumb" "no")
5812 (const_int 4084)
5813 (const_int 0)))]
8c4d8060 5814)
5815
25f905c2 5816(define_insn "pic_load_addr_thumb1"
8c4d8060 5817 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5818 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5819 "TARGET_THUMB1 && flag_pic"
8c4d8060 5820 "ldr\\t%0, %1"
a2cd141b 5821 [(set_attr "type" "load1")
8c4d8060 5822 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5823)
849170fd 5824
cffb2a26 5825(define_insn "pic_add_dot_plus_four"
15d5d060 5826 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5827 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5828 (const_int 4)
beef0fb5 5829 (match_operand 2 "" "")]
5830 UNSPEC_PIC_BASE))]
b3cd5f55 5831 "TARGET_THUMB"
cffb2a26 5832 "*
6cdcb15c 5833 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5834 INTVAL (operands[2]));
cffb2a26 5835 return \"add\\t%0, %|pc\";
5836 "
5837 [(set_attr "length" "2")]
5838)
849170fd 5839
5840(define_insn "pic_add_dot_plus_eight"
15d5d060 5841 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5842 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5843 (const_int 8)
beef0fb5 5844 (match_operand 2 "" "")]
5845 UNSPEC_PIC_BASE))]
f655717d 5846 "TARGET_ARM"
c4034607 5847 "*
6cdcb15c 5848 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5849 INTVAL (operands[2]));
15d5d060 5850 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5851 "
0d66636f 5852 [(set_attr "predicable" "yes")]
cffb2a26 5853)
849170fd 5854
f655717d 5855(define_insn "tls_load_dot_plus_eight"
cc071db6 5856 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5857 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5858 (const_int 8)
beef0fb5 5859 (match_operand 2 "" "")]
5860 UNSPEC_PIC_BASE)))]
f655717d 5861 "TARGET_ARM"
5862 "*
6cdcb15c 5863 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5864 INTVAL (operands[2]));
f655717d 5865 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5866 "
5867 [(set_attr "predicable" "yes")]
5868)
5869
5870;; PIC references to local variables can generate pic_add_dot_plus_eight
5871;; followed by a load. These sequences can be crunched down to
5872;; tls_load_dot_plus_eight by a peephole.
5873
5874(define_peephole2
c0c1fba5 5875 [(set (match_operand:SI 0 "register_operand" "")
5876 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5877 (const_int 8)
5878 (match_operand 1 "" "")]
5879 UNSPEC_PIC_BASE))
2d05dfad 5880 (set (match_operand:SI 2 "arm_general_register_operand" "")
5881 (mem:SI (match_dup 0)))]
f655717d 5882 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5883 [(set (match_dup 2)
5884 (mem:SI (unspec:SI [(match_dup 3)
5885 (const_int 8)
5886 (match_dup 1)]
5887 UNSPEC_PIC_BASE)))]
f655717d 5888 ""
5889)
5890
bac7fc85 5891(define_insn "pic_offset_arm"
5892 [(set (match_operand:SI 0 "register_operand" "=r")
5893 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5894 (unspec:SI [(match_operand:SI 2 "" "X")]
5895 UNSPEC_PIC_OFFSET))))]
5896 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5897 "ldr%?\\t%0, [%1,%2]"
5898 [(set_attr "type" "load1")]
5899)
5900
95373f08 5901(define_expand "builtin_setjmp_receiver"
5902 [(label_ref (match_operand 0 "" ""))]
5903 "flag_pic"
5904 "
5905{
b935b306 5906 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5907 register. */
2cb7d577 5908 if (arm_pic_register != INVALID_REGNUM)
5909 arm_load_pic_register (1UL << 3);
95373f08 5910 DONE;
5911}")
5912
9c08d1fa 5913;; If copying one reg to another we can set the condition codes according to
5914;; its value. Such a move is common after a return from subroutine and the
5915;; result is being tested against zero.
5916
f7fbdd4a 5917(define_insn "*movsi_compare0"
bd5b4116 5918 [(set (reg:CC CC_REGNUM)
cffb2a26 5919 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5920 (const_int 0)))
5921 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5922 (match_dup 1))]
25f905c2 5923 "TARGET_32BIT"
e2348bcb 5924 "@
40dbec34 5925 cmp%?\\t%0, #0
25f905c2 5926 sub%.\\t%0, %1, #0"
cffb2a26 5927 [(set_attr "conds" "set")]
5928)
b11cae9e 5929
b11cae9e 5930;; Subroutine to store a half word from a register into memory.
5931;; Operand 0 is the source register (HImode)
c8f69309 5932;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5933
9c08d1fa 5934;; In both this routine and the next, we must be careful not to spill
01cc3b75 5935;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5936;; can generate unrecognizable rtl.
5937
b11cae9e 5938(define_expand "storehi"
c8f69309 5939 [;; store the low byte
f082f1c4 5940 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5941 ;; extract the high byte
c8f69309 5942 (set (match_dup 2)
5943 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5944 ;; store the high byte
787f8210 5945 (set (match_dup 4) (match_dup 5))]
cffb2a26 5946 "TARGET_ARM"
b11cae9e 5947 "
215b30b3 5948 {
537ffcfc 5949 rtx op1 = operands[1];
5950 rtx addr = XEXP (op1, 0);
215b30b3 5951 enum rtx_code code = GET_CODE (addr);
5952
0438d37f 5953 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5954 || code == MINUS)
537ffcfc 5955 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5956
537ffcfc 5957 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5958 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5959 operands[3] = gen_lowpart (QImode, operands[0]);
5960 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5961 operands[2] = gen_reg_rtx (SImode);
5962 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5963 }"
5964)
b11cae9e 5965
c7597b5d 5966(define_expand "storehi_bigend"
f082f1c4 5967 [(set (match_dup 4) (match_dup 3))
c7597b5d 5968 (set (match_dup 2)
5969 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5970 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5971 "TARGET_ARM"
b11cae9e 5972 "
215b30b3 5973 {
537ffcfc 5974 rtx op1 = operands[1];
5975 rtx addr = XEXP (op1, 0);
215b30b3 5976 enum rtx_code code = GET_CODE (addr);
5977
0438d37f 5978 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5979 || code == MINUS)
537ffcfc 5980 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5981
537ffcfc 5982 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5983 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5984 operands[3] = gen_lowpart (QImode, operands[0]);
5985 operands[0] = gen_lowpart (SImode, operands[0]);
5986 operands[2] = gen_reg_rtx (SImode);
787f8210 5987 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5988 }"
5989)
c7597b5d 5990
5991;; Subroutine to store a half word integer constant into memory.
5992(define_expand "storeinthi"
f082f1c4 5993 [(set (match_operand 0 "" "")
787f8210 5994 (match_operand 1 "" ""))
9e8503e6 5995 (set (match_dup 3) (match_dup 2))]
cffb2a26 5996 "TARGET_ARM"
c7597b5d 5997 "
215b30b3 5998 {
5999 HOST_WIDE_INT value = INTVAL (operands[1]);
6000 rtx addr = XEXP (operands[0], 0);
537ffcfc 6001 rtx op0 = operands[0];
215b30b3 6002 enum rtx_code code = GET_CODE (addr);
c7597b5d 6003
0438d37f 6004 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6005 || code == MINUS)
537ffcfc 6006 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6007
215b30b3 6008 operands[1] = gen_reg_rtx (SImode);
6009 if (BYTES_BIG_ENDIAN)
6010 {
6011 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6012 if ((value & 255) == ((value >> 8) & 255))
6013 operands[2] = operands[1];
6014 else
6015 {
6016 operands[2] = gen_reg_rtx (SImode);
6017 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6018 }
6019 }
6020 else
6021 {
6022 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6023 if ((value & 255) == ((value >> 8) & 255))
6024 operands[2] = operands[1];
6025 else
6026 {
6027 operands[2] = gen_reg_rtx (SImode);
6028 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6029 }
6030 }
c7597b5d 6031
537ffcfc 6032 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6033 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6034 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6035 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6036 }"
6037)
b11cae9e 6038
f7fbdd4a 6039(define_expand "storehi_single_op"
6040 [(set (match_operand:HI 0 "memory_operand" "")
6041 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6042 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6043 "
215b30b3 6044 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6045 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6046 "
6047)
f7fbdd4a 6048
b11cae9e 6049(define_expand "movhi"
6050 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6051 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6052 "TARGET_EITHER"
b11cae9e 6053 "
cffb2a26 6054 if (TARGET_ARM)
b11cae9e 6055 {
e1ba4a27 6056 if (can_create_pseudo_p ())
cffb2a26 6057 {
0438d37f 6058 if (MEM_P (operands[0]))
b11cae9e 6059 {
cffb2a26 6060 if (arm_arch4)
6061 {
6062 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6063 DONE;
6064 }
0438d37f 6065 if (CONST_INT_P (operands[1]))
cffb2a26 6066 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6067 else
cffb2a26 6068 {
0438d37f 6069 if (MEM_P (operands[1]))
cffb2a26 6070 operands[1] = force_reg (HImode, operands[1]);
6071 if (BYTES_BIG_ENDIAN)
6072 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6073 else
6074 emit_insn (gen_storehi (operands[1], operands[0]));
6075 }
6076 DONE;
b11cae9e 6077 }
cffb2a26 6078 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6079 else if (CONST_INT_P (operands[1]))
9c08d1fa 6080 {
cffb2a26 6081 rtx reg = gen_reg_rtx (SImode);
6082 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6083
6084 /* If the constant is already valid, leave it alone. */
215b30b3 6085 if (!const_ok_for_arm (val))
cffb2a26 6086 {
6087 /* If setting all the top bits will make the constant
6088 loadable in a single instruction, then set them.
6089 Otherwise, sign extend the number. */
6090
215b30b3 6091 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6092 val |= ~0xffff;
6093 else if (val & 0x8000)
6094 val |= ~0xffff;
6095 }
6096
6097 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6098 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6099 }
e1ba4a27 6100 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6101 && MEM_P (operands[1]))
0045890a 6102 {
6103 rtx reg = gen_reg_rtx (SImode);
6104
6105 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6106 operands[1] = gen_lowpart (HImode, reg);
6107 }
215b30b3 6108 else if (!arm_arch4)
f7fbdd4a 6109 {
0438d37f 6110 if (MEM_P (operands[1]))
cffb2a26 6111 {
c1a66faf 6112 rtx base;
6113 rtx offset = const0_rtx;
6114 rtx reg = gen_reg_rtx (SImode);
6115
0438d37f 6116 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6117 || (GET_CODE (base) == PLUS
0438d37f 6118 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6119 && ((INTVAL(offset) & 1) != 1)
0438d37f 6120 && REG_P (base = XEXP (base, 0))))
c1a66faf 6121 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6122 {
8deb3959 6123 rtx new_rtx;
c1a66faf 6124
8deb3959 6125 new_rtx = widen_memory_access (operands[1], SImode,
6126 ((INTVAL (offset) & ~3)
6127 - INTVAL (offset)));
6128 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6129 if (((INTVAL (offset) & 2) != 0)
6130 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6131 {
6132 rtx reg2 = gen_reg_rtx (SImode);
6133
6134 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6135 reg = reg2;
6136 }
206ee9a2 6137 }
c1a66faf 6138 else
6139 emit_insn (gen_movhi_bytes (reg, operands[1]));
6140
6141 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6142 }
6143 }
6144 }
674a8f0b 6145 /* Handle loading a large integer during reload. */
0438d37f 6146 else if (CONST_INT_P (operands[1])
215b30b3 6147 && !const_ok_for_arm (INTVAL (operands[1]))
6148 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6149 {
6150 /* Writing a constant to memory needs a scratch, which should
6151 be handled with SECONDARY_RELOADs. */
0438d37f 6152 gcc_assert (REG_P (operands[0]));
cffb2a26 6153
6154 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6155 emit_insn (gen_movsi (operands[0], operands[1]));
6156 DONE;
6157 }
6158 }
25f905c2 6159 else if (TARGET_THUMB2)
6160 {
6161 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6162 if (can_create_pseudo_p ())
25f905c2 6163 {
0438d37f 6164 if (!REG_P (operands[0]))
25f905c2 6165 operands[1] = force_reg (HImode, operands[1]);
6166 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6167 else if (CONST_INT_P (operands[1]))
25f905c2 6168 {
6169 rtx reg = gen_reg_rtx (SImode);
6170 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6171
6172 emit_insn (gen_movsi (reg, GEN_INT (val)));
6173 operands[1] = gen_lowpart (HImode, reg);
6174 }
6175 }
6176 }
6177 else /* TARGET_THUMB1 */
cffb2a26 6178 {
e1ba4a27 6179 if (can_create_pseudo_p ())
cffb2a26 6180 {
0438d37f 6181 if (CONST_INT_P (operands[1]))
6cffc037 6182 {
6183 rtx reg = gen_reg_rtx (SImode);
6184
6185 emit_insn (gen_movsi (reg, operands[1]));
6186 operands[1] = gen_lowpart (HImode, reg);
6187 }
cffb2a26 6188
6189 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6190 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6191 virtual register (also rejected as illegitimate for HImode/QImode)
6192 relative address. */
cffb2a26 6193 /* ??? This should perhaps be fixed elsewhere, for instance, in
6194 fixup_stack_1, by checking for other kinds of invalid addresses,
6195 e.g. a bare reference to a virtual register. This may confuse the
6196 alpha though, which must handle this case differently. */
0438d37f 6197 if (MEM_P (operands[0])
215b30b3 6198 && !memory_address_p (GET_MODE (operands[0]),
6199 XEXP (operands[0], 0)))
537ffcfc 6200 operands[0]
6201 = replace_equiv_address (operands[0],
6202 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6203
0438d37f 6204 if (MEM_P (operands[1])
215b30b3 6205 && !memory_address_p (GET_MODE (operands[1]),
6206 XEXP (operands[1], 0)))
537ffcfc 6207 operands[1]
6208 = replace_equiv_address (operands[1],
6209 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6210
0438d37f 6211 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6212 {
6213 rtx reg = gen_reg_rtx (SImode);
6214
6215 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6216 operands[1] = gen_lowpart (HImode, reg);
6217 }
6218
0438d37f 6219 if (MEM_P (operands[0]))
6cffc037 6220 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6221 }
0438d37f 6222 else if (CONST_INT_P (operands[1])
234f6557 6223 && !satisfies_constraint_I (operands[1]))
cffb2a26 6224 {
6cffc037 6225 /* Handle loading a large integer during reload. */
6226
cffb2a26 6227 /* Writing a constant to memory needs a scratch, which should
6228 be handled with SECONDARY_RELOADs. */
0438d37f 6229 gcc_assert (REG_P (operands[0]));
cffb2a26 6230
1a83b3ff 6231 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6232 emit_insn (gen_movsi (operands[0], operands[1]));
6233 DONE;
6234 }
b11cae9e 6235 }
cffb2a26 6236 "
6237)
6238
25f905c2 6239(define_insn "*thumb1_movhi_insn"
a941568e 6240 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6241 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 6242 "TARGET_THUMB1
cffb2a26 6243 && ( register_operand (operands[0], HImode)
6244 || register_operand (operands[1], HImode))"
6245 "*
6246 switch (which_alternative)
d79300ac 6247 {
cffb2a26 6248 case 0: return \"add %0, %1, #0\";
6249 case 2: return \"strh %1, %0\";
6250 case 3: return \"mov %0, %1\";
6251 case 4: return \"mov %0, %1\";
6252 case 5: return \"mov %0, %1\";
ed29c566 6253 default: gcc_unreachable ();
cffb2a26 6254 case 1:
6255 /* The stack pointer can end up being taken as an index register.
6256 Catch this case here and deal with it. */
6257 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
0438d37f 6258 && REG_P (XEXP (XEXP (operands[1], 0), 0))
cffb2a26 6259 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
6260 {
6261 rtx ops[2];
6262 ops[0] = operands[0];
6263 ops[1] = XEXP (XEXP (operands[1], 0), 0);
6264
6265 output_asm_insn (\"mov %0, %1\", ops);
6266
6267 XEXP (XEXP (operands[1], 0), 0) = operands[0];
6268
6269 }
6270 return \"ldrh %0, %1\";
6271 }"
6272 [(set_attr "length" "2,4,2,2,2,2")
747b7458 6273 (set_attr "type" "*,load1,store1,*,*,*")
6274 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 6275
b11cae9e 6276
25f7a26e 6277(define_expand "movhi_bytes"
eab14235 6278 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6279 (set (match_dup 3)
eab14235 6280 (zero_extend:SI (match_dup 6)))
25f7a26e 6281 (set (match_operand:SI 0 "" "")
6282 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6283 "TARGET_ARM"
25f7a26e 6284 "
215b30b3 6285 {
6286 rtx mem1, mem2;
6287 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6288
788fcce0 6289 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6290 mem2 = change_address (operands[1], QImode,
6291 plus_constant (Pmode, addr, 1));
215b30b3 6292 operands[0] = gen_lowpart (SImode, operands[0]);
6293 operands[1] = mem1;
6294 operands[2] = gen_reg_rtx (SImode);
6295 operands[3] = gen_reg_rtx (SImode);
6296 operands[6] = mem2;
25f7a26e 6297
215b30b3 6298 if (BYTES_BIG_ENDIAN)
6299 {
6300 operands[4] = operands[2];
6301 operands[5] = operands[3];
6302 }
6303 else
6304 {
6305 operands[4] = operands[3];
6306 operands[5] = operands[2];
6307 }
6308 }"
6309)
25f7a26e 6310
c7597b5d 6311(define_expand "movhi_bigend"
6312 [(set (match_dup 2)
6313 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6314 (const_int 16)))
6315 (set (match_dup 3)
6316 (ashiftrt:SI (match_dup 2) (const_int 16)))
6317 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6318 (match_dup 4))]
cffb2a26 6319 "TARGET_ARM"
c7597b5d 6320 "
6321 operands[2] = gen_reg_rtx (SImode);
6322 operands[3] = gen_reg_rtx (SImode);
787f8210 6323 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6324 "
6325)
b11cae9e 6326
a2f10574 6327;; Pattern to recognize insn generated default case above
f7fbdd4a 6328(define_insn "*movhi_insn_arch4"
cde1623a 6329 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 6330 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 6331 "TARGET_ARM
6332 && arm_arch4
85e02ccb 6333 && (register_operand (operands[0], HImode)
6334 || register_operand (operands[1], HImode))"
f7fbdd4a 6335 "@
6336 mov%?\\t%0, %1\\t%@ movhi
6337 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 6338 str%(h%)\\t%1, %0\\t%@ movhi
6339 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 6340 [(set_attr "type" "*,*,store1,load1")
0d66636f 6341 (set_attr "predicable" "yes")
d2a518d1 6342 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 6343 (set_attr "pool_range" "*,*,*,256")
6344 (set_attr "neg_pool_range" "*,*,*,244")]
6345)
f7fbdd4a 6346
f7fbdd4a 6347(define_insn "*movhi_bytes"
25f7a26e 6348 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
6349 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 6350 "TARGET_ARM"
25f7a26e 6351 "@
6352 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6353 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6354 [(set_attr "predicable" "yes")
6355 (set_attr "insn" "mov,mvn")]
0d66636f 6356)
25f7a26e 6357
f90b51f1 6358(define_expand "thumb_movhi_clobber"
6359 [(set (match_operand:HI 0 "memory_operand" "")
6360 (match_operand:HI 1 "register_operand" ""))
6361 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 6362 "TARGET_THUMB1"
f90b51f1 6363 "
6364 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
6365 && REGNO (operands[1]) <= LAST_LO_REGNUM)
6366 {
6367 emit_insn (gen_movhi (operands[0], operands[1]));
6368 DONE;
6369 }
6370 /* XXX Fixme, need to handle other cases here as well. */
6371 gcc_unreachable ();
6372 "
cffb2a26 6373)
6374
bc5c7e08 6375;; We use a DImode scratch because we may occasionally need an additional
6376;; temporary if the address isn't offsettable -- push_reload doesn't seem
6377;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6378(define_expand "reload_outhi"
cffb2a26 6379 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6380 (match_operand:HI 1 "s_register_operand" "r")
6381 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6382 "TARGET_EITHER"
6383 "if (TARGET_ARM)
6384 arm_reload_out_hi (operands);
6385 else
6386 thumb_reload_out_hi (operands);
d3373b54 6387 DONE;
cffb2a26 6388 "
6389)
d3373b54 6390
25f7a26e 6391(define_expand "reload_inhi"
6392 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6393 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6394 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6395 "TARGET_EITHER"
25f7a26e 6396 "
cffb2a26 6397 if (TARGET_ARM)
6398 arm_reload_in_hi (operands);
6399 else
6400 thumb_reload_out_hi (operands);
25f7a26e 6401 DONE;
6402")
6403
9c08d1fa 6404(define_expand "movqi"
6405 [(set (match_operand:QI 0 "general_operand" "")
6406 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6407 "TARGET_EITHER"
9c08d1fa 6408 "
6cffc037 6409 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6410
e1ba4a27 6411 if (can_create_pseudo_p ())
cffb2a26 6412 {
0438d37f 6413 if (CONST_INT_P (operands[1]))
6cffc037 6414 {
6415 rtx reg = gen_reg_rtx (SImode);
6416
03770691 6417 /* For thumb we want an unsigned immediate, then we are more likely
6418 to be able to use a movs insn. */
6419 if (TARGET_THUMB)
6420 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6421
6cffc037 6422 emit_insn (gen_movsi (reg, operands[1]));
6423 operands[1] = gen_lowpart (QImode, reg);
6424 }
cffb2a26 6425
6cffc037 6426 if (TARGET_THUMB)
6427 {
cffb2a26 6428 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6429 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6430 virtual register (also rejected as illegitimate for HImode/QImode)
6431 relative address. */
cffb2a26 6432 /* ??? This should perhaps be fixed elsewhere, for instance, in
6433 fixup_stack_1, by checking for other kinds of invalid addresses,
6434 e.g. a bare reference to a virtual register. This may confuse the
6435 alpha though, which must handle this case differently. */
0438d37f 6436 if (MEM_P (operands[0])
215b30b3 6437 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6438 XEXP (operands[0], 0)))
537ffcfc 6439 operands[0]
6440 = replace_equiv_address (operands[0],
6441 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6442 if (MEM_P (operands[1])
215b30b3 6443 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6444 XEXP (operands[1], 0)))
537ffcfc 6445 operands[1]
6446 = replace_equiv_address (operands[1],
6447 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6448 }
6449
0438d37f 6450 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6451 {
6452 rtx reg = gen_reg_rtx (SImode);
6453
6454 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6455 operands[1] = gen_lowpart (QImode, reg);
6456 }
6457
0438d37f 6458 if (MEM_P (operands[0]))
6cffc037 6459 operands[1] = force_reg (QImode, operands[1]);
6460 }
6461 else if (TARGET_THUMB
0438d37f 6462 && CONST_INT_P (operands[1])
234f6557 6463 && !satisfies_constraint_I (operands[1]))
6cffc037 6464 {
674a8f0b 6465 /* Handle loading a large integer during reload. */
cffb2a26 6466
6cffc037 6467 /* Writing a constant to memory needs a scratch, which should
6468 be handled with SECONDARY_RELOADs. */
0438d37f 6469 gcc_assert (REG_P (operands[0]));
6cffc037 6470
6471 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6472 emit_insn (gen_movsi (operands[0], operands[1]));
6473 DONE;
cffb2a26 6474 }
6475 "
6476)
b11cae9e 6477
9c08d1fa 6478
cffb2a26 6479(define_insn "*arm_movqi_insn"
a54e3e7b 6480 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
6481 (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
25f905c2 6482 "TARGET_32BIT
cffb2a26 6483 && ( register_operand (operands[0], QImode)
6484 || register_operand (operands[1], QImode))"
5565501b 6485 "@
6486 mov%?\\t%0, %1
6487 mvn%?\\t%0, #%B1
25f905c2 6488 ldr%(b%)\\t%0, %1
a54e3e7b 6489 str%(b%)\\t%1, %0
6490 ldr%(b%)\\t%0, %1
25f905c2 6491 str%(b%)\\t%1, %0"
a54e3e7b 6492 [(set_attr "type" "*,*,load1,store1,load1,store1")
6493 (set_attr "insn" "mov,mvn,*,*,*,*")
6494 (set_attr "predicable" "yes")
6495 (set_attr "arch" "any,any,t2,t2,any,any")
6496 (set_attr "length" "4,4,2,2,4,4")]
cffb2a26 6497)
6498
25f905c2 6499(define_insn "*thumb1_movqi_insn"
cffb2a26 6500 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 6501 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 6502 "TARGET_THUMB1
cffb2a26 6503 && ( register_operand (operands[0], QImode)
6504 || register_operand (operands[1], QImode))"
6505 "@
6506 add\\t%0, %1, #0
6507 ldrb\\t%0, %1
6508 strb\\t%1, %0
6509 mov\\t%0, %1
6510 mov\\t%0, %1
6511 mov\\t%0, %1"
6512 [(set_attr "length" "2")
a2cd141b 6513 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 6514 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 6515 (set_attr "pool_range" "*,32,*,*,*,*")
6516 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 6517
9b8516be 6518;; HFmode moves
6519(define_expand "movhf"
6520 [(set (match_operand:HF 0 "general_operand" "")
6521 (match_operand:HF 1 "general_operand" ""))]
6522 "TARGET_EITHER"
6523 "
6524 if (TARGET_32BIT)
6525 {
0438d37f 6526 if (MEM_P (operands[0]))
9b8516be 6527 operands[1] = force_reg (HFmode, operands[1]);
6528 }
6529 else /* TARGET_THUMB1 */
6530 {
6531 if (can_create_pseudo_p ())
6532 {
0438d37f 6533 if (!REG_P (operands[0]))
9b8516be 6534 operands[1] = force_reg (HFmode, operands[1]);
6535 }
6536 }
6537 "
6538)
6539
6540(define_insn "*arm32_movhf"
6541 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6542 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 6543 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6544 && ( s_register_operand (operands[0], HFmode)
6545 || s_register_operand (operands[1], HFmode))"
6546 "*
6547 switch (which_alternative)
6548 {
6549 case 0: /* ARM register from memory */
6550 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6551 case 1: /* memory from ARM register */
6552 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6553 case 2: /* ARM register from ARM register */
6554 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6555 case 3: /* ARM register from constant */
6556 {
6557 REAL_VALUE_TYPE r;
6558 long bits;
6559 rtx ops[4];
6560
6561 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6562 bits = real_to_target (NULL, &r, HFmode);
6563 ops[0] = operands[0];
6564 ops[1] = GEN_INT (bits);
6565 ops[2] = GEN_INT (bits & 0xff00);
6566 ops[3] = GEN_INT (bits & 0x00ff);
6567
6568 if (arm_arch_thumb2)
6569 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6570 else
6571 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6572 return \"\";
6573 }
6574 default:
6575 gcc_unreachable ();
6576 }
6577 "
6578 [(set_attr "conds" "unconditional")
6579 (set_attr "type" "load1,store1,*,*")
d2a518d1 6580 (set_attr "insn" "*,*,mov,mov")
9b8516be 6581 (set_attr "length" "4,4,4,8")
d2a518d1 6582 (set_attr "predicable" "yes")]
9b8516be 6583)
6584
6585(define_insn "*thumb1_movhf"
6586 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6587 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6588 "TARGET_THUMB1
6589 && ( s_register_operand (operands[0], HFmode)
6590 || s_register_operand (operands[1], HFmode))"
6591 "*
6592 switch (which_alternative)
6593 {
6594 case 1:
6595 {
6596 rtx addr;
0438d37f 6597 gcc_assert (MEM_P (operands[1]));
9b8516be 6598 addr = XEXP (operands[1], 0);
6599 if (GET_CODE (addr) == LABEL_REF
6600 || (GET_CODE (addr) == CONST
6601 && GET_CODE (XEXP (addr, 0)) == PLUS
6602 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
0438d37f 6603 && CONST_INT_P (XEXP (XEXP (addr, 0), 1))))
9b8516be 6604 {
6605 /* Constant pool entry. */
6606 return \"ldr\\t%0, %1\";
6607 }
6608 return \"ldrh\\t%0, %1\";
6609 }
6610 case 2: return \"strh\\t%1, %0\";
6611 default: return \"mov\\t%0, %1\";
6612 }
6613 "
6614 [(set_attr "length" "2")
6615 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6616 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6617 (set_attr "pool_range" "*,1020,*,*,*")
6618 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6619
87b22bf7 6620(define_expand "movsf"
6621 [(set (match_operand:SF 0 "general_operand" "")
6622 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6623 "TARGET_EITHER"
87b22bf7 6624 "
25f905c2 6625 if (TARGET_32BIT)
cffb2a26 6626 {
0438d37f 6627 if (MEM_P (operands[0]))
cffb2a26 6628 operands[1] = force_reg (SFmode, operands[1]);
6629 }
25f905c2 6630 else /* TARGET_THUMB1 */
cffb2a26 6631 {
e1ba4a27 6632 if (can_create_pseudo_p ())
cffb2a26 6633 {
0438d37f 6634 if (!REG_P (operands[0]))
cffb2a26 6635 operands[1] = force_reg (SFmode, operands[1]);
6636 }
6637 }
6638 "
6639)
6640
03d440a6 6641;; Transform a floating-point move of a constant into a core register into
6642;; an SImode operation.
cffb2a26 6643(define_split
03d440a6 6644 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6645 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6646 "TARGET_EITHER
cffb2a26 6647 && reload_completed
0438d37f 6648 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6649 [(set (match_dup 2) (match_dup 3))]
6650 "
6651 operands[2] = gen_lowpart (SImode, operands[0]);
6652 operands[3] = gen_lowpart (SImode, operands[1]);
6653 if (operands[2] == 0 || operands[3] == 0)
6654 FAIL;
215b30b3 6655 "
6656)
87b22bf7 6657
cffb2a26 6658(define_insn "*arm_movsf_soft_insn"
6659 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6660 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6661 "TARGET_32BIT
cffb2a26 6662 && TARGET_SOFT_FLOAT
0438d37f 6663 && (!MEM_P (operands[0])
215b30b3 6664 || register_operand (operands[1], SFmode))"
9a1112d7 6665 "@
6666 mov%?\\t%0, %1
6667 ldr%?\\t%0, %1\\t%@ float
6668 str%?\\t%1, %0\\t%@ float"
cde1623a 6669 [(set_attr "predicable" "yes")
a2cd141b 6670 (set_attr "type" "*,load1,store1")
d2a518d1 6671 (set_attr "insn" "mov,*,*")
cffb2a26 6672 (set_attr "pool_range" "*,4096,*")
cde1623a 6673 (set_attr "arm_neg_pool_range" "*,4084,*")
6674 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6675)
6676
6677;;; ??? This should have alternatives for constants.
25f905c2 6678(define_insn "*thumb1_movsf_insn"
215b30b3 6679 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6680 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6681 "TARGET_THUMB1
cffb2a26 6682 && ( register_operand (operands[0], SFmode)
6683 || register_operand (operands[1], SFmode))"
6684 "@
6685 add\\t%0, %1, #0
6686 ldmia\\t%1, {%0}
6687 stmia\\t%0, {%1}
6688 ldr\\t%0, %1
6689 str\\t%1, %0
6690 mov\\t%0, %1
6691 mov\\t%0, %1"
6692 [(set_attr "length" "2")
a2cd141b 6693 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6694 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6695 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6696 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6697)
9a1112d7 6698
9c08d1fa 6699(define_expand "movdf"
87b22bf7 6700 [(set (match_operand:DF 0 "general_operand" "")
6701 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6702 "TARGET_EITHER"
9c08d1fa 6703 "
25f905c2 6704 if (TARGET_32BIT)
cffb2a26 6705 {
0438d37f 6706 if (MEM_P (operands[0]))
cffb2a26 6707 operands[1] = force_reg (DFmode, operands[1]);
6708 }
6709 else /* TARGET_THUMB */
6710 {
e1ba4a27 6711 if (can_create_pseudo_p ())
cffb2a26 6712 {
0438d37f 6713 if (!REG_P (operands[0]))
cffb2a26 6714 operands[1] = force_reg (DFmode, operands[1]);
6715 }
6716 }
6717 "
6718)
b11cae9e 6719
9c08d1fa 6720;; Reloading a df mode value stored in integer regs to memory can require a
6721;; scratch reg.
6722(define_expand "reload_outdf"
cffb2a26 6723 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6724 (match_operand:DF 1 "s_register_operand" "r")
6725 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6726 "TARGET_THUMB2"
87b22bf7 6727 "
215b30b3 6728 {
6729 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6730
215b30b3 6731 if (code == REG)
6732 operands[2] = XEXP (operands[0], 0);
6733 else if (code == POST_INC || code == PRE_DEC)
6734 {
6735 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6736 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6737 emit_insn (gen_movdi (operands[0], operands[1]));
6738 DONE;
6739 }
6740 else if (code == PRE_INC)
6741 {
6742 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6743
215b30b3 6744 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6745 operands[2] = reg;
6746 }
6747 else if (code == POST_DEC)
6748 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6749 else
6750 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6751 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6752
788fcce0 6753 emit_insn (gen_rtx_SET (VOIDmode,
6754 replace_equiv_address (operands[0], operands[2]),
215b30b3 6755 operands[1]));
f7fbdd4a 6756
215b30b3 6757 if (code == POST_DEC)
6758 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6759
6760 DONE;
6761 }"
6762)
9c08d1fa 6763
9a1112d7 6764(define_insn "*movdf_soft_insn"
359a6e9f 6765 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6766 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6767 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6768 && ( register_operand (operands[0], DFmode)
6769 || register_operand (operands[1], DFmode))"
d51f92df 6770 "*
6771 switch (which_alternative)
6772 {
6773 case 0:
6774 case 1:
6775 case 2:
6776 return \"#\";
6777 default:
26ff80c0 6778 return output_move_double (operands, true, NULL);
d51f92df 6779 }
6780 "
359a6e9f 6781 [(set_attr "length" "8,12,16,8,8")
6782 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6783 (set_attr "pool_range" "*,*,*,1020,*")
8848d797 6784 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6785 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6786)
6787
6788;;; ??? This should have alternatives for constants.
6789;;; ??? This was originally identical to the movdi_insn pattern.
6790;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6791;;; thumb_reorg with a memory reference.
6792(define_insn "*thumb_movdf_insn"
215b30b3 6793 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6794 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6795 "TARGET_THUMB1
cffb2a26 6796 && ( register_operand (operands[0], DFmode)
6797 || register_operand (operands[1], DFmode))"
6798 "*
6799 switch (which_alternative)
6800 {
6801 default:
6802 case 0:
6803 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6804 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6805 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6806 case 1:
6807 return \"ldmia\\t%1, {%0, %H0}\";
6808 case 2:
6809 return \"stmia\\t%0, {%1, %H1}\";
6810 case 3:
6811 return thumb_load_double_from_address (operands);
6812 case 4:
1a83b3ff 6813 operands[2] = gen_rtx_MEM (SImode,
29c05e22 6814 plus_constant (Pmode,
6815 XEXP (operands[0], 0), 4));
cffb2a26 6816 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6817 return \"\";
6818 case 5:
6819 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6820 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6821 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6822 }
6823 "
6824 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6825 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6826 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6827 (set_attr "pool_range" "*,*,*,1020,*,*")]
6828)
b11cae9e 6829\f
b11cae9e 6830
9c08d1fa 6831;; load- and store-multiple insns
6832;; The arm can load/store any set of registers, provided that they are in
320ea44d 6833;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6834
9c08d1fa 6835(define_expand "load_multiple"
6836 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6837 (match_operand:SI 1 "" ""))
6838 (use (match_operand:SI 2 "" ""))])]
25f905c2 6839 "TARGET_32BIT"
9580c25f 6840{
6841 HOST_WIDE_INT offset = 0;
6842
bd5b4116 6843 /* Support only fixed point registers. */
0438d37f 6844 if (!CONST_INT_P (operands[2])
9c08d1fa 6845 || INTVAL (operands[2]) > 14
6846 || INTVAL (operands[2]) < 2
0438d37f 6847 || !MEM_P (operands[1])
6848 || !REG_P (operands[0])
bd5b4116 6849 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6850 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6851 FAIL;
6852
6853 operands[3]
320ea44d 6854 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6855 INTVAL (operands[2]),
f082f1c4 6856 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6857 FALSE, operands[1], &offset);
9580c25f 6858})
b11cae9e 6859
9c08d1fa 6860(define_expand "store_multiple"
6861 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6862 (match_operand:SI 1 "" ""))
6863 (use (match_operand:SI 2 "" ""))])]
25f905c2 6864 "TARGET_32BIT"
9580c25f 6865{
6866 HOST_WIDE_INT offset = 0;
6867
674a8f0b 6868 /* Support only fixed point registers. */
0438d37f 6869 if (!CONST_INT_P (operands[2])
9c08d1fa 6870 || INTVAL (operands[2]) > 14
6871 || INTVAL (operands[2]) < 2
0438d37f 6872 || !REG_P (operands[1])
6873 || !MEM_P (operands[0])
bd5b4116 6874 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6875 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6876 FAIL;
6877
6878 operands[3]
320ea44d 6879 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6880 INTVAL (operands[2]),
f082f1c4 6881 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6882 FALSE, operands[0], &offset);
9580c25f 6883})
b11cae9e 6884
9c08d1fa 6885
6886;; Move a block of memory if it is word aligned and MORE than 2 words long.
6887;; We could let this apply for blocks of less than this, but it clobbers so
6888;; many registers that there is then probably a better way.
6889
008c057d 6890(define_expand "movmemqi"
34191dd1 6891 [(match_operand:BLK 0 "general_operand" "")
6892 (match_operand:BLK 1 "general_operand" "")
6893 (match_operand:SI 2 "const_int_operand" "")
6894 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6895 "TARGET_EITHER"
9c08d1fa 6896 "
25f905c2 6897 if (TARGET_32BIT)
cffb2a26 6898 {
008c057d 6899 if (arm_gen_movmemqi (operands))
cffb2a26 6900 DONE;
6901 FAIL;
6902 }
25f905c2 6903 else /* TARGET_THUMB1 */
cffb2a26 6904 {
6905 if ( INTVAL (operands[3]) != 4
6906 || INTVAL (operands[2]) > 48)
6907 FAIL;
6908
008c057d 6909 thumb_expand_movmemqi (operands);
cffb2a26 6910 DONE;
6911 }
6912 "
6913)
6914
2162064c 6915;; Thumb block-move insns
cffb2a26 6916
6917(define_insn "movmem12b"
960f3acf 6918 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6919 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6920 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6921 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6922 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6923 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6924 (set (match_operand:SI 0 "register_operand" "=l")
6925 (plus:SI (match_dup 2) (const_int 12)))
6926 (set (match_operand:SI 1 "register_operand" "=l")
6927 (plus:SI (match_dup 3) (const_int 12)))
6928 (clobber (match_scratch:SI 4 "=&l"))
6929 (clobber (match_scratch:SI 5 "=&l"))
6930 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6931 "TARGET_THUMB1"
cffb2a26 6932 "* return thumb_output_move_mem_multiple (3, operands);"
6933 [(set_attr "length" "4")
215b30b3 6934 ; This isn't entirely accurate... It loads as well, but in terms of
6935 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6936 (set_attr "type" "store3")]
6937)
6938
6939(define_insn "movmem8b"
960f3acf 6940 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6941 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6942 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6943 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6944 (set (match_operand:SI 0 "register_operand" "=l")
6945 (plus:SI (match_dup 2) (const_int 8)))
6946 (set (match_operand:SI 1 "register_operand" "=l")
6947 (plus:SI (match_dup 3) (const_int 8)))
6948 (clobber (match_scratch:SI 4 "=&l"))
6949 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6950 "TARGET_THUMB1"
cffb2a26 6951 "* return thumb_output_move_mem_multiple (2, operands);"
6952 [(set_attr "length" "4")
215b30b3 6953 ; This isn't entirely accurate... It loads as well, but in terms of
6954 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6955 (set_attr "type" "store2")]
6956)
6957
9c08d1fa 6958\f
b11cae9e 6959
341940e8 6960;; Compare & branch insns
8d232dc7 6961;; The range calculations are based as follows:
341940e8 6962;; For forward branches, the address calculation returns the address of
6963;; the next instruction. This is 2 beyond the branch instruction.
6964;; For backward branches, the address calculation returns the address of
6965;; the first instruction in this pattern (cmp). This is 2 before the branch
6966;; instruction for the shortest sequence, and 4 before the branch instruction
6967;; if we have to jump around an unconditional branch.
6968;; To the basic branch range the PC offset must be added (this is +4).
6969;; So for forward branches we have
6970;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6971;; And for backward branches we have
6972;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6973;;
6974;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6975;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6976
aeac46d4 6977(define_expand "cbranchsi4"
6978 [(set (pc) (if_then_else
aa06947a 6979 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6980 [(match_operand:SI 1 "s_register_operand" "")
6981 (match_operand:SI 2 "nonmemory_operand" "")])
6982 (label_ref (match_operand 3 "" ""))
6983 (pc)))]
f9aa4160 6984 "TARGET_EITHER"
aeac46d4 6985 "
74f4459c 6986 if (!TARGET_THUMB1)
6987 {
f9aa4160 6988 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6989 FAIL;
74f4459c 6990 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6991 operands[3]));
6992 DONE;
6993 }
25f905c2 6994 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6995 {
6996 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6997 operands[3], operands[0]));
6998 DONE;
6999 }
25f905c2 7000 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7001 operands[2] = force_reg (SImode, operands[2]);
7002 ")
7003
a8e6c15d 7004;; A pattern to recognize a special situation and optimize for it.
7005;; On the thumb, zero-extension from memory is preferrable to sign-extension
7006;; due to the available addressing modes. Hence, convert a signed comparison
7007;; with zero into an unsigned comparison with 127 if possible.
7008(define_expand "cbranchqi4"
7009 [(set (pc) (if_then_else
7010 (match_operator 0 "lt_ge_comparison_operator"
7011 [(match_operand:QI 1 "memory_operand" "")
7012 (match_operand:QI 2 "const0_operand" "")])
7013 (label_ref (match_operand 3 "" ""))
7014 (pc)))]
7015 "TARGET_THUMB1"
7016{
d0f6c30d 7017 rtx xops[4];
a8e6c15d 7018 xops[1] = gen_reg_rtx (SImode);
7019 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
7020 xops[2] = GEN_INT (127);
7021 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
7022 VOIDmode, xops[1], xops[2]);
7023 xops[3] = operands[3];
7024 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
7025 DONE;
7026})
7027
74f4459c 7028(define_expand "cbranchsf4"
7029 [(set (pc) (if_then_else
aa06947a 7030 (match_operator 0 "expandable_comparison_operator"
74f4459c 7031 [(match_operand:SF 1 "s_register_operand" "")
7032 (match_operand:SF 2 "arm_float_compare_operand" "")])
7033 (label_ref (match_operand 3 "" ""))
7034 (pc)))]
7035 "TARGET_32BIT && TARGET_HARD_FLOAT"
7036 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7037 operands[3])); DONE;"
7038)
7039
7040(define_expand "cbranchdf4"
7041 [(set (pc) (if_then_else
aa06947a 7042 (match_operator 0 "expandable_comparison_operator"
74f4459c 7043 [(match_operand:DF 1 "s_register_operand" "")
7044 (match_operand:DF 2 "arm_float_compare_operand" "")])
7045 (label_ref (match_operand 3 "" ""))
7046 (pc)))]
a50d7267 7047 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7048 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7049 operands[3])); DONE;"
7050)
7051
74f4459c 7052(define_expand "cbranchdi4"
7053 [(set (pc) (if_then_else
aa06947a 7054 (match_operator 0 "expandable_comparison_operator"
a8045a4f 7055 [(match_operand:DI 1 "cmpdi_operand" "")
7056 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7057 (label_ref (match_operand 3 "" ""))
7058 (pc)))]
a8045a4f 7059 "TARGET_32BIT"
7060 "{
a8045a4f 7061 /* We should not have two constants. */
7062 gcc_assert (GET_MODE (operands[1]) == DImode
7063 || GET_MODE (operands[2]) == DImode);
7064
0438d37f 7065 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7066 FAIL;
7067 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7068 operands[3]));
7069 DONE;
7070 }"
74f4459c 7071)
7072
d60047aa 7073(define_insn "cbranchsi4_insn"
aeac46d4 7074 [(set (pc) (if_then_else
7075 (match_operator 0 "arm_comparison_operator"
747b7458 7076 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 7077 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 7078 (label_ref (match_operand 3 "" ""))
7079 (pc)))]
25f905c2 7080 "TARGET_THUMB1"
747b7458 7081{
7082 rtx t = cfun->machine->thumb1_cc_insn;
7083 if (t != NULL_RTX)
d60047aa 7084 {
747b7458 7085 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
7086 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
7087 t = NULL_RTX;
7088 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
7089 {
7090 if (!noov_comparison_operator (operands[0], VOIDmode))
7091 t = NULL_RTX;
7092 }
7093 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 7094 t = NULL_RTX;
7095 }
d60047aa 7096 if (t == NULL_RTX)
747b7458 7097 {
7098 output_asm_insn ("cmp\t%1, %2", operands);
7099 cfun->machine->thumb1_cc_insn = insn;
7100 cfun->machine->thumb1_cc_op0 = operands[1];
7101 cfun->machine->thumb1_cc_op1 = operands[2];
7102 cfun->machine->thumb1_cc_mode = CCmode;
7103 }
7104 else
7105 /* Ensure we emit the right type of condition code on the jump. */
7106 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
7107 CC_REGNUM);
aeac46d4 7108
cffb2a26 7109 switch (get_attr_length (insn))
7110 {
7111 case 4: return \"b%d0\\t%l3\";
7112 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7113 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7114 }
747b7458 7115}
cffb2a26 7116 [(set (attr "far_jump")
7117 (if_then_else
7118 (eq_attr "length" "8")
7119 (const_string "yes")
7120 (const_string "no")))
7121 (set (attr "length")
7122 (if_then_else
7123 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7124 (le (minus (match_dup 3) (pc)) (const_int 256)))
7125 (const_int 4)
7126 (if_then_else
7127 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 7128 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7129 (const_int 6)
7130 (const_int 8))))]
7131)
7132
aeac46d4 7133(define_insn "cbranchsi4_scratch"
7134 [(set (pc) (if_then_else
7135 (match_operator 4 "arm_comparison_operator"
7136 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 7137 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 7138 (label_ref (match_operand 3 "" ""))
7139 (pc)))
7140 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 7141 "TARGET_THUMB1"
aeac46d4 7142 "*
7143 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
7144
7145 switch (get_attr_length (insn))
7146 {
7147 case 4: return \"b%d4\\t%l3\";
7148 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7149 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7150 }
7151 "
7152 [(set (attr "far_jump")
7153 (if_then_else
7154 (eq_attr "length" "8")
7155 (const_string "yes")
7156 (const_string "no")))
7157 (set (attr "length")
7158 (if_then_else
7159 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7160 (le (minus (match_dup 3) (pc)) (const_int 256)))
7161 (const_int 4)
7162 (if_then_else
7163 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7164 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7165 (const_int 6)
7166 (const_int 8))))]
7167)
446a1e96 7168
cffb2a26 7169(define_insn "*negated_cbranchsi4"
7170 [(set (pc)
7171 (if_then_else
aed179ae 7172 (match_operator 0 "equality_operator"
aeac46d4 7173 [(match_operand:SI 1 "s_register_operand" "l")
7174 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
7175 (label_ref (match_operand 3 "" ""))
215b30b3 7176 (pc)))]
25f905c2 7177 "TARGET_THUMB1"
cffb2a26 7178 "*
7179 output_asm_insn (\"cmn\\t%1, %2\", operands);
7180 switch (get_attr_length (insn))
7181 {
7182 case 4: return \"b%d0\\t%l3\";
7183 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7184 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7185 }
7186 "
7187 [(set (attr "far_jump")
7188 (if_then_else
7189 (eq_attr "length" "8")
7190 (const_string "yes")
7191 (const_string "no")))
7192 (set (attr "length")
7193 (if_then_else
7194 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 7195 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 7196 (const_int 4)
7197 (if_then_else
341940e8 7198 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7199 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7200 (const_int 6)
7201 (const_int 8))))]
7202)
7203
58d6528b 7204(define_insn "*tbit_cbranch"
7205 [(set (pc)
7206 (if_then_else
7207 (match_operator 0 "equality_operator"
7208 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7209 (const_int 1)
7210 (match_operand:SI 2 "const_int_operand" "i"))
7211 (const_int 0)])
7212 (label_ref (match_operand 3 "" ""))
7213 (pc)))
7214 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7215 "TARGET_THUMB1"
58d6528b 7216 "*
7217 {
7218 rtx op[3];
7219 op[0] = operands[4];
7220 op[1] = operands[1];
7221 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
7222
86efa74d 7223 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7224 switch (get_attr_length (insn))
7225 {
7226 case 4: return \"b%d0\\t%l3\";
7227 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7228 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7229 }
7230 }"
7231 [(set (attr "far_jump")
7232 (if_then_else
7233 (eq_attr "length" "8")
7234 (const_string "yes")
7235 (const_string "no")))
7236 (set (attr "length")
7237 (if_then_else
7238 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7239 (le (minus (match_dup 3) (pc)) (const_int 256)))
7240 (const_int 4)
7241 (if_then_else
7242 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7243 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7244 (const_int 6)
7245 (const_int 8))))]
7246)
7247
7248(define_insn "*tlobits_cbranch"
7249 [(set (pc)
7250 (if_then_else
7251 (match_operator 0 "equality_operator"
7252 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7253 (match_operand:SI 2 "const_int_operand" "i")
7254 (const_int 0))
7255 (const_int 0)])
7256 (label_ref (match_operand 3 "" ""))
7257 (pc)))
7258 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7259 "TARGET_THUMB1"
86efa74d 7260 "*
7261 {
7262 rtx op[3];
7263 op[0] = operands[4];
7264 op[1] = operands[1];
7265 op[2] = GEN_INT (32 - INTVAL (operands[2]));
7266
58d6528b 7267 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7268 switch (get_attr_length (insn))
7269 {
7270 case 4: return \"b%d0\\t%l3\";
7271 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7272 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7273 }
7274 }"
7275 [(set (attr "far_jump")
7276 (if_then_else
7277 (eq_attr "length" "8")
7278 (const_string "yes")
7279 (const_string "no")))
7280 (set (attr "length")
7281 (if_then_else
7282 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7283 (le (minus (match_dup 3) (pc)) (const_int 256)))
7284 (const_int 4)
7285 (if_then_else
7286 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7287 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7288 (const_int 6)
7289 (const_int 8))))]
7290)
747b7458 7291
aeac46d4 7292(define_insn "*tstsi3_cbranch"
58d6528b 7293 [(set (pc)
7294 (if_then_else
aeac46d4 7295 (match_operator 3 "equality_operator"
7296 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7297 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 7298 (const_int 0)])
aeac46d4 7299 (label_ref (match_operand 2 "" ""))
7300 (pc)))]
25f905c2 7301 "TARGET_THUMB1"
58d6528b 7302 "*
7303 {
aeac46d4 7304 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 7305 switch (get_attr_length (insn))
7306 {
aeac46d4 7307 case 4: return \"b%d3\\t%l2\";
7308 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7309 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 7310 }
7311 }"
7312 [(set (attr "far_jump")
7313 (if_then_else
7314 (eq_attr "length" "8")
7315 (const_string "yes")
7316 (const_string "no")))
7317 (set (attr "length")
7318 (if_then_else
aeac46d4 7319 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7320 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 7321 (const_int 4)
7322 (if_then_else
aeac46d4 7323 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7324 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 7325 (const_int 6)
7326 (const_int 8))))]
7327)
7328
203c488f 7329(define_insn "*cbranchne_decr1"
7330 [(set (pc)
7331 (if_then_else (match_operator 3 "equality_operator"
7332 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7333 (const_int 0)])
7334 (label_ref (match_operand 4 "" ""))
7335 (pc)))
aeac46d4 7336 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7337 (plus:SI (match_dup 2) (const_int -1)))
7338 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7339 "TARGET_THUMB1"
203c488f 7340 "*
7341 {
7342 rtx cond[2];
7343 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7344 ? GEU : LTU),
58d6528b 7345 VOIDmode, operands[2], const1_rtx);
203c488f 7346 cond[1] = operands[4];
7347
7348 if (which_alternative == 0)
7349 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7350 else if (which_alternative == 1)
7351 {
7352 /* We must provide an alternative for a hi reg because reload
7353 cannot handle output reloads on a jump instruction, but we
7354 can't subtract into that. Fortunately a mov from lo to hi
7355 does not clobber the condition codes. */
7356 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7357 output_asm_insn (\"mov\\t%0, %1\", operands);
7358 }
7359 else
7360 {
7361 /* Similarly, but the target is memory. */
7362 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7363 output_asm_insn (\"str\\t%1, %0\", operands);
7364 }
7365
7366 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7367 {
7368 case 4:
8aea555f 7369 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7370 return \"\";
7371 case 6:
8aea555f 7372 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7373 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7374 default:
8aea555f 7375 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7376 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7377 }
7378 }
7379 "
7380 [(set (attr "far_jump")
7381 (if_then_else
7382 (ior (and (eq (symbol_ref ("which_alternative"))
7383 (const_int 0))
7384 (eq_attr "length" "8"))
7385 (eq_attr "length" "10"))
7386 (const_string "yes")
7387 (const_string "no")))
7388 (set_attr_alternative "length"
7389 [
7390 ;; Alternative 0
7391 (if_then_else
7392 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7393 (le (minus (match_dup 4) (pc)) (const_int 256)))
7394 (const_int 4)
7395 (if_then_else
7396 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7397 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7398 (const_int 6)
7399 (const_int 8)))
7400 ;; Alternative 1
7401 (if_then_else
7402 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7403 (le (minus (match_dup 4) (pc)) (const_int 256)))
7404 (const_int 6)
7405 (if_then_else
7406 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7407 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7408 (const_int 8)
7409 (const_int 10)))
7410 ;; Alternative 2
7411 (if_then_else
7412 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7413 (le (minus (match_dup 4) (pc)) (const_int 256)))
7414 (const_int 6)
7415 (if_then_else
7416 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7417 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7418 (const_int 8)
7419 (const_int 10)))
7420 ;; Alternative 3
7421 (if_then_else
7422 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7423 (le (minus (match_dup 4) (pc)) (const_int 256)))
7424 (const_int 6)
7425 (if_then_else
7426 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7427 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7428 (const_int 8)
7429 (const_int 10)))])]
7430)
cffb2a26 7431
58d6528b 7432(define_insn "*addsi3_cbranch"
7433 [(set (pc)
7434 (if_then_else
b0694be0 7435 (match_operator 4 "arm_comparison_operator"
58d6528b 7436 [(plus:SI
e54011cb 7437 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7438 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 7439 (const_int 0)])
7440 (label_ref (match_operand 5 "" ""))
7441 (pc)))
aeac46d4 7442 (set
7443 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7444 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 7445 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 7446 "TARGET_THUMB1
58d6528b 7447 && (GET_CODE (operands[4]) == EQ
7448 || GET_CODE (operands[4]) == NE
7449 || GET_CODE (operands[4]) == GE
7450 || GET_CODE (operands[4]) == LT)"
7451 "*
7452 {
7453 rtx cond[3];
7454
956a6170 7455 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 7456 cond[1] = operands[2];
7457 cond[2] = operands[3];
7458
0438d37f 7459 if (CONST_INT_P (cond[2]) && INTVAL (cond[2]) < 0)
58d6528b 7460 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7461 else
7462 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7463
956a6170 7464 if (which_alternative >= 2
58d6528b 7465 && which_alternative < 4)
7466 output_asm_insn (\"mov\\t%0, %1\", operands);
7467 else if (which_alternative >= 4)
7468 output_asm_insn (\"str\\t%1, %0\", operands);
7469
d0f6c30d 7470 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 7471 {
7472 case 4:
7473 return \"b%d4\\t%l5\";
7474 case 6:
7475 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7476 default:
7477 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7478 }
7479 }
7480 "
7481 [(set (attr "far_jump")
7482 (if_then_else
7483 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7484 (const_int 2))
58d6528b 7485 (eq_attr "length" "8"))
7486 (eq_attr "length" "10"))
7487 (const_string "yes")
7488 (const_string "no")))
7489 (set (attr "length")
7490 (if_then_else
7491 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7492 (const_int 2))
58d6528b 7493 (if_then_else
7494 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7495 (le (minus (match_dup 5) (pc)) (const_int 256)))
7496 (const_int 4)
7497 (if_then_else
7498 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7499 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7500 (const_int 6)
7501 (const_int 8)))
7502 (if_then_else
7503 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7504 (le (minus (match_dup 5) (pc)) (const_int 256)))
7505 (const_int 6)
7506 (if_then_else
7507 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7508 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7509 (const_int 8)
7510 (const_int 10)))))]
7511)
7512
7513(define_insn "*addsi3_cbranch_scratch"
7514 [(set (pc)
7515 (if_then_else
b0694be0 7516 (match_operator 3 "arm_comparison_operator"
58d6528b 7517 [(plus:SI
7518 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7519 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7520 (const_int 0)])
7521 (label_ref (match_operand 4 "" ""))
7522 (pc)))
7523 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7524 "TARGET_THUMB1
58d6528b 7525 && (GET_CODE (operands[3]) == EQ
7526 || GET_CODE (operands[3]) == NE
7527 || GET_CODE (operands[3]) == GE
7528 || GET_CODE (operands[3]) == LT)"
7529 "*
7530 {
7531 switch (which_alternative)
7532 {
7533 case 0:
7534 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7535 break;
7536 case 1:
7537 output_asm_insn (\"cmn\t%1, %2\", operands);
7538 break;
0f5e9701 7539 case 2:
3a445a04 7540 if (INTVAL (operands[2]) < 0)
7541 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7542 else
7543 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7544 break;
0f5e9701 7545 case 3:
3a445a04 7546 if (INTVAL (operands[2]) < 0)
7547 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7548 else
7549 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7550 break;
7551 }
7552
7553 switch (get_attr_length (insn))
7554 {
7555 case 4:
7556 return \"b%d3\\t%l4\";
7557 case 6:
7558 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7559 default:
7560 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7561 }
7562 }
7563 "
7564 [(set (attr "far_jump")
7565 (if_then_else
7566 (eq_attr "length" "8")
7567 (const_string "yes")
7568 (const_string "no")))
7569 (set (attr "length")
7570 (if_then_else
7571 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7572 (le (minus (match_dup 4) (pc)) (const_int 256)))
7573 (const_int 4)
7574 (if_then_else
7575 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7576 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7577 (const_int 6)
7578 (const_int 8))))]
7579)
7580
58d6528b 7581
9c08d1fa 7582;; Comparison and test insns
7583
cffb2a26 7584(define_insn "*arm_cmpsi_insn"
bd5b4116 7585 [(set (reg:CC CC_REGNUM)
a6864a24 7586 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7587 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
25f905c2 7588 "TARGET_32BIT"
5565501b 7589 "@
a6864a24 7590 cmp%?\\t%0, %1
7591 cmp%?\\t%0, %1
aea4c774 7592 cmp%?\\t%0, %1
7593 cmn%?\\t%0, #%n1"
a6864a24 7594 [(set_attr "conds" "set")
7595 (set_attr "arch" "t2,t2,any,any")
596e5e8f 7596 (set_attr "length" "2,2,4,4")
7597 (set_attr "predicable" "yes")]
cffb2a26 7598)
b11cae9e 7599
d5d4dc8d 7600(define_insn "*cmpsi_shiftsi"
bd5b4116 7601 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7602 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7603 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7604 [(match_operand:SI 1 "s_register_operand" "r,r")
7605 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7606 "TARGET_32BIT"
aea4c774 7607 "cmp%?\\t%0, %1%S3"
344495ea 7608 [(set_attr "conds" "set")
331beb1a 7609 (set_attr "shift" "1")
d5d4dc8d 7610 (set_attr "arch" "32,a")
7611 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7612
d5d4dc8d 7613(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7614 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7615 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7616 [(match_operand:SI 1 "s_register_operand" "r,r")
7617 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7618 (match_operand:SI 0 "s_register_operand" "r,r")))]
7619 "TARGET_32BIT"
aea4c774 7620 "cmp%?\\t%0, %1%S3"
344495ea 7621 [(set_attr "conds" "set")
331beb1a 7622 (set_attr "shift" "1")
d5d4dc8d 7623 (set_attr "arch" "32,a")
7624 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7625
25f905c2 7626(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7627 [(set (reg:CC_Z CC_REGNUM)
7628 (compare:CC_Z
7629 (neg:SI (match_operator:SI 1 "shift_operator"
7630 [(match_operand:SI 2 "s_register_operand" "r")
7631 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7632 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7633 "TARGET_ARM"
aed179ae 7634 "cmn%?\\t%0, %2%S1"
344495ea 7635 [(set_attr "conds" "set")
aed179ae 7636 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7637 (const_string "alu_shift")
596e5e8f 7638 (const_string "alu_shift_reg")))
7639 (set_attr "predicable" "yes")]
0d66636f 7640)
b11cae9e 7641
a8045a4f 7642;; DImode comparisons. The generic code generates branches that
7643;; if-conversion can not reduce to a conditional compare, so we do
7644;; that directly.
7645
7646(define_insn "*arm_cmpdi_insn"
7647 [(set (reg:CC_NCV CC_REGNUM)
7648 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7649 (match_operand:DI 1 "arm_di_operand" "rDi")))
7650 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7651 "TARGET_32BIT"
a8045a4f 7652 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7653 [(set_attr "conds" "set")
7654 (set_attr "length" "8")]
7655)
7656
7657(define_insn "*arm_cmpdi_unsigned"
7658 [(set (reg:CC_CZ CC_REGNUM)
7659 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7660 (match_operand:DI 1 "arm_di_operand" "rDi")))]
48a98053 7661 "TARGET_32BIT"
7662 "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
a8045a4f 7663 [(set_attr "conds" "set")
7664 (set_attr "length" "8")]
7665)
7666
7667(define_insn "*arm_cmpdi_zero"
7668 [(set (reg:CC_Z CC_REGNUM)
7669 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7670 (const_int 0)))
7671 (clobber (match_scratch:SI 1 "=r"))]
7672 "TARGET_32BIT"
7673 "orr%.\\t%1, %Q0, %R0"
7674 [(set_attr "conds" "set")]
7675)
7676
7677(define_insn "*thumb_cmpdi_zero"
7678 [(set (reg:CC_Z CC_REGNUM)
7679 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7680 (const_int 0)))
7681 (clobber (match_scratch:SI 1 "=l"))]
7682 "TARGET_THUMB1"
7683 "orr\\t%1, %Q0, %R0"
7684 [(set_attr "conds" "set")
7685 (set_attr "length" "2")]
7686)
7687
9c08d1fa 7688; This insn allows redundant compares to be removed by cse, nothing should
7689; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7690; is deleted later on. The match_dup will match the mode here, so that
7691; mode changes of the condition codes aren't lost by this even though we don't
7692; specify what they are.
7693
8a18b90c 7694(define_insn "*deleted_compare"
9c08d1fa 7695 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7696 "TARGET_32BIT"
40dbec34 7697 "\\t%@ deleted compare"
cffb2a26 7698 [(set_attr "conds" "set")
7699 (set_attr "length" "0")]
7700)
9c08d1fa 7701
7702\f
7703;; Conditional branch insns
7704
74f4459c 7705(define_expand "cbranch_cc"
9c08d1fa 7706 [(set (pc)
74f4459c 7707 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7708 (match_operand 2 "" "")])
7709 (label_ref (match_operand 3 "" ""))
9c08d1fa 7710 (pc)))]
25f905c2 7711 "TARGET_32BIT"
74f4459c 7712 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7713 operands[1], operands[2], NULL_RTX);
74f4459c 7714 operands[2] = const0_rtx;"
8fa3ba89 7715)
7716
7717;;
7718;; Patterns to match conditional branch insns.
7719;;
7720
ffcc986d 7721(define_insn "arm_cond_branch"
9c08d1fa 7722 [(set (pc)
8fa3ba89 7723 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7724 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7725 (label_ref (match_operand 0 "" ""))
7726 (pc)))]
25f905c2 7727 "TARGET_32BIT"
d75350ce 7728 "*
9c08d1fa 7729 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7730 {
7731 arm_ccfsm_state += 2;
7732 return \"\";
7733 }
e2348bcb 7734 return \"b%d1\\t%l0\";
cffb2a26 7735 "
a2cd141b 7736 [(set_attr "conds" "use")
a6864a24 7737 (set_attr "type" "branch")
7738 (set (attr "length")
7739 (if_then_else
0bf497f5 7740 (and (match_test "TARGET_THUMB2")
a6864a24 7741 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7742 (le (minus (match_dup 0) (pc)) (const_int 256))))
7743 (const_int 2)
7744 (const_int 4)))]
cffb2a26 7745)
d75350ce 7746
cffb2a26 7747(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7748 [(set (pc)
8fa3ba89 7749 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7750 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7751 (pc)
7752 (label_ref (match_operand 0 "" ""))))]
25f905c2 7753 "TARGET_32BIT"
d75350ce 7754 "*
9c08d1fa 7755 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7756 {
7757 arm_ccfsm_state += 2;
7758 return \"\";
7759 }
e2348bcb 7760 return \"b%D1\\t%l0\";
cffb2a26 7761 "
a2cd141b 7762 [(set_attr "conds" "use")
a6864a24 7763 (set_attr "type" "branch")
7764 (set (attr "length")
7765 (if_then_else
0bf497f5 7766 (and (match_test "TARGET_THUMB2")
a6864a24 7767 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7768 (le (minus (match_dup 0) (pc)) (const_int 256))))
7769 (const_int 2)
7770 (const_int 4)))]
cffb2a26 7771)
7772
b11cae9e 7773\f
9c08d1fa 7774
7775; scc insns
7776
74f4459c 7777(define_expand "cstore_cc"
7db9af5d 7778 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7779 (match_operator:SI 1 "" [(match_operand 2 "" "")
7780 (match_operand 3 "" "")]))]
25f905c2 7781 "TARGET_32BIT"
74f4459c 7782 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7783 operands[2], operands[3], NULL_RTX);
74f4459c 7784 operands[3] = const0_rtx;"
8fa3ba89 7785)
7786
f7fbdd4a 7787(define_insn "*mov_scc"
9c08d1fa 7788 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7789 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7790 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7791 "TARGET_ARM"
4d61e570 7792 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7793 [(set_attr "conds" "use")
d2a518d1 7794 (set_attr "insn" "mov")
cffb2a26 7795 (set_attr "length" "8")]
7796)
9c08d1fa 7797
f7fbdd4a 7798(define_insn "*mov_negscc"
9c08d1fa 7799 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7800 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7801 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7802 "TARGET_ARM"
4d61e570 7803 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7804 [(set_attr "conds" "use")
d2a518d1 7805 (set_attr "insn" "mov")
cffb2a26 7806 (set_attr "length" "8")]
7807)
9c08d1fa 7808
f7fbdd4a 7809(define_insn "*mov_notscc"
9c08d1fa 7810 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7811 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7812 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7813 "TARGET_ARM"
7d0a3bab 7814 "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7815 [(set_attr "conds" "use")
d2a518d1 7816 (set_attr "insn" "mov")
cffb2a26 7817 (set_attr "length" "8")]
7818)
9c08d1fa 7819
595d88b5 7820(define_expand "cstoresi4"
7821 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7822 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7823 [(match_operand:SI 2 "s_register_operand" "")
7824 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7825 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7826 "{
7827 rtx op3, scratch, scratch2;
7828
74f4459c 7829 if (!TARGET_THUMB1)
7830 {
7831 if (!arm_add_operand (operands[3], SImode))
7832 operands[3] = force_reg (SImode, operands[3]);
7833 emit_insn (gen_cstore_cc (operands[0], operands[1],
7834 operands[2], operands[3]));
7835 DONE;
7836 }
7837
595d88b5 7838 if (operands[3] == const0_rtx)
7839 {
7840 switch (GET_CODE (operands[1]))
7841 {
7842 case EQ:
25f905c2 7843 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7844 break;
7845
7846 case NE:
25f905c2 7847 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7848 break;
7849
7850 case LE:
7851 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7852 NULL_RTX, 0, OPTAB_WIDEN);
7853 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7854 NULL_RTX, 0, OPTAB_WIDEN);
7855 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7856 operands[0], 1, OPTAB_WIDEN);
7857 break;
7858
7859 case GE:
7860 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7861 NULL_RTX, 1);
7862 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7863 NULL_RTX, 1, OPTAB_WIDEN);
7864 break;
7865
7866 case GT:
7867 scratch = expand_binop (SImode, ashr_optab, operands[2],
7868 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7869 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7870 NULL_RTX, 0, OPTAB_WIDEN);
7871 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7872 0, OPTAB_WIDEN);
7873 break;
7874
7875 /* LT is handled by generic code. No need for unsigned with 0. */
7876 default:
7877 FAIL;
7878 }
7879 DONE;
7880 }
7881
7882 switch (GET_CODE (operands[1]))
7883 {
7884 case EQ:
7885 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7886 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7887 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7888 break;
7889
7890 case NE:
7891 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7892 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7893 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7894 break;
7895
7896 case LE:
7897 op3 = force_reg (SImode, operands[3]);
7898
7899 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7900 NULL_RTX, 1, OPTAB_WIDEN);
7901 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7902 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7903 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7904 op3, operands[2]));
7905 break;
7906
7907 case GE:
7908 op3 = operands[3];
25f905c2 7909 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7910 op3 = force_reg (SImode, op3);
7911 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7912 NULL_RTX, 0, OPTAB_WIDEN);
7913 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7914 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7915 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7916 operands[2], op3));
7917 break;
7918
7919 case LEU:
7920 op3 = force_reg (SImode, operands[3]);
7921 scratch = force_reg (SImode, const0_rtx);
25f905c2 7922 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7923 op3, operands[2]));
7924 break;
7925
7926 case GEU:
7927 op3 = operands[3];
25f905c2 7928 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7929 op3 = force_reg (SImode, op3);
7930 scratch = force_reg (SImode, const0_rtx);
25f905c2 7931 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7932 operands[2], op3));
7933 break;
7934
7935 case LTU:
7936 op3 = operands[3];
25f905c2 7937 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7938 op3 = force_reg (SImode, op3);
7939 scratch = gen_reg_rtx (SImode);
408b7ae5 7940 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7941 break;
7942
7943 case GTU:
7944 op3 = force_reg (SImode, operands[3]);
7945 scratch = gen_reg_rtx (SImode);
408b7ae5 7946 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7947 break;
7948
7949 /* No good sequences for GT, LT. */
7950 default:
7951 FAIL;
7952 }
7953 DONE;
7954}")
7955
74f4459c 7956(define_expand "cstoresf4"
7957 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7958 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7959 [(match_operand:SF 2 "s_register_operand" "")
7960 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7961 "TARGET_32BIT && TARGET_HARD_FLOAT"
7962 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7963 operands[2], operands[3])); DONE;"
7964)
7965
7966(define_expand "cstoredf4"
7967 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7968 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7969 [(match_operand:DF 2 "s_register_operand" "")
7970 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7971 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7972 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7973 operands[2], operands[3])); DONE;"
7974)
7975
74f4459c 7976(define_expand "cstoredi4"
7977 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7978 (match_operator:SI 1 "expandable_comparison_operator"
a8045a4f 7979 [(match_operand:DI 2 "cmpdi_operand" "")
7980 (match_operand:DI 3 "cmpdi_operand" "")]))]
7981 "TARGET_32BIT"
7982 "{
a8045a4f 7983 /* We should not have two constants. */
7984 gcc_assert (GET_MODE (operands[2]) == DImode
7985 || GET_MODE (operands[3]) == DImode);
7986
f9aa4160 7987 if (!arm_validize_comparison (&operands[1],
7988 &operands[2],
7989 &operands[3]))
7990 FAIL;
7991 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7992 operands[3]));
7993 DONE;
7994 }"
74f4459c 7995)
7996
25f905c2 7997(define_expand "cstoresi_eq0_thumb1"
595d88b5 7998 [(parallel
7999 [(set (match_operand:SI 0 "s_register_operand" "")
8000 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8001 (const_int 0)))
8002 (clobber (match_dup:SI 2))])]
25f905c2 8003 "TARGET_THUMB1"
595d88b5 8004 "operands[2] = gen_reg_rtx (SImode);"
8005)
8006
25f905c2 8007(define_expand "cstoresi_ne0_thumb1"
595d88b5 8008 [(parallel
8009 [(set (match_operand:SI 0 "s_register_operand" "")
8010 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8011 (const_int 0)))
8012 (clobber (match_dup:SI 2))])]
25f905c2 8013 "TARGET_THUMB1"
595d88b5 8014 "operands[2] = gen_reg_rtx (SImode);"
8015)
8016
25f905c2 8017(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 8018 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8019 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8020 (const_int 0)))
8021 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 8022 "TARGET_THUMB1"
595d88b5 8023 "@
8024 neg\\t%0, %1\;adc\\t%0, %0, %1
8025 neg\\t%2, %1\;adc\\t%0, %1, %2"
8026 [(set_attr "length" "4")]
8027)
8028
25f905c2 8029(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 8030 [(set (match_operand:SI 0 "s_register_operand" "=l")
8031 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8032 (const_int 0)))
8033 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8034 "TARGET_THUMB1"
595d88b5 8035 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8036 [(set_attr "length" "4")]
8037)
8038
408b7ae5 8039;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 8040(define_insn "cstoresi_nltu_thumb1"
595d88b5 8041 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8042 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8043 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8044 "TARGET_THUMB1"
595d88b5 8045 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8046 [(set_attr "length" "4")]
8047)
8048
408b7ae5 8049(define_insn_and_split "cstoresi_ltu_thumb1"
8050 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8051 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8052 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8053 "TARGET_THUMB1"
8054 "#"
8055 "TARGET_THUMB1"
8056 [(set (match_dup 3)
8057 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8058 (set (match_dup 0) (neg:SI (match_dup 3)))]
8059 "operands[3] = gen_reg_rtx (SImode);"
8060 [(set_attr "length" "4")]
8061)
8062
595d88b5 8063;; Used as part of the expansion of thumb les sequence.
25f905c2 8064(define_insn "thumb1_addsi3_addgeu"
595d88b5 8065 [(set (match_operand:SI 0 "s_register_operand" "=l")
8066 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8067 (match_operand:SI 2 "s_register_operand" "l"))
8068 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8069 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8070 "TARGET_THUMB1"
595d88b5 8071 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8072 [(set_attr "length" "4")]
8073)
8074
9c08d1fa 8075\f
39b5e676 8076;; Conditional move insns
8077
8078(define_expand "movsicc"
8a18b90c 8079 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8080 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 8081 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8082 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8083 "TARGET_32BIT"
39b5e676 8084 "
215b30b3 8085 {
f9aa4160 8086 enum rtx_code code;
278b301d 8087 rtx ccreg;
8088
f9aa4160 8089 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8090 &XEXP (operands[1], 1)))
278b301d 8091 FAIL;
f9aa4160 8092
8093 code = GET_CODE (operands[1]);
74f4459c 8094 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8095 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8096 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8097 }"
8098)
39b5e676 8099
8100(define_expand "movsfcc"
8a18b90c 8101 [(set (match_operand:SF 0 "s_register_operand" "")
aa06947a 8102 (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8103 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 8104 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 8105 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8106 "
215b30b3 8107 {
8108 enum rtx_code code = GET_CODE (operands[1]);
8109 rtx ccreg;
f082f1c4 8110
f9aa4160 8111 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8112 &XEXP (operands[1], 1)))
8113 FAIL;
39b5e676 8114
f9aa4160 8115 code = GET_CODE (operands[1]);
74f4459c 8116 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8117 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8118 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8119 }"
8120)
39b5e676 8121
8122(define_expand "movdfcc"
8a18b90c 8123 [(set (match_operand:DF 0 "s_register_operand" "")
aa06947a 8124 (if_then_else:DF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8125 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 8126 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 8127 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 8128 "
215b30b3 8129 {
8130 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8131 rtx ccreg;
39b5e676 8132
f9aa4160 8133 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8134 &XEXP (operands[1], 1)))
8135 FAIL;
8136 code = GET_CODE (operands[1]);
74f4459c 8137 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8138 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8139 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8140 }"
8141)
39b5e676 8142
8143(define_insn "*movsicc_insn"
f082f1c4 8144 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8145 (if_then_else:SI
8fa3ba89 8146 (match_operator 3 "arm_comparison_operator"
8a18b90c 8147 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8148 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8149 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8150 "TARGET_ARM"
39b5e676 8151 "@
8a18b90c 8152 mov%D3\\t%0, %2
8153 mvn%D3\\t%0, #%B2
f082f1c4 8154 mov%d3\\t%0, %1
8155 mvn%d3\\t%0, #%B1
8a18b90c 8156 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8157 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8158 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8159 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8160 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8161 (set_attr "conds" "use")
8162 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 8163)
39b5e676 8164
39b5e676 8165(define_insn "*movsfcc_soft_insn"
f082f1c4 8166 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8167 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8168 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8169 (match_operand:SF 1 "s_register_operand" "0,r")
8170 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8171 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8172 "@
8173 mov%D3\\t%0, %2
8174 mov%d3\\t%0, %1"
d2a518d1 8175 [(set_attr "conds" "use")
8176 (set_attr "insn" "mov")]
8fa3ba89 8177)
39b5e676 8178
39b5e676 8179\f
9c08d1fa 8180;; Jump and linkage insns
8181
cffb2a26 8182(define_expand "jump"
9c08d1fa 8183 [(set (pc)
8184 (label_ref (match_operand 0 "" "")))]
cffb2a26 8185 "TARGET_EITHER"
9c08d1fa 8186 ""
cffb2a26 8187)
8188
8189(define_insn "*arm_jump"
8190 [(set (pc)
8191 (label_ref (match_operand 0 "" "")))]
25f905c2 8192 "TARGET_32BIT"
9c08d1fa 8193 "*
0d66636f 8194 {
8195 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8196 {
8197 arm_ccfsm_state += 2;
8198 return \"\";
8199 }
8200 return \"b%?\\t%l0\";
8201 }
8202 "
a6864a24 8203 [(set_attr "predicable" "yes")
8204 (set (attr "length")
8205 (if_then_else
0bf497f5 8206 (and (match_test "TARGET_THUMB2")
a6864a24 8207 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8208 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8209 (const_int 2)
8210 (const_int 4)))]
0d66636f 8211)
9c08d1fa 8212
cffb2a26 8213(define_insn "*thumb_jump"
8214 [(set (pc)
8215 (label_ref (match_operand 0 "" "")))]
25f905c2 8216 "TARGET_THUMB1"
cffb2a26 8217 "*
8218 if (get_attr_length (insn) == 2)
8219 return \"b\\t%l0\";
8220 return \"bl\\t%l0\\t%@ far jump\";
8221 "
8222 [(set (attr "far_jump")
8223 (if_then_else
8224 (eq_attr "length" "4")
8225 (const_string "yes")
8226 (const_string "no")))
8227 (set (attr "length")
8228 (if_then_else
911ed8af 8229 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8230 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8231 (const_int 2)
8232 (const_int 4)))]
8233)
8234
d3373b54 8235(define_expand "call"
8236 [(parallel [(call (match_operand 0 "memory_operand" "")
8237 (match_operand 1 "general_operand" ""))
cffb2a26 8238 (use (match_operand 2 "" ""))
bd5b4116 8239 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8240 "TARGET_EITHER"
6c4c2133 8241 "
8242 {
bac7fc85 8243 rtx callee, pat;
bbe777ea 8244
bbe777ea 8245 /* In an untyped call, we can get NULL for operand 2. */
8246 if (operands[2] == NULL_RTX)
8247 operands[2] = const0_rtx;
8248
de55252a 8249 /* Decide if we should generate indirect calls by loading the
85c36fd1 8250 32-bit address of the callee into a register before performing the
de55252a 8251 branch and link. */
8252 callee = XEXP (operands[0], 0);
8253 if (GET_CODE (callee) == SYMBOL_REF
8254 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8255 : !REG_P (callee))
bbe777ea 8256 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8257
8258 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8259 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8260 DONE;
6c4c2133 8261 }"
8262)
d3373b54 8263
bac7fc85 8264(define_expand "call_internal"
8265 [(parallel [(call (match_operand 0 "memory_operand" "")
8266 (match_operand 1 "general_operand" ""))
8267 (use (match_operand 2 "" ""))
8268 (clobber (reg:SI LR_REGNUM))])])
8269
f1039640 8270(define_insn "*call_reg_armv5"
d3373b54 8271 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8272 (match_operand 1 "" ""))
8273 (use (match_operand 2 "" ""))
bd5b4116 8274 (clobber (reg:SI LR_REGNUM))]
f1039640 8275 "TARGET_ARM && arm_arch5"
8276 "blx%?\\t%0"
8277 [(set_attr "type" "call")]
8278)
8279
8280(define_insn "*call_reg_arm"
8281 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8282 (match_operand 1 "" ""))
8283 (use (match_operand 2 "" ""))
8284 (clobber (reg:SI LR_REGNUM))]
8285 "TARGET_ARM && !arm_arch5"
9c08d1fa 8286 "*
5565501b 8287 return output_call (operands);
cffb2a26 8288 "
8289 ;; length is worst case, normally it is only two
8290 [(set_attr "length" "12")
8291 (set_attr "type" "call")]
8292)
9c08d1fa 8293
89504fc1 8294
8295;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8296;; considered a function call by the branch predictor of some cores (PR40887).
8297;; Falls back to blx rN (*call_reg_armv5).
8298
f7fbdd4a 8299(define_insn "*call_mem"
a3c63a9d 8300 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8301 (match_operand 1 "" ""))
8302 (use (match_operand 2 "" ""))
bd5b4116 8303 (clobber (reg:SI LR_REGNUM))]
89504fc1 8304 "TARGET_ARM && !arm_arch5"
9c08d1fa 8305 "*
5565501b 8306 return output_call_mem (operands);
cffb2a26 8307 "
8308 [(set_attr "length" "12")
8309 (set_attr "type" "call")]
8310)
8311
25f905c2 8312(define_insn "*call_reg_thumb1_v5"
cffb2a26 8313 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8314 (match_operand 1 "" ""))
8315 (use (match_operand 2 "" ""))
bd5b4116 8316 (clobber (reg:SI LR_REGNUM))]
25f905c2 8317 "TARGET_THUMB1 && arm_arch5"
f1039640 8318 "blx\\t%0"
8319 [(set_attr "length" "2")
8320 (set_attr "type" "call")]
cffb2a26 8321)
8322
25f905c2 8323(define_insn "*call_reg_thumb1"
f1039640 8324 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8325 (match_operand 1 "" ""))
8326 (use (match_operand 2 "" ""))
bd5b4116 8327 (clobber (reg:SI LR_REGNUM))]
25f905c2 8328 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8329 "*
8330 {
150502c9 8331 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8332 return thumb_call_via_reg (operands[0]);
150502c9 8333 else if (operands[1] == const0_rtx)
f1039640 8334 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8335 else if (frame_pointer_needed)
8336 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8337 else
150502c9 8338 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8339 }"
8340 [(set_attr "type" "call")]
8341)
9c08d1fa 8342
d3373b54 8343(define_expand "call_value"
e0698af7 8344 [(parallel [(set (match_operand 0 "" "")
8345 (call (match_operand 1 "memory_operand" "")
8346 (match_operand 2 "general_operand" "")))
cffb2a26 8347 (use (match_operand 3 "" ""))
bd5b4116 8348 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8349 "TARGET_EITHER"
6c4c2133 8350 "
8351 {
bac7fc85 8352 rtx pat, callee;
bbe777ea 8353
8354 /* In an untyped call, we can get NULL for operand 2. */
8355 if (operands[3] == 0)
8356 operands[3] = const0_rtx;
8357
de55252a 8358 /* Decide if we should generate indirect calls by loading the
8359 32-bit address of the callee into a register before performing the
8360 branch and link. */
8361 callee = XEXP (operands[1], 0);
8362 if (GET_CODE (callee) == SYMBOL_REF
8363 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8364 : !REG_P (callee))
78fe751b 8365 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8366
8367 pat = gen_call_value_internal (operands[0], operands[1],
8368 operands[2], operands[3]);
8369 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8370 DONE;
6c4c2133 8371 }"
8372)
d3373b54 8373
bac7fc85 8374(define_expand "call_value_internal"
8375 [(parallel [(set (match_operand 0 "" "")
8376 (call (match_operand 1 "memory_operand" "")
8377 (match_operand 2 "general_operand" "")))
8378 (use (match_operand 3 "" ""))
8379 (clobber (reg:SI LR_REGNUM))])])
8380
f1039640 8381(define_insn "*call_value_reg_armv5"
27ed6835 8382 [(set (match_operand 0 "" "")
755eb2b4 8383 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8384 (match_operand 2 "" "")))
bbe777ea 8385 (use (match_operand 3 "" ""))
bd5b4116 8386 (clobber (reg:SI LR_REGNUM))]
f1039640 8387 "TARGET_ARM && arm_arch5"
8388 "blx%?\\t%1"
8389 [(set_attr "type" "call")]
8390)
8391
8392(define_insn "*call_value_reg_arm"
8393 [(set (match_operand 0 "" "")
8394 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8395 (match_operand 2 "" "")))
8396 (use (match_operand 3 "" ""))
8397 (clobber (reg:SI LR_REGNUM))]
8398 "TARGET_ARM && !arm_arch5"
9c08d1fa 8399 "*
215b30b3 8400 return output_call (&operands[1]);
cffb2a26 8401 "
8402 [(set_attr "length" "12")
8403 (set_attr "type" "call")]
8404)
9c08d1fa 8405
89504fc1 8406;; Note: see *call_mem
8407
f7fbdd4a 8408(define_insn "*call_value_mem"
27ed6835 8409 [(set (match_operand 0 "" "")
a3c63a9d 8410 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8411 (match_operand 2 "" "")))
bbe777ea 8412 (use (match_operand 3 "" ""))
bd5b4116 8413 (clobber (reg:SI LR_REGNUM))]
89504fc1 8414 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8415 "*
215b30b3 8416 return output_call_mem (&operands[1]);
cffb2a26 8417 "
8418 [(set_attr "length" "12")
8419 (set_attr "type" "call")]
8420)
9c08d1fa 8421
25f905c2 8422(define_insn "*call_value_reg_thumb1_v5"
f1039640 8423 [(set (match_operand 0 "" "")
8424 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8425 (match_operand 2 "" "")))
8426 (use (match_operand 3 "" ""))
8427 (clobber (reg:SI LR_REGNUM))]
25f905c2 8428 "TARGET_THUMB1 && arm_arch5"
f1039640 8429 "blx\\t%1"
8430 [(set_attr "length" "2")
8431 (set_attr "type" "call")]
8432)
8433
25f905c2 8434(define_insn "*call_value_reg_thumb1"
f1039640 8435 [(set (match_operand 0 "" "")
8436 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8437 (match_operand 2 "" "")))
8438 (use (match_operand 3 "" ""))
8439 (clobber (reg:SI LR_REGNUM))]
25f905c2 8440 "TARGET_THUMB1 && !arm_arch5"
f1039640 8441 "*
8442 {
150502c9 8443 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8444 return thumb_call_via_reg (operands[1]);
150502c9 8445 else if (operands[2] == const0_rtx)
f1039640 8446 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8447 else if (frame_pointer_needed)
8448 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8449 else
150502c9 8450 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8451 }"
8452 [(set_attr "type" "call")]
8453)
8454
9c08d1fa 8455;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8456;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8457
f7fbdd4a 8458(define_insn "*call_symbol"
27ed6835 8459 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8460 (match_operand 1 "" ""))
bbe777ea 8461 (use (match_operand 2 "" ""))
bd5b4116 8462 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8463 "TARGET_32BIT
cffb2a26 8464 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8465 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8466 "*
8467 {
55c1e470 8468 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8469 }"
cffb2a26 8470 [(set_attr "type" "call")]
8471)
9c08d1fa 8472
f7fbdd4a 8473(define_insn "*call_value_symbol"
ccd90aaa 8474 [(set (match_operand 0 "" "")
27ed6835 8475 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8476 (match_operand:SI 2 "" "")))
bbe777ea 8477 (use (match_operand 3 "" ""))
bd5b4116 8478 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8479 "TARGET_32BIT
cffb2a26 8480 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8481 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8482 "*
8483 {
55c1e470 8484 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8485 }"
cffb2a26 8486 [(set_attr "type" "call")]
8487)
8488
8489(define_insn "*call_insn"
27ed6835 8490 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8491 (match_operand:SI 1 "" ""))
8492 (use (match_operand 2 "" ""))
bd5b4116 8493 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8494 "TARGET_THUMB1
1675c6e9 8495 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8496 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8497 "bl\\t%a0"
8498 [(set_attr "length" "4")
8499 (set_attr "type" "call")]
8500)
8501
8502(define_insn "*call_value_insn"
ccd90aaa 8503 [(set (match_operand 0 "" "")
27ed6835 8504 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8505 (match_operand 2 "" "")))
8506 (use (match_operand 3 "" ""))
bd5b4116 8507 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8508 "TARGET_THUMB1
1675c6e9 8509 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8510 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8511 "bl\\t%a1"
8512 [(set_attr "length" "4")
8513 (set_attr "type" "call")]
8514)
9c08d1fa 8515
1c494086 8516;; We may also be able to do sibcalls for Thumb, but it's much harder...
8517(define_expand "sibcall"
8518 [(parallel [(call (match_operand 0 "memory_operand" "")
8519 (match_operand 1 "general_operand" ""))
2ba80634 8520 (return)
8521 (use (match_operand 2 "" ""))])]
d68c2c10 8522 "TARGET_32BIT"
1c494086 8523 "
8524 {
8525 if (operands[2] == NULL_RTX)
8526 operands[2] = const0_rtx;
1c494086 8527 }"
8528)
8529
8530(define_expand "sibcall_value"
ccd90aaa 8531 [(parallel [(set (match_operand 0 "" "")
1c494086 8532 (call (match_operand 1 "memory_operand" "")
8533 (match_operand 2 "general_operand" "")))
2ba80634 8534 (return)
8535 (use (match_operand 3 "" ""))])]
d68c2c10 8536 "TARGET_32BIT"
1c494086 8537 "
8538 {
8539 if (operands[3] == NULL_RTX)
8540 operands[3] = const0_rtx;
1c494086 8541 }"
8542)
8543
8544(define_insn "*sibcall_insn"
8545 [(call (mem:SI (match_operand:SI 0 "" "X"))
8546 (match_operand 1 "" ""))
2ba80634 8547 (return)
8548 (use (match_operand 2 "" ""))]
d68c2c10 8549 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8550 "*
8551 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8552 "
8553 [(set_attr "type" "call")]
8554)
8555
8556(define_insn "*sibcall_value_insn"
ccd90aaa 8557 [(set (match_operand 0 "" "")
755eb2b4 8558 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8559 (match_operand 2 "" "")))
2ba80634 8560 (return)
8561 (use (match_operand 3 "" ""))]
d68c2c10 8562 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8563 "*
8564 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8565 "
8566 [(set_attr "type" "call")]
8567)
8568
d68c2c10 8569(define_expand "return"
8570 [(return)]
8cba51a5 8571 "(TARGET_ARM || (TARGET_THUMB2
8572 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8573 && !IS_STACKALIGN (arm_current_func_type ())))
8574 && USE_RETURN_INSN (FALSE)"
8575 "
8576 {
8577 if (TARGET_THUMB2)
8578 {
8579 thumb2_expand_return ();
8580 DONE;
8581 }
8582 }
8583 "
8584)
d68c2c10 8585
9c08d1fa 8586;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8587(define_insn "*arm_return"
9c08d1fa 8588 [(return)]
cffb2a26 8589 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8590 "*
9c08d1fa 8591 {
cffb2a26 8592 if (arm_ccfsm_state == 2)
8593 {
8594 arm_ccfsm_state += 2;
8595 return \"\";
8596 }
e2549f81 8597 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8598 }"
a2cd141b 8599 [(set_attr "type" "load1")
755eb2b4 8600 (set_attr "length" "12")
0d66636f 8601 (set_attr "predicable" "yes")]
cffb2a26 8602)
9c08d1fa 8603
f7fbdd4a 8604(define_insn "*cond_return"
9c08d1fa 8605 [(set (pc)
8fa3ba89 8606 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8607 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8608 (return)
8609 (pc)))]
cffb2a26 8610 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8611 "*
8fa3ba89 8612 {
8613 if (arm_ccfsm_state == 2)
8614 {
8615 arm_ccfsm_state += 2;
8616 return \"\";
8617 }
e2549f81 8618 return output_return_instruction (operands[0], true, false, false);
8fa3ba89 8619 }"
8620 [(set_attr "conds" "use")
755eb2b4 8621 (set_attr "length" "12")
a2cd141b 8622 (set_attr "type" "load1")]
8fa3ba89 8623)
9c08d1fa 8624
f7fbdd4a 8625(define_insn "*cond_return_inverted"
9c08d1fa 8626 [(set (pc)
8fa3ba89 8627 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8628 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8629 (pc)
8630 (return)))]
cffb2a26 8631 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8632 "*
8fa3ba89 8633 {
8634 if (arm_ccfsm_state == 2)
8635 {
8636 arm_ccfsm_state += 2;
8637 return \"\";
8638 }
e2549f81 8639 return output_return_instruction (operands[0], true, true, false);
8fa3ba89 8640 }"
8641 [(set_attr "conds" "use")
37a1317b 8642 (set_attr "length" "12")
a2cd141b 8643 (set_attr "type" "load1")]
8fa3ba89 8644)
9c08d1fa 8645
e2549f81 8646(define_insn "*arm_simple_return"
8647 [(simple_return)]
8648 "TARGET_ARM"
8649 "*
8650 {
8651 if (arm_ccfsm_state == 2)
8652 {
8653 arm_ccfsm_state += 2;
8654 return \"\";
8655 }
8656 return output_return_instruction (const_true_rtx, true, false, true);
8657 }"
8658 [(set_attr "type" "branch")
8659 (set_attr "length" "4")
8660 (set_attr "predicable" "yes")]
8661)
8662
68121397 8663;; Generate a sequence of instructions to determine if the processor is
8664;; in 26-bit or 32-bit mode, and return the appropriate return address
8665;; mask.
8666
8667(define_expand "return_addr_mask"
8668 [(set (match_dup 1)
8669 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8670 (const_int 0)))
8671 (set (match_operand:SI 0 "s_register_operand" "")
8672 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8673 (const_int -1)
8674 (const_int 67108860)))] ; 0x03fffffc
8675 "TARGET_ARM"
8676 "
62eddbd4 8677 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8678 ")
8679
8680(define_insn "*check_arch2"
8681 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8682 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8683 (const_int 0)))]
8684 "TARGET_ARM"
8685 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8686 [(set_attr "length" "8")
8687 (set_attr "conds" "set")]
8688)
8689
9c08d1fa 8690;; Call subroutine returning any type.
8691
8692(define_expand "untyped_call"
8693 [(parallel [(call (match_operand 0 "" "")
8694 (const_int 0))
8695 (match_operand 1 "" "")
8696 (match_operand 2 "" "")])]
ccd90aaa 8697 "TARGET_EITHER"
9c08d1fa 8698 "
215b30b3 8699 {
8700 int i;
ccd90aaa 8701 rtx par = gen_rtx_PARALLEL (VOIDmode,
8702 rtvec_alloc (XVECLEN (operands[2], 0)));
8703 rtx addr = gen_reg_rtx (Pmode);
8704 rtx mem;
8705 int size = 0;
9c08d1fa 8706
ccd90aaa 8707 emit_move_insn (addr, XEXP (operands[1], 0));
8708 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8709
215b30b3 8710 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8711 {
ccd90aaa 8712 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8713
ccd90aaa 8714 /* Default code only uses r0 as a return value, but we could
8715 be using anything up to 4 registers. */
8716 if (REGNO (src) == R0_REGNUM)
8717 src = gen_rtx_REG (TImode, R0_REGNUM);
8718
8719 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8720 GEN_INT (size));
8721 size += GET_MODE_SIZE (GET_MODE (src));
8722 }
8723
8724 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8725 const0_rtx));
8726
8727 size = 0;
8728
8729 for (i = 0; i < XVECLEN (par, 0); i++)
8730 {
8731 HOST_WIDE_INT offset = 0;
8732 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8733
8734 if (size != 0)
29c05e22 8735 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8736
8737 mem = change_address (mem, GET_MODE (reg), NULL);
8738 if (REGNO (reg) == R0_REGNUM)
8739 {
8740 /* On thumb we have to use a write-back instruction. */
320ea44d 8741 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8742 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8743 size = TARGET_ARM ? 16 : 0;
8744 }
8745 else
8746 {
8747 emit_move_insn (mem, reg);
8748 size = GET_MODE_SIZE (GET_MODE (reg));
8749 }
215b30b3 8750 }
9c08d1fa 8751
215b30b3 8752 /* The optimizer does not know that the call sets the function value
8753 registers we stored in the result block. We avoid problems by
8754 claiming that all hard registers are used and clobbered at this
8755 point. */
8756 emit_insn (gen_blockage ());
8757
8758 DONE;
8759 }"
8760)
9c08d1fa 8761
ccd90aaa 8762(define_expand "untyped_return"
8763 [(match_operand:BLK 0 "memory_operand" "")
8764 (match_operand 1 "" "")]
8765 "TARGET_EITHER"
8766 "
8767 {
8768 int i;
8769 rtx addr = gen_reg_rtx (Pmode);
8770 rtx mem;
8771 int size = 0;
8772
8773 emit_move_insn (addr, XEXP (operands[0], 0));
8774 mem = change_address (operands[0], BLKmode, addr);
8775
8776 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8777 {
8778 HOST_WIDE_INT offset = 0;
8779 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8780
8781 if (size != 0)
29c05e22 8782 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8783
8784 mem = change_address (mem, GET_MODE (reg), NULL);
8785 if (REGNO (reg) == R0_REGNUM)
8786 {
8787 /* On thumb we have to use a write-back instruction. */
320ea44d 8788 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8789 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8790 size = TARGET_ARM ? 16 : 0;
8791 }
8792 else
8793 {
8794 emit_move_insn (reg, mem);
8795 size = GET_MODE_SIZE (GET_MODE (reg));
8796 }
8797 }
8798
8799 /* Emit USE insns before the return. */
8800 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8801 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8802
8803 /* Construct the return. */
8804 expand_naked_return ();
8805
8806 DONE;
8807 }"
8808)
8809
9c08d1fa 8810;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8811;; all of memory. This blocks insns from being moved across this point.
8812
8813(define_insn "blockage"
e1159bbe 8814 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8815 "TARGET_EITHER"
9c08d1fa 8816 ""
cffb2a26 8817 [(set_attr "length" "0")
8818 (set_attr "type" "block")]
8819)
9c08d1fa 8820
f7fbdd4a 8821(define_expand "casesi"
8822 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8823 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8824 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8825 (match_operand:SI 3 "" "") ; table label
8826 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8827 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8828 "
215b30b3 8829 {
e6ac8414 8830 enum insn_code code;
215b30b3 8831 if (operands[1] != const0_rtx)
8832 {
e6ac8414 8833 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8834
215b30b3 8835 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8836 gen_int_mode (-INTVAL (operands[1]),
8837 SImode)));
215b30b3 8838 operands[0] = reg;
8839 }
9c08d1fa 8840
25f905c2 8841 if (TARGET_ARM)
e6ac8414 8842 code = CODE_FOR_arm_casesi_internal;
3db2019b 8843 else if (TARGET_THUMB1)
e6ac8414 8844 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8845 else if (flag_pic)
e6ac8414 8846 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8847 else
e6ac8414 8848 code = CODE_FOR_thumb2_casesi_internal;
8849
8850 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8851 operands[2] = force_reg (SImode, operands[2]);
8852
8853 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8854 operands[3], operands[4]));
215b30b3 8855 DONE;
8856 }"
8857)
f7fbdd4a 8858
f082f1c4 8859;; The USE in this pattern is needed to tell flow analysis that this is
8860;; a CASESI insn. It has no other purpose.
25f905c2 8861(define_insn "arm_casesi_internal"
f082f1c4 8862 [(parallel [(set (pc)
8863 (if_then_else
8864 (leu (match_operand:SI 0 "s_register_operand" "r")
8865 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8866 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8867 (label_ref (match_operand 2 "" ""))))
8868 (label_ref (match_operand 3 "" ""))))
bd5b4116 8869 (clobber (reg:CC CC_REGNUM))
f082f1c4 8870 (use (label_ref (match_dup 2)))])]
cffb2a26 8871 "TARGET_ARM"
f7fbdd4a 8872 "*
0d66636f 8873 if (flag_pic)
8874 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8875 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8876 "
8877 [(set_attr "conds" "clob")
8878 (set_attr "length" "12")]
8879)
9c08d1fa 8880
e6ac8414 8881(define_expand "thumb1_casesi_internal_pic"
8882 [(match_operand:SI 0 "s_register_operand" "")
8883 (match_operand:SI 1 "thumb1_cmp_operand" "")
8884 (match_operand 2 "" "")
8885 (match_operand 3 "" "")]
3db2019b 8886 "TARGET_THUMB1"
e6ac8414 8887 {
8888 rtx reg0;
8889 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8890 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8891 operands[3]));
8892 reg0 = gen_rtx_REG (SImode, 0);
8893 emit_move_insn (reg0, operands[0]);
8894 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8895 DONE;
8896 }
8897)
8898
8899(define_insn "thumb1_casesi_dispatch"
8900 [(parallel [(set (pc) (unspec [(reg:SI 0)
8901 (label_ref (match_operand 0 "" ""))
8902;; (label_ref (match_operand 1 "" ""))
8903]
8904 UNSPEC_THUMB1_CASESI))
8905 (clobber (reg:SI IP_REGNUM))
8906 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8907 "TARGET_THUMB1"
e6ac8414 8908 "* return thumb1_output_casesi(operands);"
8909 [(set_attr "length" "4")]
8910)
8911
cffb2a26 8912(define_expand "indirect_jump"
9c08d1fa 8913 [(set (pc)
cffb2a26 8914 (match_operand:SI 0 "s_register_operand" ""))]
8915 "TARGET_EITHER"
25f905c2 8916 "
8917 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8918 address and use bx. */
8919 if (TARGET_THUMB2)
8920 {
8921 rtx tmp;
8922 tmp = gen_reg_rtx (SImode);
8923 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8924 operands[0] = tmp;
8925 }
8926 "
cffb2a26 8927)
8928
f1039640 8929;; NB Never uses BX.
cffb2a26 8930(define_insn "*arm_indirect_jump"
8931 [(set (pc)
8932 (match_operand:SI 0 "s_register_operand" "r"))]
8933 "TARGET_ARM"
8934 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8935 [(set_attr "predicable" "yes")]
cffb2a26 8936)
9c08d1fa 8937
f7fbdd4a 8938(define_insn "*load_indirect_jump"
9c08d1fa 8939 [(set (pc)
8940 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8941 "TARGET_ARM"
8942 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8943 [(set_attr "type" "load1")
61a2d04c 8944 (set_attr "pool_range" "4096")
8945 (set_attr "neg_pool_range" "4084")
0d66636f 8946 (set_attr "predicable" "yes")]
cffb2a26 8947)
8948
f1039640 8949;; NB Never uses BX.
25f905c2 8950(define_insn "*thumb1_indirect_jump"
cffb2a26 8951 [(set (pc)
8952 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8953 "TARGET_THUMB1"
cffb2a26 8954 "mov\\tpc, %0"
8955 [(set_attr "conds" "clob")
8956 (set_attr "length" "2")]
8957)
8958
9c08d1fa 8959\f
8960;; Misc insns
8961
8962(define_insn "nop"
8963 [(const_int 0)]
cffb2a26 8964 "TARGET_EITHER"
8965 "*
25f905c2 8966 if (TARGET_UNIFIED_ASM)
8967 return \"nop\";
cffb2a26 8968 if (TARGET_ARM)
8969 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8970 return \"mov\\tr8, r8\";
8971 "
8972 [(set (attr "length")
8973 (if_then_else (eq_attr "is_thumb" "yes")
8974 (const_int 2)
8975 (const_int 4)))]
8976)
8977
9c08d1fa 8978\f
8979;; Patterns to allow combination of arithmetic, cond code and shifts
8980
f7fbdd4a 8981(define_insn "*arith_shiftsi"
7392680c 8982 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9c08d1fa 8983 (match_operator:SI 1 "shiftable_operator"
8984 [(match_operator:SI 3 "shift_operator"
7392680c 8985 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
8986 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
8987 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
d5d4dc8d 8988 "TARGET_32BIT"
6c4c2133 8989 "%i1%?\\t%0, %2, %4%S3"
344495ea 8990 [(set_attr "predicable" "yes")
331beb1a 8991 (set_attr "shift" "4")
7392680c 8992 (set_attr "arch" "a,t2,t2,a")
8993 ;; Thumb2 doesn't allow the stack pointer to be used for
8994 ;; operand1 for all operations other than add and sub. In this case
8995 ;; the minus operation is a candidate for an rsub and hence needs
8996 ;; to be disabled.
8997 ;; We have to make sure to disable the fourth alternative if
d5d4dc8d 8998 ;; the shift_operator is MULT, since otherwise the insn will
8999 ;; also match a multiply_accumulate pattern and validate_change
9000 ;; will allow a replacement of the constant with a register
9001 ;; despite the checks done in shift_operator.
9002 (set_attr_alternative "insn_enabled"
9003 [(const_string "yes")
7392680c 9004 (if_then_else
9005 (match_operand:SI 1 "add_operator" "")
9006 (const_string "yes") (const_string "no"))
9007 (const_string "yes")
d5d4dc8d 9008 (if_then_else
9009 (match_operand:SI 3 "mult_operator" "")
9010 (const_string "no") (const_string "yes"))])
7392680c 9011 (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
9c08d1fa 9012
d7863cfe 9013(define_split
9014 [(set (match_operand:SI 0 "s_register_operand" "")
9015 (match_operator:SI 1 "shiftable_operator"
9016 [(match_operator:SI 2 "shiftable_operator"
9017 [(match_operator:SI 3 "shift_operator"
9018 [(match_operand:SI 4 "s_register_operand" "")
9019 (match_operand:SI 5 "reg_or_int_operand" "")])
9020 (match_operand:SI 6 "s_register_operand" "")])
9021 (match_operand:SI 7 "arm_rhs_operand" "")]))
9022 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 9023 "TARGET_32BIT"
d7863cfe 9024 [(set (match_dup 8)
9025 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9026 (match_dup 6)]))
9027 (set (match_dup 0)
9028 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9029 "")
9030
f7fbdd4a 9031(define_insn "*arith_shiftsi_compare0"
bd5b4116 9032 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9033 (compare:CC_NOOV
9034 (match_operator:SI 1 "shiftable_operator"
9035 [(match_operator:SI 3 "shift_operator"
9036 [(match_operand:SI 4 "s_register_operand" "r,r")
9037 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9038 (match_operand:SI 2 "s_register_operand" "r,r")])
9039 (const_int 0)))
9040 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 9041 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9042 (match_dup 2)]))]
d5d4dc8d 9043 "TARGET_32BIT"
25f905c2 9044 "%i1%.\\t%0, %2, %4%S3"
344495ea 9045 [(set_attr "conds" "set")
331beb1a 9046 (set_attr "shift" "4")
d5d4dc8d 9047 (set_attr "arch" "32,a")
9048 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9049
f7fbdd4a 9050(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9051 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9052 (compare:CC_NOOV
9053 (match_operator:SI 1 "shiftable_operator"
9054 [(match_operator:SI 3 "shift_operator"
9055 [(match_operand:SI 4 "s_register_operand" "r,r")
9056 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9057 (match_operand:SI 2 "s_register_operand" "r,r")])
9058 (const_int 0)))
9059 (clobber (match_scratch:SI 0 "=r,r"))]
9060 "TARGET_32BIT"
25f905c2 9061 "%i1%.\\t%0, %2, %4%S3"
344495ea 9062 [(set_attr "conds" "set")
331beb1a 9063 (set_attr "shift" "4")
d5d4dc8d 9064 (set_attr "arch" "32,a")
9065 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9066
f7fbdd4a 9067(define_insn "*sub_shiftsi"
d5d4dc8d 9068 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9069 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 9070 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9071 [(match_operand:SI 3 "s_register_operand" "r,r")
9072 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9073 "TARGET_32BIT"
6c4c2133 9074 "sub%?\\t%0, %1, %3%S2"
344495ea 9075 [(set_attr "predicable" "yes")
331beb1a 9076 (set_attr "shift" "3")
d5d4dc8d 9077 (set_attr "arch" "32,a")
9078 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9079
f7fbdd4a 9080(define_insn "*sub_shiftsi_compare0"
bd5b4116 9081 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9082 (compare:CC_NOOV
d5d4dc8d 9083 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9084 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9085 [(match_operand:SI 3 "s_register_operand" "r,r")
9086 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9087 (const_int 0)))
d5d4dc8d 9088 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9089 (minus:SI (match_dup 1)
9090 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9091 "TARGET_32BIT"
25f905c2 9092 "sub%.\\t%0, %1, %3%S2"
344495ea 9093 [(set_attr "conds" "set")
a2cd141b 9094 (set_attr "shift" "3")
d5d4dc8d 9095 (set_attr "arch" "32,a")
9096 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9097
f7fbdd4a 9098(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9099 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9100 (compare:CC_NOOV
d5d4dc8d 9101 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9102 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9103 [(match_operand:SI 3 "s_register_operand" "r,r")
9104 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9105 (const_int 0)))
d5d4dc8d 9106 (clobber (match_scratch:SI 0 "=r,r"))]
9107 "TARGET_32BIT"
25f905c2 9108 "sub%.\\t%0, %1, %3%S2"
344495ea 9109 [(set_attr "conds" "set")
a2cd141b 9110 (set_attr "shift" "3")
d5d4dc8d 9111 (set_attr "arch" "32,a")
9112 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9113\f
9114
f7fbdd4a 9115(define_insn "*and_scc"
9c08d1fa 9116 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9117 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9118 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9119 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9120 "TARGET_ARM"
e2348bcb 9121 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9122 [(set_attr "conds" "use")
d2a518d1 9123 (set_attr "insn" "mov")
8fa3ba89 9124 (set_attr "length" "8")]
9125)
9c08d1fa 9126
f7fbdd4a 9127(define_insn "*ior_scc"
9c08d1fa 9128 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9129 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9130 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9131 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9132 "TARGET_ARM"
e2348bcb 9133 "@
899850b0 9134 orr%d2\\t%0, %1, #1
9135 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9136 [(set_attr "conds" "use")
9137 (set_attr "length" "4,8")]
9138)
9c08d1fa 9139
2df9477b 9140; A series of splitters for the compare_scc pattern below. Note that
9141; order is important.
9142(define_split
9143 [(set (match_operand:SI 0 "s_register_operand" "")
9144 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9145 (const_int 0)))
9146 (clobber (reg:CC CC_REGNUM))]
9147 "TARGET_32BIT && reload_completed"
9148 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9149
9150(define_split
9151 [(set (match_operand:SI 0 "s_register_operand" "")
9152 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9153 (const_int 0)))
9154 (clobber (reg:CC CC_REGNUM))]
9155 "TARGET_32BIT && reload_completed"
9156 [(set (match_dup 0) (not:SI (match_dup 1)))
9157 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9158
9159(define_split
9160 [(set (match_operand:SI 0 "s_register_operand" "")
9161 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9162 (const_int 0)))
9163 (clobber (reg:CC CC_REGNUM))]
9164 "TARGET_32BIT && reload_completed"
9165 [(parallel
080c0b9a 9166 [(set (reg:CC CC_REGNUM)
9167 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9168 (set (match_dup 0)
9169 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9170 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9171 (set (match_dup 0) (const_int 0)))])
9172
9173(define_split
9174 [(set (match_operand:SI 0 "s_register_operand" "")
9175 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9176 (match_operand:SI 2 "const_int_operand" "")))
9177 (clobber (reg:CC CC_REGNUM))]
9178 "TARGET_32BIT && reload_completed"
9179 [(parallel
9180 [(set (reg:CC CC_REGNUM)
9181 (compare:CC (match_dup 1) (match_dup 2)))
9182 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9183 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9184 (set (match_dup 0) (const_int 1)))]
9185{
9186 operands[3] = GEN_INT (-INTVAL (operands[2]));
9187})
9188
9189(define_split
9190 [(set (match_operand:SI 0 "s_register_operand" "")
9191 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9192 (match_operand:SI 2 "arm_add_operand" "")))
9193 (clobber (reg:CC CC_REGNUM))]
9194 "TARGET_32BIT && reload_completed"
9195 [(parallel
9196 [(set (reg:CC_NOOV CC_REGNUM)
9197 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9198 (const_int 0)))
9199 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9200 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9201 (set (match_dup 0) (const_int 1)))])
9202
9203(define_insn_and_split "*compare_scc"
5565501b 9204 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9205 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9206 [(match_operand:SI 2 "s_register_operand" "r,r")
9207 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9208 (clobber (reg:CC CC_REGNUM))]
2df9477b 9209 "TARGET_32BIT"
9210 "#"
9211 "&& reload_completed"
9212 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9213 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9214 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9215{
9216 rtx tmp1;
9217 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9218 operands[2], operands[3]);
9219 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9220
2df9477b 9221 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9222
2df9477b 9223 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9224 if (mode == CCFPmode || mode == CCFPEmode)
9225 rc = reverse_condition_maybe_unordered (rc);
9226 else
9227 rc = reverse_condition (rc);
9228 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9229})
9c08d1fa 9230
080c0b9a 9231;; Attempt to improve the sequence generated by the compare_scc splitters
9232;; not to use conditional execution.
9233(define_peephole2
9234 [(set (reg:CC CC_REGNUM)
9235 (compare:CC (match_operand:SI 1 "register_operand" "")
9236 (match_operand:SI 2 "arm_rhs_operand" "")))
9237 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9238 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9239 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9240 (set (match_dup 0) (const_int 1)))
9241 (match_scratch:SI 3 "r")]
9242 "TARGET_32BIT"
922b6913 9243 [(parallel
9244 [(set (reg:CC CC_REGNUM)
9245 (compare:CC (match_dup 1) (match_dup 2)))
9246 (set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 9247 (parallel
9248 [(set (reg:CC CC_REGNUM)
9249 (compare:CC (const_int 0) (match_dup 3)))
9250 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
922b6913 9251 (parallel
9252 [(set (match_dup 0)
9253 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9254 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))
9255 (clobber (reg:CC CC_REGNUM))])])
080c0b9a 9256
f7fbdd4a 9257(define_insn "*cond_move"
9c08d1fa 9258 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9259 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9260 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9261 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9262 (const_int 0)])
9263 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9264 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9265 "TARGET_ARM"
9c08d1fa 9266 "*
8fa3ba89 9267 if (GET_CODE (operands[3]) == NE)
9268 {
9269 if (which_alternative != 1)
9270 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9271 if (which_alternative != 0)
9272 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9273 return \"\";
9274 }
9275 if (which_alternative != 0)
9276 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9277 if (which_alternative != 1)
9278 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9279 return \"\";
9280 "
9281 [(set_attr "conds" "use")
d2a518d1 9282 (set_attr "insn" "mov")
8fa3ba89 9283 (set_attr "length" "4,4,8")]
9284)
9c08d1fa 9285
f7fbdd4a 9286(define_insn "*cond_arith"
9c08d1fa 9287 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9288 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9289 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9290 [(match_operand:SI 2 "s_register_operand" "r,r")
9291 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9292 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9293 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9294 "TARGET_ARM"
9c08d1fa 9295 "*
8fa3ba89 9296 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9297 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9298
8fa3ba89 9299 output_asm_insn (\"cmp\\t%2, %3\", operands);
9300 if (GET_CODE (operands[5]) == AND)
9301 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9302 else if (GET_CODE (operands[5]) == MINUS)
9303 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9304 else if (which_alternative != 0)
9305 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9306 return \"%i5%d4\\t%0, %1, #1\";
9307 "
9308 [(set_attr "conds" "clob")
9309 (set_attr "length" "12")]
9310)
9c08d1fa 9311
f7fbdd4a 9312(define_insn "*cond_sub"
9c08d1fa 9313 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9314 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9315 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9316 [(match_operand:SI 2 "s_register_operand" "r,r")
9317 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9318 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9319 "TARGET_ARM"
9c08d1fa 9320 "*
8fa3ba89 9321 output_asm_insn (\"cmp\\t%2, %3\", operands);
9322 if (which_alternative != 0)
9323 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9324 return \"sub%d4\\t%0, %1, #1\";
9325 "
9326 [(set_attr "conds" "clob")
9327 (set_attr "length" "8,12")]
9328)
9c08d1fa 9329
aea4c774 9330(define_insn "*cmp_ite0"
cffb2a26 9331 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9332 (compare
9333 (if_then_else:SI
8fa3ba89 9334 (match_operator 4 "arm_comparison_operator"
2ff91fec 9335 [(match_operand:SI 0 "s_register_operand"
9336 "l,l,l,r,r,r,r,r,r")
9337 (match_operand:SI 1 "arm_add_operand"
9338 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9339 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9340 [(match_operand:SI 2 "s_register_operand"
9341 "l,r,r,l,l,r,r,r,r")
9342 (match_operand:SI 3 "arm_add_operand"
9343 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9344 (const_int 0))
9345 (const_int 0)))]
2ff91fec 9346 "TARGET_32BIT"
9c08d1fa 9347 "*
aea4c774 9348 {
2ff91fec 9349 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9350 {
9351 {\"cmp%d5\\t%0, %1\",
9352 \"cmp%d4\\t%2, %3\"},
9353 {\"cmn%d5\\t%0, #%n1\",
9354 \"cmp%d4\\t%2, %3\"},
9355 {\"cmp%d5\\t%0, %1\",
9356 \"cmn%d4\\t%2, #%n3\"},
9357 {\"cmn%d5\\t%0, #%n1\",
9358 \"cmn%d4\\t%2, #%n3\"}
9359 };
9360 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9361 {
9362 {\"cmp\\t%2, %3\",
9363 \"cmp\\t%0, %1\"},
9364 {\"cmp\\t%2, %3\",
9365 \"cmn\\t%0, #%n1\"},
9366 {\"cmn\\t%2, #%n3\",
9367 \"cmp\\t%0, %1\"},
9368 {\"cmn\\t%2, #%n3\",
9369 \"cmn\\t%0, #%n1\"}
9370 };
9371 static const char * const ite[2] =
8fa3ba89 9372 {
2ff91fec 9373 \"it\\t%d5\",
9374 \"it\\t%d4\"
8fa3ba89 9375 };
2ff91fec 9376 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9377 CMP_CMP, CMN_CMP, CMP_CMP,
9378 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9379 int swap =
9380 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9381
2ff91fec 9382 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9383 if (TARGET_THUMB2) {
9384 output_asm_insn (ite[swap], operands);
9385 }
9386 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9387 return \"\";
8fa3ba89 9388 }"
9389 [(set_attr "conds" "set")
2ff91fec 9390 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9391 (set_attr_alternative "length"
9392 [(const_int 6)
9393 (const_int 8)
9394 (const_int 8)
9395 (const_int 8)
9396 (const_int 8)
9397 (if_then_else (eq_attr "is_thumb" "no")
9398 (const_int 8)
9399 (const_int 10))
9400 (if_then_else (eq_attr "is_thumb" "no")
9401 (const_int 8)
9402 (const_int 10))
9403 (if_then_else (eq_attr "is_thumb" "no")
9404 (const_int 8)
9405 (const_int 10))
9406 (if_then_else (eq_attr "is_thumb" "no")
9407 (const_int 8)
9408 (const_int 10))])]
8fa3ba89 9409)
9c08d1fa 9410
aea4c774 9411(define_insn "*cmp_ite1"
cffb2a26 9412 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9413 (compare
9414 (if_then_else:SI
8fa3ba89 9415 (match_operator 4 "arm_comparison_operator"
2ff91fec 9416 [(match_operand:SI 0 "s_register_operand"
9417 "l,l,l,r,r,r,r,r,r")
9418 (match_operand:SI 1 "arm_add_operand"
9419 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9420 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9421 [(match_operand:SI 2 "s_register_operand"
9422 "l,r,r,l,l,r,r,r,r")
9423 (match_operand:SI 3 "arm_add_operand"
9424 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9425 (const_int 1))
9426 (const_int 0)))]
2ff91fec 9427 "TARGET_32BIT"
9c08d1fa 9428 "*
9c08d1fa 9429 {
2ff91fec 9430 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9431 {
9432 {\"cmp\\t%0, %1\",
9433 \"cmp\\t%2, %3\"},
9434 {\"cmn\\t%0, #%n1\",
9435 \"cmp\\t%2, %3\"},
9436 {\"cmp\\t%0, %1\",
9437 \"cmn\\t%2, #%n3\"},
9438 {\"cmn\\t%0, #%n1\",
9439 \"cmn\\t%2, #%n3\"}
9440 };
9441 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9442 {
2ff91fec 9443 {\"cmp%d4\\t%2, %3\",
9444 \"cmp%D5\\t%0, %1\"},
9445 {\"cmp%d4\\t%2, %3\",
9446 \"cmn%D5\\t%0, #%n1\"},
9447 {\"cmn%d4\\t%2, #%n3\",
9448 \"cmp%D5\\t%0, %1\"},
9449 {\"cmn%d4\\t%2, #%n3\",
9450 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9451 };
2ff91fec 9452 static const char * const ite[2] =
9453 {
9454 \"it\\t%d4\",
9455 \"it\\t%D5\"
9456 };
9457 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9458 CMP_CMP, CMN_CMP, CMP_CMP,
9459 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9460 int swap =
9461 comparison_dominates_p (GET_CODE (operands[5]),
9462 reverse_condition (GET_CODE (operands[4])));
9463
2ff91fec 9464 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9465 if (TARGET_THUMB2) {
9466 output_asm_insn (ite[swap], operands);
9467 }
9468 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9469 return \"\";
215b30b3 9470 }"
8fa3ba89 9471 [(set_attr "conds" "set")
2ff91fec 9472 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9473 (set_attr_alternative "length"
9474 [(const_int 6)
9475 (const_int 8)
9476 (const_int 8)
9477 (const_int 8)
9478 (const_int 8)
9479 (if_then_else (eq_attr "is_thumb" "no")
9480 (const_int 8)
9481 (const_int 10))
9482 (if_then_else (eq_attr "is_thumb" "no")
9483 (const_int 8)
9484 (const_int 10))
9485 (if_then_else (eq_attr "is_thumb" "no")
9486 (const_int 8)
9487 (const_int 10))
9488 (if_then_else (eq_attr "is_thumb" "no")
9489 (const_int 8)
9490 (const_int 10))])]
8fa3ba89 9491)
9c08d1fa 9492
f6c53574 9493(define_insn "*cmp_and"
9494 [(set (match_operand 6 "dominant_cc_register" "")
9495 (compare
9496 (and:SI
9497 (match_operator 4 "arm_comparison_operator"
2ff91fec 9498 [(match_operand:SI 0 "s_register_operand"
9499 "l,l,l,r,r,r,r,r,r")
9500 (match_operand:SI 1 "arm_add_operand"
9501 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9502 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9503 [(match_operand:SI 2 "s_register_operand"
9504 "l,r,r,l,l,r,r,r,r")
9505 (match_operand:SI 3 "arm_add_operand"
9506 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9507 (const_int 0)))]
2ff91fec 9508 "TARGET_32BIT"
f6c53574 9509 "*
9510 {
2ff91fec 9511 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9512 {
2ff91fec 9513 {\"cmp%d5\\t%0, %1\",
9514 \"cmp%d4\\t%2, %3\"},
9515 {\"cmn%d5\\t%0, #%n1\",
9516 \"cmp%d4\\t%2, %3\"},
9517 {\"cmp%d5\\t%0, %1\",
9518 \"cmn%d4\\t%2, #%n3\"},
9519 {\"cmn%d5\\t%0, #%n1\",
9520 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9521 };
2ff91fec 9522 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9523 {
9524 {\"cmp\\t%2, %3\",
9525 \"cmp\\t%0, %1\"},
9526 {\"cmp\\t%2, %3\",
9527 \"cmn\\t%0, #%n1\"},
9528 {\"cmn\\t%2, #%n3\",
9529 \"cmp\\t%0, %1\"},
9530 {\"cmn\\t%2, #%n3\",
9531 \"cmn\\t%0, #%n1\"}
9532 };
9533 static const char *const ite[2] =
9534 {
9535 \"it\\t%d5\",
9536 \"it\\t%d4\"
9537 };
9538 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9539 CMP_CMP, CMN_CMP, CMP_CMP,
9540 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9541 int swap =
9542 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9543
2ff91fec 9544 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9545 if (TARGET_THUMB2) {
9546 output_asm_insn (ite[swap], operands);
9547 }
9548 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9549 return \"\";
f6c53574 9550 }"
9551 [(set_attr "conds" "set")
9552 (set_attr "predicable" "no")
2ff91fec 9553 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9554 (set_attr_alternative "length"
9555 [(const_int 6)
9556 (const_int 8)
9557 (const_int 8)
9558 (const_int 8)
9559 (const_int 8)
9560 (if_then_else (eq_attr "is_thumb" "no")
9561 (const_int 8)
9562 (const_int 10))
9563 (if_then_else (eq_attr "is_thumb" "no")
9564 (const_int 8)
9565 (const_int 10))
9566 (if_then_else (eq_attr "is_thumb" "no")
9567 (const_int 8)
9568 (const_int 10))
9569 (if_then_else (eq_attr "is_thumb" "no")
9570 (const_int 8)
9571 (const_int 10))])]
f6c53574 9572)
9573
9574(define_insn "*cmp_ior"
9575 [(set (match_operand 6 "dominant_cc_register" "")
9576 (compare
9577 (ior:SI
9578 (match_operator 4 "arm_comparison_operator"
2ff91fec 9579 [(match_operand:SI 0 "s_register_operand"
9580 "l,l,l,r,r,r,r,r,r")
9581 (match_operand:SI 1 "arm_add_operand"
9582 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9583 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9584 [(match_operand:SI 2 "s_register_operand"
9585 "l,r,r,l,l,r,r,r,r")
9586 (match_operand:SI 3 "arm_add_operand"
9587 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9588 (const_int 0)))]
2ff91fec 9589 "TARGET_32BIT"
f6c53574 9590 "*
f6c53574 9591 {
2ff91fec 9592 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9593 {
9594 {\"cmp\\t%0, %1\",
9595 \"cmp\\t%2, %3\"},
9596 {\"cmn\\t%0, #%n1\",
9597 \"cmp\\t%2, %3\"},
9598 {\"cmp\\t%0, %1\",
9599 \"cmn\\t%2, #%n3\"},
9600 {\"cmn\\t%0, #%n1\",
9601 \"cmn\\t%2, #%n3\"}
9602 };
9603 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9604 {
9605 {\"cmp%D4\\t%2, %3\",
9606 \"cmp%D5\\t%0, %1\"},
9607 {\"cmp%D4\\t%2, %3\",
9608 \"cmn%D5\\t%0, #%n1\"},
9609 {\"cmn%D4\\t%2, #%n3\",
9610 \"cmp%D5\\t%0, %1\"},
9611 {\"cmn%D4\\t%2, #%n3\",
9612 \"cmn%D5\\t%0, #%n1\"}
9613 };
9614 static const char *const ite[2] =
9615 {
9616 \"it\\t%D4\",
9617 \"it\\t%D5\"
9618 };
9619 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9620 CMP_CMP, CMN_CMP, CMP_CMP,
9621 CMN_CMP, CMP_CMN, CMN_CMN};
9622 int swap =
9623 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9624
9625 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9626 if (TARGET_THUMB2) {
9627 output_asm_insn (ite[swap], operands);
9628 }
9629 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9630 return \"\";
9631 }
9632 "
f6c53574 9633 [(set_attr "conds" "set")
2ff91fec 9634 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9635 (set_attr_alternative "length"
9636 [(const_int 6)
9637 (const_int 8)
9638 (const_int 8)
9639 (const_int 8)
9640 (const_int 8)
9641 (if_then_else (eq_attr "is_thumb" "no")
9642 (const_int 8)
9643 (const_int 10))
9644 (if_then_else (eq_attr "is_thumb" "no")
9645 (const_int 8)
9646 (const_int 10))
9647 (if_then_else (eq_attr "is_thumb" "no")
9648 (const_int 8)
9649 (const_int 10))
9650 (if_then_else (eq_attr "is_thumb" "no")
9651 (const_int 8)
9652 (const_int 10))])]
f6c53574 9653)
9654
3c5afce6 9655(define_insn_and_split "*ior_scc_scc"
9656 [(set (match_operand:SI 0 "s_register_operand" "=r")
9657 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9658 [(match_operand:SI 1 "s_register_operand" "r")
9659 (match_operand:SI 2 "arm_add_operand" "rIL")])
9660 (match_operator:SI 6 "arm_comparison_operator"
9661 [(match_operand:SI 4 "s_register_operand" "r")
9662 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9663 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9664 "TARGET_32BIT
3c5afce6 9665 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9666 != CCmode)"
9667 "#"
2ff91fec 9668 "TARGET_32BIT && reload_completed"
3c5afce6 9669 [(set (match_dup 7)
9670 (compare
9671 (ior:SI
9672 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9673 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9674 (const_int 0)))
9675 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9676 "operands[7]
9677 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9678 DOM_CC_X_OR_Y),
601f584c 9679 CC_REGNUM);"
9680 [(set_attr "conds" "clob")
9681 (set_attr "length" "16")])
9682
9683; If the above pattern is followed by a CMP insn, then the compare is
9684; redundant, since we can rework the conditional instruction that follows.
9685(define_insn_and_split "*ior_scc_scc_cmp"
9686 [(set (match_operand 0 "dominant_cc_register" "")
9687 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9688 [(match_operand:SI 1 "s_register_operand" "r")
9689 (match_operand:SI 2 "arm_add_operand" "rIL")])
9690 (match_operator:SI 6 "arm_comparison_operator"
9691 [(match_operand:SI 4 "s_register_operand" "r")
9692 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9693 (const_int 0)))
9694 (set (match_operand:SI 7 "s_register_operand" "=r")
9695 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9696 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9697 "TARGET_32BIT"
601f584c 9698 "#"
2ff91fec 9699 "TARGET_32BIT && reload_completed"
601f584c 9700 [(set (match_dup 0)
9701 (compare
9702 (ior:SI
9703 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9704 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9705 (const_int 0)))
9706 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9707 ""
9708 [(set_attr "conds" "set")
9709 (set_attr "length" "16")])
3c5afce6 9710
9711(define_insn_and_split "*and_scc_scc"
9712 [(set (match_operand:SI 0 "s_register_operand" "=r")
9713 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9714 [(match_operand:SI 1 "s_register_operand" "r")
9715 (match_operand:SI 2 "arm_add_operand" "rIL")])
9716 (match_operator:SI 6 "arm_comparison_operator"
9717 [(match_operand:SI 4 "s_register_operand" "r")
9718 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9719 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9720 "TARGET_32BIT
3c5afce6 9721 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9722 != CCmode)"
9723 "#"
2ff91fec 9724 "TARGET_32BIT && reload_completed
601f584c 9725 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9726 != CCmode)"
3c5afce6 9727 [(set (match_dup 7)
9728 (compare
9729 (and:SI
9730 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9731 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9732 (const_int 0)))
9733 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9734 "operands[7]
9735 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9736 DOM_CC_X_AND_Y),
601f584c 9737 CC_REGNUM);"
9738 [(set_attr "conds" "clob")
9739 (set_attr "length" "16")])
9740
9741; If the above pattern is followed by a CMP insn, then the compare is
9742; redundant, since we can rework the conditional instruction that follows.
9743(define_insn_and_split "*and_scc_scc_cmp"
9744 [(set (match_operand 0 "dominant_cc_register" "")
9745 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9746 [(match_operand:SI 1 "s_register_operand" "r")
9747 (match_operand:SI 2 "arm_add_operand" "rIL")])
9748 (match_operator:SI 6 "arm_comparison_operator"
9749 [(match_operand:SI 4 "s_register_operand" "r")
9750 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9751 (const_int 0)))
9752 (set (match_operand:SI 7 "s_register_operand" "=r")
9753 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9754 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9755 "TARGET_32BIT"
601f584c 9756 "#"
2ff91fec 9757 "TARGET_32BIT && reload_completed"
601f584c 9758 [(set (match_dup 0)
9759 (compare
9760 (and:SI
9761 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9762 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9763 (const_int 0)))
9764 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9765 ""
9766 [(set_attr "conds" "set")
9767 (set_attr "length" "16")])
9768
9769;; If there is no dominance in the comparison, then we can still save an
9770;; instruction in the AND case, since we can know that the second compare
9771;; need only zero the value if false (if true, then the value is already
9772;; correct).
9773(define_insn_and_split "*and_scc_scc_nodom"
9774 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9775 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9776 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9777 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9778 (match_operator:SI 6 "arm_comparison_operator"
9779 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9780 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9781 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9782 "TARGET_32BIT
601f584c 9783 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9784 == CCmode)"
9785 "#"
2ff91fec 9786 "TARGET_32BIT && reload_completed"
601f584c 9787 [(parallel [(set (match_dup 0)
9788 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9789 (clobber (reg:CC CC_REGNUM))])
9790 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9791 (set (match_dup 0)
9792 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9793 (match_dup 0)
9794 (const_int 0)))]
9795 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9796 operands[4], operands[5]),
9797 CC_REGNUM);
9798 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9799 operands[5]);"
9800 [(set_attr "conds" "clob")
9801 (set_attr "length" "20")])
3c5afce6 9802
3a0bdee0 9803(define_split
9804 [(set (reg:CC_NOOV CC_REGNUM)
9805 (compare:CC_NOOV (ior:SI
9806 (and:SI (match_operand:SI 0 "s_register_operand" "")
9807 (const_int 1))
b0694be0 9808 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9809 [(match_operand:SI 2 "s_register_operand" "")
9810 (match_operand:SI 3 "arm_add_operand" "")]))
9811 (const_int 0)))
9812 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9813 "TARGET_ARM"
9814 [(set (match_dup 4)
9815 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9816 (match_dup 0)))
9817 (set (reg:CC_NOOV CC_REGNUM)
9818 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9819 (const_int 0)))]
9820 "")
9821
9822(define_split
9823 [(set (reg:CC_NOOV CC_REGNUM)
9824 (compare:CC_NOOV (ior:SI
b0694be0 9825 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9826 [(match_operand:SI 2 "s_register_operand" "")
9827 (match_operand:SI 3 "arm_add_operand" "")])
9828 (and:SI (match_operand:SI 0 "s_register_operand" "")
9829 (const_int 1)))
9830 (const_int 0)))
9831 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9832 "TARGET_ARM"
9833 [(set (match_dup 4)
9834 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9835 (match_dup 0)))
9836 (set (reg:CC_NOOV CC_REGNUM)
9837 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9838 (const_int 0)))]
9839 "")
25f905c2 9840;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9841
f7fbdd4a 9842(define_insn "*negscc"
9c08d1fa 9843 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9844 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9845 [(match_operand:SI 1 "s_register_operand" "r")
9846 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9847 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9848 "TARGET_ARM"
9c08d1fa 9849 "*
2ca2ec2e 9850 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9851 return \"mov\\t%0, %1, asr #31\";
9852
9c08d1fa 9853 if (GET_CODE (operands[3]) == NE)
e2348bcb 9854 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9855
e2348bcb 9856 output_asm_insn (\"cmp\\t%1, %2\", operands);
9857 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9858 return \"mvn%d3\\t%0, #0\";
215b30b3 9859 "
8fa3ba89 9860 [(set_attr "conds" "clob")
9861 (set_attr "length" "12")]
9862)
9c08d1fa 9863
9864(define_insn "movcond"
9865 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9866 (if_then_else:SI
8fa3ba89 9867 (match_operator 5 "arm_comparison_operator"
5565501b 9868 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9869 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9870 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9871 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9872 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9873 "TARGET_ARM"
9c08d1fa 9874 "*
9875 if (GET_CODE (operands[5]) == LT
9876 && (operands[4] == const0_rtx))
9877 {
0438d37f 9878 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9879 {
9c08d1fa 9880 if (operands[2] == const0_rtx)
e2348bcb 9881 return \"and\\t%0, %1, %3, asr #31\";
9882 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9883 }
0438d37f 9884 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9885 {
9c08d1fa 9886 if (operands[1] == const0_rtx)
e2348bcb 9887 return \"bic\\t%0, %2, %3, asr #31\";
9888 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9889 }
9890 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9891 are constants. */
9c08d1fa 9892 }
e2348bcb 9893
9c08d1fa 9894 if (GET_CODE (operands[5]) == GE
9895 && (operands[4] == const0_rtx))
9896 {
0438d37f 9897 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9898 {
9c08d1fa 9899 if (operands[2] == const0_rtx)
e2348bcb 9900 return \"bic\\t%0, %1, %3, asr #31\";
9901 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9902 }
0438d37f 9903 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9904 {
9c08d1fa 9905 if (operands[1] == const0_rtx)
e2348bcb 9906 return \"and\\t%0, %2, %3, asr #31\";
9907 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9908 }
9909 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9910 are constants. */
9c08d1fa 9911 }
0438d37f 9912 if (CONST_INT_P (operands[4])
9c08d1fa 9913 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9914 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9915 else
e2348bcb 9916 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9917 if (which_alternative != 0)
e2348bcb 9918 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9919 if (which_alternative != 1)
e2348bcb 9920 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9921 return \"\";
215b30b3 9922 "
8fa3ba89 9923 [(set_attr "conds" "clob")
9924 (set_attr "length" "8,8,12")]
9925)
9c08d1fa 9926
25f905c2 9927;; ??? The patterns below need checking for Thumb-2 usefulness.
9928
8a18b90c 9929(define_insn "*ifcompare_plus_move"
9930 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9931 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9932 [(match_operand:SI 4 "s_register_operand" "r,r")
9933 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9934 (plus:SI
9935 (match_operand:SI 2 "s_register_operand" "r,r")
9936 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9937 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9938 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9939 "TARGET_ARM"
8a18b90c 9940 "#"
8fa3ba89 9941 [(set_attr "conds" "clob")
9942 (set_attr "length" "8,12")]
9943)
8a18b90c 9944
9945(define_insn "*if_plus_move"
129a2fe4 9946 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9947 (if_then_else:SI
8fa3ba89 9948 (match_operator 4 "arm_comparison_operator"
8a18b90c 9949 [(match_operand 5 "cc_register" "") (const_int 0)])
9950 (plus:SI
129a2fe4 9951 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9952 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9953 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9954 "TARGET_ARM"
8a18b90c 9955 "@
9956 add%d4\\t%0, %2, %3
9957 sub%d4\\t%0, %2, #%n3
9958 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9959 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9960 [(set_attr "conds" "use")
9961 (set_attr "length" "4,4,8,8")
9962 (set_attr "type" "*,*,*,*")]
9963)
8a18b90c 9964
9965(define_insn "*ifcompare_move_plus"
5565501b 9966 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9967 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9968 [(match_operand:SI 4 "s_register_operand" "r,r")
9969 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9970 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9971 (plus:SI
9972 (match_operand:SI 2 "s_register_operand" "r,r")
9973 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9974 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9975 "TARGET_ARM"
8a18b90c 9976 "#"
8fa3ba89 9977 [(set_attr "conds" "clob")
9978 (set_attr "length" "8,12")]
9979)
8a18b90c 9980
9981(define_insn "*if_move_plus"
129a2fe4 9982 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9983 (if_then_else:SI
8fa3ba89 9984 (match_operator 4 "arm_comparison_operator"
8a18b90c 9985 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9986 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9987 (plus:SI
129a2fe4 9988 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9989 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9990 "TARGET_ARM"
8a18b90c 9991 "@
9992 add%D4\\t%0, %2, %3
9993 sub%D4\\t%0, %2, #%n3
9994 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9995 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9996 [(set_attr "conds" "use")
9997 (set_attr "length" "4,4,8,8")
9998 (set_attr "type" "*,*,*,*")]
9999)
8a18b90c 10000
10001(define_insn "*ifcompare_arith_arith"
10002 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10003 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10004 [(match_operand:SI 5 "s_register_operand" "r")
10005 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10006 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10007 [(match_operand:SI 1 "s_register_operand" "r")
10008 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10009 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10010 [(match_operand:SI 3 "s_register_operand" "r")
10011 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10012 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10013 "TARGET_ARM"
8a18b90c 10014 "#"
8fa3ba89 10015 [(set_attr "conds" "clob")
10016 (set_attr "length" "12")]
10017)
9c08d1fa 10018
8a18b90c 10019(define_insn "*if_arith_arith"
10020 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10021 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10022 [(match_operand 8 "cc_register" "") (const_int 0)])
10023 (match_operator:SI 6 "shiftable_operator"
10024 [(match_operand:SI 1 "s_register_operand" "r")
10025 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10026 (match_operator:SI 7 "shiftable_operator"
10027 [(match_operand:SI 3 "s_register_operand" "r")
10028 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10029 "TARGET_ARM"
8a18b90c 10030 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10031 [(set_attr "conds" "use")
10032 (set_attr "length" "8")]
10033)
8a18b90c 10034
f7fbdd4a 10035(define_insn "*ifcompare_arith_move"
9c08d1fa 10036 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10037 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10038 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10039 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10040 (match_operator:SI 7 "shiftable_operator"
10041 [(match_operand:SI 4 "s_register_operand" "r,r")
10042 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10043 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10044 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10045 "TARGET_ARM"
9c08d1fa 10046 "*
9c08d1fa 10047 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10048 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10049 everything is in registers then we can do this in two instructions. */
9c08d1fa 10050 if (operands[3] == const0_rtx
10051 && GET_CODE (operands[7]) != AND
0438d37f 10052 && REG_P (operands[5])
10053 && REG_P (operands[1])
9c08d1fa 10054 && REGNO (operands[1]) == REGNO (operands[4])
10055 && REGNO (operands[4]) != REGNO (operands[0]))
10056 {
10057 if (GET_CODE (operands[6]) == LT)
40dbec34 10058 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10059 else if (GET_CODE (operands[6]) == GE)
40dbec34 10060 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10061 }
0438d37f 10062 if (CONST_INT_P (operands[3])
9c08d1fa 10063 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10064 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10065 else
e2348bcb 10066 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10067 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10068 if (which_alternative != 0)
129a2fe4 10069 return \"mov%D6\\t%0, %1\";
9c08d1fa 10070 return \"\";
215b30b3 10071 "
8fa3ba89 10072 [(set_attr "conds" "clob")
10073 (set_attr "length" "8,12")]
10074)
9c08d1fa 10075
8a18b90c 10076(define_insn "*if_arith_move"
129a2fe4 10077 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10078 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10079 [(match_operand 6 "cc_register" "") (const_int 0)])
10080 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10081 [(match_operand:SI 2 "s_register_operand" "r,r")
10082 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10083 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10084 "TARGET_ARM"
8a18b90c 10085 "@
10086 %I5%d4\\t%0, %2, %3
129a2fe4 10087 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10088 [(set_attr "conds" "use")
10089 (set_attr "length" "4,8")
10090 (set_attr "type" "*,*")]
10091)
8a18b90c 10092
f7fbdd4a 10093(define_insn "*ifcompare_move_arith"
9c08d1fa 10094 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10095 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10096 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10097 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10098 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10099 (match_operator:SI 7 "shiftable_operator"
10100 [(match_operand:SI 2 "s_register_operand" "r,r")
10101 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10102 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10103 "TARGET_ARM"
9c08d1fa 10104 "*
9c08d1fa 10105 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10106 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10107 everything is in registers then we can do this in two instructions */
10108 if (operands[5] == const0_rtx
10109 && GET_CODE (operands[7]) != AND
0438d37f 10110 && REG_P (operands[3])
10111 && REG_P (operands[1])
9c08d1fa 10112 && REGNO (operands[1]) == REGNO (operands[2])
10113 && REGNO (operands[2]) != REGNO (operands[0]))
10114 {
10115 if (GET_CODE (operands[6]) == GE)
40dbec34 10116 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10117 else if (GET_CODE (operands[6]) == LT)
40dbec34 10118 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10119 }
40dbec34 10120
0438d37f 10121 if (CONST_INT_P (operands[5])
9c08d1fa 10122 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10123 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10124 else
e2348bcb 10125 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10126
9c08d1fa 10127 if (which_alternative != 0)
129a2fe4 10128 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10129 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10130 "
8fa3ba89 10131 [(set_attr "conds" "clob")
10132 (set_attr "length" "8,12")]
10133)
9c08d1fa 10134
8a18b90c 10135(define_insn "*if_move_arith"
129a2fe4 10136 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10137 (if_then_else:SI
8fa3ba89 10138 (match_operator 4 "arm_comparison_operator"
8a18b90c 10139 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10140 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10141 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10142 [(match_operand:SI 2 "s_register_operand" "r,r")
10143 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10144 "TARGET_ARM"
8a18b90c 10145 "@
10146 %I5%D4\\t%0, %2, %3
129a2fe4 10147 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10148 [(set_attr "conds" "use")
10149 (set_attr "length" "4,8")
10150 (set_attr "type" "*,*")]
10151)
8a18b90c 10152
10153(define_insn "*ifcompare_move_not"
9c08d1fa 10154 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10155 (if_then_else:SI
8fa3ba89 10156 (match_operator 5 "arm_comparison_operator"
8a18b90c 10157 [(match_operand:SI 3 "s_register_operand" "r,r")
10158 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10159 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10160 (not:SI
10161 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10162 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10163 "TARGET_ARM"
8a18b90c 10164 "#"
8fa3ba89 10165 [(set_attr "conds" "clob")
10166 (set_attr "length" "8,12")]
10167)
9c08d1fa 10168
8a18b90c 10169(define_insn "*if_move_not"
10170 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10171 (if_then_else:SI
8fa3ba89 10172 (match_operator 4 "arm_comparison_operator"
8a18b90c 10173 [(match_operand 3 "cc_register" "") (const_int 0)])
10174 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10175 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10176 "TARGET_ARM"
8a18b90c 10177 "@
10178 mvn%D4\\t%0, %2
10179 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10180 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10181 [(set_attr "conds" "use")
d2a518d1 10182 (set_attr "insn" "mvn")
8fa3ba89 10183 (set_attr "length" "4,8,8")]
10184)
8a18b90c 10185
10186(define_insn "*ifcompare_not_move"
9c08d1fa 10187 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10188 (if_then_else:SI
8fa3ba89 10189 (match_operator 5 "arm_comparison_operator"
8a18b90c 10190 [(match_operand:SI 3 "s_register_operand" "r,r")
10191 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10192 (not:SI
10193 (match_operand:SI 2 "s_register_operand" "r,r"))
10194 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10195 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10196 "TARGET_ARM"
8a18b90c 10197 "#"
8fa3ba89 10198 [(set_attr "conds" "clob")
10199 (set_attr "length" "8,12")]
10200)
9c08d1fa 10201
8a18b90c 10202(define_insn "*if_not_move"
10203 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10204 (if_then_else:SI
8fa3ba89 10205 (match_operator 4 "arm_comparison_operator"
8a18b90c 10206 [(match_operand 3 "cc_register" "") (const_int 0)])
10207 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10208 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10209 "TARGET_ARM"
8a18b90c 10210 "@
10211 mvn%d4\\t%0, %2
10212 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10213 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10214 [(set_attr "conds" "use")
d2a518d1 10215 (set_attr "insn" "mvn")
8fa3ba89 10216 (set_attr "length" "4,8,8")]
10217)
8a18b90c 10218
10219(define_insn "*ifcompare_shift_move"
9c08d1fa 10220 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10221 (if_then_else:SI
8fa3ba89 10222 (match_operator 6 "arm_comparison_operator"
8a18b90c 10223 [(match_operand:SI 4 "s_register_operand" "r,r")
10224 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10225 (match_operator:SI 7 "shift_operator"
10226 [(match_operand:SI 2 "s_register_operand" "r,r")
10227 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10228 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10229 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10230 "TARGET_ARM"
9c08d1fa 10231 "#"
8fa3ba89 10232 [(set_attr "conds" "clob")
10233 (set_attr "length" "8,12")]
10234)
9c08d1fa 10235
8a18b90c 10236(define_insn "*if_shift_move"
10237 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10238 (if_then_else:SI
8fa3ba89 10239 (match_operator 5 "arm_comparison_operator"
8a18b90c 10240 [(match_operand 6 "cc_register" "") (const_int 0)])
10241 (match_operator:SI 4 "shift_operator"
10242 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10243 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10244 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10245 "TARGET_ARM"
5565501b 10246 "@
8a18b90c 10247 mov%d5\\t%0, %2%S4
10248 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10249 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10250 [(set_attr "conds" "use")
331beb1a 10251 (set_attr "shift" "2")
a2cd141b 10252 (set_attr "length" "4,8,8")
d2a518d1 10253 (set_attr "insn" "mov")
a2cd141b 10254 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10255 (const_string "alu_shift")
10256 (const_string "alu_shift_reg")))]
8fa3ba89 10257)
5565501b 10258
8a18b90c 10259(define_insn "*ifcompare_move_shift"
10260 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10261 (if_then_else:SI
8fa3ba89 10262 (match_operator 6 "arm_comparison_operator"
8a18b90c 10263 [(match_operand:SI 4 "s_register_operand" "r,r")
10264 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10265 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10266 (match_operator:SI 7 "shift_operator"
8a18b90c 10267 [(match_operand:SI 2 "s_register_operand" "r,r")
10268 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10269 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10270 "TARGET_ARM"
8a18b90c 10271 "#"
8fa3ba89 10272 [(set_attr "conds" "clob")
10273 (set_attr "length" "8,12")]
10274)
5565501b 10275
8a18b90c 10276(define_insn "*if_move_shift"
10277 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10278 (if_then_else:SI
8fa3ba89 10279 (match_operator 5 "arm_comparison_operator"
8a18b90c 10280 [(match_operand 6 "cc_register" "") (const_int 0)])
10281 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10282 (match_operator:SI 4 "shift_operator"
10283 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10284 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10285 "TARGET_ARM"
5565501b 10286 "@
8a18b90c 10287 mov%D5\\t%0, %2%S4
10288 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10289 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10290 [(set_attr "conds" "use")
331beb1a 10291 (set_attr "shift" "2")
a2cd141b 10292 (set_attr "length" "4,8,8")
d2a518d1 10293 (set_attr "insn" "mov")
a2cd141b 10294 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10295 (const_string "alu_shift")
10296 (const_string "alu_shift_reg")))]
8fa3ba89 10297)
9c08d1fa 10298
f7fbdd4a 10299(define_insn "*ifcompare_shift_shift"
8a18b90c 10300 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10301 (if_then_else:SI
8fa3ba89 10302 (match_operator 7 "arm_comparison_operator"
8a18b90c 10303 [(match_operand:SI 5 "s_register_operand" "r")
10304 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10305 (match_operator:SI 8 "shift_operator"
8a18b90c 10306 [(match_operand:SI 1 "s_register_operand" "r")
10307 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10308 (match_operator:SI 9 "shift_operator"
8a18b90c 10309 [(match_operand:SI 3 "s_register_operand" "r")
10310 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10311 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10312 "TARGET_ARM"
8a18b90c 10313 "#"
8fa3ba89 10314 [(set_attr "conds" "clob")
10315 (set_attr "length" "12")]
10316)
9c08d1fa 10317
8a18b90c 10318(define_insn "*if_shift_shift"
10319 [(set (match_operand:SI 0 "s_register_operand" "=r")
10320 (if_then_else:SI
8fa3ba89 10321 (match_operator 5 "arm_comparison_operator"
8a18b90c 10322 [(match_operand 8 "cc_register" "") (const_int 0)])
10323 (match_operator:SI 6 "shift_operator"
10324 [(match_operand:SI 1 "s_register_operand" "r")
10325 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10326 (match_operator:SI 7 "shift_operator"
10327 [(match_operand:SI 3 "s_register_operand" "r")
10328 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10329 "TARGET_ARM"
8a18b90c 10330 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10331 [(set_attr "conds" "use")
331beb1a 10332 (set_attr "shift" "1")
a2cd141b 10333 (set_attr "length" "8")
d2a518d1 10334 (set_attr "insn" "mov")
a2cd141b 10335 (set (attr "type") (if_then_else
10336 (and (match_operand 2 "const_int_operand" "")
10337 (match_operand 4 "const_int_operand" ""))
10338 (const_string "alu_shift")
10339 (const_string "alu_shift_reg")))]
8fa3ba89 10340)
8a18b90c 10341
f7fbdd4a 10342(define_insn "*ifcompare_not_arith"
8a18b90c 10343 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10344 (if_then_else:SI
8fa3ba89 10345 (match_operator 6 "arm_comparison_operator"
8a18b90c 10346 [(match_operand:SI 4 "s_register_operand" "r")
10347 (match_operand:SI 5 "arm_add_operand" "rIL")])
10348 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10349 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10350 [(match_operand:SI 2 "s_register_operand" "r")
10351 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10352 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10353 "TARGET_ARM"
8a18b90c 10354 "#"
8fa3ba89 10355 [(set_attr "conds" "clob")
10356 (set_attr "length" "12")]
10357)
9c08d1fa 10358
8a18b90c 10359(define_insn "*if_not_arith"
10360 [(set (match_operand:SI 0 "s_register_operand" "=r")
10361 (if_then_else:SI
8fa3ba89 10362 (match_operator 5 "arm_comparison_operator"
8a18b90c 10363 [(match_operand 4 "cc_register" "") (const_int 0)])
10364 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10365 (match_operator:SI 6 "shiftable_operator"
10366 [(match_operand:SI 2 "s_register_operand" "r")
10367 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10368 "TARGET_ARM"
8a18b90c 10369 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10370 [(set_attr "conds" "use")
d2a518d1 10371 (set_attr "insn" "mvn")
8fa3ba89 10372 (set_attr "length" "8")]
10373)
8a18b90c 10374
10375(define_insn "*ifcompare_arith_not"
10376 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10377 (if_then_else:SI
8fa3ba89 10378 (match_operator 6 "arm_comparison_operator"
8a18b90c 10379 [(match_operand:SI 4 "s_register_operand" "r")
10380 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10381 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10382 [(match_operand:SI 2 "s_register_operand" "r")
10383 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10384 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10385 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10386 "TARGET_ARM"
8a18b90c 10387 "#"
8fa3ba89 10388 [(set_attr "conds" "clob")
10389 (set_attr "length" "12")]
10390)
9c08d1fa 10391
8a18b90c 10392(define_insn "*if_arith_not"
10393 [(set (match_operand:SI 0 "s_register_operand" "=r")
10394 (if_then_else:SI
8fa3ba89 10395 (match_operator 5 "arm_comparison_operator"
8a18b90c 10396 [(match_operand 4 "cc_register" "") (const_int 0)])
10397 (match_operator:SI 6 "shiftable_operator"
10398 [(match_operand:SI 2 "s_register_operand" "r")
10399 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10400 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10401 "TARGET_ARM"
8a18b90c 10402 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10403 [(set_attr "conds" "use")
d2a518d1 10404 (set_attr "insn" "mvn")
8fa3ba89 10405 (set_attr "length" "8")]
10406)
8a18b90c 10407
f7fbdd4a 10408(define_insn "*ifcompare_neg_move"
8a18b90c 10409 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10410 (if_then_else:SI
8fa3ba89 10411 (match_operator 5 "arm_comparison_operator"
8a18b90c 10412 [(match_operand:SI 3 "s_register_operand" "r,r")
10413 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10414 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10415 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10416 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10417 "TARGET_ARM"
8a18b90c 10418 "#"
8fa3ba89 10419 [(set_attr "conds" "clob")
10420 (set_attr "length" "8,12")]
10421)
8a18b90c 10422
10423(define_insn "*if_neg_move"
10424 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10425 (if_then_else:SI
8fa3ba89 10426 (match_operator 4 "arm_comparison_operator"
8a18b90c 10427 [(match_operand 3 "cc_register" "") (const_int 0)])
10428 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10429 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10430 "TARGET_ARM"
8a18b90c 10431 "@
10432 rsb%d4\\t%0, %2, #0
10433 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10434 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10435 [(set_attr "conds" "use")
10436 (set_attr "length" "4,8,8")]
10437)
9c08d1fa 10438
f7fbdd4a 10439(define_insn "*ifcompare_move_neg"
8a18b90c 10440 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10441 (if_then_else:SI
8fa3ba89 10442 (match_operator 5 "arm_comparison_operator"
8a18b90c 10443 [(match_operand:SI 3 "s_register_operand" "r,r")
10444 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10445 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10446 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10447 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10448 "TARGET_ARM"
8a18b90c 10449 "#"
8fa3ba89 10450 [(set_attr "conds" "clob")
10451 (set_attr "length" "8,12")]
10452)
8a18b90c 10453
10454(define_insn "*if_move_neg"
10455 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10456 (if_then_else:SI
8fa3ba89 10457 (match_operator 4 "arm_comparison_operator"
8a18b90c 10458 [(match_operand 3 "cc_register" "") (const_int 0)])
10459 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10460 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10461 "TARGET_ARM"
8a18b90c 10462 "@
10463 rsb%D4\\t%0, %2, #0
10464 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10465 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10466 [(set_attr "conds" "use")
10467 (set_attr "length" "4,8,8")]
10468)
9c08d1fa 10469
f7fbdd4a 10470(define_insn "*arith_adjacentmem"
9c08d1fa 10471 [(set (match_operand:SI 0 "s_register_operand" "=r")
10472 (match_operator:SI 1 "shiftable_operator"
10473 [(match_operand:SI 2 "memory_operand" "m")
10474 (match_operand:SI 3 "memory_operand" "m")]))
10475 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10476 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10477 "*
215b30b3 10478 {
10479 rtx ldm[3];
10480 rtx arith[4];
94dee231 10481 rtx base_reg;
10482 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10483
215b30b3 10484 if (REGNO (operands[0]) > REGNO (operands[4]))
10485 {
10486 ldm[1] = operands[4];
10487 ldm[2] = operands[0];
10488 }
10489 else
10490 {
10491 ldm[1] = operands[0];
10492 ldm[2] = operands[4];
10493 }
94dee231 10494
10495 base_reg = XEXP (operands[2], 0);
10496
10497 if (!REG_P (base_reg))
10498 {
10499 val1 = INTVAL (XEXP (base_reg, 1));
10500 base_reg = XEXP (base_reg, 0);
10501 }
10502
10503 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10504 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10505
215b30b3 10506 arith[0] = operands[0];
10507 arith[3] = operands[1];
94dee231 10508
215b30b3 10509 if (val1 < val2)
10510 {
10511 arith[1] = ldm[1];
10512 arith[2] = ldm[2];
10513 }
10514 else
10515 {
10516 arith[1] = ldm[2];
10517 arith[2] = ldm[1];
10518 }
94dee231 10519
10520 ldm[0] = base_reg;
10521 if (val1 !=0 && val2 != 0)
215b30b3 10522 {
cdb1295a 10523 rtx ops[3];
10524
94dee231 10525 if (val1 == 4 || val2 == 4)
10526 /* Other val must be 8, since we know they are adjacent and neither
10527 is zero. */
25f905c2 10528 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10529 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10530 {
94dee231 10531 ldm[0] = ops[0] = operands[4];
10532 ops[1] = base_reg;
10533 ops[2] = GEN_INT (val1);
10534 output_add_immediate (ops);
10535 if (val1 < val2)
25f905c2 10536 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10537 else
25f905c2 10538 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10539 }
cdb1295a 10540 else
10541 {
10542 /* Offset is out of range for a single add, so use two ldr. */
10543 ops[0] = ldm[1];
10544 ops[1] = base_reg;
10545 ops[2] = GEN_INT (val1);
10546 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10547 ops[0] = ldm[2];
10548 ops[2] = GEN_INT (val2);
10549 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10550 }
215b30b3 10551 }
94dee231 10552 else if (val1 != 0)
215b30b3 10553 {
215b30b3 10554 if (val1 < val2)
25f905c2 10555 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10556 else
25f905c2 10557 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10558 }
10559 else
10560 {
215b30b3 10561 if (val1 < val2)
25f905c2 10562 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10563 else
25f905c2 10564 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10565 }
10566 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10567 return \"\";
10568 }"
10569 [(set_attr "length" "12")
10570 (set_attr "predicable" "yes")
a2cd141b 10571 (set_attr "type" "load1")]
215b30b3 10572)
9c08d1fa 10573
9c08d1fa 10574; This pattern is never tried by combine, so do it as a peephole
10575
a0f94409 10576(define_peephole2
372575c7 10577 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10578 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10579 (set (reg:CC CC_REGNUM)
aea4c774 10580 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10581 "TARGET_ARM"
a0f94409 10582 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10583 (set (match_dup 0) (match_dup 1))])]
10584 ""
0d66636f 10585)
9c08d1fa 10586
9c08d1fa 10587(define_split
10588 [(set (match_operand:SI 0 "s_register_operand" "")
10589 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10590 (const_int 0))
8fa3ba89 10591 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10592 [(match_operand:SI 3 "s_register_operand" "")
10593 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10594 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10595 "TARGET_ARM"
9c08d1fa 10596 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10597 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10598 (match_dup 5)))]
215b30b3 10599 ""
10600)
9c08d1fa 10601
aea4c774 10602;; This split can be used because CC_Z mode implies that the following
10603;; branch will be an equality, or an unsigned inequality, so the sign
10604;; extension is not needed.
9c08d1fa 10605
aea4c774 10606(define_split
bd5b4116 10607 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10608 (compare:CC_Z
10609 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10610 (const_int 24))
aea4c774 10611 (match_operand 1 "const_int_operand" "")))
10612 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10613 "TARGET_ARM
10614 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10615 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10616 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10617 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10618 "
9c08d1fa 10619 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10620 "
10621)
25f905c2 10622;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10623
87b22bf7 10624(define_expand "prologue"
10625 [(clobber (const_int 0))]
cffb2a26 10626 "TARGET_EITHER"
25f905c2 10627 "if (TARGET_32BIT)
cffb2a26 10628 arm_expand_prologue ();
10629 else
25f905c2 10630 thumb1_expand_prologue ();
87b22bf7 10631 DONE;
cffb2a26 10632 "
10633)
87b22bf7 10634
56d27660 10635(define_expand "epilogue"
4c44712e 10636 [(clobber (const_int 0))]
cffb2a26 10637 "TARGET_EITHER"
56d27660 10638 "
18d50ae6 10639 if (crtl->calls_eh_return)
fb94f18b 10640 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10641 if (TARGET_THUMB1)
c3635784 10642 {
10643 thumb1_expand_epilogue ();
10644 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10645 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10646 }
10647 else if (HAVE_return)
10648 {
10649 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10650 no need for explicit testing again. */
10651 emit_jump_insn (gen_return ());
10652 }
10653 else if (TARGET_32BIT)
10654 {
10655 arm_expand_epilogue (true);
10656 }
cffb2a26 10657 DONE;
10658 "
10659)
56d27660 10660
7571d3f7 10661(define_insn "prologue_thumb1_interwork"
10662 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
10663 "TARGET_THUMB1"
10664 "* return thumb1_output_interwork ();"
10665 [(set_attr "length" "8")]
10666)
10667
ef5651d0 10668;; Note - although unspec_volatile's USE all hard registers,
10669;; USEs are ignored after relaod has completed. Thus we need
10670;; to add an unspec of the link register to ensure that flow
10671;; does not think that it is unused by the sibcall branch that
10672;; will replace the standard function epilogue.
c3635784 10673(define_expand "sibcall_epilogue"
fb94f18b 10674 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10675 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10676 "TARGET_32BIT"
10677 "
10678 arm_expand_epilogue (false);
10679 DONE;
10680 "
1c494086 10681)
10682
cffb2a26 10683(define_insn "*epilogue_insns"
e1159bbe 10684 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
b1324f4f 10685 "TARGET_THUMB1"
56d27660 10686 "*
e7fd8dfa 10687 return thumb1_unexpanded_epilogue ();
cffb2a26 10688 "
215b30b3 10689 ; Length is absolute worst case
cffb2a26 10690 [(set_attr "length" "44")
defc47cf 10691 (set_attr "type" "block")
10692 ;; We don't clobber the conditions, but the potential length of this
10693 ;; operation is sufficient to make conditionalizing the sequence
10694 ;; unlikely to be profitable.
10695 (set_attr "conds" "clob")]
cffb2a26 10696)
10697
10698(define_expand "eh_epilogue"
7db9af5d 10699 [(use (match_operand:SI 0 "register_operand" ""))
10700 (use (match_operand:SI 1 "register_operand" ""))
10701 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10702 "TARGET_EITHER"
10703 "
215b30b3 10704 {
10705 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10706 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10707 {
10708 rtx ra = gen_rtx_REG (Pmode, 2);
10709
10710 emit_move_insn (ra, operands[2]);
10711 operands[2] = ra;
10712 }
5cf3595a 10713 /* This is a hack -- we may have crystalized the function type too
10714 early. */
10715 cfun->machine->func_type = 0;
215b30b3 10716 }"
10717)
56d27660 10718
9c08d1fa 10719;; This split is only used during output to reduce the number of patterns
10720;; that need assembler instructions adding to them. We allowed the setting
10721;; of the conditions to be implicit during rtl generation so that
10722;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10723;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10724;; up again here.
10725
25f905c2 10726;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10727;; conditional execution sufficient?
10728
9c08d1fa 10729(define_split
10730 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10731 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10732 [(match_operand 2 "" "") (match_operand 3 "" "")])
10733 (match_dup 0)
10734 (match_operand 4 "" "")))
bd5b4116 10735 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10736 "TARGET_ARM && reload_completed"
8fa3ba89 10737 [(set (match_dup 5) (match_dup 6))
10738 (cond_exec (match_dup 7)
10739 (set (match_dup 0) (match_dup 4)))]
10740 "
10741 {
10742 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10743 operands[2], operands[3]);
10744 enum rtx_code rc = GET_CODE (operands[1]);
10745
bd5b4116 10746 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10747 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10748 if (mode == CCFPmode || mode == CCFPEmode)
10749 rc = reverse_condition_maybe_unordered (rc);
10750 else
10751 rc = reverse_condition (rc);
10752
10753 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10754 }"
10755)
10756
10757(define_split
10758 [(set (match_operand:SI 0 "s_register_operand" "")
10759 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10760 [(match_operand 2 "" "") (match_operand 3 "" "")])
10761 (match_operand 4 "" "")
10762 (match_dup 0)))
bd5b4116 10763 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10764 "TARGET_ARM && reload_completed"
8fa3ba89 10765 [(set (match_dup 5) (match_dup 6))
10766 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10767 (set (match_dup 0) (match_dup 4)))]
10768 "
10769 {
10770 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10771 operands[2], operands[3]);
10772
bd5b4116 10773 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10774 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10775 }"
10776)
10777
10778(define_split
10779 [(set (match_operand:SI 0 "s_register_operand" "")
10780 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10781 [(match_operand 2 "" "") (match_operand 3 "" "")])
10782 (match_operand 4 "" "")
10783 (match_operand 5 "" "")))
bd5b4116 10784 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10785 "TARGET_ARM && reload_completed"
8fa3ba89 10786 [(set (match_dup 6) (match_dup 7))
10787 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10788 (set (match_dup 0) (match_dup 4)))
10789 (cond_exec (match_dup 8)
10790 (set (match_dup 0) (match_dup 5)))]
10791 "
10792 {
10793 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10794 operands[2], operands[3]);
10795 enum rtx_code rc = GET_CODE (operands[1]);
10796
bd5b4116 10797 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10798 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10799 if (mode == CCFPmode || mode == CCFPEmode)
10800 rc = reverse_condition_maybe_unordered (rc);
10801 else
10802 rc = reverse_condition (rc);
10803
10804 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10805 }"
10806)
10807
cffb2a26 10808(define_split
10809 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10810 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10811 [(match_operand:SI 2 "s_register_operand" "")
10812 (match_operand:SI 3 "arm_add_operand" "")])
10813 (match_operand:SI 4 "arm_rhs_operand" "")
10814 (not:SI
10815 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10816 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10817 "TARGET_ARM && reload_completed"
cffb2a26 10818 [(set (match_dup 6) (match_dup 7))
f6c53574 10819 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10820 (set (match_dup 0) (match_dup 4)))
10821 (cond_exec (match_dup 8)
10822 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10823 "
215b30b3 10824 {
10825 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10826 operands[2], operands[3]);
f6c53574 10827 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10828
bd5b4116 10829 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10830 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10831 if (mode == CCFPmode || mode == CCFPEmode)
10832 rc = reverse_condition_maybe_unordered (rc);
10833 else
10834 rc = reverse_condition (rc);
10835
10836 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10837 }"
10838)
cffb2a26 10839
10840(define_insn "*cond_move_not"
10841 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10842 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10843 [(match_operand 3 "cc_register" "") (const_int 0)])
10844 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10845 (not:SI
10846 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10847 "TARGET_ARM"
10848 "@
10849 mvn%D4\\t%0, %2
10850 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10851 [(set_attr "conds" "use")
d2a518d1 10852 (set_attr "insn" "mvn")
0d66636f 10853 (set_attr "length" "4,8")]
10854)
cffb2a26 10855
9c08d1fa 10856;; The next two patterns occur when an AND operation is followed by a
10857;; scc insn sequence
10858
f7fbdd4a 10859(define_insn "*sign_extract_onebit"
9c08d1fa 10860 [(set (match_operand:SI 0 "s_register_operand" "=r")
10861 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10862 (const_int 1)
ed750274 10863 (match_operand:SI 2 "const_int_operand" "n")))
10864 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10865 "TARGET_ARM"
9c08d1fa 10866 "*
0d66636f 10867 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10868 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10869 return \"mvnne\\t%0, #0\";
10870 "
10871 [(set_attr "conds" "clob")
10872 (set_attr "length" "8")]
10873)
9c08d1fa 10874
f7fbdd4a 10875(define_insn "*not_signextract_onebit"
9c08d1fa 10876 [(set (match_operand:SI 0 "s_register_operand" "=r")
10877 (not:SI
10878 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10879 (const_int 1)
ed750274 10880 (match_operand:SI 2 "const_int_operand" "n"))))
10881 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10882 "TARGET_ARM"
9c08d1fa 10883 "*
0d66636f 10884 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10885 output_asm_insn (\"tst\\t%1, %2\", operands);
10886 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10887 return \"movne\\t%0, #0\";
10888 "
10889 [(set_attr "conds" "clob")
10890 (set_attr "length" "12")]
10891)
25f905c2 10892;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10893
0d66636f 10894;; Push multiple registers to the stack. Registers are in parallel (use ...)
10895;; expressions. For simplicity, the first register is also in the unspec
10896;; part.
08508cbf 10897;; To avoid the usage of GNU extension, the length attribute is computed
10898;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10899(define_insn "*push_multi"
87b22bf7 10900 [(match_parallel 2 "multi_register_push"
7571d3f7 10901 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10902 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10903 UNSPEC_PUSH_MULT))])]
7571d3f7 10904 ""
87b22bf7 10905 "*
215b30b3 10906 {
10907 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10908
215b30b3 10909 /* For the StrongARM at least it is faster to
25f905c2 10910 use STR to store only a single register.
542d5028 10911 In Thumb mode always use push, and the assembler will pick
10912 something appropriate. */
25f905c2 10913 if (num_saves == 1 && TARGET_ARM)
61309563 10914 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10915 else
10916 {
10917 int i;
10918 char pattern[100];
ed593f11 10919
25f905c2 10920 if (TARGET_ARM)
61309563 10921 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10922 else if (TARGET_THUMB2)
10923 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10924 else
10925 strcpy (pattern, \"push\\t{%1\");
215b30b3 10926
6079f055 10927 for (i = 1; i < num_saves; i++)
215b30b3 10928 {
10929 strcat (pattern, \", %|\");
10930 strcat (pattern,
10931 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10932 }
10933
10934 strcat (pattern, \"}\");
10935 output_asm_insn (pattern, operands);
10936 }
10937
10938 return \"\";
10939 }"
a6864a24 10940 [(set_attr "type" "store4")
10941 (set (attr "length")
08508cbf 10942 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10943)
f7fbdd4a 10944
4c58c898 10945(define_insn "stack_tie"
10946 [(set (mem:BLK (scratch))
aaa37ad6 10947 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10948 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10949 UNSPEC_PRLG_STK))]
10950 ""
10951 ""
10952 [(set_attr "length" "0")]
10953)
10954
426be8c5 10955;; Pop (as used in epilogue RTL)
10956;;
10957(define_insn "*load_multiple_with_writeback"
10958 [(match_parallel 0 "load_multiple_operation"
10959 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10960 (plus:SI (match_dup 1)
10961 (match_operand:SI 2 "const_int_operand" "I")))
10962 (set (match_operand:SI 3 "s_register_operand" "=rk")
10963 (mem:SI (match_dup 1)))
10964 ])]
10965 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10966 "*
10967 {
10968 arm_output_multireg_pop (operands, /*return_pc=*/false,
10969 /*cond=*/const_true_rtx,
10970 /*reverse=*/false,
10971 /*update=*/true);
10972 return \"\";
10973 }
10974 "
10975 [(set_attr "type" "load4")
10976 (set_attr "predicable" "yes")]
10977)
10978
10979;; Pop with return (as used in epilogue RTL)
10980;;
10981;; This instruction is generated when the registers are popped at the end of
10982;; epilogue. Here, instead of popping the value into LR and then generating
10983;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10984;; with (return).
10985(define_insn "*pop_multiple_with_writeback_and_return"
10986 [(match_parallel 0 "pop_multiple_return"
10987 [(return)
10988 (set (match_operand:SI 1 "s_register_operand" "+rk")
10989 (plus:SI (match_dup 1)
10990 (match_operand:SI 2 "const_int_operand" "I")))
10991 (set (match_operand:SI 3 "s_register_operand" "=rk")
10992 (mem:SI (match_dup 1)))
10993 ])]
10994 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10995 "*
10996 {
10997 arm_output_multireg_pop (operands, /*return_pc=*/true,
10998 /*cond=*/const_true_rtx,
10999 /*reverse=*/false,
11000 /*update=*/true);
11001 return \"\";
11002 }
11003 "
11004 [(set_attr "type" "load4")
11005 (set_attr "predicable" "yes")]
11006)
11007
11008(define_insn "*pop_multiple_with_return"
11009 [(match_parallel 0 "pop_multiple_return"
11010 [(return)
11011 (set (match_operand:SI 2 "s_register_operand" "=rk")
11012 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11013 ])]
11014 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11015 "*
11016 {
11017 arm_output_multireg_pop (operands, /*return_pc=*/true,
11018 /*cond=*/const_true_rtx,
11019 /*reverse=*/false,
11020 /*update=*/false);
11021 return \"\";
11022 }
11023 "
11024 [(set_attr "type" "load4")
11025 (set_attr "predicable" "yes")]
11026)
11027
11028;; Load into PC and return
11029(define_insn "*ldr_with_return"
11030 [(return)
11031 (set (reg:SI PC_REGNUM)
11032 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11033 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11034 "ldr%?\t%|pc, [%0], #4"
11035 [(set_attr "type" "load1")
11036 (set_attr "predicable" "yes")]
11037)
1a0b0f12 11038;; Pop for floating point registers (as used in epilogue RTL)
11039(define_insn "*vfp_pop_multiple_with_writeback"
11040 [(match_parallel 0 "pop_multiple_fp"
11041 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11042 (plus:SI (match_dup 1)
11043 (match_operand:SI 2 "const_int_operand" "I")))
11044 (set (match_operand:DF 3 "arm_hard_register_operand" "")
11045 (mem:DF (match_dup 1)))])]
11046 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
11047 "*
11048 {
11049 int num_regs = XVECLEN (operands[0], 0);
11050 char pattern[100];
11051 rtx op_list[2];
11052 strcpy (pattern, \"fldmfdd\\t\");
11053 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11054 strcat (pattern, \"!, {\");
11055 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11056 strcat (pattern, \"%P0\");
11057 if ((num_regs - 1) > 1)
11058 {
11059 strcat (pattern, \"-%P1\");
11060 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11061 }
11062
11063 strcat (pattern, \"}\");
11064 output_asm_insn (pattern, op_list);
11065 return \"\";
11066 }
11067 "
11068 [(set_attr "type" "load4")
11069 (set_attr "conds" "unconditional")
11070 (set_attr "predicable" "no")]
11071)
11072
f7fbdd4a 11073;; Special patterns for dealing with the constant pool
11074
cffb2a26 11075(define_insn "align_4"
e1159bbe 11076 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11077 "TARGET_EITHER"
f7fbdd4a 11078 "*
cffb2a26 11079 assemble_align (32);
f7fbdd4a 11080 return \"\";
cffb2a26 11081 "
11082)
f7fbdd4a 11083
755eb2b4 11084(define_insn "align_8"
11085 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11086 "TARGET_EITHER"
755eb2b4 11087 "*
11088 assemble_align (64);
11089 return \"\";
11090 "
11091)
11092
cffb2a26 11093(define_insn "consttable_end"
e1159bbe 11094 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11095 "TARGET_EITHER"
f7fbdd4a 11096 "*
cffb2a26 11097 making_const_table = FALSE;
f7fbdd4a 11098 return \"\";
cffb2a26 11099 "
11100)
f7fbdd4a 11101
cffb2a26 11102(define_insn "consttable_1"
e1159bbe 11103 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 11104 "TARGET_THUMB1"
f7fbdd4a 11105 "*
cffb2a26 11106 making_const_table = TRUE;
09d688ff 11107 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 11108 assemble_zeros (3);
f7fbdd4a 11109 return \"\";
cffb2a26 11110 "
11111 [(set_attr "length" "4")]
11112)
f7fbdd4a 11113
cffb2a26 11114(define_insn "consttable_2"
e1159bbe 11115 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 11116 "TARGET_THUMB1"
f7fbdd4a 11117 "*
cffb2a26 11118 making_const_table = TRUE;
9b8516be 11119 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 11120 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 11121 assemble_zeros (2);
f7fbdd4a 11122 return \"\";
cffb2a26 11123 "
11124 [(set_attr "length" "4")]
11125)
11126
11127(define_insn "consttable_4"
e1159bbe 11128 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11129 "TARGET_EITHER"
11130 "*
11131 {
9b8516be 11132 rtx x = operands[0];
cffb2a26 11133 making_const_table = TRUE;
9b8516be 11134 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 11135 {
11136 case MODE_FLOAT:
9b8516be 11137 if (GET_MODE (x) == HFmode)
11138 arm_emit_fp16_const (x);
11139 else
11140 {
11141 REAL_VALUE_TYPE r;
11142 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
11143 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
11144 }
11145 break;
cffb2a26 11146 default:
7b04c5d5 11147 /* XXX: Sometimes gcc does something really dumb and ends up with
11148 a HIGH in a constant pool entry, usually because it's trying to
11149 load into a VFP register. We know this will always be used in
11150 combination with a LO_SUM which ignores the high bits, so just
11151 strip off the HIGH. */
11152 if (GET_CODE (x) == HIGH)
11153 x = XEXP (x, 0);
9b8516be 11154 assemble_integer (x, 4, BITS_PER_WORD, 1);
11155 mark_symbol_refs_as_used (x);
cffb2a26 11156 break;
11157 }
11158 return \"\";
11159 }"
11160 [(set_attr "length" "4")]
11161)
11162
11163(define_insn "consttable_8"
e1159bbe 11164 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11165 "TARGET_EITHER"
11166 "*
11167 {
11168 making_const_table = TRUE;
11169 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11170 {
11171 case MODE_FLOAT:
11172 {
badfe841 11173 REAL_VALUE_TYPE r;
11174 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11175 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 11176 break;
11177 }
11178 default:
09d688ff 11179 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11180 break;
11181 }
11182 return \"\";
11183 }"
11184 [(set_attr "length" "8")]
11185)
11186
d98a3884 11187(define_insn "consttable_16"
11188 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11189 "TARGET_EITHER"
11190 "*
11191 {
11192 making_const_table = TRUE;
11193 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11194 {
11195 case MODE_FLOAT:
11196 {
11197 REAL_VALUE_TYPE r;
11198 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11199 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11200 break;
11201 }
11202 default:
11203 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11204 break;
11205 }
11206 return \"\";
11207 }"
11208 [(set_attr "length" "16")]
11209)
11210
cffb2a26 11211;; Miscellaneous Thumb patterns
11212
fd957ef3 11213(define_expand "tablejump"
7db9af5d 11214 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 11215 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 11216 "TARGET_THUMB1"
fd957ef3 11217 "
11218 if (flag_pic)
11219 {
11220 /* Hopefully, CSE will eliminate this copy. */
11221 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11222 rtx reg2 = gen_reg_rtx (SImode);
11223
11224 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11225 operands[0] = reg2;
11226 }
11227 "
11228)
11229
f1039640 11230;; NB never uses BX.
25f905c2 11231(define_insn "*thumb1_tablejump"
cffb2a26 11232 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11233 (use (label_ref (match_operand 1 "" "")))]
25f905c2 11234 "TARGET_THUMB1"
fd957ef3 11235 "mov\\t%|pc, %0"
cffb2a26 11236 [(set_attr "length" "2")]
11237)
0d66636f 11238
331beb1a 11239;; V5 Instructions,
11240
8f4be2be 11241(define_insn "clzsi2"
11242 [(set (match_operand:SI 0 "s_register_operand" "=r")
11243 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11244 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11245 "clz%?\\t%0, %1"
bcaec148 11246 [(set_attr "predicable" "yes")
11247 (set_attr "insn" "clz")])
331beb1a 11248
099ad98b 11249(define_insn "rbitsi2"
11250 [(set (match_operand:SI 0 "s_register_operand" "=r")
11251 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11252 "TARGET_32BIT && arm_arch_thumb2"
11253 "rbit%?\\t%0, %1"
11254 [(set_attr "predicable" "yes")
11255 (set_attr "insn" "clz")])
11256
11257(define_expand "ctzsi2"
11258 [(set (match_operand:SI 0 "s_register_operand" "")
11259 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
11260 "TARGET_32BIT && arm_arch_thumb2"
11261 "
30191172 11262 {
11263 rtx tmp = gen_reg_rtx (SImode);
11264 emit_insn (gen_rbitsi2 (tmp, operands[1]));
11265 emit_insn (gen_clzsi2 (operands[0], tmp));
11266 }
099ad98b 11267 DONE;
11268 "
11269)
11270
e1159bbe 11271;; V5E instructions.
331beb1a 11272
11273(define_insn "prefetch"
f4e79814 11274 [(prefetch (match_operand:SI 0 "address_operand" "p")
11275 (match_operand:SI 1 "" "")
11276 (match_operand:SI 2 "" ""))]
25f905c2 11277 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 11278 "pld\\t%a0")
331beb1a 11279
0d66636f 11280;; General predication pattern
11281
11282(define_cond_exec
11283 [(match_operator 0 "arm_comparison_operator"
11284 [(match_operand 1 "cc_register" "")
11285 (const_int 0)])]
25f905c2 11286 "TARGET_32BIT"
0d66636f 11287 ""
11288)
11289
fb94f18b 11290(define_insn "force_register_use"
11291 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11292 ""
fb94f18b 11293 "%@ %0 needed"
02cfc9c9 11294 [(set_attr "length" "0")]
063a05c7 11295)
7db9af5d 11296
4c44712e 11297
11298;; Patterns for exception handling
11299
11300(define_expand "eh_return"
11301 [(use (match_operand 0 "general_operand" ""))]
11302 "TARGET_EITHER"
11303 "
11304 {
25f905c2 11305 if (TARGET_32BIT)
4c44712e 11306 emit_insn (gen_arm_eh_return (operands[0]));
11307 else
11308 emit_insn (gen_thumb_eh_return (operands[0]));
11309 DONE;
11310 }"
11311)
11312
11313;; We can't expand this before we know where the link register is stored.
11314(define_insn_and_split "arm_eh_return"
11315 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11316 VUNSPEC_EH_RETURN)
11317 (clobber (match_scratch:SI 1 "=&r"))]
11318 "TARGET_ARM"
11319 "#"
11320 "&& reload_completed"
11321 [(const_int 0)]
11322 "
11323 {
11324 arm_set_return_address (operands[0], operands[1]);
11325 DONE;
11326 }"
11327)
11328
11329(define_insn_and_split "thumb_eh_return"
11330 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11331 VUNSPEC_EH_RETURN)
11332 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 11333 "TARGET_THUMB1"
4c44712e 11334 "#"
11335 "&& reload_completed"
11336 [(const_int 0)]
11337 "
11338 {
11339 thumb_set_return_address (operands[0], operands[1]);
11340 DONE;
11341 }"
11342)
11343
f655717d 11344\f
11345;; TLS support
11346
11347(define_insn "load_tp_hard"
11348 [(set (match_operand:SI 0 "register_operand" "=r")
11349 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11350 "TARGET_HARD_TP"
11351 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11352 [(set_attr "predicable" "yes")]
11353)
11354
11355;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11356(define_insn "load_tp_soft"
11357 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11358 (clobber (reg:SI LR_REGNUM))
11359 (clobber (reg:SI IP_REGNUM))
11360 (clobber (reg:CC CC_REGNUM))]
11361 "TARGET_SOFT_TP"
11362 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11363 [(set_attr "conds" "clob")]
11364)
11365
f41e4452 11366;; tls descriptor call
11367(define_insn "tlscall"
11368 [(set (reg:SI R0_REGNUM)
11369 (unspec:SI [(reg:SI R0_REGNUM)
11370 (match_operand:SI 0 "" "X")
11371 (match_operand 1 "" "")] UNSPEC_TLS))
11372 (clobber (reg:SI R1_REGNUM))
11373 (clobber (reg:SI LR_REGNUM))
11374 (clobber (reg:SI CC_REGNUM))]
11375 "TARGET_GNU2_TLS"
11376 {
11377 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11378 INTVAL (operands[1]));
11379 return "bl\\t%c0(tlscall)";
11380 }
11381 [(set_attr "conds" "clob")
11382 (set_attr "length" "4")]
11383)
11384
1fe0edab 11385;; For thread pointer builtin
11386(define_expand "get_thread_pointersi"
11387 [(match_operand:SI 0 "s_register_operand" "=r")]
11388 ""
11389 "
11390 {
11391 arm_load_tp (operands[0]);
11392 DONE;
11393 }")
11394
f41e4452 11395;;
11396
aabe09ac 11397;; We only care about the lower 16 bits of the constant
11398;; being inserted into the upper 16 bits of the register.
eca5c984 11399(define_insn "*arm_movtas_ze"
11400 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11401 (const_int 16)
11402 (const_int 16))
11403 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 11404 "arm_arch_thumb2"
aabe09ac 11405 "movt%?\t%0, %L1"
eca5c984 11406 [(set_attr "predicable" "yes")
11407 (set_attr "length" "4")]
11408)
11409
c0fc3696 11410(define_insn "*arm_rev"
a486b499 11411 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11412 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11413 "arm_arch6"
11414 "@
11415 rev\t%0, %1
11416 rev%?\t%0, %1
11417 rev%?\t%0, %1"
11418 [(set_attr "arch" "t1,t2,32")
11419 (set_attr "length" "2,2,4")]
ff82f757 11420)
11421
11422(define_expand "arm_legacy_rev"
11423 [(set (match_operand:SI 2 "s_register_operand" "")
11424 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11425 (const_int 16))
11426 (match_dup 1)))
11427 (set (match_dup 2)
11428 (lshiftrt:SI (match_dup 2)
11429 (const_int 8)))
11430 (set (match_operand:SI 3 "s_register_operand" "")
11431 (rotatert:SI (match_dup 1)
11432 (const_int 8)))
11433 (set (match_dup 2)
11434 (and:SI (match_dup 2)
11435 (const_int -65281)))
11436 (set (match_operand:SI 0 "s_register_operand" "")
11437 (xor:SI (match_dup 3)
11438 (match_dup 2)))]
11439 "TARGET_32BIT"
11440 ""
11441)
11442
11443;; Reuse temporaries to keep register pressure down.
11444(define_expand "thumb_legacy_rev"
11445 [(set (match_operand:SI 2 "s_register_operand" "")
11446 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11447 (const_int 24)))
11448 (set (match_operand:SI 3 "s_register_operand" "")
11449 (lshiftrt:SI (match_dup 1)
11450 (const_int 24)))
11451 (set (match_dup 3)
11452 (ior:SI (match_dup 3)
11453 (match_dup 2)))
11454 (set (match_operand:SI 4 "s_register_operand" "")
11455 (const_int 16))
11456 (set (match_operand:SI 5 "s_register_operand" "")
11457 (rotatert:SI (match_dup 1)
11458 (match_dup 4)))
11459 (set (match_dup 2)
11460 (ashift:SI (match_dup 5)
11461 (const_int 24)))
11462 (set (match_dup 5)
11463 (lshiftrt:SI (match_dup 5)
11464 (const_int 24)))
11465 (set (match_dup 5)
11466 (ior:SI (match_dup 5)
11467 (match_dup 2)))
11468 (set (match_dup 5)
11469 (rotatert:SI (match_dup 5)
11470 (match_dup 4)))
11471 (set (match_operand:SI 0 "s_register_operand" "")
11472 (ior:SI (match_dup 5)
11473 (match_dup 3)))]
11474 "TARGET_THUMB"
11475 ""
11476)
11477
11478(define_expand "bswapsi2"
11479 [(set (match_operand:SI 0 "s_register_operand" "=r")
11480 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11481"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11482"
8d1af482 11483 if (!arm_arch6)
11484 {
11485 rtx op2 = gen_reg_rtx (SImode);
11486 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11487
8d1af482 11488 if (TARGET_THUMB)
11489 {
11490 rtx op4 = gen_reg_rtx (SImode);
11491 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11492
8d1af482 11493 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11494 op2, op3, op4, op5));
11495 }
11496 else
11497 {
11498 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11499 op2, op3));
11500 }
ff82f757 11501
8d1af482 11502 DONE;
11503 }
ff82f757 11504 "
11505)
11506
a486b499 11507;; bswap16 patterns: use revsh and rev16 instructions for the signed
11508;; and unsigned variants, respectively. For rev16, expose
11509;; byte-swapping in the lower 16 bits only.
11510(define_insn "*arm_revsh"
11511 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11512 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11513 "arm_arch6"
11514 "@
11515 revsh\t%0, %1
11516 revsh%?\t%0, %1
11517 revsh%?\t%0, %1"
11518 [(set_attr "arch" "t1,t2,32")
11519 (set_attr "length" "2,2,4")]
11520)
11521
11522(define_insn "*arm_rev16"
11523 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11524 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11525 "arm_arch6"
11526 "@
11527 rev16\t%0, %1
11528 rev16%?\t%0, %1
11529 rev16%?\t%0, %1"
11530 [(set_attr "arch" "t1,t2,32")
11531 (set_attr "length" "2,2,4")]
11532)
11533
11534(define_expand "bswaphi2"
11535 [(set (match_operand:HI 0 "s_register_operand" "=r")
11536 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11537"arm_arch6"
11538""
11539)
11540
1653cf17 11541;; Patterns for LDRD/STRD in Thumb2 mode
11542
11543(define_insn "*thumb2_ldrd"
11544 [(set (match_operand:SI 0 "s_register_operand" "=r")
11545 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11546 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11547 (set (match_operand:SI 3 "s_register_operand" "=r")
11548 (mem:SI (plus:SI (match_dup 1)
11549 (match_operand:SI 4 "const_int_operand" ""))))]
11550 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11551 && current_tune->prefer_ldrd_strd
11552 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11553 && (operands_ok_ldrd_strd (operands[0], operands[3],
11554 operands[1], INTVAL (operands[2]),
11555 false, true))"
11556 "ldrd%?\t%0, %3, [%1, %2]"
11557 [(set_attr "type" "load2")
11558 (set_attr "predicable" "yes")])
11559
11560(define_insn "*thumb2_ldrd_base"
11561 [(set (match_operand:SI 0 "s_register_operand" "=r")
11562 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11563 (set (match_operand:SI 2 "s_register_operand" "=r")
11564 (mem:SI (plus:SI (match_dup 1)
11565 (const_int 4))))]
11566 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11567 && current_tune->prefer_ldrd_strd
11568 && (operands_ok_ldrd_strd (operands[0], operands[2],
11569 operands[1], 0, false, true))"
11570 "ldrd%?\t%0, %2, [%1]"
11571 [(set_attr "type" "load2")
11572 (set_attr "predicable" "yes")])
11573
11574(define_insn "*thumb2_ldrd_base_neg"
11575 [(set (match_operand:SI 0 "s_register_operand" "=r")
11576 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11577 (const_int -4))))
11578 (set (match_operand:SI 2 "s_register_operand" "=r")
11579 (mem:SI (match_dup 1)))]
11580 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11581 && current_tune->prefer_ldrd_strd
11582 && (operands_ok_ldrd_strd (operands[0], operands[2],
11583 operands[1], -4, false, true))"
11584 "ldrd%?\t%0, %2, [%1, #-4]"
11585 [(set_attr "type" "load2")
11586 (set_attr "predicable" "yes")])
11587
11588(define_insn "*thumb2_strd"
11589 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11590 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11591 (match_operand:SI 2 "s_register_operand" "r"))
11592 (set (mem:SI (plus:SI (match_dup 0)
11593 (match_operand:SI 3 "const_int_operand" "")))
11594 (match_operand:SI 4 "s_register_operand" "r"))]
11595 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11596 && current_tune->prefer_ldrd_strd
11597 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11598 && (operands_ok_ldrd_strd (operands[2], operands[4],
11599 operands[0], INTVAL (operands[1]),
11600 false, false))"
11601 "strd%?\t%2, %4, [%0, %1]"
11602 [(set_attr "type" "store2")
11603 (set_attr "predicable" "yes")])
11604
11605(define_insn "*thumb2_strd_base"
11606 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11607 (match_operand:SI 1 "s_register_operand" "r"))
11608 (set (mem:SI (plus:SI (match_dup 0)
11609 (const_int 4)))
11610 (match_operand:SI 2 "s_register_operand" "r"))]
11611 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11612 && current_tune->prefer_ldrd_strd
11613 && (operands_ok_ldrd_strd (operands[1], operands[2],
11614 operands[0], 0, false, false))"
11615 "strd%?\t%1, %2, [%0]"
11616 [(set_attr "type" "store2")
11617 (set_attr "predicable" "yes")])
11618
11619(define_insn "*thumb2_strd_base_neg"
11620 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11621 (const_int -4)))
11622 (match_operand:SI 1 "s_register_operand" "r"))
11623 (set (mem:SI (match_dup 0))
11624 (match_operand:SI 2 "s_register_operand" "r"))]
11625 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11626 && current_tune->prefer_ldrd_strd
11627 && (operands_ok_ldrd_strd (operands[1], operands[2],
11628 operands[0], -4, false, false))"
11629 "strd%?\t%1, %2, [%0, #-4]"
11630 [(set_attr "type" "store2")
11631 (set_attr "predicable" "yes")])
11632
11633
320ea44d 11634;; Load the load/store multiple patterns
11635(include "ldmstm.md")
426be8c5 11636
11637;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11638;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11639(define_insn "*load_multiple"
11640 [(match_parallel 0 "load_multiple_operation"
11641 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11642 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11643 ])]
11644 "TARGET_32BIT"
11645 "*
11646 {
11647 arm_output_multireg_pop (operands, /*return_pc=*/false,
11648 /*cond=*/const_true_rtx,
11649 /*reverse=*/false,
11650 /*update=*/false);
11651 return \"\";
11652 }
11653 "
11654 [(set_attr "predicable" "yes")]
11655)
11656
d98a3884 11657;; Vector bits common to IWMMXT and Neon
11658(include "vec-common.md")
755eb2b4 11659;; Load the Intel Wireless Multimedia Extension patterns
11660(include "iwmmxt.md")
a2cd141b 11661;; Load the VFP co-processor patterns
11662(include "vfp.md")
25f905c2 11663;; Thumb-2 patterns
11664(include "thumb2.md")
d98a3884 11665;; Neon patterns
11666(include "neon.md")
06df6b17 11667;; Synchronization Primitives
11668(include "sync.md")
bbbe4599 11669;; Fixed-point patterns
11670(include "arm-fixed.md")