]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* fold-const.c (const_binop): Adjust comment.
[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.
e7d6d136 114])
e1159bbe 115
215b30b3 116;; UNSPEC_VOLATILE Usage:
e1159bbe 117
e7d6d136 118(define_c_enum "unspecv" [
119 VUNSPEC_BLOCKAGE ; `blockage' insn to prevent scheduling across an
120 ; insn in the code.
121 VUNSPEC_EPILOGUE ; `epilogue' insn, used to represent any part of the
122 ; instruction epilogue sequence that isn't expanded
123 ; into normal RTL. Used for both normal and sibcall
124 ; epilogues.
7571d3f7 125 VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
126 ; modes from arm to thumb.
e7d6d136 127 VUNSPEC_ALIGN ; `align' insn. Used at the head of a minipool table
128 ; for inlined constants.
129 VUNSPEC_POOL_END ; `end-of-table'. Used to mark the end of a minipool
130 ; table.
131 VUNSPEC_POOL_1 ; `pool-entry(1)'. An entry in the constant pool for
132 ; an 8-bit object.
133 VUNSPEC_POOL_2 ; `pool-entry(2)'. An entry in the constant pool for
134 ; a 16-bit object.
135 VUNSPEC_POOL_4 ; `pool-entry(4)'. An entry in the constant pool for
136 ; a 32-bit object.
137 VUNSPEC_POOL_8 ; `pool-entry(8)'. An entry in the constant pool for
138 ; a 64-bit object.
139 VUNSPEC_POOL_16 ; `pool-entry(16)'. An entry in the constant pool for
140 ; a 128-bit object.
141 VUNSPEC_TMRC ; Used by the iWMMXt TMRC instruction.
142 VUNSPEC_TMCR ; Used by the iWMMXt TMCR instruction.
143 VUNSPEC_ALIGN8 ; 8-byte alignment version of VUNSPEC_ALIGN
144 VUNSPEC_WCMP_EQ ; Used by the iWMMXt WCMPEQ instructions
145 VUNSPEC_WCMP_GTU ; Used by the iWMMXt WCMPGTU instructions
146 VUNSPEC_WCMP_GT ; Used by the iwMMXT WCMPGT instructions
147 VUNSPEC_EH_RETURN ; Use to override the return address for exception
148 ; handling.
e1b93706 149 VUNSPEC_ATOMIC_CAS ; Represent an atomic compare swap.
150 VUNSPEC_ATOMIC_XCHG ; Represent an atomic exchange.
151 VUNSPEC_ATOMIC_OP ; Represent an atomic operation.
152 VUNSPEC_LL ; Represent a load-register-exclusive.
153 VUNSPEC_SC ; Represent a store-register-exclusive.
e7d6d136 154])
b11cae9e 155\f
e1159bbe 156;;---------------------------------------------------------------------------
9c08d1fa 157;; Attributes
158
a651f34d 159;; Processor type. This is created automatically from arm-cores.def.
160(include "arm-tune.md")
161
215b30b3 162; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
163; generating ARM code. This is used to control the length of some insn
164; patterns that share the same RTL in both ARM and Thumb code.
1c494086 165(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 166
ef51b8e1 167; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
168(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
169
747b7458 170; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
171(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
172
331beb1a 173;; Operand number of an input operand that is shifted. Zero if the
174;; given instruction does not shift one of its input operands.
331beb1a 175(define_attr "shift" "" (const_int 0))
176
3d91c5d6 177; Floating Point Unit. If we only have floating point emulation, then there
178; is no point in scheduling the floating point insns. (Well, for best
179; performance we should try and group them together).
bffbb863 180(define_attr "fpu" "none,vfp"
c7f506fd 181 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 182
094e994f 183; LENGTH of an instruction (in bytes)
06df6b17 184(define_attr "length" ""
e1b93706 185 (const_int 4))
9c08d1fa 186
d5d4dc8d 187; The architecture which supports the instruction (or alternative).
188; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
189; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
190; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
191; arm_arch6. This attribute is used to compute attribute "enabled",
192; use type "any" to enable an alternative in all cases.
6b8f7c28 193(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,neon_onlya8,nota8,neon_nota8,iwmmxt,iwmmxt2"
d5d4dc8d 194 (const_string "any"))
195
196(define_attr "arch_enabled" "no,yes"
197 (cond [(eq_attr "arch" "any")
198 (const_string "yes")
199
200 (and (eq_attr "arch" "a")
0bf497f5 201 (match_test "TARGET_ARM"))
d5d4dc8d 202 (const_string "yes")
203
204 (and (eq_attr "arch" "t")
0bf497f5 205 (match_test "TARGET_THUMB"))
d5d4dc8d 206 (const_string "yes")
207
208 (and (eq_attr "arch" "t1")
0bf497f5 209 (match_test "TARGET_THUMB1"))
d5d4dc8d 210 (const_string "yes")
211
212 (and (eq_attr "arch" "t2")
0bf497f5 213 (match_test "TARGET_THUMB2"))
d5d4dc8d 214 (const_string "yes")
215
216 (and (eq_attr "arch" "32")
0bf497f5 217 (match_test "TARGET_32BIT"))
d5d4dc8d 218 (const_string "yes")
219
220 (and (eq_attr "arch" "v6")
0bf497f5 221 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 222 (const_string "yes")
223
224 (and (eq_attr "arch" "nov6")
0bf497f5 225 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 226 (const_string "yes")
227
228 (and (eq_attr "arch" "onlya8")
229 (eq_attr "tune" "cortexa8"))
230 (const_string "yes")
231
10efb95f 232 (and (eq_attr "arch" "neon_onlya8")
233 (eq_attr "tune" "cortexa8")
234 (match_test "TARGET_NEON"))
235 (const_string "yes")
236
a651f34d 237 (and (eq_attr "arch" "nota8")
238 (not (eq_attr "tune" "cortexa8")))
10efb95f 239 (const_string "yes")
240
241 (and (eq_attr "arch" "neon_nota8")
242 (not (eq_attr "tune" "cortexa8"))
243 (match_test "TARGET_NEON"))
6b8f7c28 244 (const_string "yes")
245
246 (and (eq_attr "arch" "iwmmxt2")
247 (match_test "TARGET_REALLY_IWMMXT2"))
d5d4dc8d 248 (const_string "yes")]
6b8f7c28 249
d5d4dc8d 250 (const_string "no")))
251
aa06c51c 252(define_attr "opt" "any,speed,size"
253 (const_string "any"))
254
255(define_attr "opt_enabled" "no,yes"
256 (cond [(eq_attr "opt" "any")
257 (const_string "yes")
258
259 (and (eq_attr "opt" "speed")
260 (match_test "optimize_function_for_speed_p (cfun)"))
261 (const_string "yes")
262
263 (and (eq_attr "opt" "size")
264 (match_test "optimize_function_for_size_p (cfun)"))
265 (const_string "yes")]
266 (const_string "no")))
267
d5d4dc8d 268; Allows an insn to disable certain alternatives for reasons other than
269; arch support.
270(define_attr "insn_enabled" "no,yes"
271 (const_string "yes"))
272
273; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 274 (define_attr "enabled" "no,yes"
aa06c51c 275 (cond [(eq_attr "insn_enabled" "no")
276 (const_string "no")
277
278 (eq_attr "arch_enabled" "no")
279 (const_string "no")
280
281 (eq_attr "opt_enabled" "no")
282 (const_string "no")]
283 (const_string "yes")))
d5d4dc8d 284
56d27660 285; POOL_RANGE is how far away from a constant pool entry that this insn
286; can be placed. If the distance is zero, then this insn will never
287; reference the pool.
cffb2a26 288; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 289; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 290(define_attr "arm_pool_range" "" (const_int 0))
291(define_attr "thumb2_pool_range" "" (const_int 0))
292(define_attr "arm_neg_pool_range" "" (const_int 0))
293(define_attr "thumb2_neg_pool_range" "" (const_int 0))
294
295(define_attr "pool_range" ""
296 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
297 (attr "arm_pool_range")))
298(define_attr "neg_pool_range" ""
299 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
300 (attr "arm_neg_pool_range")))
56d27660 301
215b30b3 302; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 303; If such an insn references the pool, then we have no way of knowing how,
304; so use the most conservative value for pool_range.
9c08d1fa 305(define_asm_attributes
4d7a8451 306 [(set_attr "conds" "clob")
307 (set_attr "length" "4")
308 (set_attr "pool_range" "250")])
9c08d1fa 309
a2cd141b 310;; The instruction used to implement a particular pattern. This
311;; information is used by pipeline descriptions to provide accurate
312;; scheduling information.
313
314(define_attr "insn"
b49e3742 315 "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 316 (const_string "other"))
317
9c08d1fa 318; TYPE attribute is used to detect floating point instructions which, if
319; running on a co-processor can run in parallel with other, basic instructions
320; If write-buffer scheduling is enabled then it can also be used in the
321; scheduling of writes.
322
323; Classification of each insn
607978a1 324; Note: vfp.md has different meanings for some of these, and some further
325; types as well. See that file for details.
a2cd141b 326; alu any alu instruction that doesn't hit memory or fp
327; regs or have a shifted source operand
328; alu_shift any data instruction that doesn't hit memory or fp
329; regs, but has a source operand shifted by a constant
330; alu_shift_reg any data instruction that doesn't hit memory or fp
331; regs, but has a source operand shifted by a register value
f7fbdd4a 332; mult a multiply instruction
9c08d1fa 333; block blockage insn, this blocks all functional units
334; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 335; fdivd DFmode floating point division
336; fdivs SFmode floating point division
013b9671 337; f_load[sd] A single/double load from memory. Used for VFP unit.
338; f_store[sd] A single/double store to memory. Used for VFP unit.
c0e1af52 339; f_flag a transfer of co-processor flags to the CPSR
96854199 340; f_2_r transfer float to core (no memory needed)
341; r_2_f transfer core to float
c0e1af52 342; f_cvt convert floating<->integral
a2cd141b 343; branch a branch
9c08d1fa 344; call a subroutine call
a2cd141b 345; load_byte load byte(s) from memory to arm registers
346; load1 load 1 word from memory to arm registers
347; load2 load 2 words from memory to arm registers
348; load3 load 3 words from memory to arm registers
349; load4 load 4 words from memory to arm registers
350; store store 1 word to memory from arm registers
9c08d1fa 351; store2 store 2 words
352; store3 store 3 words
a2cd141b 353; store4 store 4 (or more) words
9c08d1fa 354;
bcaec148 355
9c08d1fa 356(define_attr "type"
96854199 357 "alu,\
358 alu_shift,\
359 alu_shift_reg,\
360 mult,\
361 block,\
362 float,\
363 fdivd,\
364 fdivs,\
365 fmuls,\
366 fmuld,\
367 fmacs,\
368 fmacd,\
369 f_flag,\
370 f_loads,\
371 f_loadd,\
372 f_stores,\
373 f_stored,\
374 f_2_r,\
375 r_2_f,\
376 f_cvt,\
377 branch,\
378 call,\
379 load_byte,\
380 load1,\
381 load2,\
382 load3,\
383 load4,\
384 store1,\
385 store2,\
386 store3,\
387 store4,\
388 fconsts,\
389 fconstd,\
390 fadds,\
391 faddd,\
392 ffariths,\
393 ffarithd,\
394 fcmps,\
395 fcmpd,\
396 fcpys"
397 (if_then_else
398 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,\
399 umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
400 (const_string "mult")
401 (const_string "alu")))
9c08d1fa 402
65f2f758 403; Is this an (integer side) multiply with a 64-bit result?
404(define_attr "mul64" "no,yes"
96854199 405 (if_then_else
406 (eq_attr "insn"
407 "smlalxy,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
408 (const_string "yes")
409 (const_string "no")))
65f2f758 410
6b8f7c28 411; wtype for WMMX insn scheduling purposes.
412(define_attr "wtype"
413 "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"))
414
9888ad6d 415; Load scheduling, set from the arm_ld_sched variable
4c834714 416; initialized by arm_option_override()
9888ad6d 417(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 418
c52acdd2 419;; Classification of NEON instructions for scheduling purposes.
c52acdd2 420(define_attr "neon_type"
421 "neon_int_1,\
422 neon_int_2,\
423 neon_int_3,\
424 neon_int_4,\
425 neon_int_5,\
426 neon_vqneg_vqabs,\
427 neon_vmov,\
428 neon_vaba,\
429 neon_vsma,\
430 neon_vaba_qqq,\
431 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
432 neon_mul_qqq_8_16_32_ddd_32,\
433 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
434 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
435 neon_mla_qqq_8_16,\
436 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
437 neon_mla_qqq_32_qqd_32_scalar,\
438 neon_mul_ddd_16_scalar_32_16_long_scalar,\
439 neon_mul_qqd_32_scalar,\
440 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
441 neon_shift_1,\
442 neon_shift_2,\
443 neon_shift_3,\
444 neon_vshl_ddd,\
445 neon_vqshl_vrshl_vqrshl_qqq,\
446 neon_vsra_vrsra,\
447 neon_fp_vadd_ddd_vabs_dd,\
448 neon_fp_vadd_qqq_vabs_qq,\
449 neon_fp_vsum,\
450 neon_fp_vmul_ddd,\
451 neon_fp_vmul_qqd,\
452 neon_fp_vmla_ddd,\
453 neon_fp_vmla_qqq,\
454 neon_fp_vmla_ddd_scalar,\
455 neon_fp_vmla_qqq_scalar,\
456 neon_fp_vrecps_vrsqrts_ddd,\
457 neon_fp_vrecps_vrsqrts_qqq,\
458 neon_bp_simple,\
459 neon_bp_2cycle,\
460 neon_bp_3cycle,\
461 neon_ldr,\
462 neon_str,\
463 neon_vld1_1_2_regs,\
464 neon_vld1_3_4_regs,\
465 neon_vld2_2_regs_vld1_vld2_all_lanes,\
466 neon_vld2_4_regs,\
467 neon_vld3_vld4,\
468 neon_vst1_1_2_regs_vst2_2_regs,\
469 neon_vst1_3_4_regs,\
470 neon_vst2_4_regs_vst3_vst4,\
471 neon_vst3_vst4,\
472 neon_vld1_vld2_lane,\
473 neon_vld3_vld4_lane,\
474 neon_vst1_vst2_lane,\
475 neon_vst3_vst4_lane,\
476 neon_vld3_vld4_all_lanes,\
477 neon_mcr,\
478 neon_mcr_2_mcrr,\
479 neon_mrc,\
480 neon_mrrc,\
481 neon_ldm_2,\
482 neon_stm_2,\
483 none"
484 (const_string "none"))
485
f7fbdd4a 486; condition codes: this one is used by final_prescan_insn to speed up
487; conditionalizing instructions. It saves having to scan the rtl to see if
488; it uses or alters the condition codes.
215b30b3 489;
f7fbdd4a 490; USE means that the condition codes are used by the insn in the process of
215b30b3 491; outputting code, this means (at present) that we can't use the insn in
492; inlined branches
493;
f7fbdd4a 494; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 495; well defined manner.
496;
f7fbdd4a 497; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 498; they are altered at all
499;
ad6d3e2a 500; UNCONDITIONAL means the instruction can not be conditionally executed and
501; that the instruction does not use or alter the condition codes.
c52acdd2 502;
ad6d3e2a 503; NOCOND means that the instruction does not use or alter the condition
504; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 505
b0694be0 506(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 507 (if_then_else
508 (ior (eq_attr "is_thumb1" "yes")
509 (eq_attr "type" "call"))
c1a66faf 510 (const_string "clob")
c52acdd2 511 (if_then_else (eq_attr "neon_type" "none")
512 (const_string "nocond")
513 (const_string "unconditional"))))
f7fbdd4a 514
215b30b3 515; Predicable means that the insn can be conditionally executed based on
516; an automatically added predicate (additional patterns are generated by
517; gen...). We default to 'no' because no Thumb patterns match this rule
518; and not all ARM patterns do.
0d66636f 519(define_attr "predicable" "no,yes" (const_string "no"))
520
129a2fe4 521; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
522; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 523; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 524; affect the schedule).
74a71f7d 525(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 526
215b30b3 527; WRITE_CONFLICT implies that a read following an unrelated write is likely
528; to stall the processor. Used with model_wbuf above.
9c08d1fa 529(define_attr "write_conflict" "no,yes"
530 (if_then_else (eq_attr "type"
96854199 531 "block,call,load1")
9c08d1fa 532 (const_string "yes")
533 (const_string "no")))
534
215b30b3 535; Classify the insns into those that take one cycle and those that take more
536; than one on the main cpu execution unit.
f7fbdd4a 537(define_attr "core_cycles" "single,multi"
538 (if_then_else (eq_attr "type"
96854199 539 "alu,alu_shift,float,fdivd,fdivs")
f7fbdd4a 540 (const_string "single")
541 (const_string "multi")))
542
cffb2a26 543;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 544;; distant label. Only applicable to Thumb code.
cffb2a26 545(define_attr "far_jump" "yes,no" (const_string "no"))
546
d51f92df 547
25f905c2 548;; The number of machine instructions this pattern expands to.
549;; Used for Thumb-2 conditional execution.
550(define_attr "ce_count" "" (const_int 1))
551
d51f92df 552;;---------------------------------------------------------------------------
fd781bb2 553;; Mode iterators
d51f92df 554
3de0dec6 555(include "iterators.md")
03770691 556
d51f92df 557;;---------------------------------------------------------------------------
558;; Predicates
559
9c9db025 560(include "predicates.md")
234f6557 561(include "constraints.md")
9c9db025 562
a2cd141b 563;;---------------------------------------------------------------------------
564;; Pipeline descriptions
215b30b3 565
e3879fd0 566(define_attr "tune_cortexr4" "yes,no"
567 (const (if_then_else
7d3cda8c 568 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 569 (const_string "yes")
570 (const_string "no"))))
571
a2cd141b 572;; True if the generic scheduling description should be used.
573
574(define_attr "generic_sched" "yes,no"
2546d93a 575 (const (if_then_else
65f2f758 576 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexa15,cortexm4")
2546d93a 577 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 578 (const_string "no")
579 (const_string "yes"))))
580
c0e1af52 581(define_attr "generic_vfp" "yes,no"
582 (const (if_then_else
583 (and (eq_attr "fpu" "vfp")
2546d93a 584 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 585 (eq_attr "tune_cortexr4" "no"))
c0e1af52 586 (const_string "yes")
587 (const_string "no"))))
588
6b8f7c28 589(include "marvell-f-iwmmxt.md")
a2cd141b 590(include "arm-generic.md")
591(include "arm926ejs.md")
c0e1af52 592(include "arm1020e.md")
a2cd141b 593(include "arm1026ejs.md")
594(include "arm1136jfs.md")
0e266d06 595(include "fa526.md")
596(include "fa606te.md")
597(include "fa626te.md")
598(include "fmp626.md")
599(include "fa726te.md")
3f1e069f 600(include "cortex-a5.md")
bcaec148 601(include "cortex-a8.md")
036068af 602(include "cortex-a9.md")
65f2f758 603(include "cortex-a15.md")
934a1e72 604(include "cortex-r4.md")
e3879fd0 605(include "cortex-r4f.md")
2546d93a 606(include "cortex-m4.md")
607(include "cortex-m4-fpu.md")
55e3ada8 608(include "vfp11.md")
3586df96 609
9c08d1fa 610\f
215b30b3 611;;---------------------------------------------------------------------------
e1159bbe 612;; Insn patterns
613;;
a0f94409 614;; Addition insns.
215b30b3 615
9c08d1fa 616;; Note: For DImode insns, there is normally no reason why operands should
617;; not be in the same register, what we don't want is for something being
618;; written to partially overlap something that is an input.
619
cffb2a26 620(define_expand "adddi3"
621 [(parallel
215b30b3 622 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 623 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 624 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 625 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 626 "TARGET_EITHER"
627 "
25f905c2 628 if (TARGET_THUMB1)
cffb2a26 629 {
0438d37f 630 if (!REG_P (operands[1]))
bc5a93af 631 operands[1] = force_reg (DImode, operands[1]);
0438d37f 632 if (!REG_P (operands[2]))
bc5a93af 633 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 634 }
635 "
636)
637
25f905c2 638(define_insn "*thumb1_adddi3"
cffb2a26 639 [(set (match_operand:DI 0 "register_operand" "=l")
640 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 641 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 642 (clobber (reg:CC CC_REGNUM))
cffb2a26 643 ]
25f905c2 644 "TARGET_THUMB1"
cffb2a26 645 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
646 [(set_attr "length" "4")]
647)
648
a0f94409 649(define_insn_and_split "*arm_adddi3"
10e5ccd5 650 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
651 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
652 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 653 (clobber (reg:CC CC_REGNUM))]
b805622c 654 "TARGET_32BIT && !TARGET_NEON"
33782ec7 655 "#"
94829feb 656 "TARGET_32BIT && reload_completed
657 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 658 [(parallel [(set (reg:CC_C CC_REGNUM)
659 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
660 (match_dup 1)))
661 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 662 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
663 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 664 "
665 {
666 operands[3] = gen_highpart (SImode, operands[0]);
667 operands[0] = gen_lowpart (SImode, operands[0]);
668 operands[4] = gen_highpart (SImode, operands[1]);
669 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 670 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 671 operands[2] = gen_lowpart (SImode, operands[2]);
672 }"
cffb2a26 673 [(set_attr "conds" "clob")
674 (set_attr "length" "8")]
675)
9c08d1fa 676
a0f94409 677(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 678 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
679 (plus:DI (sign_extend:DI
97499065 680 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 681 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 682 (clobber (reg:CC CC_REGNUM))]
b805622c 683 "TARGET_32BIT"
33782ec7 684 "#"
25f905c2 685 "TARGET_32BIT && reload_completed"
a0f94409 686 [(parallel [(set (reg:CC_C CC_REGNUM)
687 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
688 (match_dup 1)))
689 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 690 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 691 (const_int 31))
080c0b9a 692 (match_dup 4))
693 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 694 "
695 {
696 operands[3] = gen_highpart (SImode, operands[0]);
697 operands[0] = gen_lowpart (SImode, operands[0]);
698 operands[4] = gen_highpart (SImode, operands[1]);
699 operands[1] = gen_lowpart (SImode, operands[1]);
700 operands[2] = gen_lowpart (SImode, operands[2]);
701 }"
215b30b3 702 [(set_attr "conds" "clob")
703 (set_attr "length" "8")]
704)
9c08d1fa 705
a0f94409 706(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 707 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
708 (plus:DI (zero_extend:DI
97499065 709 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 710 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 711 (clobber (reg:CC CC_REGNUM))]
b805622c 712 "TARGET_32BIT"
33782ec7 713 "#"
25f905c2 714 "TARGET_32BIT && reload_completed"
a0f94409 715 [(parallel [(set (reg:CC_C CC_REGNUM)
716 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
717 (match_dup 1)))
718 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 719 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
720 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 721 "
722 {
723 operands[3] = gen_highpart (SImode, operands[0]);
724 operands[0] = gen_lowpart (SImode, operands[0]);
725 operands[4] = gen_highpart (SImode, operands[1]);
726 operands[1] = gen_lowpart (SImode, operands[1]);
727 operands[2] = gen_lowpart (SImode, operands[2]);
728 }"
cffb2a26 729 [(set_attr "conds" "clob")
730 (set_attr "length" "8")]
731)
b11cae9e 732
87b22bf7 733(define_expand "addsi3"
cffb2a26 734 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 735 (plus:SI (match_operand:SI 1 "s_register_operand" "")
736 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 737 "TARGET_EITHER"
87b22bf7 738 "
0438d37f 739 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 740 {
96f57e36 741 arm_split_constant (PLUS, SImode, NULL_RTX,
742 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 743 optimize && can_create_pseudo_p ());
87b22bf7 744 DONE;
745 }
cffb2a26 746 "
747)
87b22bf7 748
5bd751ff 749; If there is a scratch available, this will be faster than synthesizing the
a0f94409 750; addition.
751(define_peephole2
752 [(match_scratch:SI 3 "r")
372575c7 753 (set (match_operand:SI 0 "arm_general_register_operand" "")
754 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 755 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 756 "TARGET_32BIT &&
a0f94409 757 !(const_ok_for_arm (INTVAL (operands[2]))
758 || const_ok_for_arm (-INTVAL (operands[2])))
759 && const_ok_for_arm (~INTVAL (operands[2]))"
760 [(set (match_dup 3) (match_dup 2))
761 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
762 ""
763)
87b22bf7 764
2f02c19f 765;; The r/r/k alternative is required when reloading the address
766;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
767;; put the duplicated register first, and not try the commutative version.
a0f94409 768(define_insn_and_split "*arm_addsi3"
c24d855d 769 [(set (match_operand:SI 0 "s_register_operand" "=rk, r,k, r,r, k, r, k,k,r, k, r")
770 (plus:SI (match_operand:SI 1 "s_register_operand" "%0, rk,k, r,rk,k, rk,k,r,rk,k, rk")
771 (match_operand:SI 2 "reg_or_int_operand" "rk, rI,rI,k,Pj,Pj,L, L,L,PJ,PJ,?n")))]
25f905c2 772 "TARGET_32BIT"
5565501b 773 "@
c24d855d 774 add%?\\t%0, %0, %2
5565501b 775 add%?\\t%0, %1, %2
aaa37ad6 776 add%?\\t%0, %1, %2
2f02c19f 777 add%?\\t%0, %2, %1
d5cbae34 778 addw%?\\t%0, %1, %2
779 addw%?\\t%0, %1, %2
aaa37ad6 780 sub%?\\t%0, %1, #%n2
87b22bf7 781 sub%?\\t%0, %1, #%n2
d7757711 782 sub%?\\t%0, %1, #%n2
d5cbae34 783 subw%?\\t%0, %1, #%n2
784 subw%?\\t%0, %1, #%n2
87b22bf7 785 #"
a3ffc315 786 "TARGET_32BIT
0438d37f 787 && CONST_INT_P (operands[2])
d5cbae34 788 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 789 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 790 [(clobber (const_int 0))]
791 "
96f57e36 792 arm_split_constant (PLUS, SImode, curr_insn,
793 INTVAL (operands[2]), operands[0],
a0f94409 794 operands[1], 0);
795 DONE;
796 "
c24d855d 797 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 798 (set_attr "predicable" "yes")
c24d855d 799 (set_attr "arch" "t2,*,*,*,t2,t2,*,*,a,t2,t2,*")]
cffb2a26 800)
801
0bdb6455 802(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 803 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
804 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
805 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 806 "TARGET_THUMB1"
cffb2a26 807 "*
0d66636f 808 static const char * const asms[] =
cffb2a26 809 {
810 \"add\\t%0, %0, %2\",
811 \"sub\\t%0, %0, #%n2\",
812 \"add\\t%0, %1, %2\",
813 \"add\\t%0, %0, %2\",
814 \"add\\t%0, %0, %2\",
815 \"add\\t%0, %1, %2\",
0bdb6455 816 \"add\\t%0, %1, %2\",
817 \"#\",
bf7bc2f6 818 \"#\",
0bdb6455 819 \"#\"
cffb2a26 820 };
821 if ((which_alternative == 2 || which_alternative == 6)
0438d37f 822 && CONST_INT_P (operands[2])
cffb2a26 823 && INTVAL (operands[2]) < 0)
824 return \"sub\\t%0, %1, #%n2\";
825 return asms[which_alternative];
826 "
0bdb6455 827 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 828 && ((operands[1] != stack_pointer_rtx
829 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
830 || (operands[1] == stack_pointer_rtx
831 && INTVAL (operands[2]) > 1020))"
0bdb6455 832 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
833 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
834 {
835 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 836 if (operands[1] == stack_pointer_rtx)
837 offset -= 1020;
838 else
839 {
840 if (offset > 255)
841 offset = 255;
842 else if (offset < -255)
843 offset = -255;
844 }
0bdb6455 845 operands[3] = GEN_INT (offset);
846 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
847 }
bf7bc2f6 848 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 849)
850
851;; Reloading and elimination of the frame pointer can
852;; sometimes cause this optimization to be missed.
a0f94409 853(define_peephole2
372575c7 854 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 855 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 856 (set (match_dup 0)
372575c7 857 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 858 "TARGET_THUMB1
cffb2a26 859 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
860 && (INTVAL (operands[1]) & 3) == 0"
372575c7 861 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 862 ""
cffb2a26 863)
b11cae9e 864
90c2bcf0 865(define_insn "addsi3_compare0"
bd5b4116 866 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 867 (compare:CC_NOOV
215b30b3 868 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
869 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 870 (const_int 0)))
871 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 872 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 873 "TARGET_ARM"
5565501b 874 "@
25f905c2 875 add%.\\t%0, %1, %2
876 sub%.\\t%0, %1, #%n2"
cffb2a26 877 [(set_attr "conds" "set")]
878)
9c08d1fa 879
aea4c774 880(define_insn "*addsi3_compare0_scratch"
bd5b4116 881 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 882 (compare:CC_NOOV
215b30b3 883 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
884 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 885 (const_int 0)))]
ec792a7b 886 "TARGET_ARM"
cffb2a26 887 "@
888 cmn%?\\t%0, %1
889 cmp%?\\t%0, #%n1"
596e5e8f 890 [(set_attr "conds" "set")
891 (set_attr "predicable" "yes")]
0d66636f 892)
cffb2a26 893
aed179ae 894(define_insn "*compare_negsi_si"
895 [(set (reg:CC_Z CC_REGNUM)
896 (compare:CC_Z
897 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
898 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 899 "TARGET_32BIT"
aed179ae 900 "cmn%?\\t%1, %0"
596e5e8f 901 [(set_attr "conds" "set")
902 (set_attr "predicable" "yes")]
0d66636f 903)
aea4c774 904
203c488f 905;; This is the canonicalization of addsi3_compare0_for_combiner when the
906;; addend is a constant.
907(define_insn "*cmpsi2_addneg"
908 [(set (reg:CC CC_REGNUM)
909 (compare:CC
910 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 911 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 912 (set (match_operand:SI 0 "s_register_operand" "=r,r")
913 (plus:SI (match_dup 1)
2a977b78 914 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 915 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 916 "@
2a977b78 917 add%.\\t%0, %1, %3
918 sub%.\\t%0, %1, #%n3"
203c488f 919 [(set_attr "conds" "set")]
920)
921
922;; Convert the sequence
923;; sub rd, rn, #1
924;; cmn rd, #1 (equivalent to cmp rd, #-1)
925;; bne dest
926;; into
927;; subs rd, rn, #1
928;; bcs dest ((unsigned)rn >= 1)
929;; similarly for the beq variant using bcc.
930;; This is a common looping idiom (while (n--))
931(define_peephole2
372575c7 932 [(set (match_operand:SI 0 "arm_general_register_operand" "")
933 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 934 (const_int -1)))
935 (set (match_operand 2 "cc_register" "")
936 (compare (match_dup 0) (const_int -1)))
937 (set (pc)
938 (if_then_else (match_operator 3 "equality_operator"
939 [(match_dup 2) (const_int 0)])
940 (match_operand 4 "" "")
941 (match_operand 5 "" "")))]
25f905c2 942 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 943 [(parallel[
944 (set (match_dup 2)
945 (compare:CC
946 (match_dup 1) (const_int 1)))
947 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
948 (set (pc)
949 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
950 (match_dup 4)
951 (match_dup 5)))]
952 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
953 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
954 ? GEU : LTU),
955 VOIDmode,
956 operands[2], const0_rtx);"
957)
958
ebcc79bc 959;; The next four insns work because they compare the result with one of
960;; the operands, and we know that the use of the condition code is
961;; either GEU or LTU, so we can use the carry flag from the addition
962;; instead of doing the compare a second time.
963(define_insn "*addsi3_compare_op1"
bd5b4116 964 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 965 (compare:CC_C
966 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
967 (match_operand:SI 2 "arm_add_operand" "rI,L"))
968 (match_dup 1)))
969 (set (match_operand:SI 0 "s_register_operand" "=r,r")
970 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 971 "TARGET_32BIT"
ebcc79bc 972 "@
25f905c2 973 add%.\\t%0, %1, %2
974 sub%.\\t%0, %1, #%n2"
0d66636f 975 [(set_attr "conds" "set")]
976)
ebcc79bc 977
978(define_insn "*addsi3_compare_op2"
bd5b4116 979 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 980 (compare:CC_C
981 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
982 (match_operand:SI 2 "arm_add_operand" "rI,L"))
983 (match_dup 2)))
5565501b 984 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 985 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 986 "TARGET_32BIT"
5565501b 987 "@
25f905c2 988 add%.\\t%0, %1, %2
989 sub%.\\t%0, %1, #%n2"
0d66636f 990 [(set_attr "conds" "set")]
991)
9c08d1fa 992
ebcc79bc 993(define_insn "*compare_addsi2_op0"
bd5b4116 994 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 995 (compare:CC_C
996 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
997 (match_operand:SI 1 "arm_add_operand" "rI,L"))
998 (match_dup 0)))]
25f905c2 999 "TARGET_32BIT"
ebcc79bc 1000 "@
1001 cmn%?\\t%0, %1
1002 cmp%?\\t%0, #%n1"
596e5e8f 1003 [(set_attr "conds" "set")
1004 (set_attr "predicable" "yes")]
0d66636f 1005)
ebcc79bc 1006
1007(define_insn "*compare_addsi2_op1"
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 1)))]
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
080c0b9a 1021(define_insn "*addsi3_carryin_<optab>"
10e5ccd5 1022 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1023 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r")
1024 (match_operand:SI 2 "arm_not_operand" "rI,K"))
080c0b9a 1025 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1026 "TARGET_32BIT"
10e5ccd5 1027 "@
1028 adc%?\\t%0, %1, %2
1029 sbc%?\\t%0, %1, #%B2"
cffb2a26 1030 [(set_attr "conds" "use")]
1031)
ebcc79bc 1032
080c0b9a 1033(define_insn "*addsi3_carryin_alt2_<optab>"
10e5ccd5 1034 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
080c0b9a 1035 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
10e5ccd5 1036 (match_operand:SI 1 "s_register_operand" "%r,r"))
1037 (match_operand:SI 2 "arm_rhs_operand" "rI,K")))]
25f905c2 1038 "TARGET_32BIT"
10e5ccd5 1039 "@
1040 adc%?\\t%0, %1, %2
1041 sbc%?\\t%0, %1, #%B2"
0d66636f 1042 [(set_attr "conds" "use")]
1043)
ebcc79bc 1044
080c0b9a 1045(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1046 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1047 (plus:SI (plus:SI
1048 (match_operator:SI 2 "shift_operator"
1049 [(match_operand:SI 3 "s_register_operand" "r")
1050 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1051 (match_operand:SI 1 "s_register_operand" "r"))
1052 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1053 "TARGET_32BIT"
080c0b9a 1054 "adc%?\\t%0, %1, %3%S2"
1055 [(set_attr "conds" "use")
1056 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1057 (const_string "alu_shift")
1058 (const_string "alu_shift_reg")))]
cffb2a26 1059)
ebcc79bc 1060
922b6913 1061(define_insn "*addsi3_carryin_clobercc_<optab>"
1062 [(set (match_operand:SI 0 "s_register_operand" "=r")
1063 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1064 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1065 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1066 (clobber (reg:CC CC_REGNUM))]
1067 "TARGET_32BIT"
1068 "adc%.\\t%0, %1, %2"
1069 [(set_attr "conds" "set")]
1070)
1071
25f905c2 1072(define_expand "incscc"
1073 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1074 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1075 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1076 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1077 "TARGET_32BIT"
1078 ""
1079)
1080
1081(define_insn "*arm_incscc"
9c08d1fa 1082 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 1083 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1084 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 1085 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 1086 "TARGET_ARM"
5565501b 1087 "@
1088 add%d2\\t%0, %1, #1
1089 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 1090 [(set_attr "conds" "use")
215b30b3 1091 (set_attr "length" "4,8")]
1092)
9c08d1fa 1093
d795fb69 1094; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1095(define_split
1096 [(set (match_operand:SI 0 "s_register_operand" "")
1097 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1098 (match_operand:SI 2 "s_register_operand" ""))
1099 (const_int -1)))
1100 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1101 "TARGET_32BIT"
d795fb69 1102 [(set (match_dup 3) (match_dup 1))
1103 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1104 "
1105 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1106")
1107
604f3a0a 1108(define_expand "addsf3"
1109 [(set (match_operand:SF 0 "s_register_operand" "")
1110 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1111 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1112 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1113 "
604f3a0a 1114")
1115
604f3a0a 1116(define_expand "adddf3"
1117 [(set (match_operand:DF 0 "s_register_operand" "")
1118 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1119 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1120 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1121 "
604f3a0a 1122")
1123
cffb2a26 1124(define_expand "subdi3"
1125 [(parallel
1126 [(set (match_operand:DI 0 "s_register_operand" "")
1127 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1128 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1129 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1130 "TARGET_EITHER"
1131 "
25f905c2 1132 if (TARGET_THUMB1)
cffb2a26 1133 {
0438d37f 1134 if (!REG_P (operands[1]))
5aa8c5f0 1135 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1136 if (!REG_P (operands[2]))
5aa8c5f0 1137 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1138 }
1139 "
1140)
1141
1142(define_insn "*arm_subdi3"
1143 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1144 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1145 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1146 (clobber (reg:CC CC_REGNUM))]
94829feb 1147 "TARGET_32BIT && !TARGET_NEON"
97499065 1148 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1149 [(set_attr "conds" "clob")
1150 (set_attr "length" "8")]
1151)
1152
1153(define_insn "*thumb_subdi3"
1154 [(set (match_operand:DI 0 "register_operand" "=l")
1155 (minus:DI (match_operand:DI 1 "register_operand" "0")
1156 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1157 (clobber (reg:CC CC_REGNUM))]
25f905c2 1158 "TARGET_THUMB1"
cffb2a26 1159 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1160 [(set_attr "length" "4")]
1161)
9c08d1fa 1162
f7fbdd4a 1163(define_insn "*subdi_di_zesidi"
cffb2a26 1164 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1165 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1166 (zero_extend:DI
cffb2a26 1167 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1168 (clobber (reg:CC CC_REGNUM))]
25f905c2 1169 "TARGET_32BIT"
97499065 1170 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1171 [(set_attr "conds" "clob")
1172 (set_attr "length" "8")]
1173)
9c08d1fa 1174
f7fbdd4a 1175(define_insn "*subdi_di_sesidi"
cffb2a26 1176 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1177 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1178 (sign_extend:DI
cffb2a26 1179 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1180 (clobber (reg:CC CC_REGNUM))]
25f905c2 1181 "TARGET_32BIT"
97499065 1182 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1183 [(set_attr "conds" "clob")
1184 (set_attr "length" "8")]
1185)
9c08d1fa 1186
f7fbdd4a 1187(define_insn "*subdi_zesidi_di"
cffb2a26 1188 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1189 (minus:DI (zero_extend:DI
cffb2a26 1190 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1191 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1192 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1193 "TARGET_ARM"
97499065 1194 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1195 [(set_attr "conds" "clob")
1196 (set_attr "length" "8")]
1197)
9c08d1fa 1198
f7fbdd4a 1199(define_insn "*subdi_sesidi_di"
cffb2a26 1200 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1201 (minus:DI (sign_extend:DI
cffb2a26 1202 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1203 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1204 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1205 "TARGET_ARM"
97499065 1206 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1207 [(set_attr "conds" "clob")
1208 (set_attr "length" "8")]
1209)
9c08d1fa 1210
f7fbdd4a 1211(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1212 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1213 (minus:DI (zero_extend:DI
cffb2a26 1214 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1215 (zero_extend:DI
cffb2a26 1216 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1217 (clobber (reg:CC CC_REGNUM))]
25f905c2 1218 "TARGET_32BIT"
1219 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1220 [(set_attr "conds" "clob")
1221 (set_attr "length" "8")]
1222)
b11cae9e 1223
87b22bf7 1224(define_expand "subsi3"
cffb2a26 1225 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1226 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1227 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1228 "TARGET_EITHER"
87b22bf7 1229 "
0438d37f 1230 if (CONST_INT_P (operands[1]))
87b22bf7 1231 {
25f905c2 1232 if (TARGET_32BIT)
cffb2a26 1233 {
96f57e36 1234 arm_split_constant (MINUS, SImode, NULL_RTX,
1235 INTVAL (operands[1]), operands[0],
e1ba4a27 1236 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1237 DONE;
1238 }
25f905c2 1239 else /* TARGET_THUMB1 */
cffb2a26 1240 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1241 }
cffb2a26 1242 "
1243)
87b22bf7 1244
747b7458 1245(define_insn "thumb1_subsi3_insn"
cffb2a26 1246 [(set (match_operand:SI 0 "register_operand" "=l")
1247 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1248 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1249 "TARGET_THUMB1"
cffb2a26 1250 "sub\\t%0, %1, %2"
747b7458 1251 [(set_attr "length" "2")
1252 (set_attr "conds" "set")])
cffb2a26 1253
25f905c2 1254; ??? Check Thumb-2 split length
a0f94409 1255(define_insn_and_split "*arm_subsi3_insn"
91a5e339 1256 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r")
1257 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n")
1258 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r")))]
25f905c2 1259 "TARGET_32BIT"
e2348bcb 1260 "@
87b22bf7 1261 rsb%?\\t%0, %2, %1
aaa37ad6 1262 sub%?\\t%0, %1, %2
080c0b9a 1263 sub%?\\t%0, %1, %2
87b22bf7 1264 #"
0438d37f 1265 "&& (CONST_INT_P (operands[1])
91a5e339 1266 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1267 [(clobber (const_int 0))]
1268 "
96f57e36 1269 arm_split_constant (MINUS, SImode, curr_insn,
1270 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1271 DONE;
cffb2a26 1272 "
91a5e339 1273 [(set_attr "length" "4,4,4,16")
a0f94409 1274 (set_attr "predicable" "yes")]
1275)
1276
1277(define_peephole2
1278 [(match_scratch:SI 3 "r")
372575c7 1279 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1280 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1281 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1282 "TARGET_32BIT
a0f94409 1283 && !const_ok_for_arm (INTVAL (operands[1]))
1284 && const_ok_for_arm (~INTVAL (operands[1]))"
1285 [(set (match_dup 3) (match_dup 1))
1286 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1287 ""
cffb2a26 1288)
b11cae9e 1289
f7fbdd4a 1290(define_insn "*subsi3_compare0"
bd5b4116 1291 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1292 (compare:CC_NOOV
1293 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1294 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1295 (const_int 0)))
9c08d1fa 1296 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1297 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1298 "TARGET_32BIT"
e2348bcb 1299 "@
25f905c2 1300 sub%.\\t%0, %1, %2
1301 rsb%.\\t%0, %2, %1"
cffb2a26 1302 [(set_attr "conds" "set")]
1303)
9c08d1fa 1304
080c0b9a 1305(define_insn "*subsi3_compare"
1306 [(set (reg:CC CC_REGNUM)
1307 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1308 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1309 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1310 (minus:SI (match_dup 1) (match_dup 2)))]
1311 "TARGET_32BIT"
1312 "@
1313 sub%.\\t%0, %1, %2
1314 rsb%.\\t%0, %2, %1"
1315 [(set_attr "conds" "set")]
1316)
1317
25f905c2 1318(define_expand "decscc"
1319 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1320 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1321 (match_operator:SI 2 "arm_comparison_operator"
1322 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1323 "TARGET_32BIT"
1324 ""
1325)
1326
1327(define_insn "*arm_decscc"
cffb2a26 1328 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1329 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1330 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1331 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1332 "TARGET_ARM"
e2348bcb 1333 "@
215b30b3 1334 sub%d2\\t%0, %1, #1
1335 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1336 [(set_attr "conds" "use")
1337 (set_attr "length" "*,8")]
1338)
9c08d1fa 1339
604f3a0a 1340(define_expand "subsf3"
1341 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1342 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1343 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1344 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1345 "
604f3a0a 1346")
1347
604f3a0a 1348(define_expand "subdf3"
1349 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1350 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1351 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1352 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1353 "
604f3a0a 1354")
1355
b11cae9e 1356\f
1357;; Multiplication insns
1358
cffb2a26 1359(define_expand "mulsi3"
1360 [(set (match_operand:SI 0 "s_register_operand" "")
1361 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1362 (match_operand:SI 1 "s_register_operand" "")))]
1363 "TARGET_EITHER"
1364 ""
1365)
1366
9c08d1fa 1367;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1368(define_insn "*arm_mulsi3"
1369 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1370 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1371 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1372 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1373 "mul%?\\t%0, %2, %1"
a2cd141b 1374 [(set_attr "insn" "mul")
0d66636f 1375 (set_attr "predicable" "yes")]
cffb2a26 1376)
1377
58d7d654 1378(define_insn "*arm_mulsi3_v6"
1379 [(set (match_operand:SI 0 "s_register_operand" "=r")
1380 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1381 (match_operand:SI 2 "s_register_operand" "r")))]
1382 "TARGET_32BIT && arm_arch6"
1383 "mul%?\\t%0, %1, %2"
1384 [(set_attr "insn" "mul")
1385 (set_attr "predicable" "yes")]
1386)
1387
215b30b3 1388; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1389; 1 and 2; are the same, because reload will make operand 0 match
1390; operand 1 without realizing that this conflicts with operand 2. We fix
1391; this by adding another alternative to match this case, and then `reload'
1392; it ourselves. This alternative must come first.
cffb2a26 1393(define_insn "*thumb_mulsi3"
1394 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1395 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1396 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1397 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1398 "*
1399 if (which_alternative < 2)
20c4e896 1400 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1401 else
20c4e896 1402 return \"mul\\t%0, %2\";
cffb2a26 1403 "
1404 [(set_attr "length" "4,4,2")
a2cd141b 1405 (set_attr "insn" "mul")]
cffb2a26 1406)
b11cae9e 1407
58d7d654 1408(define_insn "*thumb_mulsi3_v6"
1409 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1410 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1411 (match_operand:SI 2 "register_operand" "l,0,0")))]
1412 "TARGET_THUMB1 && arm_arch6"
1413 "@
1490694c 1414 mul\\t%0, %2
1415 mul\\t%0, %1
58d7d654 1416 mul\\t%0, %1"
1417 [(set_attr "length" "2")
1418 (set_attr "insn" "mul")]
1419)
1420
f7fbdd4a 1421(define_insn "*mulsi3_compare0"
bd5b4116 1422 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1423 (compare:CC_NOOV (mult:SI
1424 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1425 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1426 (const_int 0)))
1427 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1428 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1429 "TARGET_ARM && !arm_arch6"
1430 "mul%.\\t%0, %2, %1"
1431 [(set_attr "conds" "set")
1432 (set_attr "insn" "muls")]
1433)
1434
1435(define_insn "*mulsi3_compare0_v6"
1436 [(set (reg:CC_NOOV CC_REGNUM)
1437 (compare:CC_NOOV (mult:SI
1438 (match_operand:SI 2 "s_register_operand" "r")
1439 (match_operand:SI 1 "s_register_operand" "r"))
1440 (const_int 0)))
1441 (set (match_operand:SI 0 "s_register_operand" "=r")
1442 (mult:SI (match_dup 2) (match_dup 1)))]
1443 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1444 "mul%.\\t%0, %2, %1"
cffb2a26 1445 [(set_attr "conds" "set")
a2cd141b 1446 (set_attr "insn" "muls")]
cffb2a26 1447)
9c08d1fa 1448
f7fbdd4a 1449(define_insn "*mulsi_compare0_scratch"
bd5b4116 1450 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1451 (compare:CC_NOOV (mult:SI
1452 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1453 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1454 (const_int 0)))
1455 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1456 "TARGET_ARM && !arm_arch6"
1457 "mul%.\\t%0, %2, %1"
1458 [(set_attr "conds" "set")
1459 (set_attr "insn" "muls")]
1460)
1461
1462(define_insn "*mulsi_compare0_scratch_v6"
1463 [(set (reg:CC_NOOV CC_REGNUM)
1464 (compare:CC_NOOV (mult:SI
1465 (match_operand:SI 2 "s_register_operand" "r")
1466 (match_operand:SI 1 "s_register_operand" "r"))
1467 (const_int 0)))
1468 (clobber (match_scratch:SI 0 "=r"))]
1469 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1470 "mul%.\\t%0, %2, %1"
cffb2a26 1471 [(set_attr "conds" "set")
a2cd141b 1472 (set_attr "insn" "muls")]
cffb2a26 1473)
9c08d1fa 1474
b11cae9e 1475;; Unnamed templates to match MLA instruction.
1476
f7fbdd4a 1477(define_insn "*mulsi3addsi"
9c08d1fa 1478 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1479 (plus:SI
9c08d1fa 1480 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1481 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1482 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1483 "TARGET_32BIT && !arm_arch6"
1484 "mla%?\\t%0, %2, %1, %3"
1485 [(set_attr "insn" "mla")
1486 (set_attr "predicable" "yes")]
1487)
1488
1489(define_insn "*mulsi3addsi_v6"
1490 [(set (match_operand:SI 0 "s_register_operand" "=r")
1491 (plus:SI
1492 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1493 (match_operand:SI 1 "s_register_operand" "r"))
1494 (match_operand:SI 3 "s_register_operand" "r")))]
1495 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1496 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1497 [(set_attr "insn" "mla")
0d66636f 1498 (set_attr "predicable" "yes")]
1499)
b11cae9e 1500
f7fbdd4a 1501(define_insn "*mulsi3addsi_compare0"
bd5b4116 1502 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1503 (compare:CC_NOOV
1504 (plus:SI (mult:SI
1505 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1506 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1507 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1508 (const_int 0)))
9c08d1fa 1509 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1510 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1511 (match_dup 3)))]
58d7d654 1512 "TARGET_ARM && arm_arch6"
1513 "mla%.\\t%0, %2, %1, %3"
1514 [(set_attr "conds" "set")
1515 (set_attr "insn" "mlas")]
1516)
1517
1518(define_insn "*mulsi3addsi_compare0_v6"
1519 [(set (reg:CC_NOOV CC_REGNUM)
1520 (compare:CC_NOOV
1521 (plus:SI (mult:SI
1522 (match_operand:SI 2 "s_register_operand" "r")
1523 (match_operand:SI 1 "s_register_operand" "r"))
1524 (match_operand:SI 3 "s_register_operand" "r"))
1525 (const_int 0)))
1526 (set (match_operand:SI 0 "s_register_operand" "=r")
1527 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1528 (match_dup 3)))]
1529 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1530 "mla%.\\t%0, %2, %1, %3"
0d66636f 1531 [(set_attr "conds" "set")
a2cd141b 1532 (set_attr "insn" "mlas")]
0d66636f 1533)
9c08d1fa 1534
f7fbdd4a 1535(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1536 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1537 (compare:CC_NOOV
1538 (plus:SI (mult:SI
1539 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1540 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1541 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1542 (const_int 0)))
9c08d1fa 1543 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1544 "TARGET_ARM && !arm_arch6"
1545 "mla%.\\t%0, %2, %1, %3"
1546 [(set_attr "conds" "set")
1547 (set_attr "insn" "mlas")]
1548)
1549
1550(define_insn "*mulsi3addsi_compare0_scratch_v6"
1551 [(set (reg:CC_NOOV CC_REGNUM)
1552 (compare:CC_NOOV
1553 (plus:SI (mult:SI
1554 (match_operand:SI 2 "s_register_operand" "r")
1555 (match_operand:SI 1 "s_register_operand" "r"))
1556 (match_operand:SI 3 "s_register_operand" "r"))
1557 (const_int 0)))
1558 (clobber (match_scratch:SI 0 "=r"))]
1559 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1560 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1561 [(set_attr "conds" "set")
a2cd141b 1562 (set_attr "insn" "mlas")]
cffb2a26 1563)
f7fbdd4a 1564
89545238 1565(define_insn "*mulsi3subsi"
1566 [(set (match_operand:SI 0 "s_register_operand" "=r")
1567 (minus:SI
1568 (match_operand:SI 3 "s_register_operand" "r")
1569 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1570 (match_operand:SI 1 "s_register_operand" "r"))))]
1571 "TARGET_32BIT && arm_arch_thumb2"
1572 "mls%?\\t%0, %2, %1, %3"
1573 [(set_attr "insn" "mla")
1574 (set_attr "predicable" "yes")]
1575)
1576
5cdca009 1577(define_expand "maddsidi4"
1578 [(set (match_operand:DI 0 "s_register_operand" "")
1579 (plus:DI
1580 (mult:DI
1581 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1582 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1583 (match_operand:DI 3 "s_register_operand" "")))]
1584 "TARGET_32BIT && arm_arch3m"
1585 "")
82b85d08 1586
1587(define_insn "*mulsidi3adddi"
fe8dbf85 1588 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1589 (plus:DI
215b30b3 1590 (mult:DI
fe8dbf85 1591 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1592 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1593 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1594 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1595 "smlal%?\\t%Q0, %R0, %3, %2"
1596 [(set_attr "insn" "smlal")
1597 (set_attr "predicable" "yes")]
1598)
1599
1600(define_insn "*mulsidi3adddi_v6"
1601 [(set (match_operand:DI 0 "s_register_operand" "=r")
1602 (plus:DI
1603 (mult:DI
1604 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1605 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1606 (match_operand:DI 1 "s_register_operand" "0")))]
1607 "TARGET_32BIT && arm_arch6"
fe8dbf85 1608 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1609 [(set_attr "insn" "smlal")
0d66636f 1610 (set_attr "predicable" "yes")]
1611)
82b85d08 1612
957788b0 1613;; 32x32->64 widening multiply.
1614;; As with mulsi3, the only difference between the v3-5 and v6+
1615;; versions of these patterns is the requirement that the output not
1616;; overlap the inputs, but that still means we have to have a named
1617;; expander and two different starred insns.
1618
1619(define_expand "mulsidi3"
1620 [(set (match_operand:DI 0 "s_register_operand" "")
1621 (mult:DI
1622 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1623 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1624 "TARGET_32BIT && arm_arch3m"
1625 ""
1626)
1627
1628(define_insn "*mulsidi3_nov6"
f7fbdd4a 1629 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1630 (mult:DI
1631 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1632 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1633 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1634 "smull%?\\t%Q0, %R0, %1, %2"
1635 [(set_attr "insn" "smull")
1636 (set_attr "predicable" "yes")]
1637)
1638
957788b0 1639(define_insn "*mulsidi3_v6"
58d7d654 1640 [(set (match_operand:DI 0 "s_register_operand" "=r")
1641 (mult:DI
1642 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1643 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1644 "TARGET_32BIT && arm_arch6"
97499065 1645 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1646 [(set_attr "insn" "smull")
0d66636f 1647 (set_attr "predicable" "yes")]
1648)
f7fbdd4a 1649
957788b0 1650(define_expand "umulsidi3"
1651 [(set (match_operand:DI 0 "s_register_operand" "")
1652 (mult:DI
1653 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1654 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1655 "TARGET_32BIT && arm_arch3m"
1656 ""
1657)
1658
1659(define_insn "*umulsidi3_nov6"
f7fbdd4a 1660 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1661 (mult:DI
1662 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1663 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1664 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1665 "umull%?\\t%Q0, %R0, %1, %2"
1666 [(set_attr "insn" "umull")
1667 (set_attr "predicable" "yes")]
1668)
1669
957788b0 1670(define_insn "*umulsidi3_v6"
58d7d654 1671 [(set (match_operand:DI 0 "s_register_operand" "=r")
1672 (mult:DI
1673 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1674 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1675 "TARGET_32BIT && arm_arch6"
97499065 1676 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1677 [(set_attr "insn" "umull")
0d66636f 1678 (set_attr "predicable" "yes")]
1679)
b11cae9e 1680
5cdca009 1681(define_expand "umaddsidi4"
1682 [(set (match_operand:DI 0 "s_register_operand" "")
1683 (plus:DI
1684 (mult:DI
1685 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1686 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1687 (match_operand:DI 3 "s_register_operand" "")))]
1688 "TARGET_32BIT && arm_arch3m"
1689 "")
82b85d08 1690
1691(define_insn "*umulsidi3adddi"
8ead09f9 1692 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1693 (plus:DI
215b30b3 1694 (mult:DI
fe8dbf85 1695 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1696 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1697 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1698 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1699 "umlal%?\\t%Q0, %R0, %3, %2"
1700 [(set_attr "insn" "umlal")
1701 (set_attr "predicable" "yes")]
1702)
1703
1704(define_insn "*umulsidi3adddi_v6"
1705 [(set (match_operand:DI 0 "s_register_operand" "=r")
1706 (plus:DI
1707 (mult:DI
1708 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1709 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1710 (match_operand:DI 1 "s_register_operand" "0")))]
1711 "TARGET_32BIT && arm_arch6"
fe8dbf85 1712 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1713 [(set_attr "insn" "umlal")
0d66636f 1714 (set_attr "predicable" "yes")]
1715)
82b85d08 1716
957788b0 1717(define_expand "smulsi3_highpart"
1718 [(parallel
1719 [(set (match_operand:SI 0 "s_register_operand" "")
1720 (truncate:SI
1721 (lshiftrt:DI
1722 (mult:DI
1723 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1724 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1725 (const_int 32))))
1726 (clobber (match_scratch:SI 3 ""))])]
1727 "TARGET_32BIT && arm_arch3m"
1728 ""
1729)
1730
1731(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1732 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1733 (truncate:SI
1734 (lshiftrt:DI
215b30b3 1735 (mult:DI
e5fea38e 1736 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1737 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1738 (const_int 32))))
1739 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1740 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1741 "smull%?\\t%3, %0, %2, %1"
1742 [(set_attr "insn" "smull")
1743 (set_attr "predicable" "yes")]
1744)
1745
957788b0 1746(define_insn "*smulsi3_highpart_v6"
58d7d654 1747 [(set (match_operand:SI 0 "s_register_operand" "=r")
1748 (truncate:SI
1749 (lshiftrt:DI
1750 (mult:DI
1751 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1752 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1753 (const_int 32))))
1754 (clobber (match_scratch:SI 3 "=r"))]
1755 "TARGET_32BIT && arm_arch6"
f082f1c4 1756 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1757 [(set_attr "insn" "smull")
0d66636f 1758 (set_attr "predicable" "yes")]
cffb2a26 1759)
f082f1c4 1760
957788b0 1761(define_expand "umulsi3_highpart"
1762 [(parallel
1763 [(set (match_operand:SI 0 "s_register_operand" "")
1764 (truncate:SI
1765 (lshiftrt:DI
1766 (mult:DI
1767 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1768 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1769 (const_int 32))))
1770 (clobber (match_scratch:SI 3 ""))])]
1771 "TARGET_32BIT && arm_arch3m"
1772 ""
1773)
1774
1775(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1776 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1777 (truncate:SI
1778 (lshiftrt:DI
215b30b3 1779 (mult:DI
e5fea38e 1780 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1781 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1782 (const_int 32))))
1783 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1784 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1785 "umull%?\\t%3, %0, %2, %1"
1786 [(set_attr "insn" "umull")
1787 (set_attr "predicable" "yes")]
1788)
1789
957788b0 1790(define_insn "*umulsi3_highpart_v6"
58d7d654 1791 [(set (match_operand:SI 0 "s_register_operand" "=r")
1792 (truncate:SI
1793 (lshiftrt:DI
1794 (mult:DI
1795 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1796 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1797 (const_int 32))))
1798 (clobber (match_scratch:SI 3 "=r"))]
1799 "TARGET_32BIT && arm_arch6"
f082f1c4 1800 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1801 [(set_attr "insn" "umull")
0d66636f 1802 (set_attr "predicable" "yes")]
cffb2a26 1803)
f082f1c4 1804
331beb1a 1805(define_insn "mulhisi3"
1806 [(set (match_operand:SI 0 "s_register_operand" "=r")
1807 (mult:SI (sign_extend:SI
1808 (match_operand:HI 1 "s_register_operand" "%r"))
1809 (sign_extend:SI
1810 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1811 "TARGET_DSP_MULTIPLY"
61a2d04c 1812 "smulbb%?\\t%0, %1, %2"
a2cd141b 1813 [(set_attr "insn" "smulxy")
fec538d9 1814 (set_attr "predicable" "yes")]
1815)
1816
1817(define_insn "*mulhisi3tb"
1818 [(set (match_operand:SI 0 "s_register_operand" "=r")
1819 (mult:SI (ashiftrt:SI
1820 (match_operand:SI 1 "s_register_operand" "r")
1821 (const_int 16))
1822 (sign_extend:SI
1823 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1824 "TARGET_DSP_MULTIPLY"
fec538d9 1825 "smultb%?\\t%0, %1, %2"
a2cd141b 1826 [(set_attr "insn" "smulxy")
fec538d9 1827 (set_attr "predicable" "yes")]
1828)
1829
1830(define_insn "*mulhisi3bt"
1831 [(set (match_operand:SI 0 "s_register_operand" "=r")
1832 (mult:SI (sign_extend:SI
1833 (match_operand:HI 1 "s_register_operand" "r"))
1834 (ashiftrt:SI
1835 (match_operand:SI 2 "s_register_operand" "r")
1836 (const_int 16))))]
25f905c2 1837 "TARGET_DSP_MULTIPLY"
fec538d9 1838 "smulbt%?\\t%0, %1, %2"
a2cd141b 1839 [(set_attr "insn" "smulxy")
fec538d9 1840 (set_attr "predicable" "yes")]
1841)
1842
1843(define_insn "*mulhisi3tt"
1844 [(set (match_operand:SI 0 "s_register_operand" "=r")
1845 (mult:SI (ashiftrt:SI
1846 (match_operand:SI 1 "s_register_operand" "r")
1847 (const_int 16))
1848 (ashiftrt:SI
1849 (match_operand:SI 2 "s_register_operand" "r")
1850 (const_int 16))))]
25f905c2 1851 "TARGET_DSP_MULTIPLY"
fec538d9 1852 "smultt%?\\t%0, %1, %2"
a2cd141b 1853 [(set_attr "insn" "smulxy")
fec538d9 1854 (set_attr "predicable" "yes")]
331beb1a 1855)
1856
5cdca009 1857(define_insn "maddhisi4"
331beb1a 1858 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1859 (plus:SI (mult:SI (sign_extend:SI
1860 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1861 (sign_extend:SI
cfa6c608 1862 (match_operand:HI 2 "s_register_operand" "r")))
1863 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1864 "TARGET_DSP_MULTIPLY"
5cdca009 1865 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1866 [(set_attr "insn" "smlaxy")
fec538d9 1867 (set_attr "predicable" "yes")]
331beb1a 1868)
1869
9a92f368 1870;; Note: there is no maddhisi4ibt because this one is canonical form
1871(define_insn "*maddhisi4tb"
1872 [(set (match_operand:SI 0 "s_register_operand" "=r")
1873 (plus:SI (mult:SI (ashiftrt:SI
1874 (match_operand:SI 1 "s_register_operand" "r")
1875 (const_int 16))
1876 (sign_extend:SI
1877 (match_operand:HI 2 "s_register_operand" "r")))
1878 (match_operand:SI 3 "s_register_operand" "r")))]
1879 "TARGET_DSP_MULTIPLY"
1880 "smlatb%?\\t%0, %1, %2, %3"
1881 [(set_attr "insn" "smlaxy")
1882 (set_attr "predicable" "yes")]
1883)
1884
1885(define_insn "*maddhisi4tt"
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 (ashiftrt:SI
1891 (match_operand:SI 2 "s_register_operand" "r")
1892 (const_int 16)))
1893 (match_operand:SI 3 "s_register_operand" "r")))]
1894 "TARGET_DSP_MULTIPLY"
1895 "smlatt%?\\t%0, %1, %2, %3"
1896 [(set_attr "insn" "smlaxy")
1897 (set_attr "predicable" "yes")]
1898)
1899
aff5fb4d 1900(define_insn "maddhidi4"
331beb1a 1901 [(set (match_operand:DI 0 "s_register_operand" "=r")
1902 (plus:DI
331beb1a 1903 (mult:DI (sign_extend:DI
cfa6c608 1904 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1905 (sign_extend:DI
cfa6c608 1906 (match_operand:HI 2 "s_register_operand" "r")))
1907 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1908 "TARGET_DSP_MULTIPLY"
5cdca009 1909 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1910 [(set_attr "insn" "smlalxy")
fec538d9 1911 (set_attr "predicable" "yes")])
331beb1a 1912
9a92f368 1913;; Note: there is no maddhidi4ibt because this one is canonical form
1914(define_insn "*maddhidi4tb"
1915 [(set (match_operand:DI 0 "s_register_operand" "=r")
1916 (plus:DI
1917 (mult:DI (sign_extend:DI
1918 (ashiftrt:SI
1919 (match_operand:SI 1 "s_register_operand" "r")
1920 (const_int 16)))
1921 (sign_extend:DI
1922 (match_operand:HI 2 "s_register_operand" "r")))
1923 (match_operand:DI 3 "s_register_operand" "0")))]
1924 "TARGET_DSP_MULTIPLY"
1925 "smlaltb%?\\t%Q0, %R0, %1, %2"
1926 [(set_attr "insn" "smlalxy")
1927 (set_attr "predicable" "yes")])
1928
1929(define_insn "*maddhidi4tt"
1930 [(set (match_operand:DI 0 "s_register_operand" "=r")
1931 (plus:DI
1932 (mult:DI (sign_extend:DI
1933 (ashiftrt:SI
1934 (match_operand:SI 1 "s_register_operand" "r")
1935 (const_int 16)))
1936 (sign_extend:DI
1937 (ashiftrt:SI
1938 (match_operand:SI 2 "s_register_operand" "r")
1939 (const_int 16))))
1940 (match_operand:DI 3 "s_register_operand" "0")))]
1941 "TARGET_DSP_MULTIPLY"
1942 "smlaltt%?\\t%Q0, %R0, %1, %2"
1943 [(set_attr "insn" "smlalxy")
1944 (set_attr "predicable" "yes")])
1945
604f3a0a 1946(define_expand "mulsf3"
1947 [(set (match_operand:SF 0 "s_register_operand" "")
1948 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1949 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1950 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1951 "
604f3a0a 1952")
1953
604f3a0a 1954(define_expand "muldf3"
1955 [(set (match_operand:DF 0 "s_register_operand" "")
1956 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1957 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1958 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1959 "
604f3a0a 1960")
b11cae9e 1961\f
1962;; Division insns
1963
7db9af5d 1964(define_expand "divsf3"
1965 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1966 (div:SF (match_operand:SF 1 "s_register_operand" "")
1967 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 1968 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 1969 "")
9c08d1fa 1970
7db9af5d 1971(define_expand "divdf3"
1972 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1973 (div:DF (match_operand:DF 1 "s_register_operand" "")
1974 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 1975 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1976 "")
b11cae9e 1977\f
1978;; Boolean and,ior,xor insns
1979
f6ebffac 1980;; Split up double word logical operations
1981
1982;; Split up simple DImode logical operations. Simply perform the logical
1983;; operation on the upper and lower halves of the registers.
1984(define_split
1985 [(set (match_operand:DI 0 "s_register_operand" "")
1986 (match_operator:DI 6 "logical_binary_operator"
1987 [(match_operand:DI 1 "s_register_operand" "")
1988 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1989 "TARGET_32BIT && reload_completed
e2669ea7 1990 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1991 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1992 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1993 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1994 "
215b30b3 1995 {
1996 operands[3] = gen_highpart (SImode, operands[0]);
1997 operands[0] = gen_lowpart (SImode, operands[0]);
1998 operands[4] = gen_highpart (SImode, operands[1]);
1999 operands[1] = gen_lowpart (SImode, operands[1]);
2000 operands[5] = gen_highpart (SImode, operands[2]);
2001 operands[2] = gen_lowpart (SImode, operands[2]);
2002 }"
2003)
f6ebffac 2004
f6ebffac 2005(define_split
2006 [(set (match_operand:DI 0 "s_register_operand" "")
2007 (match_operator:DI 6 "logical_binary_operator"
2008 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2009 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2010 "TARGET_32BIT && reload_completed"
f6ebffac 2011 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2012 (set (match_dup 3) (match_op_dup:SI 6
2013 [(ashiftrt:SI (match_dup 2) (const_int 31))
2014 (match_dup 4)]))]
2015 "
215b30b3 2016 {
2017 operands[3] = gen_highpart (SImode, operands[0]);
2018 operands[0] = gen_lowpart (SImode, operands[0]);
2019 operands[4] = gen_highpart (SImode, operands[1]);
2020 operands[1] = gen_lowpart (SImode, operands[1]);
2021 operands[5] = gen_highpart (SImode, operands[2]);
2022 operands[2] = gen_lowpart (SImode, operands[2]);
2023 }"
2024)
f6ebffac 2025
f6ebffac 2026;; The zero extend of operand 2 means we can just copy the high part of
2027;; operand1 into operand0.
2028(define_split
2029 [(set (match_operand:DI 0 "s_register_operand" "")
2030 (ior:DI
2031 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2032 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2033 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2034 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2035 (set (match_dup 3) (match_dup 4))]
2036 "
215b30b3 2037 {
2038 operands[4] = gen_highpart (SImode, operands[1]);
2039 operands[3] = gen_highpart (SImode, operands[0]);
2040 operands[0] = gen_lowpart (SImode, operands[0]);
2041 operands[1] = gen_lowpart (SImode, operands[1]);
2042 }"
2043)
f6ebffac 2044
2045;; The zero extend of operand 2 means we can just copy the high part of
2046;; operand1 into operand0.
2047(define_split
2048 [(set (match_operand:DI 0 "s_register_operand" "")
2049 (xor:DI
2050 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2051 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2052 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2053 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2054 (set (match_dup 3) (match_dup 4))]
2055 "
215b30b3 2056 {
2057 operands[4] = gen_highpart (SImode, operands[1]);
2058 operands[3] = gen_highpart (SImode, operands[0]);
2059 operands[0] = gen_lowpart (SImode, operands[0]);
2060 operands[1] = gen_lowpart (SImode, operands[1]);
2061 }"
2062)
f6ebffac 2063
e2669ea7 2064(define_expand "anddi3"
2065 [(set (match_operand:DI 0 "s_register_operand" "")
2066 (and:DI (match_operand:DI 1 "s_register_operand" "")
2067 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2068 "TARGET_32BIT"
2069 ""
2070)
2071
2072(define_insn "*anddi3_insn"
cffb2a26 2073 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2074 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2075 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2076 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2077 "#"
215b30b3 2078 [(set_attr "length" "8")]
2079)
b11cae9e 2080
a0f94409 2081(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2082 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2083 (and:DI (zero_extend:DI
2084 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2085 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2086 "TARGET_32BIT"
f6ebffac 2087 "#"
25f905c2 2088 "TARGET_32BIT && reload_completed"
a0f94409 2089 ; The zero extend of operand 2 clears the high word of the output
2090 ; operand.
2091 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2092 (set (match_dup 3) (const_int 0))]
2093 "
2094 {
2095 operands[3] = gen_highpart (SImode, operands[0]);
2096 operands[0] = gen_lowpart (SImode, operands[0]);
2097 operands[1] = gen_lowpart (SImode, operands[1]);
2098 }"
215b30b3 2099 [(set_attr "length" "8")]
2100)
b11cae9e 2101
f7fbdd4a 2102(define_insn "*anddi_sesdi_di"
cffb2a26 2103 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2104 (and:DI (sign_extend:DI
2105 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2106 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2107 "TARGET_32BIT"
f6ebffac 2108 "#"
cffb2a26 2109 [(set_attr "length" "8")]
2110)
b11cae9e 2111
87b22bf7 2112(define_expand "andsi3"
cffb2a26 2113 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2114 (and:SI (match_operand:SI 1 "s_register_operand" "")
2115 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2116 "TARGET_EITHER"
87b22bf7 2117 "
25f905c2 2118 if (TARGET_32BIT)
87b22bf7 2119 {
0438d37f 2120 if (CONST_INT_P (operands[2]))
cffb2a26 2121 {
47b5b27b 2122 if (INTVAL (operands[2]) == 255 && arm_arch6)
2123 {
2124 operands[1] = convert_to_mode (QImode, operands[1], 1);
2125 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2126 operands[1]));
2127 }
2128 else
2129 arm_split_constant (AND, SImode, NULL_RTX,
2130 INTVAL (operands[2]), operands[0],
2131 operands[1],
2132 optimize && can_create_pseudo_p ());
615caa51 2133
cffb2a26 2134 DONE;
2135 }
87b22bf7 2136 }
25f905c2 2137 else /* TARGET_THUMB1 */
cffb2a26 2138 {
0438d37f 2139 if (!CONST_INT_P (operands[2]))
923ffadb 2140 {
2141 rtx tmp = force_reg (SImode, operands[2]);
2142 if (rtx_equal_p (operands[0], operands[1]))
2143 operands[2] = tmp;
2144 else
2145 {
2146 operands[2] = operands[1];
2147 operands[1] = tmp;
2148 }
2149 }
cffb2a26 2150 else
2151 {
2152 int i;
2153
215b30b3 2154 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2155 {
215b30b3 2156 operands[2] = force_reg (SImode,
2157 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2158
747b7458 2159 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2160
2161 DONE;
2162 }
87b22bf7 2163
cffb2a26 2164 for (i = 9; i <= 31; i++)
2165 {
2166 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2167 {
2168 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2169 const0_rtx));
2170 DONE;
2171 }
215b30b3 2172 else if ((((HOST_WIDE_INT) 1) << i) - 1
2173 == ~INTVAL (operands[2]))
cffb2a26 2174 {
2175 rtx shift = GEN_INT (i);
2176 rtx reg = gen_reg_rtx (SImode);
2177
2178 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2179 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2180
2181 DONE;
2182 }
2183 }
2184
2185 operands[2] = force_reg (SImode, operands[2]);
2186 }
215b30b3 2187 }
2188 "
cffb2a26 2189)
2190
25f905c2 2191; ??? Check split length for Thumb-2
a0f94409 2192(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2193 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2194 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2195 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2196 "TARGET_32BIT"
5565501b 2197 "@
2198 and%?\\t%0, %1, %2
87b22bf7 2199 bic%?\\t%0, %1, #%B2
2200 #"
25f905c2 2201 "TARGET_32BIT
0438d37f 2202 && CONST_INT_P (operands[2])
a0f94409 2203 && !(const_ok_for_arm (INTVAL (operands[2]))
2204 || const_ok_for_arm (~INTVAL (operands[2])))"
2205 [(clobber (const_int 0))]
2206 "
96f57e36 2207 arm_split_constant (AND, SImode, curr_insn,
2208 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2209 DONE;
2210 "
0d66636f 2211 [(set_attr "length" "4,4,16")
2212 (set_attr "predicable" "yes")]
cffb2a26 2213)
2214
25f905c2 2215(define_insn "*thumb1_andsi3_insn"
cffb2a26 2216 [(set (match_operand:SI 0 "register_operand" "=l")
2217 (and:SI (match_operand:SI 1 "register_operand" "%0")
2218 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2219 "TARGET_THUMB1"
747b7458 2220 "and\\t%0, %2"
2221 [(set_attr "length" "2")
2222 (set_attr "conds" "set")])
87b22bf7 2223
f7fbdd4a 2224(define_insn "*andsi3_compare0"
bd5b4116 2225 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2226 (compare:CC_NOOV
2227 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2228 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2229 (const_int 0)))
cffb2a26 2230 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2231 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2232 "TARGET_32BIT"
5565501b 2233 "@
25f905c2 2234 and%.\\t%0, %1, %2
2235 bic%.\\t%0, %1, #%B2"
cffb2a26 2236 [(set_attr "conds" "set")]
2237)
9c08d1fa 2238
f7fbdd4a 2239(define_insn "*andsi3_compare0_scratch"
bd5b4116 2240 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2241 (compare:CC_NOOV
2242 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2243 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2244 (const_int 0)))
dd193d7c 2245 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2246 "TARGET_32BIT"
5565501b 2247 "@
2248 tst%?\\t%0, %1
25f905c2 2249 bic%.\\t%2, %0, #%B1"
0d66636f 2250 [(set_attr "conds" "set")]
2251)
9c08d1fa 2252
f7fbdd4a 2253(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2254 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2255 (compare:CC_NOOV (zero_extract:SI
2256 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2257 (match_operand 1 "const_int_operand" "n")
2258 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2259 (const_int 0)))]
25f905c2 2260 "TARGET_32BIT
cffb2a26 2261 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2262 && INTVAL (operands[1]) > 0
2263 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2264 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2265 "*
5c49a439 2266 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2267 << INTVAL (operands[2]));
40dbec34 2268 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2269 return \"\";
0d66636f 2270 "
596e5e8f 2271 [(set_attr "conds" "set")
2272 (set_attr "predicable" "yes")]
0d66636f 2273)
9c08d1fa 2274
f4462328 2275(define_insn_and_split "*ne_zeroextractsi"
c4034607 2276 [(set (match_operand:SI 0 "s_register_operand" "=r")
2277 (ne:SI (zero_extract:SI
2278 (match_operand:SI 1 "s_register_operand" "r")
2279 (match_operand:SI 2 "const_int_operand" "n")
2280 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2281 (const_int 0)))
2282 (clobber (reg:CC CC_REGNUM))]
25f905c2 2283 "TARGET_32BIT
cffb2a26 2284 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2285 && INTVAL (operands[2]) > 0
2286 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2287 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2288 "#"
25f905c2 2289 "TARGET_32BIT
f4462328 2290 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2291 && INTVAL (operands[2]) > 0
2292 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2293 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2294 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2295 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2296 (const_int 0)))
2297 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2298 (set (match_dup 0)
2299 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2300 (match_dup 0) (const_int 1)))]
2301 "
2302 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2303 << INTVAL (operands[3]));
2304 "
2305 [(set_attr "conds" "clob")
25f905c2 2306 (set (attr "length")
2307 (if_then_else (eq_attr "is_thumb" "yes")
2308 (const_int 12)
2309 (const_int 8)))]
f4462328 2310)
2311
2312(define_insn_and_split "*ne_zeroextractsi_shifted"
2313 [(set (match_operand:SI 0 "s_register_operand" "=r")
2314 (ne:SI (zero_extract:SI
2315 (match_operand:SI 1 "s_register_operand" "r")
2316 (match_operand:SI 2 "const_int_operand" "n")
2317 (const_int 0))
2318 (const_int 0)))
2319 (clobber (reg:CC CC_REGNUM))]
2320 "TARGET_ARM"
2321 "#"
2322 "TARGET_ARM"
2323 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2324 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2325 (const_int 0)))
2326 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2327 (set (match_dup 0)
2328 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2329 (match_dup 0) (const_int 1)))]
2330 "
2331 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2332 "
2333 [(set_attr "conds" "clob")
2334 (set_attr "length" "8")]
2335)
2336
2337(define_insn_and_split "*ite_ne_zeroextractsi"
2338 [(set (match_operand:SI 0 "s_register_operand" "=r")
2339 (if_then_else:SI (ne (zero_extract:SI
2340 (match_operand:SI 1 "s_register_operand" "r")
2341 (match_operand:SI 2 "const_int_operand" "n")
2342 (match_operand:SI 3 "const_int_operand" "n"))
2343 (const_int 0))
2344 (match_operand:SI 4 "arm_not_operand" "rIK")
2345 (const_int 0)))
2346 (clobber (reg:CC CC_REGNUM))]
2347 "TARGET_ARM
2348 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2349 && INTVAL (operands[2]) > 0
2350 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2351 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2352 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2353 "#"
2354 "TARGET_ARM
2355 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2356 && INTVAL (operands[2]) > 0
2357 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2358 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2359 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2360 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2361 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2362 (const_int 0)))
2363 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2364 (set (match_dup 0)
2365 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2366 (match_dup 0) (match_dup 4)))]
2367 "
c4034607 2368 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2369 << INTVAL (operands[3]));
2370 "
2371 [(set_attr "conds" "clob")
2372 (set_attr "length" "8")]
2373)
2374
2375(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2376 [(set (match_operand:SI 0 "s_register_operand" "=r")
2377 (if_then_else:SI (ne (zero_extract:SI
2378 (match_operand:SI 1 "s_register_operand" "r")
2379 (match_operand:SI 2 "const_int_operand" "n")
2380 (const_int 0))
2381 (const_int 0))
2382 (match_operand:SI 3 "arm_not_operand" "rIK")
2383 (const_int 0)))
2384 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2385 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2386 "#"
f8d7bf2f 2387 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2388 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2389 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2390 (const_int 0)))
2391 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2392 (set (match_dup 0)
2393 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2394 (match_dup 0) (match_dup 3)))]
2395 "
2396 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2397 "
2398 [(set_attr "conds" "clob")
215b30b3 2399 (set_attr "length" "8")]
2400)
9c08d1fa 2401
58d6528b 2402(define_split
2403 [(set (match_operand:SI 0 "s_register_operand" "")
2404 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2405 (match_operand:SI 2 "const_int_operand" "")
2406 (match_operand:SI 3 "const_int_operand" "")))
2407 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2408 "TARGET_THUMB1"
58d6528b 2409 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2410 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2411 "{
2412 HOST_WIDE_INT temp = INTVAL (operands[2]);
2413
2414 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2415 operands[3] = GEN_INT (32 - temp);
2416 }"
2417)
2418
25f905c2 2419;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2420(define_split
2421 [(set (match_operand:SI 0 "s_register_operand" "")
2422 (match_operator:SI 1 "shiftable_operator"
2423 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2424 (match_operand:SI 3 "const_int_operand" "")
2425 (match_operand:SI 4 "const_int_operand" ""))
2426 (match_operand:SI 5 "s_register_operand" "")]))
2427 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2428 "TARGET_ARM"
2429 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2430 (set (match_dup 0)
2431 (match_op_dup 1
2432 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2433 (match_dup 5)]))]
2434 "{
2435 HOST_WIDE_INT temp = INTVAL (operands[3]);
2436
2437 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2438 operands[4] = GEN_INT (32 - temp);
2439 }"
2440)
2441
58d6528b 2442(define_split
2443 [(set (match_operand:SI 0 "s_register_operand" "")
2444 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2445 (match_operand:SI 2 "const_int_operand" "")
2446 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2447 "TARGET_THUMB1"
58d6528b 2448 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2449 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2450 "{
2451 HOST_WIDE_INT temp = INTVAL (operands[2]);
2452
2453 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2454 operands[3] = GEN_INT (32 - temp);
2455 }"
2456)
2457
d7863cfe 2458(define_split
2459 [(set (match_operand:SI 0 "s_register_operand" "")
2460 (match_operator:SI 1 "shiftable_operator"
2461 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2462 (match_operand:SI 3 "const_int_operand" "")
2463 (match_operand:SI 4 "const_int_operand" ""))
2464 (match_operand:SI 5 "s_register_operand" "")]))
2465 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2466 "TARGET_ARM"
2467 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2468 (set (match_dup 0)
2469 (match_op_dup 1
2470 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2471 (match_dup 5)]))]
2472 "{
2473 HOST_WIDE_INT temp = INTVAL (operands[3]);
2474
2475 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2476 operands[4] = GEN_INT (32 - temp);
2477 }"
2478)
2479
a42059fd 2480;;; ??? This pattern is bogus. If operand3 has bits outside the range
2481;;; represented by the bitfield, then this will produce incorrect results.
2482;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2483;;; which have a real bit-field insert instruction, the truncation happens
2484;;; in the bit-field insert instruction itself. Since arm does not have a
2485;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2486;;; the value before we insert. This loses some of the advantage of having
2487;;; this insv pattern, so this pattern needs to be reevalutated.
2488
8a18b90c 2489(define_expand "insv"
eb04cafb 2490 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2491 (match_operand 1 "general_operand" "")
2492 (match_operand 2 "general_operand" ""))
2493 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2494 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2495 "
215b30b3 2496 {
2497 int start_bit = INTVAL (operands[2]);
2498 int width = INTVAL (operands[1]);
2499 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2500 rtx target, subtarget;
2501
8b054d5a 2502 if (arm_arch_thumb2)
2503 {
eb04cafb 2504 if (unaligned_access && MEM_P (operands[0])
2505 && s_register_operand (operands[3], GET_MODE (operands[3]))
2506 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2507 {
eb04cafb 2508 rtx base_addr;
2509
2510 if (BYTES_BIG_ENDIAN)
2511 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2512 - start_bit;
8b054d5a 2513
eb04cafb 2514 if (width == 32)
8b054d5a 2515 {
eb04cafb 2516 base_addr = adjust_address (operands[0], SImode,
2517 start_bit / BITS_PER_UNIT);
2518 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2519 }
eb04cafb 2520 else
2521 {
2522 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2523
eb04cafb 2524 base_addr = adjust_address (operands[0], HImode,
2525 start_bit / BITS_PER_UNIT);
2526 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2527 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2528 }
2529 DONE;
8b054d5a 2530 }
eb04cafb 2531 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2532 {
eb04cafb 2533 bool use_bfi = TRUE;
8b054d5a 2534
0438d37f 2535 if (CONST_INT_P (operands[3]))
eb04cafb 2536 {
2537 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2538
2539 if (val == 0)
2540 {
2541 emit_insn (gen_insv_zero (operands[0], operands[1],
2542 operands[2]));
2543 DONE;
2544 }
2545
2546 /* See if the set can be done with a single orr instruction. */
2547 if (val == mask && const_ok_for_arm (val << start_bit))
2548 use_bfi = FALSE;
2549 }
2550
2551 if (use_bfi)
2552 {
0438d37f 2553 if (!REG_P (operands[3]))
eb04cafb 2554 operands[3] = force_reg (SImode, operands[3]);
2555
2556 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2557 operands[3]));
2558 DONE;
2559 }
8b054d5a 2560 }
eb04cafb 2561 else
2562 FAIL;
8b054d5a 2563 }
2564
eb04cafb 2565 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2566 FAIL;
2567
3f8fde42 2568 target = copy_rtx (operands[0]);
215b30b3 2569 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2570 subreg as the final target. */
2571 if (GET_CODE (target) == SUBREG)
2572 {
2573 subtarget = gen_reg_rtx (SImode);
2574 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2575 < GET_MODE_SIZE (SImode))
2576 target = SUBREG_REG (target);
2577 }
2578 else
2579 subtarget = target;
8a18b90c 2580
0438d37f 2581 if (CONST_INT_P (operands[3]))
215b30b3 2582 {
2583 /* Since we are inserting a known constant, we may be able to
2584 reduce the number of bits that we have to clear so that
2585 the mask becomes simple. */
2586 /* ??? This code does not check to see if the new mask is actually
2587 simpler. It may not be. */
2588 rtx op1 = gen_reg_rtx (SImode);
2589 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2590 start of this pattern. */
2591 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2592 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2593
c5b3a71b 2594 emit_insn (gen_andsi3 (op1, operands[0],
2595 gen_int_mode (~mask2, SImode)));
215b30b3 2596 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2597 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2598 }
2599 else if (start_bit == 0
2600 && !(const_ok_for_arm (mask)
2601 || const_ok_for_arm (~mask)))
2602 {
2603 /* A Trick, since we are setting the bottom bits in the word,
2604 we can shift operand[3] up, operand[0] down, OR them together
2605 and rotate the result back again. This takes 3 insns, and
5910bb95 2606 the third might be mergeable into another op. */
215b30b3 2607 /* The shift up copes with the possibility that operand[3] is
2608 wider than the bitfield. */
2609 rtx op0 = gen_reg_rtx (SImode);
2610 rtx op1 = gen_reg_rtx (SImode);
2611
2612 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2613 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2614 emit_insn (gen_iorsi3 (op1, op1, op0));
2615 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2616 }
2617 else if ((width + start_bit == 32)
2618 && !(const_ok_for_arm (mask)
2619 || const_ok_for_arm (~mask)))
2620 {
2621 /* Similar trick, but slightly less efficient. */
8a18b90c 2622
215b30b3 2623 rtx op0 = gen_reg_rtx (SImode);
2624 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2625
215b30b3 2626 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2627 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2628 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2629 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2630 }
2631 else
2632 {
c5b3a71b 2633 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2634 rtx op1 = gen_reg_rtx (SImode);
2635 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2636
215b30b3 2637 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2638 {
2639 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2640
215b30b3 2641 emit_insn (gen_movsi (tmp, op0));
2642 op0 = tmp;
2643 }
8a18b90c 2644
215b30b3 2645 /* Mask out any bits in operand[3] that are not needed. */
2646 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2647
0438d37f 2648 if (CONST_INT_P (op0)
215b30b3 2649 && (const_ok_for_arm (mask << start_bit)
2650 || const_ok_for_arm (~(mask << start_bit))))
2651 {
c5b3a71b 2652 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2653 emit_insn (gen_andsi3 (op2, operands[0], op0));
2654 }
2655 else
2656 {
0438d37f 2657 if (CONST_INT_P (op0))
215b30b3 2658 {
2659 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2660
215b30b3 2661 emit_insn (gen_movsi (tmp, op0));
2662 op0 = tmp;
2663 }
2664
2665 if (start_bit != 0)
2666 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2667
215b30b3 2668 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2669 }
8a18b90c 2670
215b30b3 2671 if (start_bit != 0)
2672 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2673
215b30b3 2674 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2675 }
f082f1c4 2676
215b30b3 2677 if (subtarget != target)
2678 {
2679 /* If TARGET is still a SUBREG, then it must be wider than a word,
2680 so we must be careful only to set the subword we were asked to. */
2681 if (GET_CODE (target) == SUBREG)
2682 emit_move_insn (target, subtarget);
2683 else
2684 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2685 }
8a18b90c 2686
215b30b3 2687 DONE;
2688 }"
2689)
8a18b90c 2690
8b054d5a 2691(define_insn "insv_zero"
2692 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2693 (match_operand:SI 1 "const_int_operand" "M")
2694 (match_operand:SI 2 "const_int_operand" "M"))
2695 (const_int 0))]
2696 "arm_arch_thumb2"
2697 "bfc%?\t%0, %2, %1"
2698 [(set_attr "length" "4")
2699 (set_attr "predicable" "yes")]
2700)
2701
2702(define_insn "insv_t2"
2703 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2704 (match_operand:SI 1 "const_int_operand" "M")
2705 (match_operand:SI 2 "const_int_operand" "M"))
2706 (match_operand:SI 3 "s_register_operand" "r"))]
2707 "arm_arch_thumb2"
2708 "bfi%?\t%0, %3, %2, %1"
2709 [(set_attr "length" "4")
2710 (set_attr "predicable" "yes")]
2711)
2712
215b30b3 2713; constants for op 2 will never be given to these patterns.
a0f94409 2714(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2715 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2716 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2717 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2718 "TARGET_32BIT"
f6ebffac 2719 "#"
e2669ea7 2720 "TARGET_32BIT && reload_completed
2721 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2722 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2723 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2724 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2725 "
2726 {
2727 operands[3] = gen_highpart (SImode, operands[0]);
2728 operands[0] = gen_lowpart (SImode, operands[0]);
2729 operands[4] = gen_highpart (SImode, operands[1]);
2730 operands[1] = gen_lowpart (SImode, operands[1]);
2731 operands[5] = gen_highpart (SImode, operands[2]);
2732 operands[2] = gen_lowpart (SImode, operands[2]);
2733 }"
0d66636f 2734 [(set_attr "length" "8")
2735 (set_attr "predicable" "yes")]
2736)
9c08d1fa 2737
a0f94409 2738(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2739 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2740 (and:DI (not:DI (zero_extend:DI
2741 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2742 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2743 "TARGET_32BIT"
e2348bcb 2744 "@
97499065 2745 bic%?\\t%Q0, %Q1, %2
f6ebffac 2746 #"
a0f94409 2747 ; (not (zero_extend ...)) allows us to just copy the high word from
2748 ; operand1 to operand0.
25f905c2 2749 "TARGET_32BIT
a0f94409 2750 && reload_completed
2751 && operands[0] != operands[1]"
5a097f7d 2752 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2753 (set (match_dup 3) (match_dup 4))]
2754 "
2755 {
2756 operands[3] = gen_highpart (SImode, operands[0]);
2757 operands[0] = gen_lowpart (SImode, operands[0]);
2758 operands[4] = gen_highpart (SImode, operands[1]);
2759 operands[1] = gen_lowpart (SImode, operands[1]);
2760 }"
0d66636f 2761 [(set_attr "length" "4,8")
2762 (set_attr "predicable" "yes")]
2763)
9c08d1fa 2764
a0f94409 2765(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2766 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2767 (and:DI (not:DI (sign_extend:DI
2768 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2769 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2770 "TARGET_32BIT"
f6ebffac 2771 "#"
25f905c2 2772 "TARGET_32BIT && reload_completed"
5a097f7d 2773 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2774 (set (match_dup 3) (and:SI (not:SI
2775 (ashiftrt:SI (match_dup 2) (const_int 31)))
2776 (match_dup 4)))]
2777 "
2778 {
2779 operands[3] = gen_highpart (SImode, operands[0]);
2780 operands[0] = gen_lowpart (SImode, operands[0]);
2781 operands[4] = gen_highpart (SImode, operands[1]);
2782 operands[1] = gen_lowpart (SImode, operands[1]);
2783 }"
0d66636f 2784 [(set_attr "length" "8")
2785 (set_attr "predicable" "yes")]
2786)
9c08d1fa 2787
8a18b90c 2788(define_insn "andsi_notsi_si"
9c08d1fa 2789 [(set (match_operand:SI 0 "s_register_operand" "=r")
2790 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2791 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2792 "TARGET_32BIT"
0d66636f 2793 "bic%?\\t%0, %1, %2"
2794 [(set_attr "predicable" "yes")]
2795)
b11cae9e 2796
747b7458 2797(define_insn "thumb1_bicsi3"
cffb2a26 2798 [(set (match_operand:SI 0 "register_operand" "=l")
2799 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2800 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2801 "TARGET_THUMB1"
747b7458 2802 "bic\\t%0, %1"
2803 [(set_attr "length" "2")
2804 (set_attr "conds" "set")])
cffb2a26 2805
8a18b90c 2806(define_insn "andsi_not_shiftsi_si"
a2cd141b 2807 [(set (match_operand:SI 0 "s_register_operand" "=r")
2808 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2809 [(match_operand:SI 2 "s_register_operand" "r")
2810 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2811 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2812 "TARGET_ARM"
6c4c2133 2813 "bic%?\\t%0, %1, %2%S4"
344495ea 2814 [(set_attr "predicable" "yes")
331beb1a 2815 (set_attr "shift" "2")
a2cd141b 2816 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2817 (const_string "alu_shift")
2818 (const_string "alu_shift_reg")))]
6c4c2133 2819)
8a18b90c 2820
f7fbdd4a 2821(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2822 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2823 (compare:CC_NOOV
2824 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2825 (match_operand:SI 1 "s_register_operand" "r"))
2826 (const_int 0)))
9c08d1fa 2827 (set (match_operand:SI 0 "s_register_operand" "=r")
2828 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2829 "TARGET_32BIT"
2830 "bic%.\\t%0, %1, %2"
0d66636f 2831 [(set_attr "conds" "set")]
2832)
9c08d1fa 2833
f7fbdd4a 2834(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2835 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2836 (compare:CC_NOOV
2837 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2838 (match_operand:SI 1 "s_register_operand" "r"))
2839 (const_int 0)))
9c08d1fa 2840 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2841 "TARGET_32BIT"
2842 "bic%.\\t%0, %1, %2"
0d66636f 2843 [(set_attr "conds" "set")]
2844)
9c08d1fa 2845
e2669ea7 2846(define_expand "iordi3"
2847 [(set (match_operand:DI 0 "s_register_operand" "")
2848 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2849 (match_operand:DI 2 "neon_logic_op2" "")))]
2850 "TARGET_32BIT"
2851 ""
2852)
2853
2854(define_insn "*iordi3_insn"
cffb2a26 2855 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2856 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2857 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2858 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2859 "#"
0d66636f 2860 [(set_attr "length" "8")
2861 (set_attr "predicable" "yes")]
cffb2a26 2862)
9c08d1fa 2863
f7fbdd4a 2864(define_insn "*iordi_zesidi_di"
9c08d1fa 2865 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2866 (ior:DI (zero_extend:DI
2867 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2868 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2869 "TARGET_32BIT"
e2348bcb 2870 "@
97499065 2871 orr%?\\t%Q0, %Q1, %2
f6ebffac 2872 #"
0d66636f 2873 [(set_attr "length" "4,8")
2874 (set_attr "predicable" "yes")]
cffb2a26 2875)
9c08d1fa 2876
f7fbdd4a 2877(define_insn "*iordi_sesidi_di"
9c08d1fa 2878 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2879 (ior:DI (sign_extend:DI
2880 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2881 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2882 "TARGET_32BIT"
f6ebffac 2883 "#"
0d66636f 2884 [(set_attr "length" "8")
2885 (set_attr "predicable" "yes")]
cffb2a26 2886)
9c08d1fa 2887
87b22bf7 2888(define_expand "iorsi3"
cffb2a26 2889 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2890 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2891 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2892 "TARGET_EITHER"
87b22bf7 2893 "
0438d37f 2894 if (CONST_INT_P (operands[2]))
87b22bf7 2895 {
25f905c2 2896 if (TARGET_32BIT)
cffb2a26 2897 {
96f57e36 2898 arm_split_constant (IOR, SImode, NULL_RTX,
2899 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2900 optimize && can_create_pseudo_p ());
cffb2a26 2901 DONE;
2902 }
25f905c2 2903 else /* TARGET_THUMB1 */
923ffadb 2904 {
2905 rtx tmp = force_reg (SImode, operands[2]);
2906 if (rtx_equal_p (operands[0], operands[1]))
2907 operands[2] = tmp;
2908 else
2909 {
2910 operands[2] = operands[1];
2911 operands[1] = tmp;
2912 }
2913 }
87b22bf7 2914 }
cffb2a26 2915 "
2916)
87b22bf7 2917
d5d4dc8d 2918(define_insn_and_split "*iorsi3_insn"
2919 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2920 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2921 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2922 "TARGET_32BIT"
87b22bf7 2923 "@
2924 orr%?\\t%0, %1, %2
d5d4dc8d 2925 orn%?\\t%0, %1, #%B2
87b22bf7 2926 #"
d5d4dc8d 2927 "TARGET_32BIT
0438d37f 2928 && CONST_INT_P (operands[2])
d5d4dc8d 2929 && !(const_ok_for_arm (INTVAL (operands[2]))
2930 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2931 [(clobber (const_int 0))]
d5d4dc8d 2932{
96f57e36 2933 arm_split_constant (IOR, SImode, curr_insn,
2934 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2935 DONE;
d5d4dc8d 2936}
2937 [(set_attr "length" "4,4,16")
2938 (set_attr "arch" "32,t2,32")
2939 (set_attr "predicable" "yes")])
cffb2a26 2940
747b7458 2941(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2942 [(set (match_operand:SI 0 "register_operand" "=l")
2943 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2944 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2945 "TARGET_THUMB1"
747b7458 2946 "orr\\t%0, %2"
2947 [(set_attr "length" "2")
2948 (set_attr "conds" "set")])
9c08d1fa 2949
a0f94409 2950(define_peephole2
2951 [(match_scratch:SI 3 "r")
372575c7 2952 (set (match_operand:SI 0 "arm_general_register_operand" "")
2953 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2954 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2955 "TARGET_ARM
a0f94409 2956 && !const_ok_for_arm (INTVAL (operands[2]))
2957 && const_ok_for_arm (~INTVAL (operands[2]))"
2958 [(set (match_dup 3) (match_dup 2))
2959 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2960 ""
215b30b3 2961)
a0f94409 2962
f7fbdd4a 2963(define_insn "*iorsi3_compare0"
bd5b4116 2964 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2965 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2966 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2967 (const_int 0)))
2968 (set (match_operand:SI 0 "s_register_operand" "=r")
2969 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2970 "TARGET_32BIT"
2971 "orr%.\\t%0, %1, %2"
cffb2a26 2972 [(set_attr "conds" "set")]
2973)
9c08d1fa 2974
f7fbdd4a 2975(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2976 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2977 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2978 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2979 (const_int 0)))
2980 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2981 "TARGET_32BIT"
2982 "orr%.\\t%0, %1, %2"
0d66636f 2983 [(set_attr "conds" "set")]
2984)
9c08d1fa 2985
e2669ea7 2986(define_expand "xordi3"
2987 [(set (match_operand:DI 0 "s_register_operand" "")
2988 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2989 (match_operand:DI 2 "s_register_operand" "")))]
2990 "TARGET_32BIT"
2991 ""
2992)
2993
2994(define_insn "*xordi3_insn"
cffb2a26 2995 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2996 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2997 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2998 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2999 "#"
0d66636f 3000 [(set_attr "length" "8")
3001 (set_attr "predicable" "yes")]
cffb2a26 3002)
9c08d1fa 3003
f7fbdd4a 3004(define_insn "*xordi_zesidi_di"
9c08d1fa 3005 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3006 (xor:DI (zero_extend:DI
3007 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3008 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3009 "TARGET_32BIT"
e2348bcb 3010 "@
97499065 3011 eor%?\\t%Q0, %Q1, %2
f6ebffac 3012 #"
0d66636f 3013 [(set_attr "length" "4,8")
3014 (set_attr "predicable" "yes")]
cffb2a26 3015)
9c08d1fa 3016
f7fbdd4a 3017(define_insn "*xordi_sesidi_di"
9c08d1fa 3018 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3019 (xor:DI (sign_extend:DI
3020 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3021 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3022 "TARGET_32BIT"
f6ebffac 3023 "#"
0d66636f 3024 [(set_attr "length" "8")
3025 (set_attr "predicable" "yes")]
cffb2a26 3026)
9c08d1fa 3027
cffb2a26 3028(define_expand "xorsi3"
3029 [(set (match_operand:SI 0 "s_register_operand" "")
3030 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3031 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3032 "TARGET_EITHER"
0438d37f 3033 "if (CONST_INT_P (operands[2]))
923ffadb 3034 {
3035 if (TARGET_32BIT)
3036 {
3037 arm_split_constant (XOR, SImode, NULL_RTX,
3038 INTVAL (operands[2]), operands[0], operands[1],
3039 optimize && can_create_pseudo_p ());
3040 DONE;
3041 }
3042 else /* TARGET_THUMB1 */
3043 {
3044 rtx tmp = force_reg (SImode, operands[2]);
3045 if (rtx_equal_p (operands[0], operands[1]))
3046 operands[2] = tmp;
3047 else
3048 {
3049 operands[2] = operands[1];
3050 operands[1] = tmp;
3051 }
3052 }
3053 }"
cffb2a26 3054)
3055
5dcb35d9 3056(define_insn_and_split "*arm_xorsi3"
3057 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3058 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3059 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
25f905c2 3060 "TARGET_32BIT"
5dcb35d9 3061 "@
3062 eor%?\\t%0, %1, %2
3063 #"
3064 "TARGET_32BIT
0438d37f 3065 && CONST_INT_P (operands[2])
5dcb35d9 3066 && !const_ok_for_arm (INTVAL (operands[2]))"
3067 [(clobber (const_int 0))]
3068{
3069 arm_split_constant (XOR, SImode, curr_insn,
3070 INTVAL (operands[2]), operands[0], operands[1], 0);
3071 DONE;
3072}
3073 [(set_attr "length" "4,16")
3074 (set_attr "predicable" "yes")]
cffb2a26 3075)
3076
747b7458 3077(define_insn "*thumb1_xorsi3_insn"
cffb2a26 3078 [(set (match_operand:SI 0 "register_operand" "=l")
3079 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3080 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3081 "TARGET_THUMB1"
747b7458 3082 "eor\\t%0, %2"
3083 [(set_attr "length" "2")
3084 (set_attr "conds" "set")])
9c08d1fa 3085
f7fbdd4a 3086(define_insn "*xorsi3_compare0"
bd5b4116 3087 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3088 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3089 (match_operand:SI 2 "arm_rhs_operand" "rI"))
3090 (const_int 0)))
3091 (set (match_operand:SI 0 "s_register_operand" "=r")
3092 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3093 "TARGET_32BIT"
3094 "eor%.\\t%0, %1, %2"
0d66636f 3095 [(set_attr "conds" "set")]
3096)
9c08d1fa 3097
f7fbdd4a 3098(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3099 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3100 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
3101 (match_operand:SI 1 "arm_rhs_operand" "rI"))
3102 (const_int 0)))]
25f905c2 3103 "TARGET_32BIT"
40dbec34 3104 "teq%?\\t%0, %1"
cffb2a26 3105 [(set_attr "conds" "set")]
3106)
9c08d1fa 3107
215b30b3 3108; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3109; (NOT D) we can sometimes merge the final NOT into one of the following
3110; insns.
9c08d1fa 3111
3112(define_split
a058e94a 3113 [(set (match_operand:SI 0 "s_register_operand" "")
3114 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3115 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3116 (match_operand:SI 3 "arm_rhs_operand" "")))
3117 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3118 "TARGET_32BIT"
9c08d1fa 3119 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3120 (not:SI (match_dup 3))))
3121 (set (match_dup 0) (not:SI (match_dup 4)))]
3122 ""
3123)
3124
f7fbdd4a 3125(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 3126 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3127 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3128 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3129 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3130 "TARGET_32BIT"
40dbec34 3131 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 3132 [(set_attr "length" "8")
25f905c2 3133 (set_attr "ce_count" "2")
0d66636f 3134 (set_attr "predicable" "yes")]
cffb2a26 3135)
9c08d1fa 3136
25f905c2 3137; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3138; insns are available?
d7863cfe 3139(define_split
3140 [(set (match_operand:SI 0 "s_register_operand" "")
3141 (match_operator:SI 1 "logical_binary_operator"
3142 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3143 (match_operand:SI 3 "const_int_operand" "")
3144 (match_operand:SI 4 "const_int_operand" ""))
3145 (match_operator:SI 9 "logical_binary_operator"
3146 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3147 (match_operand:SI 6 "const_int_operand" ""))
3148 (match_operand:SI 7 "s_register_operand" "")])]))
3149 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3150 "TARGET_32BIT
d7863cfe 3151 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3152 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3153 [(set (match_dup 8)
3154 (match_op_dup 1
3155 [(ashift:SI (match_dup 2) (match_dup 4))
3156 (match_dup 5)]))
3157 (set (match_dup 0)
3158 (match_op_dup 1
3159 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3160 (match_dup 7)]))]
3161 "
3162 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3163")
3164
3165(define_split
3166 [(set (match_operand:SI 0 "s_register_operand" "")
3167 (match_operator:SI 1 "logical_binary_operator"
3168 [(match_operator:SI 9 "logical_binary_operator"
3169 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3170 (match_operand:SI 6 "const_int_operand" ""))
3171 (match_operand:SI 7 "s_register_operand" "")])
3172 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3173 (match_operand:SI 3 "const_int_operand" "")
3174 (match_operand:SI 4 "const_int_operand" ""))]))
3175 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3176 "TARGET_32BIT
d7863cfe 3177 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3178 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3179 [(set (match_dup 8)
3180 (match_op_dup 1
3181 [(ashift:SI (match_dup 2) (match_dup 4))
3182 (match_dup 5)]))
3183 (set (match_dup 0)
3184 (match_op_dup 1
3185 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3186 (match_dup 7)]))]
3187 "
3188 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3189")
3190
3191(define_split
3192 [(set (match_operand:SI 0 "s_register_operand" "")
3193 (match_operator:SI 1 "logical_binary_operator"
3194 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3195 (match_operand:SI 3 "const_int_operand" "")
3196 (match_operand:SI 4 "const_int_operand" ""))
3197 (match_operator:SI 9 "logical_binary_operator"
3198 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3199 (match_operand:SI 6 "const_int_operand" ""))
3200 (match_operand:SI 7 "s_register_operand" "")])]))
3201 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3202 "TARGET_32BIT
d7863cfe 3203 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3204 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3205 [(set (match_dup 8)
3206 (match_op_dup 1
3207 [(ashift:SI (match_dup 2) (match_dup 4))
3208 (match_dup 5)]))
3209 (set (match_dup 0)
3210 (match_op_dup 1
3211 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3212 (match_dup 7)]))]
3213 "
3214 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3215")
3216
3217(define_split
3218 [(set (match_operand:SI 0 "s_register_operand" "")
3219 (match_operator:SI 1 "logical_binary_operator"
3220 [(match_operator:SI 9 "logical_binary_operator"
3221 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3222 (match_operand:SI 6 "const_int_operand" ""))
3223 (match_operand:SI 7 "s_register_operand" "")])
3224 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3225 (match_operand:SI 3 "const_int_operand" "")
3226 (match_operand:SI 4 "const_int_operand" ""))]))
3227 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3228 "TARGET_32BIT
d7863cfe 3229 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3230 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3231 [(set (match_dup 8)
3232 (match_op_dup 1
3233 [(ashift:SI (match_dup 2) (match_dup 4))
3234 (match_dup 5)]))
3235 (set (match_dup 0)
3236 (match_op_dup 1
3237 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3238 (match_dup 7)]))]
3239 "
3240 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3241")
9c08d1fa 3242\f
3243
3244;; Minimum and maximum insns
3245
8b9dc177 3246(define_expand "smaxsi3"
3247 [(parallel [
3248 (set (match_operand:SI 0 "s_register_operand" "")
3249 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3250 (match_operand:SI 2 "arm_rhs_operand" "")))
3251 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3252 "TARGET_32BIT"
8b9dc177 3253 "
8774928b 3254 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3255 {
3256 /* No need for a clobber of the condition code register here. */
3257 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3258 gen_rtx_SMAX (SImode, operands[1],
3259 operands[2])));
3260 DONE;
3261 }
3262")
3263
3264(define_insn "*smax_0"
3265 [(set (match_operand:SI 0 "s_register_operand" "=r")
3266 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3267 (const_int 0)))]
25f905c2 3268 "TARGET_32BIT"
8b9dc177 3269 "bic%?\\t%0, %1, %1, asr #31"
3270 [(set_attr "predicable" "yes")]
3271)
3272
8774928b 3273(define_insn "*smax_m1"
3274 [(set (match_operand:SI 0 "s_register_operand" "=r")
3275 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3276 (const_int -1)))]
25f905c2 3277 "TARGET_32BIT"
8774928b 3278 "orr%?\\t%0, %1, %1, asr #31"
3279 [(set_attr "predicable" "yes")]
3280)
3281
25f905c2 3282(define_insn "*arm_smax_insn"
8b9dc177 3283 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3284 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3285 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3286 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3287 "TARGET_ARM"
e2348bcb 3288 "@
3289 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3290 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3291 [(set_attr "conds" "clob")
8b9dc177 3292 (set_attr "length" "8,12")]
cffb2a26 3293)
9c08d1fa 3294
8b9dc177 3295(define_expand "sminsi3"
3296 [(parallel [
3297 (set (match_operand:SI 0 "s_register_operand" "")
3298 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3299 (match_operand:SI 2 "arm_rhs_operand" "")))
3300 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3301 "TARGET_32BIT"
8b9dc177 3302 "
3303 if (operands[2] == const0_rtx)
3304 {
3305 /* No need for a clobber of the condition code register here. */
3306 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3307 gen_rtx_SMIN (SImode, operands[1],
3308 operands[2])));
3309 DONE;
3310 }
3311")
3312
3313(define_insn "*smin_0"
3314 [(set (match_operand:SI 0 "s_register_operand" "=r")
3315 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3316 (const_int 0)))]
25f905c2 3317 "TARGET_32BIT"
8b9dc177 3318 "and%?\\t%0, %1, %1, asr #31"
3319 [(set_attr "predicable" "yes")]
3320)
3321
25f905c2 3322(define_insn "*arm_smin_insn"
8b9dc177 3323 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3324 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3325 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3326 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3327 "TARGET_ARM"
e2348bcb 3328 "@
3329 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3330 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3331 [(set_attr "conds" "clob")
8b9dc177 3332 (set_attr "length" "8,12")]
0d66636f 3333)
9c08d1fa 3334
25f905c2 3335(define_expand "umaxsi3"
3336 [(parallel [
3337 (set (match_operand:SI 0 "s_register_operand" "")
3338 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3339 (match_operand:SI 2 "arm_rhs_operand" "")))
3340 (clobber (reg:CC CC_REGNUM))])]
3341 "TARGET_32BIT"
3342 ""
3343)
3344
3345(define_insn "*arm_umaxsi3"
9c08d1fa 3346 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3347 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3348 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3349 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3350 "TARGET_ARM"
e2348bcb 3351 "@
3352 cmp\\t%1, %2\;movcc\\t%0, %2
3353 cmp\\t%1, %2\;movcs\\t%0, %1
3354 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3355 [(set_attr "conds" "clob")
3356 (set_attr "length" "8,8,12")]
3357)
9c08d1fa 3358
25f905c2 3359(define_expand "uminsi3"
3360 [(parallel [
3361 (set (match_operand:SI 0 "s_register_operand" "")
3362 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3363 (match_operand:SI 2 "arm_rhs_operand" "")))
3364 (clobber (reg:CC CC_REGNUM))])]
3365 "TARGET_32BIT"
3366 ""
3367)
3368
3369(define_insn "*arm_uminsi3"
9c08d1fa 3370 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3371 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3372 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3373 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3374 "TARGET_ARM"
e2348bcb 3375 "@
3376 cmp\\t%1, %2\;movcs\\t%0, %2
3377 cmp\\t%1, %2\;movcc\\t%0, %1
3378 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3379 [(set_attr "conds" "clob")
3380 (set_attr "length" "8,8,12")]
3381)
9c08d1fa 3382
8a18b90c 3383(define_insn "*store_minmaxsi"
9c08d1fa 3384 [(set (match_operand:SI 0 "memory_operand" "=m")
3385 (match_operator:SI 3 "minmax_operator"
3386 [(match_operand:SI 1 "s_register_operand" "r")
3387 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3388 (clobber (reg:CC CC_REGNUM))]
25f905c2 3389 "TARGET_32BIT"
9c08d1fa 3390 "*
dc55b8a9 3391 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3392 operands[1], operands[2]);
e2348bcb 3393 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3394 if (TARGET_THUMB2)
3395 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3396 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3397 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3398 return \"\";
0d66636f 3399 "
3400 [(set_attr "conds" "clob")
25f905c2 3401 (set (attr "length")
3402 (if_then_else (eq_attr "is_thumb" "yes")
3403 (const_int 14)
3404 (const_int 12)))
0d66636f 3405 (set_attr "type" "store1")]
3406)
9c08d1fa 3407
8a18b90c 3408; Reject the frame pointer in operand[1], since reloading this after
3409; it has been eliminated can cause carnage.
f7fbdd4a 3410(define_insn "*minmax_arithsi"
9c08d1fa 3411 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3412 (match_operator:SI 4 "shiftable_operator"
3413 [(match_operator:SI 5 "minmax_operator"
3414 [(match_operand:SI 2 "s_register_operand" "r,r")
3415 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3416 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3417 (clobber (reg:CC CC_REGNUM))]
25f905c2 3418 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3419 "*
0d66636f 3420 {
3421 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3422 bool need_else;
3423
3424 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3425 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3426 need_else = true;
3427 else
3428 need_else = false;
0d66636f 3429
dc55b8a9 3430 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3431 operands[2], operands[3]);
0d66636f 3432 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3433 if (TARGET_THUMB2)
3434 {
3435 if (need_else)
3436 output_asm_insn (\"ite\\t%d5\", operands);
3437 else
3438 output_asm_insn (\"it\\t%d5\", operands);
3439 }
0d66636f 3440 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3441 if (need_else)
0d66636f 3442 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3443 return \"\";
215b30b3 3444 }"
0d66636f 3445 [(set_attr "conds" "clob")
25f905c2 3446 (set (attr "length")
3447 (if_then_else (eq_attr "is_thumb" "yes")
3448 (const_int 14)
3449 (const_int 12)))]
0d66636f 3450)
9c08d1fa 3451
b49e3742 3452(define_code_iterator SAT [smin smax])
3453(define_code_iterator SATrev [smin smax])
3454(define_code_attr SATlo [(smin "1") (smax "2")])
3455(define_code_attr SAThi [(smin "2") (smax "1")])
3456
3457(define_insn "*satsi_<SAT:code>"
3458 [(set (match_operand:SI 0 "s_register_operand" "=r")
3459 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3460 (match_operand:SI 1 "const_int_operand" "i"))
3461 (match_operand:SI 2 "const_int_operand" "i")))]
3462 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3463 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3464{
3465 int mask;
3466 bool signed_sat;
3467 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3468 &mask, &signed_sat))
3469 gcc_unreachable ();
3470
3471 operands[1] = GEN_INT (mask);
3472 if (signed_sat)
3473 return "ssat%?\t%0, %1, %3";
3474 else
3475 return "usat%?\t%0, %1, %3";
3476}
3477 [(set_attr "predicable" "yes")
3478 (set_attr "insn" "sat")])
3479
3480(define_insn "*satsi_<SAT:code>_shift"
3481 [(set (match_operand:SI 0 "s_register_operand" "=r")
3482 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3483 [(match_operand:SI 4 "s_register_operand" "r")
3484 (match_operand:SI 5 "const_int_operand" "i")])
3485 (match_operand:SI 1 "const_int_operand" "i"))
3486 (match_operand:SI 2 "const_int_operand" "i")))]
3487 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3488 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3489{
3490 int mask;
3491 bool signed_sat;
3492 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3493 &mask, &signed_sat))
3494 gcc_unreachable ();
3495
3496 operands[1] = GEN_INT (mask);
3497 if (signed_sat)
3498 return "ssat%?\t%0, %1, %4%S3";
3499 else
3500 return "usat%?\t%0, %1, %4%S3";
3501}
3502 [(set_attr "predicable" "yes")
3503 (set_attr "insn" "sat")
3504 (set_attr "shift" "3")
3505 (set_attr "type" "alu_shift")])
b11cae9e 3506\f
3507;; Shift and rotation insns
3508
a2cd141b 3509(define_expand "ashldi3"
3510 [(set (match_operand:DI 0 "s_register_operand" "")
3511 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3512 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3513 "TARGET_32BIT"
a2cd141b 3514 "
aa06c51c 3515 if (TARGET_NEON)
3516 {
3517 /* Delay the decision whether to use NEON or core-regs until
3518 register allocation. */
3519 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3520 DONE;
3521 }
3522 else
3523 {
3524 /* Only the NEON case can handle in-memory shift counts. */
3525 if (!reg_or_int_operand (operands[2], SImode))
3526 operands[2] = force_reg (SImode, operands[2]);
3527 }
3528
b805622c 3529 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3530 ; /* No special preparation statements; expand pattern as above. */
3531 else
a2cd141b 3532 {
ffcc986d 3533 rtx scratch1, scratch2;
3534
3535 if (CONST_INT_P (operands[2])
3536 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3537 {
3538 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3539 DONE;
3540 }
ffcc986d 3541
3542 /* Ideally we should use iwmmxt here if we could know that operands[1]
3543 ends up already living in an iwmmxt register. Otherwise it's
3544 cheaper to have the alternate code being generated than moving
3545 values to iwmmxt regs and back. */
3546
3547 /* If we're optimizing for size, we prefer the libgcc calls. */
3548 if (optimize_function_for_size_p (cfun))
3549 FAIL;
3550
3551 /* Expand operation using core-registers.
3552 'FAIL' would achieve the same thing, but this is a bit smarter. */
3553 scratch1 = gen_reg_rtx (SImode);
3554 scratch2 = gen_reg_rtx (SImode);
3555 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3556 operands[2], scratch1, scratch2);
3557 DONE;
a2cd141b 3558 }
a2cd141b 3559 "
3560)
3561
3562(define_insn "arm_ashldi3_1bit"
50ad1bf9 3563 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3564 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3565 (const_int 1)))
3566 (clobber (reg:CC CC_REGNUM))]
25f905c2 3567 "TARGET_32BIT"
a2cd141b 3568 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3569 [(set_attr "conds" "clob")
3570 (set_attr "length" "8")]
3571)
3572
87b22bf7 3573(define_expand "ashlsi3"
cffb2a26 3574 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3575 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3576 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3577 "TARGET_EITHER"
87b22bf7 3578 "
0438d37f 3579 if (CONST_INT_P (operands[2])
87b22bf7 3580 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3581 {
3582 emit_insn (gen_movsi (operands[0], const0_rtx));
3583 DONE;
3584 }
cffb2a26 3585 "
3586)
3587
25f905c2 3588(define_insn "*thumb1_ashlsi3"
cffb2a26 3589 [(set (match_operand:SI 0 "register_operand" "=l,l")
3590 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3591 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3592 "TARGET_THUMB1"
cffb2a26 3593 "lsl\\t%0, %1, %2"
747b7458 3594 [(set_attr "length" "2")
3595 (set_attr "conds" "set")])
b11cae9e 3596
a2cd141b 3597(define_expand "ashrdi3"
3598 [(set (match_operand:DI 0 "s_register_operand" "")
3599 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3600 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3601 "TARGET_32BIT"
a2cd141b 3602 "
aa06c51c 3603 if (TARGET_NEON)
3604 {
3605 /* Delay the decision whether to use NEON or core-regs until
3606 register allocation. */
3607 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3608 DONE;
3609 }
3610
b805622c 3611 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3612 ; /* No special preparation statements; expand pattern as above. */
3613 else
a2cd141b 3614 {
ffcc986d 3615 rtx scratch1, scratch2;
3616
3617 if (CONST_INT_P (operands[2])
3618 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3619 {
3620 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3621 DONE;
3622 }
ffcc986d 3623
3624 /* Ideally we should use iwmmxt here if we could know that operands[1]
3625 ends up already living in an iwmmxt register. Otherwise it's
3626 cheaper to have the alternate code being generated than moving
3627 values to iwmmxt regs and back. */
3628
3629 /* If we're optimizing for size, we prefer the libgcc calls. */
3630 if (optimize_function_for_size_p (cfun))
3631 FAIL;
3632
3633 /* Expand operation using core-registers.
3634 'FAIL' would achieve the same thing, but this is a bit smarter. */
3635 scratch1 = gen_reg_rtx (SImode);
3636 scratch2 = gen_reg_rtx (SImode);
3637 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3638 operands[2], scratch1, scratch2);
3639 DONE;
a2cd141b 3640 }
a2cd141b 3641 "
3642)
3643
3644(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3645 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3646 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3647 (const_int 1)))
3648 (clobber (reg:CC CC_REGNUM))]
25f905c2 3649 "TARGET_32BIT"
a2cd141b 3650 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3651 [(set_attr "conds" "clob")
d2a518d1 3652 (set_attr "insn" "mov")
a2cd141b 3653 (set_attr "length" "8")]
3654)
3655
87b22bf7 3656(define_expand "ashrsi3"
cffb2a26 3657 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3658 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3659 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3660 "TARGET_EITHER"
87b22bf7 3661 "
0438d37f 3662 if (CONST_INT_P (operands[2])
87b22bf7 3663 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3664 operands[2] = GEN_INT (31);
cffb2a26 3665 "
3666)
3667
25f905c2 3668(define_insn "*thumb1_ashrsi3"
cffb2a26 3669 [(set (match_operand:SI 0 "register_operand" "=l,l")
3670 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3671 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3672 "TARGET_THUMB1"
cffb2a26 3673 "asr\\t%0, %1, %2"
747b7458 3674 [(set_attr "length" "2")
3675 (set_attr "conds" "set")])
b11cae9e 3676
a2cd141b 3677(define_expand "lshrdi3"
3678 [(set (match_operand:DI 0 "s_register_operand" "")
3679 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3680 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3681 "TARGET_32BIT"
a2cd141b 3682 "
aa06c51c 3683 if (TARGET_NEON)
3684 {
3685 /* Delay the decision whether to use NEON or core-regs until
3686 register allocation. */
3687 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3688 DONE;
3689 }
3690
b805622c 3691 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3692 ; /* No special preparation statements; expand pattern as above. */
3693 else
a2cd141b 3694 {
ffcc986d 3695 rtx scratch1, scratch2;
3696
3697 if (CONST_INT_P (operands[2])
3698 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3699 {
3700 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3701 DONE;
3702 }
ffcc986d 3703
3704 /* Ideally we should use iwmmxt here if we could know that operands[1]
3705 ends up already living in an iwmmxt register. Otherwise it's
3706 cheaper to have the alternate code being generated than moving
3707 values to iwmmxt regs and back. */
3708
3709 /* If we're optimizing for size, we prefer the libgcc calls. */
3710 if (optimize_function_for_size_p (cfun))
3711 FAIL;
3712
3713 /* Expand operation using core-registers.
3714 'FAIL' would achieve the same thing, but this is a bit smarter. */
3715 scratch1 = gen_reg_rtx (SImode);
3716 scratch2 = gen_reg_rtx (SImode);
3717 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3718 operands[2], scratch1, scratch2);
3719 DONE;
a2cd141b 3720 }
a2cd141b 3721 "
3722)
3723
3724(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3725 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3726 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3727 (const_int 1)))
3728 (clobber (reg:CC CC_REGNUM))]
25f905c2 3729 "TARGET_32BIT"
a2cd141b 3730 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3731 [(set_attr "conds" "clob")
d2a518d1 3732 (set_attr "insn" "mov")
a2cd141b 3733 (set_attr "length" "8")]
3734)
3735
87b22bf7 3736(define_expand "lshrsi3"
cffb2a26 3737 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3738 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3739 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3740 "TARGET_EITHER"
87b22bf7 3741 "
0438d37f 3742 if (CONST_INT_P (operands[2])
87b22bf7 3743 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3744 {
3745 emit_insn (gen_movsi (operands[0], const0_rtx));
3746 DONE;
3747 }
cffb2a26 3748 "
3749)
3750
25f905c2 3751(define_insn "*thumb1_lshrsi3"
cffb2a26 3752 [(set (match_operand:SI 0 "register_operand" "=l,l")
3753 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3754 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3755 "TARGET_THUMB1"
cffb2a26 3756 "lsr\\t%0, %1, %2"
747b7458 3757 [(set_attr "length" "2")
3758 (set_attr "conds" "set")])
b11cae9e 3759
87b22bf7 3760(define_expand "rotlsi3"
cffb2a26 3761 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3762 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3763 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3764 "TARGET_32BIT"
87b22bf7 3765 "
0438d37f 3766 if (CONST_INT_P (operands[2]))
87b22bf7 3767 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3768 else
b11cae9e 3769 {
87b22bf7 3770 rtx reg = gen_reg_rtx (SImode);
3771 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3772 operands[2] = reg;
b11cae9e 3773 }
cffb2a26 3774 "
3775)
9c08d1fa 3776
87b22bf7 3777(define_expand "rotrsi3"
cffb2a26 3778 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3779 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3780 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3781 "TARGET_EITHER"
87b22bf7 3782 "
25f905c2 3783 if (TARGET_32BIT)
cffb2a26 3784 {
0438d37f 3785 if (CONST_INT_P (operands[2])
cffb2a26 3786 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3787 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3788 }
25f905c2 3789 else /* TARGET_THUMB1 */
cffb2a26 3790 {
0438d37f 3791 if (CONST_INT_P (operands [2]))
cffb2a26 3792 operands [2] = force_reg (SImode, operands[2]);
3793 }
3794 "
3795)
87b22bf7 3796
25f905c2 3797(define_insn "*thumb1_rotrsi3"
cffb2a26 3798 [(set (match_operand:SI 0 "register_operand" "=l")
3799 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3800 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3801 "TARGET_THUMB1"
cffb2a26 3802 "ror\\t%0, %0, %2"
3803 [(set_attr "length" "2")]
3804)
3805
3806(define_insn "*arm_shiftsi3"
3807 [(set (match_operand:SI 0 "s_register_operand" "=r")
3808 (match_operator:SI 3 "shift_operator"
3809 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3810 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3811 "TARGET_32BIT"
3812 "* return arm_output_shift(operands, 0);"
344495ea 3813 [(set_attr "predicable" "yes")
331beb1a 3814 (set_attr "shift" "1")
a2cd141b 3815 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3816 (const_string "alu_shift")
3817 (const_string "alu_shift_reg")))]
6c4c2133 3818)
87b22bf7 3819
f7fbdd4a 3820(define_insn "*shiftsi3_compare0"
bd5b4116 3821 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3822 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3823 [(match_operand:SI 1 "s_register_operand" "r")
3824 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3825 (const_int 0)))
3826 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3827 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3828 "TARGET_32BIT"
3829 "* return arm_output_shift(operands, 1);"
344495ea 3830 [(set_attr "conds" "set")
331beb1a 3831 (set_attr "shift" "1")
a2cd141b 3832 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3833 (const_string "alu_shift")
3834 (const_string "alu_shift_reg")))]
0d66636f 3835)
9c08d1fa 3836
f7fbdd4a 3837(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3838 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3839 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3840 [(match_operand:SI 1 "s_register_operand" "r")
3841 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3842 (const_int 0)))
3843 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3844 "TARGET_32BIT"
3845 "* return arm_output_shift(operands, 1);"
344495ea 3846 [(set_attr "conds" "set")
a2cd141b 3847 (set_attr "shift" "1")]
0d66636f 3848)
9c08d1fa 3849
d5d4dc8d 3850(define_insn "*not_shiftsi"
3851 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3852 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3853 [(match_operand:SI 1 "s_register_operand" "r,r")
3854 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3855 "TARGET_32BIT"
6c4c2133 3856 "mvn%?\\t%0, %1%S3"
344495ea 3857 [(set_attr "predicable" "yes")
331beb1a 3858 (set_attr "shift" "1")
d2a518d1 3859 (set_attr "insn" "mvn")
d5d4dc8d 3860 (set_attr "arch" "32,a")
3861 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3862
d5d4dc8d 3863(define_insn "*not_shiftsi_compare0"
bd5b4116 3864 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3865 (compare:CC_NOOV
3866 (not:SI (match_operator:SI 3 "shift_operator"
3867 [(match_operand:SI 1 "s_register_operand" "r,r")
3868 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3869 (const_int 0)))
3870 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3871 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3872 "TARGET_32BIT"
25f905c2 3873 "mvn%.\\t%0, %1%S3"
344495ea 3874 [(set_attr "conds" "set")
331beb1a 3875 (set_attr "shift" "1")
d2a518d1 3876 (set_attr "insn" "mvn")
d5d4dc8d 3877 (set_attr "arch" "32,a")
3878 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3879
d5d4dc8d 3880(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3881 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3882 (compare:CC_NOOV
3883 (not:SI (match_operator:SI 3 "shift_operator"
3884 [(match_operand:SI 1 "s_register_operand" "r,r")
3885 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3886 (const_int 0)))
3887 (clobber (match_scratch:SI 0 "=r,r"))]
3888 "TARGET_32BIT"
25f905c2 3889 "mvn%.\\t%0, %1%S3"
344495ea 3890 [(set_attr "conds" "set")
331beb1a 3891 (set_attr "shift" "1")
d2a518d1 3892 (set_attr "insn" "mvn")
d5d4dc8d 3893 (set_attr "arch" "32,a")
3894 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3895
cffb2a26 3896;; We don't really have extzv, but defining this using shifts helps
3897;; to reduce register pressure later on.
3898
3899(define_expand "extzv"
eb04cafb 3900 [(set (match_operand 0 "s_register_operand" "")
3901 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3902 (match_operand 2 "const_int_operand" "")
3903 (match_operand 3 "const_int_operand" "")))]
8b054d5a 3904 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3905 "
3906 {
3907 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3908 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3909
8b054d5a 3910 if (arm_arch_thumb2)
3911 {
eb04cafb 3912 HOST_WIDE_INT width = INTVAL (operands[2]);
3913 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3914
3915 if (unaligned_access && MEM_P (operands[1])
3916 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3917 {
3918 rtx base_addr;
3919
3920 if (BYTES_BIG_ENDIAN)
3921 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3922 - bitpos;
3923
3924 if (width == 32)
3925 {
3926 base_addr = adjust_address (operands[1], SImode,
3927 bitpos / BITS_PER_UNIT);
3928 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3929 }
3930 else
3931 {
3932 rtx dest = operands[0];
3933 rtx tmp = gen_reg_rtx (SImode);
3934
3935 /* We may get a paradoxical subreg here. Strip it off. */
3936 if (GET_CODE (dest) == SUBREG
3937 && GET_MODE (dest) == SImode
3938 && GET_MODE (SUBREG_REG (dest)) == HImode)
3939 dest = SUBREG_REG (dest);
3940
3941 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3942 FAIL;
3943
3944 base_addr = adjust_address (operands[1], HImode,
3945 bitpos / BITS_PER_UNIT);
3946 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3947 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3948 }
3949 DONE;
3950 }
3951 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3952 {
3953 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3954 operands[3]));
3955 DONE;
3956 }
3957 else
3958 FAIL;
8b054d5a 3959 }
eb04cafb 3960
3961 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3962 FAIL;
8b054d5a 3963
cffb2a26 3964 operands[3] = GEN_INT (rshift);
3965
3966 if (lshift == 0)
3967 {
3968 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3969 DONE;
3970 }
3971
eb04cafb 3972 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3973 operands[3], gen_reg_rtx (SImode)));
3974 DONE;
215b30b3 3975 }"
cffb2a26 3976)
3977
eb04cafb 3978;; Helper for extzv, for the Thumb-1 register-shifts case.
3979
3980(define_expand "extzv_t1"
3981 [(set (match_operand:SI 4 "s_register_operand" "")
3982 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
3983 (match_operand:SI 2 "const_int_operand" "")))
3984 (set (match_operand:SI 0 "s_register_operand" "")
3985 (lshiftrt:SI (match_dup 4)
3986 (match_operand:SI 3 "const_int_operand" "")))]
3987 "TARGET_THUMB1"
3988 "")
3989
3990(define_expand "extv"
3991 [(set (match_operand 0 "s_register_operand" "")
3992 (sign_extract (match_operand 1 "nonimmediate_operand" "")
3993 (match_operand 2 "const_int_operand" "")
3994 (match_operand 3 "const_int_operand" "")))]
3995 "arm_arch_thumb2"
3996{
3997 HOST_WIDE_INT width = INTVAL (operands[2]);
3998 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3999
4000 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4001 && (bitpos % BITS_PER_UNIT) == 0)
4002 {
4003 rtx base_addr;
4004
4005 if (BYTES_BIG_ENDIAN)
4006 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4007
4008 if (width == 32)
4009 {
4010 base_addr = adjust_address (operands[1], SImode,
4011 bitpos / BITS_PER_UNIT);
4012 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4013 }
4014 else
4015 {
4016 rtx dest = operands[0];
4017 rtx tmp = gen_reg_rtx (SImode);
4018
4019 /* We may get a paradoxical subreg here. Strip it off. */
4020 if (GET_CODE (dest) == SUBREG
4021 && GET_MODE (dest) == SImode
4022 && GET_MODE (SUBREG_REG (dest)) == HImode)
4023 dest = SUBREG_REG (dest);
4024
4025 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4026 FAIL;
4027
4028 base_addr = adjust_address (operands[1], HImode,
4029 bitpos / BITS_PER_UNIT);
4030 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4031 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4032 }
4033
4034 DONE;
4035 }
4036 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4037 FAIL;
4038 else if (GET_MODE (operands[0]) == SImode
4039 && GET_MODE (operands[1]) == SImode)
4040 {
4041 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4042 operands[3]));
4043 DONE;
4044 }
4045
4046 FAIL;
4047})
4048
4049; Helper to expand register forms of extv with the proper modes.
4050
4051(define_expand "extv_regsi"
4052 [(set (match_operand:SI 0 "s_register_operand" "")
4053 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4054 (match_operand 2 "const_int_operand" "")
4055 (match_operand 3 "const_int_operand" "")))]
4056 ""
4057{
4058})
4059
4060; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4061
4062(define_insn "unaligned_loadsi"
4063 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4064 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4065 UNSPEC_UNALIGNED_LOAD))]
4066 "unaligned_access && TARGET_32BIT"
4067 "ldr%?\t%0, %1\t@ unaligned"
4068 [(set_attr "arch" "t2,any")
4069 (set_attr "length" "2,4")
4070 (set_attr "predicable" "yes")
4071 (set_attr "type" "load1")])
4072
4073(define_insn "unaligned_loadhis"
4074 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4075 (sign_extend:SI
4076 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4077 UNSPEC_UNALIGNED_LOAD)))]
4078 "unaligned_access && TARGET_32BIT"
4079 "ldr%(sh%)\t%0, %1\t@ unaligned"
4080 [(set_attr "arch" "t2,any")
4081 (set_attr "length" "2,4")
4082 (set_attr "predicable" "yes")
4083 (set_attr "type" "load_byte")])
4084
4085(define_insn "unaligned_loadhiu"
4086 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4087 (zero_extend:SI
4088 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4089 UNSPEC_UNALIGNED_LOAD)))]
4090 "unaligned_access && TARGET_32BIT"
4091 "ldr%(h%)\t%0, %1\t@ unaligned"
4092 [(set_attr "arch" "t2,any")
4093 (set_attr "length" "2,4")
4094 (set_attr "predicable" "yes")
4095 (set_attr "type" "load_byte")])
4096
4097(define_insn "unaligned_storesi"
4098 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4099 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4100 UNSPEC_UNALIGNED_STORE))]
4101 "unaligned_access && TARGET_32BIT"
4102 "str%?\t%1, %0\t@ unaligned"
4103 [(set_attr "arch" "t2,any")
4104 (set_attr "length" "2,4")
4105 (set_attr "predicable" "yes")
4106 (set_attr "type" "store1")])
4107
4108(define_insn "unaligned_storehi"
4109 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4110 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4111 UNSPEC_UNALIGNED_STORE))]
4112 "unaligned_access && TARGET_32BIT"
4113 "str%(h%)\t%1, %0\t@ unaligned"
4114 [(set_attr "arch" "t2,any")
4115 (set_attr "length" "2,4")
4116 (set_attr "predicable" "yes")
4117 (set_attr "type" "store1")])
4118
4119(define_insn "*extv_reg"
8b054d5a 4120 [(set (match_operand:SI 0 "s_register_operand" "=r")
4121 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4122 (match_operand:SI 2 "const_int_operand" "M")
4123 (match_operand:SI 3 "const_int_operand" "M")))]
4124 "arm_arch_thumb2"
4125 "sbfx%?\t%0, %1, %3, %2"
4126 [(set_attr "length" "4")
4127 (set_attr "predicable" "yes")]
4128)
4129
4130(define_insn "extzv_t2"
4131 [(set (match_operand:SI 0 "s_register_operand" "=r")
4132 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4133 (match_operand:SI 2 "const_int_operand" "M")
4134 (match_operand:SI 3 "const_int_operand" "M")))]
4135 "arm_arch_thumb2"
4136 "ubfx%?\t%0, %1, %3, %2"
4137 [(set_attr "length" "4")
4138 (set_attr "predicable" "yes")]
4139)
4140
7d3cda8c 4141
4142;; Division instructions
4143(define_insn "divsi3"
4144 [(set (match_operand:SI 0 "s_register_operand" "=r")
4145 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4146 (match_operand:SI 2 "s_register_operand" "r")))]
4147 "TARGET_IDIV"
4148 "sdiv%?\t%0, %1, %2"
4149 [(set_attr "predicable" "yes")
4150 (set_attr "insn" "sdiv")]
4151)
4152
4153(define_insn "udivsi3"
4154 [(set (match_operand:SI 0 "s_register_operand" "=r")
4155 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4156 (match_operand:SI 2 "s_register_operand" "r")))]
4157 "TARGET_IDIV"
4158 "udiv%?\t%0, %1, %2"
4159 [(set_attr "predicable" "yes")
4160 (set_attr "insn" "udiv")]
4161)
4162
b11cae9e 4163\f
4164;; Unary arithmetic insns
4165
cffb2a26 4166(define_expand "negdi2"
4167 [(parallel
8135a42b 4168 [(set (match_operand:DI 0 "s_register_operand" "")
4169 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4170 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4171 "TARGET_EITHER"
774d2fbb 4172 {
4173 if (TARGET_NEON)
4174 {
4175 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4176 DONE;
4177 }
4178 }
cffb2a26 4179)
4180
4181;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4182;; The first alternative allows the common case of a *full* overlap.
cffb2a26 4183(define_insn "*arm_negdi2"
458a8706 4184 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4185 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4186 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4187 "TARGET_ARM"
97499065 4188 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 4189 [(set_attr "conds" "clob")
4190 (set_attr "length" "8")]
4191)
b11cae9e 4192
25f905c2 4193(define_insn "*thumb1_negdi2"
8135a42b 4194 [(set (match_operand:DI 0 "register_operand" "=&l")
4195 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 4196 (clobber (reg:CC CC_REGNUM))]
25f905c2 4197 "TARGET_THUMB1"
cffb2a26 4198 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
4199 [(set_attr "length" "6")]
4200)
4201
4202(define_expand "negsi2"
4203 [(set (match_operand:SI 0 "s_register_operand" "")
4204 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4205 "TARGET_EITHER"
b11cae9e 4206 ""
cffb2a26 4207)
4208
4209(define_insn "*arm_negsi2"
4210 [(set (match_operand:SI 0 "s_register_operand" "=r")
4211 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4212 "TARGET_32BIT"
cffb2a26 4213 "rsb%?\\t%0, %1, #0"
0d66636f 4214 [(set_attr "predicable" "yes")]
cffb2a26 4215)
4216
25f905c2 4217(define_insn "*thumb1_negsi2"
cffb2a26 4218 [(set (match_operand:SI 0 "register_operand" "=l")
4219 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4220 "TARGET_THUMB1"
cffb2a26 4221 "neg\\t%0, %1"
4222 [(set_attr "length" "2")]
4223)
b11cae9e 4224
604f3a0a 4225(define_expand "negsf2"
4226 [(set (match_operand:SF 0 "s_register_operand" "")
4227 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4228 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4229 ""
4230)
4231
4232(define_expand "negdf2"
4233 [(set (match_operand:DF 0 "s_register_operand" "")
4234 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4235 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4236 "")
4237
9c08d1fa 4238;; abssi2 doesn't really clobber the condition codes if a different register
4239;; is being set. To keep things simple, assume during rtl manipulations that
4240;; it does, but tell the final scan operator the truth. Similarly for
4241;; (neg (abs...))
4242
604f3a0a 4243(define_expand "abssi2"
4244 [(parallel
4245 [(set (match_operand:SI 0 "s_register_operand" "")
4246 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4247 (clobber (match_dup 2))])]
4248 "TARGET_EITHER"
4249 "
25f905c2 4250 if (TARGET_THUMB1)
ba156559 4251 operands[2] = gen_rtx_SCRATCH (SImode);
4252 else
4253 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4254")
604f3a0a 4255
7d57ec45 4256(define_insn "*arm_abssi2"
ba156559 4257 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4258 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4259 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4260 "TARGET_ARM"
e2348bcb 4261 "@
4262 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 4263 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 4264 [(set_attr "conds" "clob,*")
331beb1a 4265 (set_attr "shift" "1")
2ad08b65 4266 (set_attr "predicable" "no, yes")
cffb2a26 4267 (set_attr "length" "8")]
4268)
9c08d1fa 4269
25f905c2 4270(define_insn_and_split "*thumb1_abssi2"
ba156559 4271 [(set (match_operand:SI 0 "s_register_operand" "=l")
4272 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
4273 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4274 "TARGET_THUMB1"
ba156559 4275 "#"
25f905c2 4276 "TARGET_THUMB1 && reload_completed"
ba156559 4277 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4278 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
4279 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4280 ""
4281 [(set_attr "length" "6")]
4282)
4283
4284(define_insn "*arm_neg_abssi2"
9c08d1fa 4285 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4286 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4287 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4288 "TARGET_ARM"
e2348bcb 4289 "@
4290 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 4291 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 4292 [(set_attr "conds" "clob,*")
331beb1a 4293 (set_attr "shift" "1")
2ad08b65 4294 (set_attr "predicable" "no, yes")
cffb2a26 4295 (set_attr "length" "8")]
4296)
b11cae9e 4297
25f905c2 4298(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 4299 [(set (match_operand:SI 0 "s_register_operand" "=l")
4300 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
4301 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4302 "TARGET_THUMB1"
ba156559 4303 "#"
25f905c2 4304 "TARGET_THUMB1 && reload_completed"
ba156559 4305 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4306 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
4307 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4308 ""
4309 [(set_attr "length" "6")]
4310)
4311
604f3a0a 4312(define_expand "abssf2"
4313 [(set (match_operand:SF 0 "s_register_operand" "")
4314 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4315 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4316 "")
4317
604f3a0a 4318(define_expand "absdf2"
4319 [(set (match_operand:DF 0 "s_register_operand" "")
4320 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4321 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4322 "")
4323
7db9af5d 4324(define_expand "sqrtsf2"
4325 [(set (match_operand:SF 0 "s_register_operand" "")
4326 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4327 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4328 "")
9c08d1fa 4329
7db9af5d 4330(define_expand "sqrtdf2"
4331 [(set (match_operand:DF 0 "s_register_operand" "")
4332 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4333 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4334 "")
9c08d1fa 4335
a0f94409 4336(define_insn_and_split "one_cmpldi2"
10efb95f 4337 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4338 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4339 "TARGET_32BIT"
10efb95f 4340 "@
4341 vmvn\t%P0, %P1
4342 #
4343 #
4344 vmvn\t%P0, %P1"
4345 "TARGET_32BIT && reload_completed
4346 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4347 [(set (match_dup 0) (not:SI (match_dup 1)))
4348 (set (match_dup 2) (not:SI (match_dup 3)))]
4349 "
4350 {
4351 operands[2] = gen_highpart (SImode, operands[0]);
4352 operands[0] = gen_lowpart (SImode, operands[0]);
4353 operands[3] = gen_highpart (SImode, operands[1]);
4354 operands[1] = gen_lowpart (SImode, operands[1]);
4355 }"
10efb95f 4356 [(set_attr "length" "*,8,8,*")
4357 (set_attr "predicable" "no,yes,yes,no")
4358 (set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
4359 (set_attr "arch" "neon_nota8,*,*,neon_onlya8")]
cffb2a26 4360)
b11cae9e 4361
cffb2a26 4362(define_expand "one_cmplsi2"
4363 [(set (match_operand:SI 0 "s_register_operand" "")
4364 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4365 "TARGET_EITHER"
b11cae9e 4366 ""
cffb2a26 4367)
4368
4369(define_insn "*arm_one_cmplsi2"
4370 [(set (match_operand:SI 0 "s_register_operand" "=r")
4371 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4372 "TARGET_32BIT"
cffb2a26 4373 "mvn%?\\t%0, %1"
d2a518d1 4374 [(set_attr "predicable" "yes")
4375 (set_attr "insn" "mvn")]
cffb2a26 4376)
4377
25f905c2 4378(define_insn "*thumb1_one_cmplsi2"
cffb2a26 4379 [(set (match_operand:SI 0 "register_operand" "=l")
4380 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4381 "TARGET_THUMB1"
cffb2a26 4382 "mvn\\t%0, %1"
d2a518d1 4383 [(set_attr "length" "2")
4384 (set_attr "insn" "mvn")]
cffb2a26 4385)
9c08d1fa 4386
f7fbdd4a 4387(define_insn "*notsi_compare0"
bd5b4116 4388 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4389 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4390 (const_int 0)))
4391 (set (match_operand:SI 0 "s_register_operand" "=r")
4392 (not:SI (match_dup 1)))]
25f905c2 4393 "TARGET_32BIT"
4394 "mvn%.\\t%0, %1"
d2a518d1 4395 [(set_attr "conds" "set")
4396 (set_attr "insn" "mvn")]
cffb2a26 4397)
9c08d1fa 4398
f7fbdd4a 4399(define_insn "*notsi_compare0_scratch"
bd5b4116 4400 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4401 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4402 (const_int 0)))
4403 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4404 "TARGET_32BIT"
4405 "mvn%.\\t%0, %1"
d2a518d1 4406 [(set_attr "conds" "set")
4407 (set_attr "insn" "mvn")]
cffb2a26 4408)
b11cae9e 4409\f
4410;; Fixed <--> Floating conversion insns
4411
9b8516be 4412(define_expand "floatsihf2"
4413 [(set (match_operand:HF 0 "general_operand" "")
4414 (float:HF (match_operand:SI 1 "general_operand" "")))]
4415 "TARGET_EITHER"
4416 "
4417 {
4418 rtx op1 = gen_reg_rtx (SFmode);
4419 expand_float (op1, operands[1], 0);
4420 op1 = convert_to_mode (HFmode, op1, 0);
4421 emit_move_insn (operands[0], op1);
4422 DONE;
4423 }"
4424)
4425
4426(define_expand "floatdihf2"
4427 [(set (match_operand:HF 0 "general_operand" "")
4428 (float:HF (match_operand:DI 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
604f3a0a 4440(define_expand "floatsisf2"
4441 [(set (match_operand:SF 0 "s_register_operand" "")
4442 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4443 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4444 "
604f3a0a 4445")
4446
604f3a0a 4447(define_expand "floatsidf2"
4448 [(set (match_operand:DF 0 "s_register_operand" "")
4449 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4450 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4451 "
604f3a0a 4452")
4453
9b8516be 4454(define_expand "fix_trunchfsi2"
4455 [(set (match_operand:SI 0 "general_operand" "")
4456 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4457 "TARGET_EITHER"
4458 "
4459 {
4460 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4461 expand_fix (operands[0], op1, 0);
4462 DONE;
4463 }"
4464)
4465
4466(define_expand "fix_trunchfdi2"
4467 [(set (match_operand:DI 0 "general_operand" "")
4468 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4469 "TARGET_EITHER"
4470 "
4471 {
4472 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4473 expand_fix (operands[0], op1, 0);
4474 DONE;
4475 }"
4476)
4477
604f3a0a 4478(define_expand "fix_truncsfsi2"
4479 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4480 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4481 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4482 "
604f3a0a 4483")
4484
604f3a0a 4485(define_expand "fix_truncdfsi2"
4486 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4487 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4488 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4489 "
604f3a0a 4490")
4491
f544c6d2 4492;; Truncation insns
b11cae9e 4493
604f3a0a 4494(define_expand "truncdfsf2"
4495 [(set (match_operand:SF 0 "s_register_operand" "")
4496 (float_truncate:SF
4497 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4498 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4499 ""
4500)
9b8516be 4501
4502/* DFmode -> HFmode conversions have to go through SFmode. */
4503(define_expand "truncdfhf2"
4504 [(set (match_operand:HF 0 "general_operand" "")
4505 (float_truncate:HF
4506 (match_operand:DF 1 "general_operand" "")))]
4507 "TARGET_EITHER"
4508 "
4509 {
4510 rtx op1;
4511 op1 = convert_to_mode (SFmode, operands[1], 0);
4512 op1 = convert_to_mode (HFmode, op1, 0);
4513 emit_move_insn (operands[0], op1);
4514 DONE;
4515 }"
4516)
b11cae9e 4517\f
9c08d1fa 4518;; Zero and sign extension instructions.
b11cae9e 4519
848e66ac 4520(define_insn "zero_extend<mode>di2"
4521 [(set (match_operand:DI 0 "s_register_operand" "=r")
6d97728e 4522 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4523 "<qhs_zextenddi_cstr>")))]
848e66ac 4524 "TARGET_32BIT <qhs_zextenddi_cond>"
4525 "#"
4526 [(set_attr "length" "8")
4527 (set_attr "ce_count" "2")
4528 (set_attr "predicable" "yes")]
25f905c2 4529)
4530
848e66ac 4531(define_insn "extend<mode>di2"
9c08d1fa 4532 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4533 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4534 "<qhs_extenddi_cstr>")))]
848e66ac 4535 "TARGET_32BIT <qhs_sextenddi_cond>"
4536 "#"
0d66636f 4537 [(set_attr "length" "8")
848e66ac 4538 (set_attr "ce_count" "2")
4539 (set_attr "shift" "1")
0d66636f 4540 (set_attr "predicable" "yes")]
4541)
9c08d1fa 4542
848e66ac 4543;; Splits for all extensions to DImode
4544(define_split
4545 [(set (match_operand:DI 0 "s_register_operand" "")
4546 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4547 "TARGET_32BIT"
848e66ac 4548 [(set (match_dup 0) (match_dup 1))]
4549{
848e66ac 4550 rtx lo_part = gen_lowpart (SImode, operands[0]);
4551 enum machine_mode src_mode = GET_MODE (operands[1]);
4552
4553 if (REG_P (operands[0])
4554 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4555 emit_clobber (operands[0]);
4556 if (!REG_P (lo_part) || src_mode != SImode
4557 || !rtx_equal_p (lo_part, operands[1]))
4558 {
4559 if (src_mode == SImode)
4560 emit_move_insn (lo_part, operands[1]);
4561 else
4562 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4563 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4564 operands[1] = lo_part;
4565 }
4566 operands[0] = gen_highpart (SImode, operands[0]);
4567 operands[1] = const0_rtx;
4568})
9c08d1fa 4569
848e66ac 4570(define_split
25f905c2 4571 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4572 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4573 "TARGET_32BIT"
848e66ac 4574 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4575{
4576 rtx lo_part = gen_lowpart (SImode, operands[0]);
4577 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4578
848e66ac 4579 if (REG_P (operands[0])
4580 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4581 emit_clobber (operands[0]);
4582
4583 if (!REG_P (lo_part) || src_mode != SImode
4584 || !rtx_equal_p (lo_part, operands[1]))
4585 {
4586 if (src_mode == SImode)
4587 emit_move_insn (lo_part, operands[1]);
4588 else
4589 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4590 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4591 operands[1] = lo_part;
4592 }
4593 operands[0] = gen_highpart (SImode, operands[0]);
4594})
9c08d1fa 4595
4596(define_expand "zero_extendhisi2"
ef51b8e1 4597 [(set (match_operand:SI 0 "s_register_operand" "")
4598 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4599 "TARGET_EITHER"
ef51b8e1 4600{
4601 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4602 {
ef51b8e1 4603 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4604 DONE;
25f7a26e 4605 }
ef51b8e1 4606 if (!arm_arch6 && !MEM_P (operands[1]))
4607 {
4608 rtx t = gen_lowpart (SImode, operands[1]);
4609 rtx tmp = gen_reg_rtx (SImode);
4610 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4611 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4612 DONE;
4613 }
4614})
9c08d1fa 4615
ef51b8e1 4616(define_split
b146458f 4617 [(set (match_operand:SI 0 "s_register_operand" "")
4618 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4619 "!TARGET_THUMB2 && !arm_arch6"
4620 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4621 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4622{
4623 operands[2] = gen_lowpart (SImode, operands[1]);
4624})
4625
4626(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4627 [(set (match_operand:SI 0 "register_operand" "=l,l")
4628 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4629 "TARGET_THUMB1"
848e66ac 4630{
a2cd141b 4631 rtx mem;
4632
ef51b8e1 4633 if (which_alternative == 0 && arm_arch6)
848e66ac 4634 return "uxth\t%0, %1";
ef51b8e1 4635 if (which_alternative == 0)
848e66ac 4636 return "#";
a2cd141b 4637
4638 mem = XEXP (operands[1], 0);
4639
4640 if (GET_CODE (mem) == CONST)
4641 mem = XEXP (mem, 0);
4642
a2cd141b 4643 if (GET_CODE (mem) == PLUS)
4644 {
4645 rtx a = XEXP (mem, 0);
a2cd141b 4646
4647 /* This can happen due to bugs in reload. */
0438d37f 4648 if (REG_P (a) && REGNO (a) == SP_REGNUM)
a2cd141b 4649 {
4650 rtx ops[2];
4651 ops[0] = operands[0];
4652 ops[1] = a;
4653
848e66ac 4654 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4655
4656 XEXP (mem, 0) = operands[0];
4657 }
a2cd141b 4658 }
4659
848e66ac 4660 return "ldrh\t%0, %1";
4661}
ef51b8e1 4662 [(set_attr_alternative "length"
4663 [(if_then_else (eq_attr "is_arch6" "yes")
4664 (const_int 2) (const_int 4))
4665 (const_int 4)])
848e66ac 4666 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4667)
4668
cffb2a26 4669(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4670 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4671 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4672 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4673 "@
4674 #
4675 ldr%(h%)\\t%0, %1"
4676 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4677 (set_attr "predicable" "yes")]
cffb2a26 4678)
f7fbdd4a 4679
a2cd141b 4680(define_insn "*arm_zero_extendhisi2_v6"
4681 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4682 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4683 "TARGET_ARM && arm_arch6"
4684 "@
4685 uxth%?\\t%0, %1
25f905c2 4686 ldr%(h%)\\t%0, %1"
a2cd141b 4687 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4688 (set_attr "predicable" "yes")]
a2cd141b 4689)
4690
4691(define_insn "*arm_zero_extendhisi2addsi"
4692 [(set (match_operand:SI 0 "s_register_operand" "=r")
4693 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4694 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4695 "TARGET_INT_SIMD"
a2cd141b 4696 "uxtah%?\\t%0, %2, %1"
4697 [(set_attr "type" "alu_shift")
4698 (set_attr "predicable" "yes")]
4699)
4700
87b22bf7 4701(define_expand "zero_extendqisi2"
cffb2a26 4702 [(set (match_operand:SI 0 "s_register_operand" "")
4703 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4704 "TARGET_EITHER"
ef51b8e1 4705{
0438d37f 4706 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 4707 {
ef51b8e1 4708 emit_insn (gen_andsi3 (operands[0],
4709 gen_lowpart (SImode, operands[1]),
4710 GEN_INT (255)));
4711 DONE;
4712 }
4713 if (!arm_arch6 && !MEM_P (operands[1]))
4714 {
4715 rtx t = gen_lowpart (SImode, operands[1]);
4716 rtx tmp = gen_reg_rtx (SImode);
4717 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4718 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4719 DONE;
4720 }
4721})
cffb2a26 4722
ef51b8e1 4723(define_split
b146458f 4724 [(set (match_operand:SI 0 "s_register_operand" "")
4725 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4726 "!arm_arch6"
4727 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4728 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4729{
4730 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4731 if (TARGET_ARM)
4732 {
4733 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4734 DONE;
4735 }
ef51b8e1 4736})
9c08d1fa 4737
25f905c2 4738(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4739 [(set (match_operand:SI 0 "register_operand" "=l,l")
4740 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4741 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4742 "@
4743 #
4744 ldrb\\t%0, %1"
4745 [(set_attr "length" "4,2")
4746 (set_attr "type" "alu_shift,load_byte")
4747 (set_attr "pool_range" "*,32")]
cffb2a26 4748)
4749
25f905c2 4750(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4751 [(set (match_operand:SI 0 "register_operand" "=l,l")
4752 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4753 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4754 "@
4755 uxtb\\t%0, %1
4756 ldrb\\t%0, %1"
848e66ac 4757 [(set_attr "length" "2")
4758 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4759)
4760
cffb2a26 4761(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4762 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4763 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4764 "TARGET_ARM && !arm_arch6"
ef51b8e1 4765 "@
4766 #
4767 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4768 [(set_attr "length" "8,4")
4769 (set_attr "type" "alu_shift,load_byte")
848e66ac 4770 (set_attr "predicable" "yes")]
cffb2a26 4771)
87b22bf7 4772
a2cd141b 4773(define_insn "*arm_zero_extendqisi2_v6"
4774 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4775 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4776 "TARGET_ARM && arm_arch6"
4777 "@
25f905c2 4778 uxtb%(%)\\t%0, %1
4779 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4780 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4781 (set_attr "predicable" "yes")]
a2cd141b 4782)
4783
4784(define_insn "*arm_zero_extendqisi2addsi"
4785 [(set (match_operand:SI 0 "s_register_operand" "=r")
4786 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4787 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4788 "TARGET_INT_SIMD"
a2cd141b 4789 "uxtab%?\\t%0, %2, %1"
4790 [(set_attr "predicable" "yes")
bcaec148 4791 (set_attr "insn" "xtab")
a2cd141b 4792 (set_attr "type" "alu_shift")]
4793)
4794
87b22bf7 4795(define_split
4796 [(set (match_operand:SI 0 "s_register_operand" "")
4797 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4798 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4799 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 4800 [(set (match_dup 2) (match_dup 1))
4801 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4802 ""
4803)
9c08d1fa 4804
8a4d25d6 4805(define_split
4806 [(set (match_operand:SI 0 "s_register_operand" "")
4807 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4808 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4809 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 4810 [(set (match_dup 2) (match_dup 1))
4811 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4812 ""
4813)
4814
1c274529 4815
4816(define_split
4817 [(set (match_operand:SI 0 "s_register_operand" "")
4818 (ior_xor:SI (and:SI (ashift:SI
4819 (match_operand:SI 1 "s_register_operand" "")
4820 (match_operand:SI 2 "const_int_operand" ""))
4821 (match_operand:SI 3 "const_int_operand" ""))
4822 (zero_extend:SI
4823 (match_operator 5 "subreg_lowpart_operator"
4824 [(match_operand:SI 4 "s_register_operand" "")]))))]
4825 "TARGET_32BIT
63787642 4826 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4827 == (GET_MODE_MASK (GET_MODE (operands[5]))
4828 & (GET_MODE_MASK (GET_MODE (operands[5]))
4829 << (INTVAL (operands[2])))))"
4830 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4831 (match_dup 4)))
4832 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4833 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4834)
4835
f7fbdd4a 4836(define_insn "*compareqi_eq0"
bd5b4116 4837 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4838 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4839 (const_int 0)))]
25f905c2 4840 "TARGET_32BIT"
596e5e8f 4841 "tst%?\\t%0, #255"
4842 [(set_attr "conds" "set")
4843 (set_attr "predicable" "yes")]
cffb2a26 4844)
b11cae9e 4845
b11cae9e 4846(define_expand "extendhisi2"
ef51b8e1 4847 [(set (match_operand:SI 0 "s_register_operand" "")
4848 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4849 "TARGET_EITHER"
ef51b8e1 4850{
4851 if (TARGET_THUMB1)
4852 {
4853 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4854 DONE;
4855 }
4856 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4857 {
4858 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4859 DONE;
4860 }
ed29c566 4861
ef51b8e1 4862 if (!arm_arch6 && !MEM_P (operands[1]))
4863 {
4864 rtx t = gen_lowpart (SImode, operands[1]);
4865 rtx tmp = gen_reg_rtx (SImode);
4866 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4867 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4868 DONE;
4869 }
4870})
cffb2a26 4871
ef51b8e1 4872(define_split
4873 [(parallel
4874 [(set (match_operand:SI 0 "register_operand" "")
4875 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4876 (clobber (match_scratch:SI 2 ""))])]
4877 "!arm_arch6"
4878 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4879 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4880{
4881 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4882})
25f7a26e 4883
a2cd141b 4884;; We used to have an early-clobber on the scratch register here.
4885;; However, there's a bug somewhere in reload which means that this
4886;; can be partially ignored during spill allocation if the memory
ed29c566 4887;; address also needs reloading; this causes us to die later on when
a2cd141b 4888;; we try to verify the operands. Fortunately, we don't really need
4889;; the early-clobber: we can always use operand 0 if operand 2
4890;; overlaps the address.
ef51b8e1 4891(define_insn "thumb1_extendhisi2"
a2cd141b 4892 [(set (match_operand:SI 0 "register_operand" "=l,l")
4893 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4894 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4895 "TARGET_THUMB1"
a2cd141b 4896 "*
4897 {
4898 rtx ops[4];
4899 rtx mem;
4900
ef51b8e1 4901 if (which_alternative == 0 && !arm_arch6)
4902 return \"#\";
a2cd141b 4903 if (which_alternative == 0)
4904 return \"sxth\\t%0, %1\";
4905
4906 mem = XEXP (operands[1], 0);
4907
4908 /* This code used to try to use 'V', and fix the address only if it was
4909 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4910 range of QImode offsets, and offsettable_address_p does a QImode
4911 address check. */
4912
4913 if (GET_CODE (mem) == CONST)
4914 mem = XEXP (mem, 0);
4915
4916 if (GET_CODE (mem) == LABEL_REF)
4917 return \"ldr\\t%0, %1\";
4918
4919 if (GET_CODE (mem) == PLUS)
4920 {
4921 rtx a = XEXP (mem, 0);
4922 rtx b = XEXP (mem, 1);
4923
4924 if (GET_CODE (a) == LABEL_REF
0438d37f 4925 && CONST_INT_P (b))
a2cd141b 4926 return \"ldr\\t%0, %1\";
4927
0438d37f 4928 if (REG_P (b))
a2cd141b 4929 return \"ldrsh\\t%0, %1\";
4930
4931 ops[1] = a;
4932 ops[2] = b;
4933 }
4934 else
4935 {
4936 ops[1] = mem;
4937 ops[2] = const0_rtx;
4938 }
4939
0438d37f 4940 gcc_assert (REG_P (ops[1]));
a2cd141b 4941
4942 ops[0] = operands[0];
4943 if (reg_mentioned_p (operands[2], ops[1]))
4944 ops[3] = ops[0];
4945 else
4946 ops[3] = operands[2];
4947 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4948 return \"\";
4949 }"
ef51b8e1 4950 [(set_attr_alternative "length"
4951 [(if_then_else (eq_attr "is_arch6" "yes")
4952 (const_int 2) (const_int 4))
4953 (const_int 4)])
a2cd141b 4954 (set_attr "type" "alu_shift,load_byte")
4955 (set_attr "pool_range" "*,1020")]
4956)
4957
25f905c2 4958;; This pattern will only be used when ldsh is not available
25f7a26e 4959(define_expand "extendhisi2_mem"
eab14235 4960 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4961 (set (match_dup 3)
eab14235 4962 (zero_extend:SI (match_dup 7)))
25f7a26e 4963 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4964 (set (match_operand:SI 0 "" "")
4965 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4966 "TARGET_ARM"
25f7a26e 4967 "
215b30b3 4968 {
4969 rtx mem1, mem2;
4970 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4971
788fcce0 4972 mem1 = change_address (operands[1], QImode, addr);
29c05e22 4973 mem2 = change_address (operands[1], QImode,
4974 plus_constant (Pmode, addr, 1));
215b30b3 4975 operands[0] = gen_lowpart (SImode, operands[0]);
4976 operands[1] = mem1;
4977 operands[2] = gen_reg_rtx (SImode);
4978 operands[3] = gen_reg_rtx (SImode);
4979 operands[6] = gen_reg_rtx (SImode);
4980 operands[7] = mem2;
25f7a26e 4981
215b30b3 4982 if (BYTES_BIG_ENDIAN)
4983 {
4984 operands[4] = operands[2];
4985 operands[5] = operands[3];
4986 }
4987 else
4988 {
4989 operands[4] = operands[3];
4990 operands[5] = operands[2];
4991 }
4992 }"
4993)
b11cae9e 4994
ef51b8e1 4995(define_split
4996 [(set (match_operand:SI 0 "register_operand" "")
4997 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4998 "!arm_arch6"
4999 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5000 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5001{
5002 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5003})
5004
a2cd141b 5005(define_insn "*arm_extendhisi2"
ef51b8e1 5006 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5007 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5008 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5009 "@
5010 #
5011 ldr%(sh%)\\t%0, %1"
5012 [(set_attr "length" "8,4")
5013 (set_attr "type" "alu_shift,load_byte")
0d66636f 5014 (set_attr "predicable" "yes")
ef51b8e1 5015 (set_attr "pool_range" "*,256")
5016 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5017)
f7fbdd4a 5018
25f905c2 5019;; ??? Check Thumb-2 pool range
a2cd141b 5020(define_insn "*arm_extendhisi2_v6"
5021 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5022 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 5023 "TARGET_32BIT && arm_arch6"
a2cd141b 5024 "@
5025 sxth%?\\t%0, %1
25f905c2 5026 ldr%(sh%)\\t%0, %1"
a2cd141b 5027 [(set_attr "type" "alu_shift,load_byte")
5028 (set_attr "predicable" "yes")
5029 (set_attr "pool_range" "*,256")
5030 (set_attr "neg_pool_range" "*,244")]
5031)
5032
5033(define_insn "*arm_extendhisi2addsi"
5034 [(set (match_operand:SI 0 "s_register_operand" "=r")
5035 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5036 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5037 "TARGET_INT_SIMD"
a2cd141b 5038 "sxtah%?\\t%0, %2, %1"
5039)
5040
c8f69309 5041(define_expand "extendqihi2"
5042 [(set (match_dup 2)
bed7d9a5 5043 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5044 (const_int 24)))
9c08d1fa 5045 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5046 (ashiftrt:SI (match_dup 2)
5047 (const_int 24)))]
cffb2a26 5048 "TARGET_ARM"
c8f69309 5049 "
215b30b3 5050 {
0438d37f 5051 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5052 {
5053 emit_insn (gen_rtx_SET (VOIDmode,
5054 operands[0],
5055 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5056 DONE;
5057 }
5058 if (!s_register_operand (operands[1], QImode))
5059 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5060 operands[0] = gen_lowpart (SImode, operands[0]);
5061 operands[1] = gen_lowpart (SImode, operands[1]);
5062 operands[2] = gen_reg_rtx (SImode);
5063 }"
5064)
f7fbdd4a 5065
25f905c2 5066(define_insn "*arm_extendqihi_insn"
b4e8a300 5067 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5068 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5069 "TARGET_ARM && arm_arch4"
25f905c2 5070 "ldr%(sb%)\\t%0, %1"
a2cd141b 5071 [(set_attr "type" "load_byte")
0d66636f 5072 (set_attr "predicable" "yes")
cffb2a26 5073 (set_attr "pool_range" "256")
5074 (set_attr "neg_pool_range" "244")]
5075)
3fc2009e 5076
b11cae9e 5077(define_expand "extendqisi2"
ef51b8e1 5078 [(set (match_operand:SI 0 "s_register_operand" "")
5079 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5080 "TARGET_EITHER"
ef51b8e1 5081{
5082 if (!arm_arch4 && MEM_P (operands[1]))
5083 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5084
ef51b8e1 5085 if (!arm_arch6 && !MEM_P (operands[1]))
5086 {
5087 rtx t = gen_lowpart (SImode, operands[1]);
5088 rtx tmp = gen_reg_rtx (SImode);
5089 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5090 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5091 DONE;
5092 }
5093})
a2cd141b 5094
ef51b8e1 5095(define_split
5096 [(set (match_operand:SI 0 "register_operand" "")
5097 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5098 "!arm_arch6"
5099 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5100 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5101{
5102 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5103})
f7fbdd4a 5104
a2cd141b 5105(define_insn "*arm_extendqisi"
ef51b8e1 5106 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5107 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5108 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5109 "@
5110 #
5111 ldr%(sb%)\\t%0, %1"
5112 [(set_attr "length" "8,4")
5113 (set_attr "type" "alu_shift,load_byte")
0d66636f 5114 (set_attr "predicable" "yes")
ef51b8e1 5115 (set_attr "pool_range" "*,256")
5116 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5117)
3fc2009e 5118
a2cd141b 5119(define_insn "*arm_extendqisi_v6"
5120 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5121 (sign_extend:SI
5122 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5123 "TARGET_ARM && arm_arch6"
b4e8a300 5124 "@
5125 sxtb%?\\t%0, %1
25f905c2 5126 ldr%(sb%)\\t%0, %1"
a2cd141b 5127 [(set_attr "type" "alu_shift,load_byte")
5128 (set_attr "predicable" "yes")
a2cd141b 5129 (set_attr "pool_range" "*,256")
5130 (set_attr "neg_pool_range" "*,244")]
5131)
5132
5133(define_insn "*arm_extendqisi2addsi"
5134 [(set (match_operand:SI 0 "s_register_operand" "=r")
5135 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5136 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5137 "TARGET_INT_SIMD"
a2cd141b 5138 "sxtab%?\\t%0, %2, %1"
5139 [(set_attr "type" "alu_shift")
bcaec148 5140 (set_attr "insn" "xtab")
a2cd141b 5141 (set_attr "predicable" "yes")]
5142)
5143
ef51b8e1 5144(define_split
5145 [(set (match_operand:SI 0 "register_operand" "")
5146 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
5147 "TARGET_THUMB1 && reload_completed"
5148 [(set (match_dup 0) (match_dup 2))
5149 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
5150{
5151 rtx addr = XEXP (operands[1], 0);
cffb2a26 5152
ef51b8e1 5153 if (GET_CODE (addr) == CONST)
5154 addr = XEXP (addr, 0);
cffb2a26 5155
ef51b8e1 5156 if (GET_CODE (addr) == PLUS
5157 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5158 /* No split necessary. */
5159 FAIL;
5160
5161 if (GET_CODE (addr) == PLUS
5162 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
5163 FAIL;
5164
5165 if (reg_overlap_mentioned_p (operands[0], addr))
5166 {
5167 rtx t = gen_lowpart (QImode, operands[0]);
5168 emit_move_insn (t, operands[1]);
5169 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
5170 DONE;
5171 }
5172
5173 if (REG_P (addr))
5174 {
5175 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
5176 operands[2] = const0_rtx;
5177 }
5178 else if (GET_CODE (addr) != PLUS)
5179 FAIL;
5180 else if (REG_P (XEXP (addr, 0)))
5181 {
5182 operands[2] = XEXP (addr, 1);
5183 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
5184 }
5185 else
5186 {
5187 operands[2] = XEXP (addr, 0);
5188 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
5189 }
cffb2a26 5190
ef51b8e1 5191 operands[3] = change_address (operands[1], QImode, addr);
5192})
5193
8a3b73a1 5194(define_peephole2
5195 [(set (match_operand:SI 0 "register_operand" "")
5196 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
5197 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
5198 (set (match_operand:SI 3 "register_operand" "")
5199 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
5200 "TARGET_THUMB1
5201 && GET_CODE (XEXP (operands[4], 0)) == PLUS
5202 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
5203 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
5204 && (peep2_reg_dead_p (3, operands[0])
5205 || rtx_equal_p (operands[0], operands[3]))
5206 && (peep2_reg_dead_p (3, operands[2])
5207 || rtx_equal_p (operands[2], operands[3]))"
5208 [(set (match_dup 2) (match_dup 1))
5209 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
5210{
5211 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
5212 operands[4] = change_address (operands[4], QImode, addr);
5213})
5214
ef51b8e1 5215(define_insn "thumb1_extendqisi2"
a2cd141b 5216 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5217 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 5218 "TARGET_THUMB1"
5219{
5220 rtx addr;
a2cd141b 5221
ef51b8e1 5222 if (which_alternative == 0 && arm_arch6)
5223 return "sxtb\\t%0, %1";
5224 if (which_alternative == 0)
5225 return "#";
a2cd141b 5226
ef51b8e1 5227 addr = XEXP (operands[1], 0);
5228 if (GET_CODE (addr) == PLUS
5229 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5230 return "ldrsb\\t%0, %1";
a2cd141b 5231
ef51b8e1 5232 return "#";
5233}
5234 [(set_attr_alternative "length"
5235 [(if_then_else (eq_attr "is_arch6" "yes")
5236 (const_int 2) (const_int 4))
5237 (const_int 2)
5238 (if_then_else (eq_attr "is_arch6" "yes")
5239 (const_int 4) (const_int 6))])
5240 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 5241)
5242
caedf871 5243(define_expand "extendsfdf2"
5244 [(set (match_operand:DF 0 "s_register_operand" "")
5245 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5246 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5247 ""
5248)
9b8516be 5249
5250/* HFmode -> DFmode conversions have to go through SFmode. */
5251(define_expand "extendhfdf2"
5252 [(set (match_operand:DF 0 "general_operand" "")
5253 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5254 "TARGET_EITHER"
5255 "
5256 {
5257 rtx op1;
5258 op1 = convert_to_mode (SFmode, operands[1], 0);
5259 op1 = convert_to_mode (DFmode, op1, 0);
5260 emit_insn (gen_movdf (operands[0], op1));
5261 DONE;
5262 }"
5263)
b11cae9e 5264\f
5265;; Move insns (including loads and stores)
5266
5267;; XXX Just some ideas about movti.
9c08d1fa 5268;; I don't think these are a good idea on the arm, there just aren't enough
5269;; registers
b11cae9e 5270;;(define_expand "loadti"
9c08d1fa 5271;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5272;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5273;; "" "")
5274
5275;;(define_expand "storeti"
5276;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5277;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5278;; "" "")
5279
5280;;(define_expand "movti"
5281;; [(set (match_operand:TI 0 "general_operand" "")
5282;; (match_operand:TI 1 "general_operand" ""))]
5283;; ""
5284;; "
5285;;{
5286;; rtx insn;
5287;;
0438d37f 5288;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5289;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5290;; if (MEM_P (operands[0]))
b11cae9e 5291;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5292;; else if (MEM_P (operands[1]))
b11cae9e 5293;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5294;; else
5295;; FAIL;
5296;;
5297;; emit_insn (insn);
5298;; DONE;
5299;;}")
5300
a2f10574 5301;; Recognize garbage generated above.
b11cae9e 5302
5303;;(define_insn ""
5304;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5305;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5306;; ""
5307;; "*
5308;; {
5309;; register mem = (which_alternative < 3);
0d66636f 5310;; register const char *template;
b11cae9e 5311;;
5312;; operands[mem] = XEXP (operands[mem], 0);
5313;; switch (which_alternative)
5314;; {
5315;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5316;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5317;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5318;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5319;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5320;; case 5: template = \"stmia\\t%0, %M1\"; break;
5321;; }
e2348bcb 5322;; output_asm_insn (template, operands);
5323;; return \"\";
b11cae9e 5324;; }")
5325
cffb2a26 5326(define_expand "movdi"
5327 [(set (match_operand:DI 0 "general_operand" "")
5328 (match_operand:DI 1 "general_operand" ""))]
5329 "TARGET_EITHER"
5330 "
e1ba4a27 5331 if (can_create_pseudo_p ())
cffb2a26 5332 {
0438d37f 5333 if (!REG_P (operands[0]))
b2778788 5334 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5335 }
5336 "
5337)
b11cae9e 5338
cffb2a26 5339(define_insn "*arm_movdi"
d51f92df 5340 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5341 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 5342 "TARGET_32BIT
b805622c 5343 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5344 && !TARGET_IWMMXT
5345 && ( register_operand (operands[0], DImode)
5346 || register_operand (operands[1], DImode))"
b11cae9e 5347 "*
d51f92df 5348 switch (which_alternative)
5349 {
5350 case 0:
5351 case 1:
5352 case 2:
5353 return \"#\";
5354 default:
26ff80c0 5355 return output_move_double (operands, true, NULL);
d51f92df 5356 }
cffb2a26 5357 "
359a6e9f 5358 [(set_attr "length" "8,12,16,8,8")
5359 (set_attr "type" "*,*,*,load2,store2")
cde1623a 5360 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5361 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 5362 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
5363 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5364)
5365
d51f92df 5366(define_split
5367 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5368 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 5369 "TARGET_32BIT
d51f92df 5370 && reload_completed
5371 && (arm_const_double_inline_cost (operands[1])
5372 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
5373 [(const_int 0)]
5374 "
5375 arm_split_constant (SET, SImode, curr_insn,
5376 INTVAL (gen_lowpart (SImode, operands[1])),
5377 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5378 arm_split_constant (SET, SImode, curr_insn,
5379 INTVAL (gen_highpart_mode (SImode,
5380 GET_MODE (operands[0]),
5381 operands[1])),
5382 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5383 DONE;
5384 "
5385)
5386
e5ba9289 5387; If optimizing for size, or if we have load delay slots, then
5388; we want to split the constant into two separate operations.
5389; In both cases this may split a trivial part into a single data op
5390; leaving a single complex constant to load. We can also get longer
5391; offsets in a LDR which means we get better chances of sharing the pool
5392; entries. Finally, we can normally do a better job of scheduling
5393; LDR instructions than we can with LDM.
5394; This pattern will only match if the one above did not.
5395(define_split
5396 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5397 (match_operand:ANY64 1 "const_double_operand" ""))]
5398 "TARGET_ARM && reload_completed
5399 && arm_const_double_by_parts (operands[1])"
5400 [(set (match_dup 0) (match_dup 1))
5401 (set (match_dup 2) (match_dup 3))]
5402 "
5403 operands[2] = gen_highpart (SImode, operands[0]);
5404 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5405 operands[1]);
5406 operands[0] = gen_lowpart (SImode, operands[0]);
5407 operands[1] = gen_lowpart (SImode, operands[1]);
5408 "
5409)
5410
d51f92df 5411(define_split
5412 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5413 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5414 "TARGET_EITHER && reload_completed"
5415 [(set (match_dup 0) (match_dup 1))
5416 (set (match_dup 2) (match_dup 3))]
5417 "
5418 operands[2] = gen_highpart (SImode, operands[0]);
5419 operands[3] = gen_highpart (SImode, operands[1]);
5420 operands[0] = gen_lowpart (SImode, operands[0]);
5421 operands[1] = gen_lowpart (SImode, operands[1]);
5422
5423 /* Handle a partial overlap. */
5424 if (rtx_equal_p (operands[0], operands[3]))
5425 {
5426 rtx tmp0 = operands[0];
5427 rtx tmp1 = operands[1];
5428
5429 operands[0] = operands[2];
5430 operands[1] = operands[3];
5431 operands[2] = tmp0;
5432 operands[3] = tmp1;
5433 }
5434 "
5435)
5436
a8a3b539 5437;; We can't actually do base+index doubleword loads if the index and
5438;; destination overlap. Split here so that we at least have chance to
5439;; schedule.
5440(define_split
5441 [(set (match_operand:DI 0 "s_register_operand" "")
5442 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5443 (match_operand:SI 2 "s_register_operand" ""))))]
5444 "TARGET_LDRD
5445 && reg_overlap_mentioned_p (operands[0], operands[1])
5446 && reg_overlap_mentioned_p (operands[0], operands[2])"
5447 [(set (match_dup 4)
5448 (plus:SI (match_dup 1)
5449 (match_dup 2)))
5450 (set (match_dup 0)
5451 (mem:DI (match_dup 4)))]
5452 "
5453 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5454 "
5455)
5456
cffb2a26 5457;;; ??? This should have alternatives for constants.
5458;;; ??? This was originally identical to the movdf_insn pattern.
5459;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5460;;; thumb_reorg with a memory reference.
25f905c2 5461(define_insn "*thumb1_movdi_insn"
215b30b3 5462 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5463 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 5464 "TARGET_THUMB1
cffb2a26 5465 && ( register_operand (operands[0], DImode)
5466 || register_operand (operands[1], DImode))"
5467 "*
5468 {
5469 switch (which_alternative)
5470 {
5471 default:
5472 case 0:
5473 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5474 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5475 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5476 case 1:
5477 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5478 case 2:
5479 operands[1] = GEN_INT (- INTVAL (operands[1]));
5480 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5481 case 3:
5482 return \"ldmia\\t%1, {%0, %H0}\";
5483 case 4:
5484 return \"stmia\\t%0, {%1, %H1}\";
5485 case 5:
5486 return thumb_load_double_from_address (operands);
5487 case 6:
1a83b3ff 5488 operands[2] = gen_rtx_MEM (SImode,
29c05e22 5489 plus_constant (Pmode, XEXP (operands[0], 0), 4));
cffb2a26 5490 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5491 return \"\";
5492 case 7:
5493 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5494 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5495 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5496 }
5497 }"
5498 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5499 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5500 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5501 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5502)
b11cae9e 5503
9c08d1fa 5504(define_expand "movsi"
5505 [(set (match_operand:SI 0 "general_operand" "")
5506 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5507 "TARGET_EITHER"
9c08d1fa 5508 "
befb0bac 5509 {
e348ff3e 5510 rtx base, offset, tmp;
5511
25f905c2 5512 if (TARGET_32BIT)
9c08d1fa 5513 {
674a8f0b 5514 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5515 if (MEM_P (operands[0]))
cffb2a26 5516 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5517 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5518 && CONST_INT_P (operands[1])
cffb2a26 5519 && !(const_ok_for_arm (INTVAL (operands[1]))
5520 || const_ok_for_arm (~INTVAL (operands[1]))))
5521 {
96f57e36 5522 arm_split_constant (SET, SImode, NULL_RTX,
5523 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5524 optimize && can_create_pseudo_p ());
cffb2a26 5525 DONE;
5526 }
5527 }
25f905c2 5528 else /* TARGET_THUMB1... */
cffb2a26 5529 {
e1ba4a27 5530 if (can_create_pseudo_p ())
cffb2a26 5531 {
0438d37f 5532 if (!REG_P (operands[0]))
cffb2a26 5533 operands[1] = force_reg (SImode, operands[1]);
5534 }
9c08d1fa 5535 }
f655717d 5536
e348ff3e 5537 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5538 {
5539 split_const (operands[1], &base, &offset);
5540 if (GET_CODE (base) == SYMBOL_REF
5541 && !offset_within_block_p (base, INTVAL (offset)))
5542 {
b308ddcf 5543 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5544 emit_move_insn (tmp, base);
5545 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5546 DONE;
5547 }
5548 }
5549
f655717d 5550 /* Recognize the case where operand[1] is a reference to thread-local
5551 data and load its address to a register. */
5552 if (arm_tls_referenced_p (operands[1]))
5553 {
5554 rtx tmp = operands[1];
5555 rtx addend = NULL;
5556
5557 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5558 {
5559 addend = XEXP (XEXP (tmp, 0), 1);
5560 tmp = XEXP (XEXP (tmp, 0), 0);
5561 }
5562
5563 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5564 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5565
e1ba4a27 5566 tmp = legitimize_tls_address (tmp,
5567 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5568 if (addend)
5569 {
5570 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5571 tmp = force_operand (tmp, operands[0]);
5572 }
5573 operands[1] = tmp;
5574 }
5575 else if (flag_pic
5576 && (CONSTANT_P (operands[1])
5577 || symbol_mentioned_p (operands[1])
5578 || label_mentioned_p (operands[1])))
5579 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5580 (!can_create_pseudo_p ()
5581 ? operands[0]
5582 : 0));
befb0bac 5583 }
215b30b3 5584 "
5585)
9c08d1fa 5586
d0e6a121 5587;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5588;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5589;; so this does not matter.
5590(define_insn "*arm_movt"
5591 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5592 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5593 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5594 "arm_arch_thumb2"
d0e6a121 5595 "movt%?\t%0, #:upper16:%c2"
5596 [(set_attr "predicable" "yes")
5597 (set_attr "length" "4")]
5598)
5599
cffb2a26 5600(define_insn "*arm_movsi_insn"
aaa37ad6 5601 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5602 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5603 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5604 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5605 && ( register_operand (operands[0], SImode)
5606 || register_operand (operands[1], SImode))"
f7fbdd4a 5607 "@
aaa37ad6 5608 mov%?\\t%0, %1
f7fbdd4a 5609 mov%?\\t%0, %1
5610 mvn%?\\t%0, #%B1
25f905c2 5611 movw%?\\t%0, %1
f7fbdd4a 5612 ldr%?\\t%0, %1
5613 str%?\\t%1, %0"
aaa37ad6 5614 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5615 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5616 (set_attr "predicable" "yes")
aaa37ad6 5617 (set_attr "pool_range" "*,*,*,*,4096,*")
5618 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5619)
87b22bf7 5620
5621(define_split
a2cd141b 5622 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5623 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5624 "TARGET_32BIT
215b30b3 5625 && (!(const_ok_for_arm (INTVAL (operands[1]))
5626 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5627 [(clobber (const_int 0))]
5628 "
96f57e36 5629 arm_split_constant (SET, SImode, NULL_RTX,
5630 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5631 DONE;
215b30b3 5632 "
5633)
9c08d1fa 5634
b8d5d078 5635;; Split symbol_refs at the later stage (after cprop), instead of generating
5636;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5637;; and lo_sum would be merged back into memory load at cprop. However,
5638;; if the default is to prefer movt/movw rather than a load from the constant
5639;; pool, the performance is better.
5640(define_split
5641 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5642 (match_operand:SI 1 "general_operand" ""))]
5643 "TARGET_32BIT
5644 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5645 && !flag_pic && !target_word_relocations
5646 && !arm_tls_referenced_p (operands[1])"
5647 [(clobber (const_int 0))]
5648{
5649 arm_emit_movpair (operands[0], operands[1]);
5650 DONE;
5651})
5652
25f905c2 5653(define_insn "*thumb1_movsi_insn"
55a0d64c 5654 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5655 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 5656 "TARGET_THUMB1
cffb2a26 5657 && ( register_operand (operands[0], SImode)
5658 || register_operand (operands[1], SImode))"
5659 "@
5660 mov %0, %1
5661 mov %0, %1
5662 #
5663 #
5664 ldmia\\t%1, {%0}
5665 stmia\\t%0, {%1}
5666 ldr\\t%0, %1
5667 str\\t%1, %0
5668 mov\\t%0, %1"
5669 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5670 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5671 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5672 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5673
5674(define_split
5675 [(set (match_operand:SI 0 "register_operand" "")
5676 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5677 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5678 [(set (match_dup 2) (match_dup 1))
5679 (set (match_dup 0) (neg:SI (match_dup 2)))]
5680 "
5681 {
5682 operands[1] = GEN_INT (- INTVAL (operands[1]));
5683 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5684 }"
cffb2a26 5685)
5686
5687(define_split
5688 [(set (match_operand:SI 0 "register_operand" "")
5689 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5690 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5691 [(set (match_dup 2) (match_dup 1))
5692 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5693 "
5694 {
e4aeee53 5695 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5696 unsigned HOST_WIDE_INT mask = 0xff;
5697 int i;
5698
5699 for (i = 0; i < 25; i++)
5700 if ((val & (mask << i)) == val)
5701 break;
5702
1276f1b8 5703 /* Don't split if the shift is zero. */
cffb2a26 5704 if (i == 0)
5705 FAIL;
5706
5707 operands[1] = GEN_INT (val >> i);
1276f1b8 5708 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5709 operands[3] = GEN_INT (i);
cffb2a26 5710 }"
5711)
5712
c5b75283 5713;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
5714(define_split
5715 [(set (match_operand:SI 0 "register_operand" "")
5716 (match_operand:SI 1 "const_int_operand" ""))]
5717 "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
5718 [(set (match_dup 2) (match_dup 1))
5719 (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
5720 "
5721 {
5722 operands[1] = GEN_INT (INTVAL (operands[1]) - 255);
5723 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5724 operands[3] = GEN_INT (255);
5725 }"
5726)
5727
67336bcf 5728;; When generating pic, we need to load the symbol offset into a register.
5729;; So that the optimizer does not confuse this with a normal symbol load
5730;; we use an unspec. The offset will be loaded from a constant pool entry,
5731;; since that is the only type of relocation we can use.
5732
94f8caca 5733;; Wrap calculation of the whole PIC address in a single pattern for the
5734;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5735;; a PIC address involves two loads from memory, so we want to CSE it
5736;; as often as possible.
5737;; This pattern will be split into one of the pic_load_addr_* patterns
5738;; and a move after GCSE optimizations.
5739;;
5740;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5741(define_expand "calculate_pic_address"
5742 [(set (match_operand:SI 0 "register_operand" "")
5743 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5744 (unspec:SI [(match_operand:SI 2 "" "")]
5745 UNSPEC_PIC_SYM))))]
5746 "flag_pic"
5747)
5748
5749;; Split calculate_pic_address into pic_load_addr_* and a move.
5750(define_split
5751 [(set (match_operand:SI 0 "register_operand" "")
5752 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5753 (unspec:SI [(match_operand:SI 2 "" "")]
5754 UNSPEC_PIC_SYM))))]
5755 "flag_pic"
5756 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5757 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5758 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5759)
5760
350ccca5 5761;; operand1 is the memory address to go into
5762;; pic_load_addr_32bit.
5763;; operand2 is the PIC label to be emitted
5764;; from pic_add_dot_plus_eight.
5765;; We do this to allow hoisting of the entire insn.
5766(define_insn_and_split "pic_load_addr_unified"
5767 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5768 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5769 (match_operand:SI 2 "" "")]
5770 UNSPEC_PIC_UNIFIED))]
5771 "flag_pic"
5772 "#"
5773 "&& reload_completed"
5774 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5775 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5776 (match_dup 2)] UNSPEC_PIC_BASE))]
5777 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5778 [(set_attr "type" "load1,load1,load1")
5779 (set_attr "pool_range" "4096,4096,1024")
5780 (set_attr "neg_pool_range" "4084,0,0")
5781 (set_attr "arch" "a,t2,t1")
5782 (set_attr "length" "8,6,4")]
5783)
5784
67336bcf 5785;; The rather odd constraints on the following are to force reload to leave
5786;; the insn alone, and to force the minipool generation pass to then move
5787;; the GOT symbol to memory.
849170fd 5788
b3cd5f55 5789(define_insn "pic_load_addr_32bit"
849170fd 5790 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5791 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5792 "TARGET_32BIT && flag_pic"
67336bcf 5793 "ldr%?\\t%0, %1"
a2cd141b 5794 [(set_attr "type" "load1")
b3cd5f55 5795 (set_attr "pool_range" "4096")
5796 (set (attr "neg_pool_range")
5797 (if_then_else (eq_attr "is_thumb" "no")
5798 (const_int 4084)
5799 (const_int 0)))]
8c4d8060 5800)
5801
25f905c2 5802(define_insn "pic_load_addr_thumb1"
8c4d8060 5803 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5804 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5805 "TARGET_THUMB1 && flag_pic"
8c4d8060 5806 "ldr\\t%0, %1"
a2cd141b 5807 [(set_attr "type" "load1")
8c4d8060 5808 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5809)
849170fd 5810
cffb2a26 5811(define_insn "pic_add_dot_plus_four"
15d5d060 5812 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5813 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5814 (const_int 4)
beef0fb5 5815 (match_operand 2 "" "")]
5816 UNSPEC_PIC_BASE))]
b3cd5f55 5817 "TARGET_THUMB"
cffb2a26 5818 "*
6cdcb15c 5819 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5820 INTVAL (operands[2]));
cffb2a26 5821 return \"add\\t%0, %|pc\";
5822 "
5823 [(set_attr "length" "2")]
5824)
849170fd 5825
5826(define_insn "pic_add_dot_plus_eight"
15d5d060 5827 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5828 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5829 (const_int 8)
beef0fb5 5830 (match_operand 2 "" "")]
5831 UNSPEC_PIC_BASE))]
f655717d 5832 "TARGET_ARM"
c4034607 5833 "*
6cdcb15c 5834 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5835 INTVAL (operands[2]));
15d5d060 5836 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5837 "
0d66636f 5838 [(set_attr "predicable" "yes")]
cffb2a26 5839)
849170fd 5840
f655717d 5841(define_insn "tls_load_dot_plus_eight"
cc071db6 5842 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5843 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5844 (const_int 8)
beef0fb5 5845 (match_operand 2 "" "")]
5846 UNSPEC_PIC_BASE)))]
f655717d 5847 "TARGET_ARM"
5848 "*
6cdcb15c 5849 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5850 INTVAL (operands[2]));
f655717d 5851 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5852 "
5853 [(set_attr "predicable" "yes")]
5854)
5855
5856;; PIC references to local variables can generate pic_add_dot_plus_eight
5857;; followed by a load. These sequences can be crunched down to
5858;; tls_load_dot_plus_eight by a peephole.
5859
5860(define_peephole2
c0c1fba5 5861 [(set (match_operand:SI 0 "register_operand" "")
5862 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5863 (const_int 8)
5864 (match_operand 1 "" "")]
5865 UNSPEC_PIC_BASE))
2d05dfad 5866 (set (match_operand:SI 2 "arm_general_register_operand" "")
5867 (mem:SI (match_dup 0)))]
f655717d 5868 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5869 [(set (match_dup 2)
5870 (mem:SI (unspec:SI [(match_dup 3)
5871 (const_int 8)
5872 (match_dup 1)]
5873 UNSPEC_PIC_BASE)))]
f655717d 5874 ""
5875)
5876
bac7fc85 5877(define_insn "pic_offset_arm"
5878 [(set (match_operand:SI 0 "register_operand" "=r")
5879 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5880 (unspec:SI [(match_operand:SI 2 "" "X")]
5881 UNSPEC_PIC_OFFSET))))]
5882 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5883 "ldr%?\\t%0, [%1,%2]"
5884 [(set_attr "type" "load1")]
5885)
5886
95373f08 5887(define_expand "builtin_setjmp_receiver"
5888 [(label_ref (match_operand 0 "" ""))]
5889 "flag_pic"
5890 "
5891{
b935b306 5892 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5893 register. */
2cb7d577 5894 if (arm_pic_register != INVALID_REGNUM)
5895 arm_load_pic_register (1UL << 3);
95373f08 5896 DONE;
5897}")
5898
9c08d1fa 5899;; If copying one reg to another we can set the condition codes according to
5900;; its value. Such a move is common after a return from subroutine and the
5901;; result is being tested against zero.
5902
f7fbdd4a 5903(define_insn "*movsi_compare0"
bd5b4116 5904 [(set (reg:CC CC_REGNUM)
cffb2a26 5905 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5906 (const_int 0)))
5907 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5908 (match_dup 1))]
25f905c2 5909 "TARGET_32BIT"
e2348bcb 5910 "@
40dbec34 5911 cmp%?\\t%0, #0
25f905c2 5912 sub%.\\t%0, %1, #0"
cffb2a26 5913 [(set_attr "conds" "set")]
5914)
b11cae9e 5915
b11cae9e 5916;; Subroutine to store a half word from a register into memory.
5917;; Operand 0 is the source register (HImode)
c8f69309 5918;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5919
9c08d1fa 5920;; In both this routine and the next, we must be careful not to spill
01cc3b75 5921;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5922;; can generate unrecognizable rtl.
5923
b11cae9e 5924(define_expand "storehi"
c8f69309 5925 [;; store the low byte
f082f1c4 5926 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5927 ;; extract the high byte
c8f69309 5928 (set (match_dup 2)
5929 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5930 ;; store the high byte
787f8210 5931 (set (match_dup 4) (match_dup 5))]
cffb2a26 5932 "TARGET_ARM"
b11cae9e 5933 "
215b30b3 5934 {
537ffcfc 5935 rtx op1 = operands[1];
5936 rtx addr = XEXP (op1, 0);
215b30b3 5937 enum rtx_code code = GET_CODE (addr);
5938
0438d37f 5939 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5940 || code == MINUS)
537ffcfc 5941 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5942
537ffcfc 5943 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5944 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5945 operands[3] = gen_lowpart (QImode, operands[0]);
5946 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5947 operands[2] = gen_reg_rtx (SImode);
5948 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5949 }"
5950)
b11cae9e 5951
c7597b5d 5952(define_expand "storehi_bigend"
f082f1c4 5953 [(set (match_dup 4) (match_dup 3))
c7597b5d 5954 (set (match_dup 2)
5955 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5956 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5957 "TARGET_ARM"
b11cae9e 5958 "
215b30b3 5959 {
537ffcfc 5960 rtx op1 = operands[1];
5961 rtx addr = XEXP (op1, 0);
215b30b3 5962 enum rtx_code code = GET_CODE (addr);
5963
0438d37f 5964 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5965 || code == MINUS)
537ffcfc 5966 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5967
537ffcfc 5968 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5969 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5970 operands[3] = gen_lowpart (QImode, operands[0]);
5971 operands[0] = gen_lowpart (SImode, operands[0]);
5972 operands[2] = gen_reg_rtx (SImode);
787f8210 5973 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5974 }"
5975)
c7597b5d 5976
5977;; Subroutine to store a half word integer constant into memory.
5978(define_expand "storeinthi"
f082f1c4 5979 [(set (match_operand 0 "" "")
787f8210 5980 (match_operand 1 "" ""))
9e8503e6 5981 (set (match_dup 3) (match_dup 2))]
cffb2a26 5982 "TARGET_ARM"
c7597b5d 5983 "
215b30b3 5984 {
5985 HOST_WIDE_INT value = INTVAL (operands[1]);
5986 rtx addr = XEXP (operands[0], 0);
537ffcfc 5987 rtx op0 = operands[0];
215b30b3 5988 enum rtx_code code = GET_CODE (addr);
c7597b5d 5989
0438d37f 5990 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5991 || code == MINUS)
537ffcfc 5992 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5993
215b30b3 5994 operands[1] = gen_reg_rtx (SImode);
5995 if (BYTES_BIG_ENDIAN)
5996 {
5997 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5998 if ((value & 255) == ((value >> 8) & 255))
5999 operands[2] = operands[1];
6000 else
6001 {
6002 operands[2] = gen_reg_rtx (SImode);
6003 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6004 }
6005 }
6006 else
6007 {
6008 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6009 if ((value & 255) == ((value >> 8) & 255))
6010 operands[2] = operands[1];
6011 else
6012 {
6013 operands[2] = gen_reg_rtx (SImode);
6014 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6015 }
6016 }
c7597b5d 6017
537ffcfc 6018 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6019 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6020 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6021 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6022 }"
6023)
b11cae9e 6024
f7fbdd4a 6025(define_expand "storehi_single_op"
6026 [(set (match_operand:HI 0 "memory_operand" "")
6027 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6028 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6029 "
215b30b3 6030 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6031 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6032 "
6033)
f7fbdd4a 6034
b11cae9e 6035(define_expand "movhi"
6036 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6037 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6038 "TARGET_EITHER"
b11cae9e 6039 "
cffb2a26 6040 if (TARGET_ARM)
b11cae9e 6041 {
e1ba4a27 6042 if (can_create_pseudo_p ())
cffb2a26 6043 {
0438d37f 6044 if (MEM_P (operands[0]))
b11cae9e 6045 {
cffb2a26 6046 if (arm_arch4)
6047 {
6048 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6049 DONE;
6050 }
0438d37f 6051 if (CONST_INT_P (operands[1]))
cffb2a26 6052 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6053 else
cffb2a26 6054 {
0438d37f 6055 if (MEM_P (operands[1]))
cffb2a26 6056 operands[1] = force_reg (HImode, operands[1]);
6057 if (BYTES_BIG_ENDIAN)
6058 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6059 else
6060 emit_insn (gen_storehi (operands[1], operands[0]));
6061 }
6062 DONE;
b11cae9e 6063 }
cffb2a26 6064 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6065 else if (CONST_INT_P (operands[1]))
9c08d1fa 6066 {
cffb2a26 6067 rtx reg = gen_reg_rtx (SImode);
6068 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6069
6070 /* If the constant is already valid, leave it alone. */
215b30b3 6071 if (!const_ok_for_arm (val))
cffb2a26 6072 {
6073 /* If setting all the top bits will make the constant
6074 loadable in a single instruction, then set them.
6075 Otherwise, sign extend the number. */
6076
215b30b3 6077 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6078 val |= ~0xffff;
6079 else if (val & 0x8000)
6080 val |= ~0xffff;
6081 }
6082
6083 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6084 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6085 }
e1ba4a27 6086 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6087 && MEM_P (operands[1]))
0045890a 6088 {
6089 rtx reg = gen_reg_rtx (SImode);
6090
6091 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6092 operands[1] = gen_lowpart (HImode, reg);
6093 }
215b30b3 6094 else if (!arm_arch4)
f7fbdd4a 6095 {
0438d37f 6096 if (MEM_P (operands[1]))
cffb2a26 6097 {
c1a66faf 6098 rtx base;
6099 rtx offset = const0_rtx;
6100 rtx reg = gen_reg_rtx (SImode);
6101
0438d37f 6102 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6103 || (GET_CODE (base) == PLUS
0438d37f 6104 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6105 && ((INTVAL(offset) & 1) != 1)
0438d37f 6106 && REG_P (base = XEXP (base, 0))))
c1a66faf 6107 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6108 {
8deb3959 6109 rtx new_rtx;
c1a66faf 6110
8deb3959 6111 new_rtx = widen_memory_access (operands[1], SImode,
6112 ((INTVAL (offset) & ~3)
6113 - INTVAL (offset)));
6114 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6115 if (((INTVAL (offset) & 2) != 0)
6116 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6117 {
6118 rtx reg2 = gen_reg_rtx (SImode);
6119
6120 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6121 reg = reg2;
6122 }
206ee9a2 6123 }
c1a66faf 6124 else
6125 emit_insn (gen_movhi_bytes (reg, operands[1]));
6126
6127 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6128 }
6129 }
6130 }
674a8f0b 6131 /* Handle loading a large integer during reload. */
0438d37f 6132 else if (CONST_INT_P (operands[1])
215b30b3 6133 && !const_ok_for_arm (INTVAL (operands[1]))
6134 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6135 {
6136 /* Writing a constant to memory needs a scratch, which should
6137 be handled with SECONDARY_RELOADs. */
0438d37f 6138 gcc_assert (REG_P (operands[0]));
cffb2a26 6139
6140 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6141 emit_insn (gen_movsi (operands[0], operands[1]));
6142 DONE;
6143 }
6144 }
25f905c2 6145 else if (TARGET_THUMB2)
6146 {
6147 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6148 if (can_create_pseudo_p ())
25f905c2 6149 {
0438d37f 6150 if (!REG_P (operands[0]))
25f905c2 6151 operands[1] = force_reg (HImode, operands[1]);
6152 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6153 else if (CONST_INT_P (operands[1]))
25f905c2 6154 {
6155 rtx reg = gen_reg_rtx (SImode);
6156 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6157
6158 emit_insn (gen_movsi (reg, GEN_INT (val)));
6159 operands[1] = gen_lowpart (HImode, reg);
6160 }
6161 }
6162 }
6163 else /* TARGET_THUMB1 */
cffb2a26 6164 {
e1ba4a27 6165 if (can_create_pseudo_p ())
cffb2a26 6166 {
0438d37f 6167 if (CONST_INT_P (operands[1]))
6cffc037 6168 {
6169 rtx reg = gen_reg_rtx (SImode);
6170
6171 emit_insn (gen_movsi (reg, operands[1]));
6172 operands[1] = gen_lowpart (HImode, reg);
6173 }
cffb2a26 6174
6175 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6176 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6177 virtual register (also rejected as illegitimate for HImode/QImode)
6178 relative address. */
cffb2a26 6179 /* ??? This should perhaps be fixed elsewhere, for instance, in
6180 fixup_stack_1, by checking for other kinds of invalid addresses,
6181 e.g. a bare reference to a virtual register. This may confuse the
6182 alpha though, which must handle this case differently. */
0438d37f 6183 if (MEM_P (operands[0])
215b30b3 6184 && !memory_address_p (GET_MODE (operands[0]),
6185 XEXP (operands[0], 0)))
537ffcfc 6186 operands[0]
6187 = replace_equiv_address (operands[0],
6188 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6189
0438d37f 6190 if (MEM_P (operands[1])
215b30b3 6191 && !memory_address_p (GET_MODE (operands[1]),
6192 XEXP (operands[1], 0)))
537ffcfc 6193 operands[1]
6194 = replace_equiv_address (operands[1],
6195 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6196
0438d37f 6197 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6198 {
6199 rtx reg = gen_reg_rtx (SImode);
6200
6201 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6202 operands[1] = gen_lowpart (HImode, reg);
6203 }
6204
0438d37f 6205 if (MEM_P (operands[0]))
6cffc037 6206 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6207 }
0438d37f 6208 else if (CONST_INT_P (operands[1])
234f6557 6209 && !satisfies_constraint_I (operands[1]))
cffb2a26 6210 {
6cffc037 6211 /* Handle loading a large integer during reload. */
6212
cffb2a26 6213 /* Writing a constant to memory needs a scratch, which should
6214 be handled with SECONDARY_RELOADs. */
0438d37f 6215 gcc_assert (REG_P (operands[0]));
cffb2a26 6216
1a83b3ff 6217 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6218 emit_insn (gen_movsi (operands[0], operands[1]));
6219 DONE;
6220 }
b11cae9e 6221 }
cffb2a26 6222 "
6223)
6224
25f905c2 6225(define_insn "*thumb1_movhi_insn"
a941568e 6226 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6227 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 6228 "TARGET_THUMB1
cffb2a26 6229 && ( register_operand (operands[0], HImode)
6230 || register_operand (operands[1], HImode))"
6231 "*
6232 switch (which_alternative)
d79300ac 6233 {
cffb2a26 6234 case 0: return \"add %0, %1, #0\";
6235 case 2: return \"strh %1, %0\";
6236 case 3: return \"mov %0, %1\";
6237 case 4: return \"mov %0, %1\";
6238 case 5: return \"mov %0, %1\";
ed29c566 6239 default: gcc_unreachable ();
cffb2a26 6240 case 1:
6241 /* The stack pointer can end up being taken as an index register.
6242 Catch this case here and deal with it. */
6243 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
0438d37f 6244 && REG_P (XEXP (XEXP (operands[1], 0), 0))
cffb2a26 6245 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
6246 {
6247 rtx ops[2];
6248 ops[0] = operands[0];
6249 ops[1] = XEXP (XEXP (operands[1], 0), 0);
6250
6251 output_asm_insn (\"mov %0, %1\", ops);
6252
6253 XEXP (XEXP (operands[1], 0), 0) = operands[0];
6254
6255 }
6256 return \"ldrh %0, %1\";
6257 }"
6258 [(set_attr "length" "2,4,2,2,2,2")
747b7458 6259 (set_attr "type" "*,load1,store1,*,*,*")
6260 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 6261
b11cae9e 6262
25f7a26e 6263(define_expand "movhi_bytes"
eab14235 6264 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6265 (set (match_dup 3)
eab14235 6266 (zero_extend:SI (match_dup 6)))
25f7a26e 6267 (set (match_operand:SI 0 "" "")
6268 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6269 "TARGET_ARM"
25f7a26e 6270 "
215b30b3 6271 {
6272 rtx mem1, mem2;
6273 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6274
788fcce0 6275 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6276 mem2 = change_address (operands[1], QImode,
6277 plus_constant (Pmode, addr, 1));
215b30b3 6278 operands[0] = gen_lowpart (SImode, operands[0]);
6279 operands[1] = mem1;
6280 operands[2] = gen_reg_rtx (SImode);
6281 operands[3] = gen_reg_rtx (SImode);
6282 operands[6] = mem2;
25f7a26e 6283
215b30b3 6284 if (BYTES_BIG_ENDIAN)
6285 {
6286 operands[4] = operands[2];
6287 operands[5] = operands[3];
6288 }
6289 else
6290 {
6291 operands[4] = operands[3];
6292 operands[5] = operands[2];
6293 }
6294 }"
6295)
25f7a26e 6296
c7597b5d 6297(define_expand "movhi_bigend"
6298 [(set (match_dup 2)
6299 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6300 (const_int 16)))
6301 (set (match_dup 3)
6302 (ashiftrt:SI (match_dup 2) (const_int 16)))
6303 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6304 (match_dup 4))]
cffb2a26 6305 "TARGET_ARM"
c7597b5d 6306 "
6307 operands[2] = gen_reg_rtx (SImode);
6308 operands[3] = gen_reg_rtx (SImode);
787f8210 6309 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6310 "
6311)
b11cae9e 6312
a2f10574 6313;; Pattern to recognize insn generated default case above
f7fbdd4a 6314(define_insn "*movhi_insn_arch4"
cde1623a 6315 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 6316 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 6317 "TARGET_ARM
6318 && arm_arch4
85e02ccb 6319 && (register_operand (operands[0], HImode)
6320 || register_operand (operands[1], HImode))"
f7fbdd4a 6321 "@
6322 mov%?\\t%0, %1\\t%@ movhi
6323 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 6324 str%(h%)\\t%1, %0\\t%@ movhi
6325 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 6326 [(set_attr "type" "*,*,store1,load1")
0d66636f 6327 (set_attr "predicable" "yes")
d2a518d1 6328 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 6329 (set_attr "pool_range" "*,*,*,256")
6330 (set_attr "neg_pool_range" "*,*,*,244")]
6331)
f7fbdd4a 6332
f7fbdd4a 6333(define_insn "*movhi_bytes"
25f7a26e 6334 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
6335 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 6336 "TARGET_ARM"
25f7a26e 6337 "@
6338 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6339 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6340 [(set_attr "predicable" "yes")
6341 (set_attr "insn" "mov,mvn")]
0d66636f 6342)
25f7a26e 6343
f90b51f1 6344(define_expand "thumb_movhi_clobber"
6345 [(set (match_operand:HI 0 "memory_operand" "")
6346 (match_operand:HI 1 "register_operand" ""))
6347 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 6348 "TARGET_THUMB1"
f90b51f1 6349 "
6350 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
6351 && REGNO (operands[1]) <= LAST_LO_REGNUM)
6352 {
6353 emit_insn (gen_movhi (operands[0], operands[1]));
6354 DONE;
6355 }
6356 /* XXX Fixme, need to handle other cases here as well. */
6357 gcc_unreachable ();
6358 "
cffb2a26 6359)
6360
bc5c7e08 6361;; We use a DImode scratch because we may occasionally need an additional
6362;; temporary if the address isn't offsettable -- push_reload doesn't seem
6363;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6364(define_expand "reload_outhi"
cffb2a26 6365 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6366 (match_operand:HI 1 "s_register_operand" "r")
6367 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6368 "TARGET_EITHER"
6369 "if (TARGET_ARM)
6370 arm_reload_out_hi (operands);
6371 else
6372 thumb_reload_out_hi (operands);
d3373b54 6373 DONE;
cffb2a26 6374 "
6375)
d3373b54 6376
25f7a26e 6377(define_expand "reload_inhi"
6378 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6379 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6380 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6381 "TARGET_EITHER"
25f7a26e 6382 "
cffb2a26 6383 if (TARGET_ARM)
6384 arm_reload_in_hi (operands);
6385 else
6386 thumb_reload_out_hi (operands);
25f7a26e 6387 DONE;
6388")
6389
9c08d1fa 6390(define_expand "movqi"
6391 [(set (match_operand:QI 0 "general_operand" "")
6392 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6393 "TARGET_EITHER"
9c08d1fa 6394 "
6cffc037 6395 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6396
e1ba4a27 6397 if (can_create_pseudo_p ())
cffb2a26 6398 {
0438d37f 6399 if (CONST_INT_P (operands[1]))
6cffc037 6400 {
6401 rtx reg = gen_reg_rtx (SImode);
6402
03770691 6403 /* For thumb we want an unsigned immediate, then we are more likely
6404 to be able to use a movs insn. */
6405 if (TARGET_THUMB)
6406 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6407
6cffc037 6408 emit_insn (gen_movsi (reg, operands[1]));
6409 operands[1] = gen_lowpart (QImode, reg);
6410 }
cffb2a26 6411
6cffc037 6412 if (TARGET_THUMB)
6413 {
cffb2a26 6414 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6415 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6416 virtual register (also rejected as illegitimate for HImode/QImode)
6417 relative address. */
cffb2a26 6418 /* ??? This should perhaps be fixed elsewhere, for instance, in
6419 fixup_stack_1, by checking for other kinds of invalid addresses,
6420 e.g. a bare reference to a virtual register. This may confuse the
6421 alpha though, which must handle this case differently. */
0438d37f 6422 if (MEM_P (operands[0])
215b30b3 6423 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6424 XEXP (operands[0], 0)))
537ffcfc 6425 operands[0]
6426 = replace_equiv_address (operands[0],
6427 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6428 if (MEM_P (operands[1])
215b30b3 6429 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6430 XEXP (operands[1], 0)))
537ffcfc 6431 operands[1]
6432 = replace_equiv_address (operands[1],
6433 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6434 }
6435
0438d37f 6436 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6437 {
6438 rtx reg = gen_reg_rtx (SImode);
6439
6440 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6441 operands[1] = gen_lowpart (QImode, reg);
6442 }
6443
0438d37f 6444 if (MEM_P (operands[0]))
6cffc037 6445 operands[1] = force_reg (QImode, operands[1]);
6446 }
6447 else if (TARGET_THUMB
0438d37f 6448 && CONST_INT_P (operands[1])
234f6557 6449 && !satisfies_constraint_I (operands[1]))
6cffc037 6450 {
674a8f0b 6451 /* Handle loading a large integer during reload. */
cffb2a26 6452
6cffc037 6453 /* Writing a constant to memory needs a scratch, which should
6454 be handled with SECONDARY_RELOADs. */
0438d37f 6455 gcc_assert (REG_P (operands[0]));
6cffc037 6456
6457 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6458 emit_insn (gen_movsi (operands[0], operands[1]));
6459 DONE;
cffb2a26 6460 }
6461 "
6462)
b11cae9e 6463
9c08d1fa 6464
cffb2a26 6465(define_insn "*arm_movqi_insn"
a54e3e7b 6466 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
6467 (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
25f905c2 6468 "TARGET_32BIT
cffb2a26 6469 && ( register_operand (operands[0], QImode)
6470 || register_operand (operands[1], QImode))"
5565501b 6471 "@
6472 mov%?\\t%0, %1
6473 mvn%?\\t%0, #%B1
25f905c2 6474 ldr%(b%)\\t%0, %1
a54e3e7b 6475 str%(b%)\\t%1, %0
6476 ldr%(b%)\\t%0, %1
25f905c2 6477 str%(b%)\\t%1, %0"
a54e3e7b 6478 [(set_attr "type" "*,*,load1,store1,load1,store1")
6479 (set_attr "insn" "mov,mvn,*,*,*,*")
6480 (set_attr "predicable" "yes")
6481 (set_attr "arch" "any,any,t2,t2,any,any")
6482 (set_attr "length" "4,4,2,2,4,4")]
cffb2a26 6483)
6484
25f905c2 6485(define_insn "*thumb1_movqi_insn"
cffb2a26 6486 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 6487 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 6488 "TARGET_THUMB1
cffb2a26 6489 && ( register_operand (operands[0], QImode)
6490 || register_operand (operands[1], QImode))"
6491 "@
6492 add\\t%0, %1, #0
6493 ldrb\\t%0, %1
6494 strb\\t%1, %0
6495 mov\\t%0, %1
6496 mov\\t%0, %1
6497 mov\\t%0, %1"
6498 [(set_attr "length" "2")
a2cd141b 6499 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 6500 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 6501 (set_attr "pool_range" "*,32,*,*,*,*")
6502 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 6503
9b8516be 6504;; HFmode moves
6505(define_expand "movhf"
6506 [(set (match_operand:HF 0 "general_operand" "")
6507 (match_operand:HF 1 "general_operand" ""))]
6508 "TARGET_EITHER"
6509 "
6510 if (TARGET_32BIT)
6511 {
0438d37f 6512 if (MEM_P (operands[0]))
9b8516be 6513 operands[1] = force_reg (HFmode, operands[1]);
6514 }
6515 else /* TARGET_THUMB1 */
6516 {
6517 if (can_create_pseudo_p ())
6518 {
0438d37f 6519 if (!REG_P (operands[0]))
9b8516be 6520 operands[1] = force_reg (HFmode, operands[1]);
6521 }
6522 }
6523 "
6524)
6525
6526(define_insn "*arm32_movhf"
6527 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6528 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 6529 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6530 && ( s_register_operand (operands[0], HFmode)
6531 || s_register_operand (operands[1], HFmode))"
6532 "*
6533 switch (which_alternative)
6534 {
6535 case 0: /* ARM register from memory */
6536 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6537 case 1: /* memory from ARM register */
6538 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6539 case 2: /* ARM register from ARM register */
6540 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6541 case 3: /* ARM register from constant */
6542 {
6543 REAL_VALUE_TYPE r;
6544 long bits;
6545 rtx ops[4];
6546
6547 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6548 bits = real_to_target (NULL, &r, HFmode);
6549 ops[0] = operands[0];
6550 ops[1] = GEN_INT (bits);
6551 ops[2] = GEN_INT (bits & 0xff00);
6552 ops[3] = GEN_INT (bits & 0x00ff);
6553
6554 if (arm_arch_thumb2)
6555 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6556 else
6557 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6558 return \"\";
6559 }
6560 default:
6561 gcc_unreachable ();
6562 }
6563 "
6564 [(set_attr "conds" "unconditional")
6565 (set_attr "type" "load1,store1,*,*")
d2a518d1 6566 (set_attr "insn" "*,*,mov,mov")
9b8516be 6567 (set_attr "length" "4,4,4,8")
d2a518d1 6568 (set_attr "predicable" "yes")]
9b8516be 6569)
6570
6571(define_insn "*thumb1_movhf"
6572 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6573 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6574 "TARGET_THUMB1
6575 && ( s_register_operand (operands[0], HFmode)
6576 || s_register_operand (operands[1], HFmode))"
6577 "*
6578 switch (which_alternative)
6579 {
6580 case 1:
6581 {
6582 rtx addr;
0438d37f 6583 gcc_assert (MEM_P (operands[1]));
9b8516be 6584 addr = XEXP (operands[1], 0);
6585 if (GET_CODE (addr) == LABEL_REF
6586 || (GET_CODE (addr) == CONST
6587 && GET_CODE (XEXP (addr, 0)) == PLUS
6588 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
0438d37f 6589 && CONST_INT_P (XEXP (XEXP (addr, 0), 1))))
9b8516be 6590 {
6591 /* Constant pool entry. */
6592 return \"ldr\\t%0, %1\";
6593 }
6594 return \"ldrh\\t%0, %1\";
6595 }
6596 case 2: return \"strh\\t%1, %0\";
6597 default: return \"mov\\t%0, %1\";
6598 }
6599 "
6600 [(set_attr "length" "2")
6601 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6602 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6603 (set_attr "pool_range" "*,1020,*,*,*")
6604 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6605
87b22bf7 6606(define_expand "movsf"
6607 [(set (match_operand:SF 0 "general_operand" "")
6608 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6609 "TARGET_EITHER"
87b22bf7 6610 "
25f905c2 6611 if (TARGET_32BIT)
cffb2a26 6612 {
0438d37f 6613 if (MEM_P (operands[0]))
cffb2a26 6614 operands[1] = force_reg (SFmode, operands[1]);
6615 }
25f905c2 6616 else /* TARGET_THUMB1 */
cffb2a26 6617 {
e1ba4a27 6618 if (can_create_pseudo_p ())
cffb2a26 6619 {
0438d37f 6620 if (!REG_P (operands[0]))
cffb2a26 6621 operands[1] = force_reg (SFmode, operands[1]);
6622 }
6623 }
6624 "
6625)
6626
03d440a6 6627;; Transform a floating-point move of a constant into a core register into
6628;; an SImode operation.
cffb2a26 6629(define_split
03d440a6 6630 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6631 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6632 "TARGET_EITHER
cffb2a26 6633 && reload_completed
0438d37f 6634 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6635 [(set (match_dup 2) (match_dup 3))]
6636 "
6637 operands[2] = gen_lowpart (SImode, operands[0]);
6638 operands[3] = gen_lowpart (SImode, operands[1]);
6639 if (operands[2] == 0 || operands[3] == 0)
6640 FAIL;
215b30b3 6641 "
6642)
87b22bf7 6643
cffb2a26 6644(define_insn "*arm_movsf_soft_insn"
6645 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6646 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6647 "TARGET_32BIT
cffb2a26 6648 && TARGET_SOFT_FLOAT
0438d37f 6649 && (!MEM_P (operands[0])
215b30b3 6650 || register_operand (operands[1], SFmode))"
9a1112d7 6651 "@
6652 mov%?\\t%0, %1
6653 ldr%?\\t%0, %1\\t%@ float
6654 str%?\\t%1, %0\\t%@ float"
cde1623a 6655 [(set_attr "predicable" "yes")
a2cd141b 6656 (set_attr "type" "*,load1,store1")
d2a518d1 6657 (set_attr "insn" "mov,*,*")
cffb2a26 6658 (set_attr "pool_range" "*,4096,*")
cde1623a 6659 (set_attr "arm_neg_pool_range" "*,4084,*")
6660 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6661)
6662
6663;;; ??? This should have alternatives for constants.
25f905c2 6664(define_insn "*thumb1_movsf_insn"
215b30b3 6665 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6666 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6667 "TARGET_THUMB1
cffb2a26 6668 && ( register_operand (operands[0], SFmode)
6669 || register_operand (operands[1], SFmode))"
6670 "@
6671 add\\t%0, %1, #0
6672 ldmia\\t%1, {%0}
6673 stmia\\t%0, {%1}
6674 ldr\\t%0, %1
6675 str\\t%1, %0
6676 mov\\t%0, %1
6677 mov\\t%0, %1"
6678 [(set_attr "length" "2")
a2cd141b 6679 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6680 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6681 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6682 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6683)
9a1112d7 6684
9c08d1fa 6685(define_expand "movdf"
87b22bf7 6686 [(set (match_operand:DF 0 "general_operand" "")
6687 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6688 "TARGET_EITHER"
9c08d1fa 6689 "
25f905c2 6690 if (TARGET_32BIT)
cffb2a26 6691 {
0438d37f 6692 if (MEM_P (operands[0]))
cffb2a26 6693 operands[1] = force_reg (DFmode, operands[1]);
6694 }
6695 else /* TARGET_THUMB */
6696 {
e1ba4a27 6697 if (can_create_pseudo_p ())
cffb2a26 6698 {
0438d37f 6699 if (!REG_P (operands[0]))
cffb2a26 6700 operands[1] = force_reg (DFmode, operands[1]);
6701 }
6702 }
6703 "
6704)
b11cae9e 6705
9c08d1fa 6706;; Reloading a df mode value stored in integer regs to memory can require a
6707;; scratch reg.
6708(define_expand "reload_outdf"
cffb2a26 6709 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6710 (match_operand:DF 1 "s_register_operand" "r")
6711 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6712 "TARGET_THUMB2"
87b22bf7 6713 "
215b30b3 6714 {
6715 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6716
215b30b3 6717 if (code == REG)
6718 operands[2] = XEXP (operands[0], 0);
6719 else if (code == POST_INC || code == PRE_DEC)
6720 {
6721 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6722 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6723 emit_insn (gen_movdi (operands[0], operands[1]));
6724 DONE;
6725 }
6726 else if (code == PRE_INC)
6727 {
6728 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6729
215b30b3 6730 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6731 operands[2] = reg;
6732 }
6733 else if (code == POST_DEC)
6734 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6735 else
6736 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6737 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6738
788fcce0 6739 emit_insn (gen_rtx_SET (VOIDmode,
6740 replace_equiv_address (operands[0], operands[2]),
215b30b3 6741 operands[1]));
f7fbdd4a 6742
215b30b3 6743 if (code == POST_DEC)
6744 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6745
6746 DONE;
6747 }"
6748)
9c08d1fa 6749
9a1112d7 6750(define_insn "*movdf_soft_insn"
359a6e9f 6751 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6752 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6753 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6754 && ( register_operand (operands[0], DFmode)
6755 || register_operand (operands[1], DFmode))"
d51f92df 6756 "*
6757 switch (which_alternative)
6758 {
6759 case 0:
6760 case 1:
6761 case 2:
6762 return \"#\";
6763 default:
26ff80c0 6764 return output_move_double (operands, true, NULL);
d51f92df 6765 }
6766 "
359a6e9f 6767 [(set_attr "length" "8,12,16,8,8")
6768 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6769 (set_attr "pool_range" "*,*,*,1020,*")
8848d797 6770 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6771 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6772)
6773
6774;;; ??? This should have alternatives for constants.
6775;;; ??? This was originally identical to the movdi_insn pattern.
6776;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6777;;; thumb_reorg with a memory reference.
6778(define_insn "*thumb_movdf_insn"
215b30b3 6779 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6780 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6781 "TARGET_THUMB1
cffb2a26 6782 && ( register_operand (operands[0], DFmode)
6783 || register_operand (operands[1], DFmode))"
6784 "*
6785 switch (which_alternative)
6786 {
6787 default:
6788 case 0:
6789 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6790 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6791 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6792 case 1:
6793 return \"ldmia\\t%1, {%0, %H0}\";
6794 case 2:
6795 return \"stmia\\t%0, {%1, %H1}\";
6796 case 3:
6797 return thumb_load_double_from_address (operands);
6798 case 4:
1a83b3ff 6799 operands[2] = gen_rtx_MEM (SImode,
29c05e22 6800 plus_constant (Pmode,
6801 XEXP (operands[0], 0), 4));
cffb2a26 6802 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6803 return \"\";
6804 case 5:
6805 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6806 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6807 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6808 }
6809 "
6810 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6811 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6812 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6813 (set_attr "pool_range" "*,*,*,1020,*,*")]
6814)
b11cae9e 6815\f
b11cae9e 6816
9c08d1fa 6817;; load- and store-multiple insns
6818;; The arm can load/store any set of registers, provided that they are in
320ea44d 6819;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6820
9c08d1fa 6821(define_expand "load_multiple"
6822 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6823 (match_operand:SI 1 "" ""))
6824 (use (match_operand:SI 2 "" ""))])]
25f905c2 6825 "TARGET_32BIT"
9580c25f 6826{
6827 HOST_WIDE_INT offset = 0;
6828
bd5b4116 6829 /* Support only fixed point registers. */
0438d37f 6830 if (!CONST_INT_P (operands[2])
9c08d1fa 6831 || INTVAL (operands[2]) > 14
6832 || INTVAL (operands[2]) < 2
0438d37f 6833 || !MEM_P (operands[1])
6834 || !REG_P (operands[0])
bd5b4116 6835 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6836 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6837 FAIL;
6838
6839 operands[3]
320ea44d 6840 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6841 INTVAL (operands[2]),
f082f1c4 6842 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6843 FALSE, operands[1], &offset);
9580c25f 6844})
b11cae9e 6845
9c08d1fa 6846(define_expand "store_multiple"
6847 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6848 (match_operand:SI 1 "" ""))
6849 (use (match_operand:SI 2 "" ""))])]
25f905c2 6850 "TARGET_32BIT"
9580c25f 6851{
6852 HOST_WIDE_INT offset = 0;
6853
674a8f0b 6854 /* Support only fixed point registers. */
0438d37f 6855 if (!CONST_INT_P (operands[2])
9c08d1fa 6856 || INTVAL (operands[2]) > 14
6857 || INTVAL (operands[2]) < 2
0438d37f 6858 || !REG_P (operands[1])
6859 || !MEM_P (operands[0])
bd5b4116 6860 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6861 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6862 FAIL;
6863
6864 operands[3]
320ea44d 6865 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6866 INTVAL (operands[2]),
f082f1c4 6867 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6868 FALSE, operands[0], &offset);
9580c25f 6869})
b11cae9e 6870
9c08d1fa 6871
6872;; Move a block of memory if it is word aligned and MORE than 2 words long.
6873;; We could let this apply for blocks of less than this, but it clobbers so
6874;; many registers that there is then probably a better way.
6875
008c057d 6876(define_expand "movmemqi"
34191dd1 6877 [(match_operand:BLK 0 "general_operand" "")
6878 (match_operand:BLK 1 "general_operand" "")
6879 (match_operand:SI 2 "const_int_operand" "")
6880 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6881 "TARGET_EITHER"
9c08d1fa 6882 "
25f905c2 6883 if (TARGET_32BIT)
cffb2a26 6884 {
008c057d 6885 if (arm_gen_movmemqi (operands))
cffb2a26 6886 DONE;
6887 FAIL;
6888 }
25f905c2 6889 else /* TARGET_THUMB1 */
cffb2a26 6890 {
6891 if ( INTVAL (operands[3]) != 4
6892 || INTVAL (operands[2]) > 48)
6893 FAIL;
6894
008c057d 6895 thumb_expand_movmemqi (operands);
cffb2a26 6896 DONE;
6897 }
6898 "
6899)
6900
2162064c 6901;; Thumb block-move insns
cffb2a26 6902
6903(define_insn "movmem12b"
960f3acf 6904 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6905 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6906 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6907 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6908 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6909 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6910 (set (match_operand:SI 0 "register_operand" "=l")
6911 (plus:SI (match_dup 2) (const_int 12)))
6912 (set (match_operand:SI 1 "register_operand" "=l")
6913 (plus:SI (match_dup 3) (const_int 12)))
6914 (clobber (match_scratch:SI 4 "=&l"))
6915 (clobber (match_scratch:SI 5 "=&l"))
6916 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6917 "TARGET_THUMB1"
cffb2a26 6918 "* return thumb_output_move_mem_multiple (3, operands);"
6919 [(set_attr "length" "4")
215b30b3 6920 ; This isn't entirely accurate... It loads as well, but in terms of
6921 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6922 (set_attr "type" "store3")]
6923)
6924
6925(define_insn "movmem8b"
960f3acf 6926 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6927 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6928 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6929 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6930 (set (match_operand:SI 0 "register_operand" "=l")
6931 (plus:SI (match_dup 2) (const_int 8)))
6932 (set (match_operand:SI 1 "register_operand" "=l")
6933 (plus:SI (match_dup 3) (const_int 8)))
6934 (clobber (match_scratch:SI 4 "=&l"))
6935 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6936 "TARGET_THUMB1"
cffb2a26 6937 "* return thumb_output_move_mem_multiple (2, operands);"
6938 [(set_attr "length" "4")
215b30b3 6939 ; This isn't entirely accurate... It loads as well, but in terms of
6940 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6941 (set_attr "type" "store2")]
6942)
6943
9c08d1fa 6944\f
b11cae9e 6945
341940e8 6946;; Compare & branch insns
8d232dc7 6947;; The range calculations are based as follows:
341940e8 6948;; For forward branches, the address calculation returns the address of
6949;; the next instruction. This is 2 beyond the branch instruction.
6950;; For backward branches, the address calculation returns the address of
6951;; the first instruction in this pattern (cmp). This is 2 before the branch
6952;; instruction for the shortest sequence, and 4 before the branch instruction
6953;; if we have to jump around an unconditional branch.
6954;; To the basic branch range the PC offset must be added (this is +4).
6955;; So for forward branches we have
6956;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6957;; And for backward branches we have
6958;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6959;;
6960;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6961;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6962
aeac46d4 6963(define_expand "cbranchsi4"
6964 [(set (pc) (if_then_else
aa06947a 6965 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6966 [(match_operand:SI 1 "s_register_operand" "")
6967 (match_operand:SI 2 "nonmemory_operand" "")])
6968 (label_ref (match_operand 3 "" ""))
6969 (pc)))]
f9aa4160 6970 "TARGET_EITHER"
aeac46d4 6971 "
74f4459c 6972 if (!TARGET_THUMB1)
6973 {
f9aa4160 6974 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6975 FAIL;
74f4459c 6976 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6977 operands[3]));
6978 DONE;
6979 }
25f905c2 6980 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6981 {
6982 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6983 operands[3], operands[0]));
6984 DONE;
6985 }
25f905c2 6986 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6987 operands[2] = force_reg (SImode, operands[2]);
6988 ")
6989
a8e6c15d 6990;; A pattern to recognize a special situation and optimize for it.
6991;; On the thumb, zero-extension from memory is preferrable to sign-extension
6992;; due to the available addressing modes. Hence, convert a signed comparison
6993;; with zero into an unsigned comparison with 127 if possible.
6994(define_expand "cbranchqi4"
6995 [(set (pc) (if_then_else
6996 (match_operator 0 "lt_ge_comparison_operator"
6997 [(match_operand:QI 1 "memory_operand" "")
6998 (match_operand:QI 2 "const0_operand" "")])
6999 (label_ref (match_operand 3 "" ""))
7000 (pc)))]
7001 "TARGET_THUMB1"
7002{
d0f6c30d 7003 rtx xops[4];
a8e6c15d 7004 xops[1] = gen_reg_rtx (SImode);
7005 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
7006 xops[2] = GEN_INT (127);
7007 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
7008 VOIDmode, xops[1], xops[2]);
7009 xops[3] = operands[3];
7010 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
7011 DONE;
7012})
7013
74f4459c 7014(define_expand "cbranchsf4"
7015 [(set (pc) (if_then_else
aa06947a 7016 (match_operator 0 "expandable_comparison_operator"
74f4459c 7017 [(match_operand:SF 1 "s_register_operand" "")
7018 (match_operand:SF 2 "arm_float_compare_operand" "")])
7019 (label_ref (match_operand 3 "" ""))
7020 (pc)))]
7021 "TARGET_32BIT && TARGET_HARD_FLOAT"
7022 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7023 operands[3])); DONE;"
7024)
7025
7026(define_expand "cbranchdf4"
7027 [(set (pc) (if_then_else
aa06947a 7028 (match_operator 0 "expandable_comparison_operator"
74f4459c 7029 [(match_operand:DF 1 "s_register_operand" "")
7030 (match_operand:DF 2 "arm_float_compare_operand" "")])
7031 (label_ref (match_operand 3 "" ""))
7032 (pc)))]
a50d7267 7033 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7034 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7035 operands[3])); DONE;"
7036)
7037
74f4459c 7038(define_expand "cbranchdi4"
7039 [(set (pc) (if_then_else
aa06947a 7040 (match_operator 0 "expandable_comparison_operator"
a8045a4f 7041 [(match_operand:DI 1 "cmpdi_operand" "")
7042 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7043 (label_ref (match_operand 3 "" ""))
7044 (pc)))]
a8045a4f 7045 "TARGET_32BIT"
7046 "{
a8045a4f 7047 /* We should not have two constants. */
7048 gcc_assert (GET_MODE (operands[1]) == DImode
7049 || GET_MODE (operands[2]) == DImode);
7050
0438d37f 7051 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7052 FAIL;
7053 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7054 operands[3]));
7055 DONE;
7056 }"
74f4459c 7057)
7058
d60047aa 7059(define_insn "cbranchsi4_insn"
aeac46d4 7060 [(set (pc) (if_then_else
7061 (match_operator 0 "arm_comparison_operator"
747b7458 7062 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 7063 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 7064 (label_ref (match_operand 3 "" ""))
7065 (pc)))]
25f905c2 7066 "TARGET_THUMB1"
747b7458 7067{
7068 rtx t = cfun->machine->thumb1_cc_insn;
7069 if (t != NULL_RTX)
d60047aa 7070 {
747b7458 7071 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
7072 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
7073 t = NULL_RTX;
7074 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
7075 {
7076 if (!noov_comparison_operator (operands[0], VOIDmode))
7077 t = NULL_RTX;
7078 }
7079 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 7080 t = NULL_RTX;
7081 }
d60047aa 7082 if (t == NULL_RTX)
747b7458 7083 {
7084 output_asm_insn ("cmp\t%1, %2", operands);
7085 cfun->machine->thumb1_cc_insn = insn;
7086 cfun->machine->thumb1_cc_op0 = operands[1];
7087 cfun->machine->thumb1_cc_op1 = operands[2];
7088 cfun->machine->thumb1_cc_mode = CCmode;
7089 }
7090 else
7091 /* Ensure we emit the right type of condition code on the jump. */
7092 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
7093 CC_REGNUM);
aeac46d4 7094
cffb2a26 7095 switch (get_attr_length (insn))
7096 {
7097 case 4: return \"b%d0\\t%l3\";
7098 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7099 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7100 }
747b7458 7101}
cffb2a26 7102 [(set (attr "far_jump")
7103 (if_then_else
7104 (eq_attr "length" "8")
7105 (const_string "yes")
7106 (const_string "no")))
7107 (set (attr "length")
7108 (if_then_else
7109 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7110 (le (minus (match_dup 3) (pc)) (const_int 256)))
7111 (const_int 4)
7112 (if_then_else
7113 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 7114 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7115 (const_int 6)
7116 (const_int 8))))]
7117)
7118
aeac46d4 7119(define_insn "cbranchsi4_scratch"
7120 [(set (pc) (if_then_else
7121 (match_operator 4 "arm_comparison_operator"
7122 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 7123 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 7124 (label_ref (match_operand 3 "" ""))
7125 (pc)))
7126 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 7127 "TARGET_THUMB1"
aeac46d4 7128 "*
7129 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
7130
7131 switch (get_attr_length (insn))
7132 {
7133 case 4: return \"b%d4\\t%l3\";
7134 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7135 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7136 }
7137 "
7138 [(set (attr "far_jump")
7139 (if_then_else
7140 (eq_attr "length" "8")
7141 (const_string "yes")
7142 (const_string "no")))
7143 (set (attr "length")
7144 (if_then_else
7145 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7146 (le (minus (match_dup 3) (pc)) (const_int 256)))
7147 (const_int 4)
7148 (if_then_else
7149 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7150 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7151 (const_int 6)
7152 (const_int 8))))]
7153)
446a1e96 7154
747b7458 7155;; Two peepholes to generate subtract of 0 instead of a move if the
7156;; condition codes will be useful.
446a1e96 7157(define_peephole2
7158 [(set (match_operand:SI 0 "low_register_operand" "")
7159 (match_operand:SI 1 "low_register_operand" ""))
7160 (set (pc)
7161 (if_then_else (match_operator 2 "arm_comparison_operator"
7162 [(match_dup 1) (const_int 0)])
7163 (label_ref (match_operand 3 "" ""))
7164 (pc)))]
7165 "TARGET_THUMB1"
747b7458 7166 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7167 (set (pc)
7168 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 7169 (label_ref (match_dup 3))
747b7458 7170 (pc)))]
7171 "")
446a1e96 7172
7173;; Sigh! This variant shouldn't be needed, but combine often fails to
7174;; merge cases like this because the op1 is a hard register in
07d32235 7175;; arm_class_likely_spilled_p.
446a1e96 7176(define_peephole2
7177 [(set (match_operand:SI 0 "low_register_operand" "")
7178 (match_operand:SI 1 "low_register_operand" ""))
7179 (set (pc)
7180 (if_then_else (match_operator 2 "arm_comparison_operator"
7181 [(match_dup 0) (const_int 0)])
7182 (label_ref (match_operand 3 "" ""))
7183 (pc)))]
7184 "TARGET_THUMB1"
747b7458 7185 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7186 (set (pc)
7187 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 7188 (label_ref (match_dup 3))
747b7458 7189 (pc)))]
7190 "")
446a1e96 7191
cffb2a26 7192(define_insn "*negated_cbranchsi4"
7193 [(set (pc)
7194 (if_then_else
aed179ae 7195 (match_operator 0 "equality_operator"
aeac46d4 7196 [(match_operand:SI 1 "s_register_operand" "l")
7197 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
7198 (label_ref (match_operand 3 "" ""))
215b30b3 7199 (pc)))]
25f905c2 7200 "TARGET_THUMB1"
cffb2a26 7201 "*
7202 output_asm_insn (\"cmn\\t%1, %2\", operands);
7203 switch (get_attr_length (insn))
7204 {
7205 case 4: return \"b%d0\\t%l3\";
7206 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7207 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7208 }
7209 "
7210 [(set (attr "far_jump")
7211 (if_then_else
7212 (eq_attr "length" "8")
7213 (const_string "yes")
7214 (const_string "no")))
7215 (set (attr "length")
7216 (if_then_else
7217 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 7218 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 7219 (const_int 4)
7220 (if_then_else
341940e8 7221 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7222 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7223 (const_int 6)
7224 (const_int 8))))]
7225)
7226
58d6528b 7227(define_insn "*tbit_cbranch"
7228 [(set (pc)
7229 (if_then_else
7230 (match_operator 0 "equality_operator"
7231 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7232 (const_int 1)
7233 (match_operand:SI 2 "const_int_operand" "i"))
7234 (const_int 0)])
7235 (label_ref (match_operand 3 "" ""))
7236 (pc)))
7237 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7238 "TARGET_THUMB1"
58d6528b 7239 "*
7240 {
7241 rtx op[3];
7242 op[0] = operands[4];
7243 op[1] = operands[1];
7244 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
7245
86efa74d 7246 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7247 switch (get_attr_length (insn))
7248 {
7249 case 4: return \"b%d0\\t%l3\";
7250 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7251 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7252 }
7253 }"
7254 [(set (attr "far_jump")
7255 (if_then_else
7256 (eq_attr "length" "8")
7257 (const_string "yes")
7258 (const_string "no")))
7259 (set (attr "length")
7260 (if_then_else
7261 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7262 (le (minus (match_dup 3) (pc)) (const_int 256)))
7263 (const_int 4)
7264 (if_then_else
7265 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7266 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7267 (const_int 6)
7268 (const_int 8))))]
7269)
7270
7271(define_insn "*tlobits_cbranch"
7272 [(set (pc)
7273 (if_then_else
7274 (match_operator 0 "equality_operator"
7275 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7276 (match_operand:SI 2 "const_int_operand" "i")
7277 (const_int 0))
7278 (const_int 0)])
7279 (label_ref (match_operand 3 "" ""))
7280 (pc)))
7281 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7282 "TARGET_THUMB1"
86efa74d 7283 "*
7284 {
7285 rtx op[3];
7286 op[0] = operands[4];
7287 op[1] = operands[1];
7288 op[2] = GEN_INT (32 - INTVAL (operands[2]));
7289
58d6528b 7290 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7291 switch (get_attr_length (insn))
7292 {
7293 case 4: return \"b%d0\\t%l3\";
7294 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7295 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7296 }
7297 }"
7298 [(set (attr "far_jump")
7299 (if_then_else
7300 (eq_attr "length" "8")
7301 (const_string "yes")
7302 (const_string "no")))
7303 (set (attr "length")
7304 (if_then_else
7305 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7306 (le (minus (match_dup 3) (pc)) (const_int 256)))
7307 (const_int 4)
7308 (if_then_else
7309 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7310 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7311 (const_int 6)
7312 (const_int 8))))]
7313)
747b7458 7314
aeac46d4 7315(define_insn "*tstsi3_cbranch"
58d6528b 7316 [(set (pc)
7317 (if_then_else
aeac46d4 7318 (match_operator 3 "equality_operator"
7319 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7320 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 7321 (const_int 0)])
aeac46d4 7322 (label_ref (match_operand 2 "" ""))
7323 (pc)))]
25f905c2 7324 "TARGET_THUMB1"
58d6528b 7325 "*
7326 {
aeac46d4 7327 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 7328 switch (get_attr_length (insn))
7329 {
aeac46d4 7330 case 4: return \"b%d3\\t%l2\";
7331 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7332 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 7333 }
7334 }"
7335 [(set (attr "far_jump")
7336 (if_then_else
7337 (eq_attr "length" "8")
7338 (const_string "yes")
7339 (const_string "no")))
7340 (set (attr "length")
7341 (if_then_else
aeac46d4 7342 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7343 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 7344 (const_int 4)
7345 (if_then_else
aeac46d4 7346 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7347 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 7348 (const_int 6)
7349 (const_int 8))))]
7350)
7351
203c488f 7352(define_insn "*cbranchne_decr1"
7353 [(set (pc)
7354 (if_then_else (match_operator 3 "equality_operator"
7355 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7356 (const_int 0)])
7357 (label_ref (match_operand 4 "" ""))
7358 (pc)))
aeac46d4 7359 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7360 (plus:SI (match_dup 2) (const_int -1)))
7361 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7362 "TARGET_THUMB1"
203c488f 7363 "*
7364 {
7365 rtx cond[2];
7366 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7367 ? GEU : LTU),
58d6528b 7368 VOIDmode, operands[2], const1_rtx);
203c488f 7369 cond[1] = operands[4];
7370
7371 if (which_alternative == 0)
7372 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7373 else if (which_alternative == 1)
7374 {
7375 /* We must provide an alternative for a hi reg because reload
7376 cannot handle output reloads on a jump instruction, but we
7377 can't subtract into that. Fortunately a mov from lo to hi
7378 does not clobber the condition codes. */
7379 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7380 output_asm_insn (\"mov\\t%0, %1\", operands);
7381 }
7382 else
7383 {
7384 /* Similarly, but the target is memory. */
7385 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7386 output_asm_insn (\"str\\t%1, %0\", operands);
7387 }
7388
7389 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7390 {
7391 case 4:
8aea555f 7392 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7393 return \"\";
7394 case 6:
8aea555f 7395 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7396 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7397 default:
8aea555f 7398 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7399 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7400 }
7401 }
7402 "
7403 [(set (attr "far_jump")
7404 (if_then_else
7405 (ior (and (eq (symbol_ref ("which_alternative"))
7406 (const_int 0))
7407 (eq_attr "length" "8"))
7408 (eq_attr "length" "10"))
7409 (const_string "yes")
7410 (const_string "no")))
7411 (set_attr_alternative "length"
7412 [
7413 ;; Alternative 0
7414 (if_then_else
7415 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7416 (le (minus (match_dup 4) (pc)) (const_int 256)))
7417 (const_int 4)
7418 (if_then_else
7419 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7420 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7421 (const_int 6)
7422 (const_int 8)))
7423 ;; Alternative 1
7424 (if_then_else
7425 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7426 (le (minus (match_dup 4) (pc)) (const_int 256)))
7427 (const_int 6)
7428 (if_then_else
7429 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7430 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7431 (const_int 8)
7432 (const_int 10)))
7433 ;; Alternative 2
7434 (if_then_else
7435 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7436 (le (minus (match_dup 4) (pc)) (const_int 256)))
7437 (const_int 6)
7438 (if_then_else
7439 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7440 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7441 (const_int 8)
7442 (const_int 10)))
7443 ;; Alternative 3
7444 (if_then_else
7445 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7446 (le (minus (match_dup 4) (pc)) (const_int 256)))
7447 (const_int 6)
7448 (if_then_else
7449 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7450 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7451 (const_int 8)
7452 (const_int 10)))])]
7453)
cffb2a26 7454
58d6528b 7455(define_insn "*addsi3_cbranch"
7456 [(set (pc)
7457 (if_then_else
b0694be0 7458 (match_operator 4 "arm_comparison_operator"
58d6528b 7459 [(plus:SI
e54011cb 7460 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7461 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 7462 (const_int 0)])
7463 (label_ref (match_operand 5 "" ""))
7464 (pc)))
aeac46d4 7465 (set
7466 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7467 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 7468 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 7469 "TARGET_THUMB1
58d6528b 7470 && (GET_CODE (operands[4]) == EQ
7471 || GET_CODE (operands[4]) == NE
7472 || GET_CODE (operands[4]) == GE
7473 || GET_CODE (operands[4]) == LT)"
7474 "*
7475 {
7476 rtx cond[3];
7477
956a6170 7478 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 7479 cond[1] = operands[2];
7480 cond[2] = operands[3];
7481
0438d37f 7482 if (CONST_INT_P (cond[2]) && INTVAL (cond[2]) < 0)
58d6528b 7483 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7484 else
7485 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7486
956a6170 7487 if (which_alternative >= 2
58d6528b 7488 && which_alternative < 4)
7489 output_asm_insn (\"mov\\t%0, %1\", operands);
7490 else if (which_alternative >= 4)
7491 output_asm_insn (\"str\\t%1, %0\", operands);
7492
d0f6c30d 7493 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 7494 {
7495 case 4:
7496 return \"b%d4\\t%l5\";
7497 case 6:
7498 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7499 default:
7500 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7501 }
7502 }
7503 "
7504 [(set (attr "far_jump")
7505 (if_then_else
7506 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7507 (const_int 2))
58d6528b 7508 (eq_attr "length" "8"))
7509 (eq_attr "length" "10"))
7510 (const_string "yes")
7511 (const_string "no")))
7512 (set (attr "length")
7513 (if_then_else
7514 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7515 (const_int 2))
58d6528b 7516 (if_then_else
7517 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7518 (le (minus (match_dup 5) (pc)) (const_int 256)))
7519 (const_int 4)
7520 (if_then_else
7521 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7522 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7523 (const_int 6)
7524 (const_int 8)))
7525 (if_then_else
7526 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7527 (le (minus (match_dup 5) (pc)) (const_int 256)))
7528 (const_int 6)
7529 (if_then_else
7530 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7531 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7532 (const_int 8)
7533 (const_int 10)))))]
7534)
7535
7536(define_insn "*addsi3_cbranch_scratch"
7537 [(set (pc)
7538 (if_then_else
b0694be0 7539 (match_operator 3 "arm_comparison_operator"
58d6528b 7540 [(plus:SI
7541 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7542 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7543 (const_int 0)])
7544 (label_ref (match_operand 4 "" ""))
7545 (pc)))
7546 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7547 "TARGET_THUMB1
58d6528b 7548 && (GET_CODE (operands[3]) == EQ
7549 || GET_CODE (operands[3]) == NE
7550 || GET_CODE (operands[3]) == GE
7551 || GET_CODE (operands[3]) == LT)"
7552 "*
7553 {
7554 switch (which_alternative)
7555 {
7556 case 0:
7557 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7558 break;
7559 case 1:
7560 output_asm_insn (\"cmn\t%1, %2\", operands);
7561 break;
0f5e9701 7562 case 2:
3a445a04 7563 if (INTVAL (operands[2]) < 0)
7564 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7565 else
7566 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7567 break;
0f5e9701 7568 case 3:
3a445a04 7569 if (INTVAL (operands[2]) < 0)
7570 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7571 else
7572 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7573 break;
7574 }
7575
7576 switch (get_attr_length (insn))
7577 {
7578 case 4:
7579 return \"b%d3\\t%l4\";
7580 case 6:
7581 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7582 default:
7583 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7584 }
7585 }
7586 "
7587 [(set (attr "far_jump")
7588 (if_then_else
7589 (eq_attr "length" "8")
7590 (const_string "yes")
7591 (const_string "no")))
7592 (set (attr "length")
7593 (if_then_else
7594 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7595 (le (minus (match_dup 4) (pc)) (const_int 256)))
7596 (const_int 4)
7597 (if_then_else
7598 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7599 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7600 (const_int 6)
7601 (const_int 8))))]
7602)
7603
58d6528b 7604
9c08d1fa 7605;; Comparison and test insns
7606
cffb2a26 7607(define_insn "*arm_cmpsi_insn"
bd5b4116 7608 [(set (reg:CC CC_REGNUM)
a6864a24 7609 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7610 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
25f905c2 7611 "TARGET_32BIT"
5565501b 7612 "@
a6864a24 7613 cmp%?\\t%0, %1
7614 cmp%?\\t%0, %1
aea4c774 7615 cmp%?\\t%0, %1
7616 cmn%?\\t%0, #%n1"
a6864a24 7617 [(set_attr "conds" "set")
7618 (set_attr "arch" "t2,t2,any,any")
596e5e8f 7619 (set_attr "length" "2,2,4,4")
7620 (set_attr "predicable" "yes")]
cffb2a26 7621)
b11cae9e 7622
d5d4dc8d 7623(define_insn "*cmpsi_shiftsi"
bd5b4116 7624 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7625 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7626 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7627 [(match_operand:SI 1 "s_register_operand" "r,r")
7628 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7629 "TARGET_32BIT"
aea4c774 7630 "cmp%?\\t%0, %1%S3"
344495ea 7631 [(set_attr "conds" "set")
331beb1a 7632 (set_attr "shift" "1")
d5d4dc8d 7633 (set_attr "arch" "32,a")
7634 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7635
d5d4dc8d 7636(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7637 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7638 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7639 [(match_operand:SI 1 "s_register_operand" "r,r")
7640 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7641 (match_operand:SI 0 "s_register_operand" "r,r")))]
7642 "TARGET_32BIT"
aea4c774 7643 "cmp%?\\t%0, %1%S3"
344495ea 7644 [(set_attr "conds" "set")
331beb1a 7645 (set_attr "shift" "1")
d5d4dc8d 7646 (set_attr "arch" "32,a")
7647 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7648
25f905c2 7649(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7650 [(set (reg:CC_Z CC_REGNUM)
7651 (compare:CC_Z
7652 (neg:SI (match_operator:SI 1 "shift_operator"
7653 [(match_operand:SI 2 "s_register_operand" "r")
7654 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7655 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7656 "TARGET_ARM"
aed179ae 7657 "cmn%?\\t%0, %2%S1"
344495ea 7658 [(set_attr "conds" "set")
aed179ae 7659 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7660 (const_string "alu_shift")
596e5e8f 7661 (const_string "alu_shift_reg")))
7662 (set_attr "predicable" "yes")]
0d66636f 7663)
b11cae9e 7664
a8045a4f 7665;; DImode comparisons. The generic code generates branches that
7666;; if-conversion can not reduce to a conditional compare, so we do
7667;; that directly.
7668
7669(define_insn "*arm_cmpdi_insn"
7670 [(set (reg:CC_NCV CC_REGNUM)
7671 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7672 (match_operand:DI 1 "arm_di_operand" "rDi")))
7673 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7674 "TARGET_32BIT"
a8045a4f 7675 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7676 [(set_attr "conds" "set")
7677 (set_attr "length" "8")]
7678)
7679
7680(define_insn "*arm_cmpdi_unsigned"
7681 [(set (reg:CC_CZ CC_REGNUM)
7682 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7683 (match_operand:DI 1 "arm_di_operand" "rDi")))]
48a98053 7684 "TARGET_32BIT"
7685 "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
a8045a4f 7686 [(set_attr "conds" "set")
7687 (set_attr "length" "8")]
7688)
7689
7690(define_insn "*arm_cmpdi_zero"
7691 [(set (reg:CC_Z CC_REGNUM)
7692 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7693 (const_int 0)))
7694 (clobber (match_scratch:SI 1 "=r"))]
7695 "TARGET_32BIT"
7696 "orr%.\\t%1, %Q0, %R0"
7697 [(set_attr "conds" "set")]
7698)
7699
7700(define_insn "*thumb_cmpdi_zero"
7701 [(set (reg:CC_Z CC_REGNUM)
7702 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7703 (const_int 0)))
7704 (clobber (match_scratch:SI 1 "=l"))]
7705 "TARGET_THUMB1"
7706 "orr\\t%1, %Q0, %R0"
7707 [(set_attr "conds" "set")
7708 (set_attr "length" "2")]
7709)
7710
9c08d1fa 7711; This insn allows redundant compares to be removed by cse, nothing should
7712; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7713; is deleted later on. The match_dup will match the mode here, so that
7714; mode changes of the condition codes aren't lost by this even though we don't
7715; specify what they are.
7716
8a18b90c 7717(define_insn "*deleted_compare"
9c08d1fa 7718 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7719 "TARGET_32BIT"
40dbec34 7720 "\\t%@ deleted compare"
cffb2a26 7721 [(set_attr "conds" "set")
7722 (set_attr "length" "0")]
7723)
9c08d1fa 7724
7725\f
7726;; Conditional branch insns
7727
74f4459c 7728(define_expand "cbranch_cc"
9c08d1fa 7729 [(set (pc)
74f4459c 7730 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7731 (match_operand 2 "" "")])
7732 (label_ref (match_operand 3 "" ""))
9c08d1fa 7733 (pc)))]
25f905c2 7734 "TARGET_32BIT"
74f4459c 7735 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7736 operands[1], operands[2], NULL_RTX);
74f4459c 7737 operands[2] = const0_rtx;"
8fa3ba89 7738)
7739
7740;;
7741;; Patterns to match conditional branch insns.
7742;;
7743
ffcc986d 7744(define_insn "arm_cond_branch"
9c08d1fa 7745 [(set (pc)
8fa3ba89 7746 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7747 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7748 (label_ref (match_operand 0 "" ""))
7749 (pc)))]
25f905c2 7750 "TARGET_32BIT"
d75350ce 7751 "*
9c08d1fa 7752 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7753 {
7754 arm_ccfsm_state += 2;
7755 return \"\";
7756 }
e2348bcb 7757 return \"b%d1\\t%l0\";
cffb2a26 7758 "
a2cd141b 7759 [(set_attr "conds" "use")
a6864a24 7760 (set_attr "type" "branch")
7761 (set (attr "length")
7762 (if_then_else
0bf497f5 7763 (and (match_test "TARGET_THUMB2")
a6864a24 7764 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7765 (le (minus (match_dup 0) (pc)) (const_int 256))))
7766 (const_int 2)
7767 (const_int 4)))]
cffb2a26 7768)
d75350ce 7769
cffb2a26 7770(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7771 [(set (pc)
8fa3ba89 7772 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7773 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7774 (pc)
7775 (label_ref (match_operand 0 "" ""))))]
25f905c2 7776 "TARGET_32BIT"
d75350ce 7777 "*
9c08d1fa 7778 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7779 {
7780 arm_ccfsm_state += 2;
7781 return \"\";
7782 }
e2348bcb 7783 return \"b%D1\\t%l0\";
cffb2a26 7784 "
a2cd141b 7785 [(set_attr "conds" "use")
a6864a24 7786 (set_attr "type" "branch")
7787 (set (attr "length")
7788 (if_then_else
0bf497f5 7789 (and (match_test "TARGET_THUMB2")
a6864a24 7790 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7791 (le (minus (match_dup 0) (pc)) (const_int 256))))
7792 (const_int 2)
7793 (const_int 4)))]
cffb2a26 7794)
7795
b11cae9e 7796\f
9c08d1fa 7797
7798; scc insns
7799
74f4459c 7800(define_expand "cstore_cc"
7db9af5d 7801 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7802 (match_operator:SI 1 "" [(match_operand 2 "" "")
7803 (match_operand 3 "" "")]))]
25f905c2 7804 "TARGET_32BIT"
74f4459c 7805 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7806 operands[2], operands[3], NULL_RTX);
74f4459c 7807 operands[3] = const0_rtx;"
8fa3ba89 7808)
7809
f7fbdd4a 7810(define_insn "*mov_scc"
9c08d1fa 7811 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7812 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7813 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7814 "TARGET_ARM"
4d61e570 7815 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7816 [(set_attr "conds" "use")
d2a518d1 7817 (set_attr "insn" "mov")
cffb2a26 7818 (set_attr "length" "8")]
7819)
9c08d1fa 7820
f7fbdd4a 7821(define_insn "*mov_negscc"
9c08d1fa 7822 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7823 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7824 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7825 "TARGET_ARM"
4d61e570 7826 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7827 [(set_attr "conds" "use")
d2a518d1 7828 (set_attr "insn" "mov")
cffb2a26 7829 (set_attr "length" "8")]
7830)
9c08d1fa 7831
f7fbdd4a 7832(define_insn "*mov_notscc"
9c08d1fa 7833 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7834 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7835 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7836 "TARGET_ARM"
7d0a3bab 7837 "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7838 [(set_attr "conds" "use")
d2a518d1 7839 (set_attr "insn" "mov")
cffb2a26 7840 (set_attr "length" "8")]
7841)
9c08d1fa 7842
595d88b5 7843(define_expand "cstoresi4"
7844 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7845 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7846 [(match_operand:SI 2 "s_register_operand" "")
7847 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7848 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7849 "{
7850 rtx op3, scratch, scratch2;
7851
74f4459c 7852 if (!TARGET_THUMB1)
7853 {
7854 if (!arm_add_operand (operands[3], SImode))
7855 operands[3] = force_reg (SImode, operands[3]);
7856 emit_insn (gen_cstore_cc (operands[0], operands[1],
7857 operands[2], operands[3]));
7858 DONE;
7859 }
7860
595d88b5 7861 if (operands[3] == const0_rtx)
7862 {
7863 switch (GET_CODE (operands[1]))
7864 {
7865 case EQ:
25f905c2 7866 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7867 break;
7868
7869 case NE:
25f905c2 7870 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7871 break;
7872
7873 case LE:
7874 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7875 NULL_RTX, 0, OPTAB_WIDEN);
7876 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7877 NULL_RTX, 0, OPTAB_WIDEN);
7878 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7879 operands[0], 1, OPTAB_WIDEN);
7880 break;
7881
7882 case GE:
7883 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7884 NULL_RTX, 1);
7885 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7886 NULL_RTX, 1, OPTAB_WIDEN);
7887 break;
7888
7889 case GT:
7890 scratch = expand_binop (SImode, ashr_optab, operands[2],
7891 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7892 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7893 NULL_RTX, 0, OPTAB_WIDEN);
7894 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7895 0, OPTAB_WIDEN);
7896 break;
7897
7898 /* LT is handled by generic code. No need for unsigned with 0. */
7899 default:
7900 FAIL;
7901 }
7902 DONE;
7903 }
7904
7905 switch (GET_CODE (operands[1]))
7906 {
7907 case EQ:
7908 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7909 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7910 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7911 break;
7912
7913 case NE:
7914 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7915 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7916 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7917 break;
7918
7919 case LE:
7920 op3 = force_reg (SImode, operands[3]);
7921
7922 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7923 NULL_RTX, 1, OPTAB_WIDEN);
7924 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7925 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7926 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7927 op3, operands[2]));
7928 break;
7929
7930 case GE:
7931 op3 = operands[3];
25f905c2 7932 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7933 op3 = force_reg (SImode, op3);
7934 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7935 NULL_RTX, 0, OPTAB_WIDEN);
7936 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7937 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7938 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7939 operands[2], op3));
7940 break;
7941
7942 case LEU:
7943 op3 = force_reg (SImode, operands[3]);
7944 scratch = force_reg (SImode, const0_rtx);
25f905c2 7945 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7946 op3, operands[2]));
7947 break;
7948
7949 case GEU:
7950 op3 = operands[3];
25f905c2 7951 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7952 op3 = force_reg (SImode, op3);
7953 scratch = force_reg (SImode, const0_rtx);
25f905c2 7954 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7955 operands[2], op3));
7956 break;
7957
7958 case LTU:
7959 op3 = operands[3];
25f905c2 7960 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7961 op3 = force_reg (SImode, op3);
7962 scratch = gen_reg_rtx (SImode);
408b7ae5 7963 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7964 break;
7965
7966 case GTU:
7967 op3 = force_reg (SImode, operands[3]);
7968 scratch = gen_reg_rtx (SImode);
408b7ae5 7969 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7970 break;
7971
7972 /* No good sequences for GT, LT. */
7973 default:
7974 FAIL;
7975 }
7976 DONE;
7977}")
7978
74f4459c 7979(define_expand "cstoresf4"
7980 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7981 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7982 [(match_operand:SF 2 "s_register_operand" "")
7983 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7984 "TARGET_32BIT && TARGET_HARD_FLOAT"
7985 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7986 operands[2], operands[3])); DONE;"
7987)
7988
7989(define_expand "cstoredf4"
7990 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7991 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7992 [(match_operand:DF 2 "s_register_operand" "")
7993 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7994 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7995 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7996 operands[2], operands[3])); DONE;"
7997)
7998
74f4459c 7999(define_expand "cstoredi4"
8000 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8001 (match_operator:SI 1 "expandable_comparison_operator"
a8045a4f 8002 [(match_operand:DI 2 "cmpdi_operand" "")
8003 (match_operand:DI 3 "cmpdi_operand" "")]))]
8004 "TARGET_32BIT"
8005 "{
a8045a4f 8006 /* We should not have two constants. */
8007 gcc_assert (GET_MODE (operands[2]) == DImode
8008 || GET_MODE (operands[3]) == DImode);
8009
f9aa4160 8010 if (!arm_validize_comparison (&operands[1],
8011 &operands[2],
8012 &operands[3]))
8013 FAIL;
8014 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 8015 operands[3]));
8016 DONE;
8017 }"
74f4459c 8018)
8019
25f905c2 8020(define_expand "cstoresi_eq0_thumb1"
595d88b5 8021 [(parallel
8022 [(set (match_operand:SI 0 "s_register_operand" "")
8023 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8024 (const_int 0)))
8025 (clobber (match_dup:SI 2))])]
25f905c2 8026 "TARGET_THUMB1"
595d88b5 8027 "operands[2] = gen_reg_rtx (SImode);"
8028)
8029
25f905c2 8030(define_expand "cstoresi_ne0_thumb1"
595d88b5 8031 [(parallel
8032 [(set (match_operand:SI 0 "s_register_operand" "")
8033 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8034 (const_int 0)))
8035 (clobber (match_dup:SI 2))])]
25f905c2 8036 "TARGET_THUMB1"
595d88b5 8037 "operands[2] = gen_reg_rtx (SImode);"
8038)
8039
25f905c2 8040(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 8041 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8042 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8043 (const_int 0)))
8044 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 8045 "TARGET_THUMB1"
595d88b5 8046 "@
8047 neg\\t%0, %1\;adc\\t%0, %0, %1
8048 neg\\t%2, %1\;adc\\t%0, %1, %2"
8049 [(set_attr "length" "4")]
8050)
8051
25f905c2 8052(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 8053 [(set (match_operand:SI 0 "s_register_operand" "=l")
8054 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8055 (const_int 0)))
8056 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8057 "TARGET_THUMB1"
595d88b5 8058 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8059 [(set_attr "length" "4")]
8060)
8061
408b7ae5 8062;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 8063(define_insn "cstoresi_nltu_thumb1"
595d88b5 8064 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8065 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8066 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8067 "TARGET_THUMB1"
595d88b5 8068 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8069 [(set_attr "length" "4")]
8070)
8071
408b7ae5 8072(define_insn_and_split "cstoresi_ltu_thumb1"
8073 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8074 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8075 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8076 "TARGET_THUMB1"
8077 "#"
8078 "TARGET_THUMB1"
8079 [(set (match_dup 3)
8080 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8081 (set (match_dup 0) (neg:SI (match_dup 3)))]
8082 "operands[3] = gen_reg_rtx (SImode);"
8083 [(set_attr "length" "4")]
8084)
8085
595d88b5 8086;; Used as part of the expansion of thumb les sequence.
25f905c2 8087(define_insn "thumb1_addsi3_addgeu"
595d88b5 8088 [(set (match_operand:SI 0 "s_register_operand" "=l")
8089 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8090 (match_operand:SI 2 "s_register_operand" "l"))
8091 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8092 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8093 "TARGET_THUMB1"
595d88b5 8094 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8095 [(set_attr "length" "4")]
8096)
8097
9c08d1fa 8098\f
39b5e676 8099;; Conditional move insns
8100
8101(define_expand "movsicc"
8a18b90c 8102 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8103 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 8104 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8105 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8106 "TARGET_32BIT"
39b5e676 8107 "
215b30b3 8108 {
f9aa4160 8109 enum rtx_code code;
278b301d 8110 rtx ccreg;
8111
f9aa4160 8112 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8113 &XEXP (operands[1], 1)))
278b301d 8114 FAIL;
f9aa4160 8115
8116 code = GET_CODE (operands[1]);
74f4459c 8117 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8118 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8119 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8120 }"
8121)
39b5e676 8122
8123(define_expand "movsfcc"
8a18b90c 8124 [(set (match_operand:SF 0 "s_register_operand" "")
aa06947a 8125 (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8126 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 8127 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 8128 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8129 "
215b30b3 8130 {
8131 enum rtx_code code = GET_CODE (operands[1]);
8132 rtx ccreg;
f082f1c4 8133
f9aa4160 8134 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8135 &XEXP (operands[1], 1)))
8136 FAIL;
39b5e676 8137
f9aa4160 8138 code = GET_CODE (operands[1]);
74f4459c 8139 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8140 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8141 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8142 }"
8143)
39b5e676 8144
8145(define_expand "movdfcc"
8a18b90c 8146 [(set (match_operand:DF 0 "s_register_operand" "")
aa06947a 8147 (if_then_else:DF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8148 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 8149 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 8150 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 8151 "
215b30b3 8152 {
8153 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8154 rtx ccreg;
39b5e676 8155
f9aa4160 8156 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8157 &XEXP (operands[1], 1)))
8158 FAIL;
8159 code = GET_CODE (operands[1]);
74f4459c 8160 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8161 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8162 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8163 }"
8164)
39b5e676 8165
8166(define_insn "*movsicc_insn"
f082f1c4 8167 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8168 (if_then_else:SI
8fa3ba89 8169 (match_operator 3 "arm_comparison_operator"
8a18b90c 8170 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8171 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8172 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8173 "TARGET_ARM"
39b5e676 8174 "@
8a18b90c 8175 mov%D3\\t%0, %2
8176 mvn%D3\\t%0, #%B2
f082f1c4 8177 mov%d3\\t%0, %1
8178 mvn%d3\\t%0, #%B1
8a18b90c 8179 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8180 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8181 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8182 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8183 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8184 (set_attr "conds" "use")
8185 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 8186)
39b5e676 8187
39b5e676 8188(define_insn "*movsfcc_soft_insn"
f082f1c4 8189 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8190 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8191 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8192 (match_operand:SF 1 "s_register_operand" "0,r")
8193 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8194 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8195 "@
8196 mov%D3\\t%0, %2
8197 mov%d3\\t%0, %1"
d2a518d1 8198 [(set_attr "conds" "use")
8199 (set_attr "insn" "mov")]
8fa3ba89 8200)
39b5e676 8201
39b5e676 8202\f
9c08d1fa 8203;; Jump and linkage insns
8204
cffb2a26 8205(define_expand "jump"
9c08d1fa 8206 [(set (pc)
8207 (label_ref (match_operand 0 "" "")))]
cffb2a26 8208 "TARGET_EITHER"
9c08d1fa 8209 ""
cffb2a26 8210)
8211
8212(define_insn "*arm_jump"
8213 [(set (pc)
8214 (label_ref (match_operand 0 "" "")))]
25f905c2 8215 "TARGET_32BIT"
9c08d1fa 8216 "*
0d66636f 8217 {
8218 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8219 {
8220 arm_ccfsm_state += 2;
8221 return \"\";
8222 }
8223 return \"b%?\\t%l0\";
8224 }
8225 "
a6864a24 8226 [(set_attr "predicable" "yes")
8227 (set (attr "length")
8228 (if_then_else
0bf497f5 8229 (and (match_test "TARGET_THUMB2")
a6864a24 8230 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8231 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8232 (const_int 2)
8233 (const_int 4)))]
0d66636f 8234)
9c08d1fa 8235
cffb2a26 8236(define_insn "*thumb_jump"
8237 [(set (pc)
8238 (label_ref (match_operand 0 "" "")))]
25f905c2 8239 "TARGET_THUMB1"
cffb2a26 8240 "*
8241 if (get_attr_length (insn) == 2)
8242 return \"b\\t%l0\";
8243 return \"bl\\t%l0\\t%@ far jump\";
8244 "
8245 [(set (attr "far_jump")
8246 (if_then_else
8247 (eq_attr "length" "4")
8248 (const_string "yes")
8249 (const_string "no")))
8250 (set (attr "length")
8251 (if_then_else
911ed8af 8252 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8253 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8254 (const_int 2)
8255 (const_int 4)))]
8256)
8257
d3373b54 8258(define_expand "call"
8259 [(parallel [(call (match_operand 0 "memory_operand" "")
8260 (match_operand 1 "general_operand" ""))
cffb2a26 8261 (use (match_operand 2 "" ""))
bd5b4116 8262 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8263 "TARGET_EITHER"
6c4c2133 8264 "
8265 {
bac7fc85 8266 rtx callee, pat;
bbe777ea 8267
bbe777ea 8268 /* In an untyped call, we can get NULL for operand 2. */
8269 if (operands[2] == NULL_RTX)
8270 operands[2] = const0_rtx;
8271
de55252a 8272 /* Decide if we should generate indirect calls by loading the
85c36fd1 8273 32-bit address of the callee into a register before performing the
de55252a 8274 branch and link. */
8275 callee = XEXP (operands[0], 0);
8276 if (GET_CODE (callee) == SYMBOL_REF
8277 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8278 : !REG_P (callee))
bbe777ea 8279 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8280
8281 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8282 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8283 DONE;
6c4c2133 8284 }"
8285)
d3373b54 8286
bac7fc85 8287(define_expand "call_internal"
8288 [(parallel [(call (match_operand 0 "memory_operand" "")
8289 (match_operand 1 "general_operand" ""))
8290 (use (match_operand 2 "" ""))
8291 (clobber (reg:SI LR_REGNUM))])])
8292
f1039640 8293(define_insn "*call_reg_armv5"
d3373b54 8294 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8295 (match_operand 1 "" ""))
8296 (use (match_operand 2 "" ""))
bd5b4116 8297 (clobber (reg:SI LR_REGNUM))]
f1039640 8298 "TARGET_ARM && arm_arch5"
8299 "blx%?\\t%0"
8300 [(set_attr "type" "call")]
8301)
8302
8303(define_insn "*call_reg_arm"
8304 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8305 (match_operand 1 "" ""))
8306 (use (match_operand 2 "" ""))
8307 (clobber (reg:SI LR_REGNUM))]
8308 "TARGET_ARM && !arm_arch5"
9c08d1fa 8309 "*
5565501b 8310 return output_call (operands);
cffb2a26 8311 "
8312 ;; length is worst case, normally it is only two
8313 [(set_attr "length" "12")
8314 (set_attr "type" "call")]
8315)
9c08d1fa 8316
89504fc1 8317
8318;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8319;; considered a function call by the branch predictor of some cores (PR40887).
8320;; Falls back to blx rN (*call_reg_armv5).
8321
f7fbdd4a 8322(define_insn "*call_mem"
a3c63a9d 8323 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8324 (match_operand 1 "" ""))
8325 (use (match_operand 2 "" ""))
bd5b4116 8326 (clobber (reg:SI LR_REGNUM))]
89504fc1 8327 "TARGET_ARM && !arm_arch5"
9c08d1fa 8328 "*
5565501b 8329 return output_call_mem (operands);
cffb2a26 8330 "
8331 [(set_attr "length" "12")
8332 (set_attr "type" "call")]
8333)
8334
25f905c2 8335(define_insn "*call_reg_thumb1_v5"
cffb2a26 8336 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8337 (match_operand 1 "" ""))
8338 (use (match_operand 2 "" ""))
bd5b4116 8339 (clobber (reg:SI LR_REGNUM))]
25f905c2 8340 "TARGET_THUMB1 && arm_arch5"
f1039640 8341 "blx\\t%0"
8342 [(set_attr "length" "2")
8343 (set_attr "type" "call")]
cffb2a26 8344)
8345
25f905c2 8346(define_insn "*call_reg_thumb1"
f1039640 8347 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8348 (match_operand 1 "" ""))
8349 (use (match_operand 2 "" ""))
bd5b4116 8350 (clobber (reg:SI LR_REGNUM))]
25f905c2 8351 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8352 "*
8353 {
150502c9 8354 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8355 return thumb_call_via_reg (operands[0]);
150502c9 8356 else if (operands[1] == const0_rtx)
f1039640 8357 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8358 else if (frame_pointer_needed)
8359 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8360 else
150502c9 8361 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8362 }"
8363 [(set_attr "type" "call")]
8364)
9c08d1fa 8365
d3373b54 8366(define_expand "call_value"
e0698af7 8367 [(parallel [(set (match_operand 0 "" "")
8368 (call (match_operand 1 "memory_operand" "")
8369 (match_operand 2 "general_operand" "")))
cffb2a26 8370 (use (match_operand 3 "" ""))
bd5b4116 8371 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8372 "TARGET_EITHER"
6c4c2133 8373 "
8374 {
bac7fc85 8375 rtx pat, callee;
bbe777ea 8376
8377 /* In an untyped call, we can get NULL for operand 2. */
8378 if (operands[3] == 0)
8379 operands[3] = const0_rtx;
8380
de55252a 8381 /* Decide if we should generate indirect calls by loading the
8382 32-bit address of the callee into a register before performing the
8383 branch and link. */
8384 callee = XEXP (operands[1], 0);
8385 if (GET_CODE (callee) == SYMBOL_REF
8386 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8387 : !REG_P (callee))
78fe751b 8388 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8389
8390 pat = gen_call_value_internal (operands[0], operands[1],
8391 operands[2], operands[3]);
8392 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8393 DONE;
6c4c2133 8394 }"
8395)
d3373b54 8396
bac7fc85 8397(define_expand "call_value_internal"
8398 [(parallel [(set (match_operand 0 "" "")
8399 (call (match_operand 1 "memory_operand" "")
8400 (match_operand 2 "general_operand" "")))
8401 (use (match_operand 3 "" ""))
8402 (clobber (reg:SI LR_REGNUM))])])
8403
f1039640 8404(define_insn "*call_value_reg_armv5"
27ed6835 8405 [(set (match_operand 0 "" "")
755eb2b4 8406 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8407 (match_operand 2 "" "")))
bbe777ea 8408 (use (match_operand 3 "" ""))
bd5b4116 8409 (clobber (reg:SI LR_REGNUM))]
f1039640 8410 "TARGET_ARM && arm_arch5"
8411 "blx%?\\t%1"
8412 [(set_attr "type" "call")]
8413)
8414
8415(define_insn "*call_value_reg_arm"
8416 [(set (match_operand 0 "" "")
8417 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8418 (match_operand 2 "" "")))
8419 (use (match_operand 3 "" ""))
8420 (clobber (reg:SI LR_REGNUM))]
8421 "TARGET_ARM && !arm_arch5"
9c08d1fa 8422 "*
215b30b3 8423 return output_call (&operands[1]);
cffb2a26 8424 "
8425 [(set_attr "length" "12")
8426 (set_attr "type" "call")]
8427)
9c08d1fa 8428
89504fc1 8429;; Note: see *call_mem
8430
f7fbdd4a 8431(define_insn "*call_value_mem"
27ed6835 8432 [(set (match_operand 0 "" "")
a3c63a9d 8433 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8434 (match_operand 2 "" "")))
bbe777ea 8435 (use (match_operand 3 "" ""))
bd5b4116 8436 (clobber (reg:SI LR_REGNUM))]
89504fc1 8437 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8438 "*
215b30b3 8439 return output_call_mem (&operands[1]);
cffb2a26 8440 "
8441 [(set_attr "length" "12")
8442 (set_attr "type" "call")]
8443)
9c08d1fa 8444
25f905c2 8445(define_insn "*call_value_reg_thumb1_v5"
f1039640 8446 [(set (match_operand 0 "" "")
8447 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8448 (match_operand 2 "" "")))
8449 (use (match_operand 3 "" ""))
8450 (clobber (reg:SI LR_REGNUM))]
25f905c2 8451 "TARGET_THUMB1 && arm_arch5"
f1039640 8452 "blx\\t%1"
8453 [(set_attr "length" "2")
8454 (set_attr "type" "call")]
8455)
8456
25f905c2 8457(define_insn "*call_value_reg_thumb1"
f1039640 8458 [(set (match_operand 0 "" "")
8459 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8460 (match_operand 2 "" "")))
8461 (use (match_operand 3 "" ""))
8462 (clobber (reg:SI LR_REGNUM))]
25f905c2 8463 "TARGET_THUMB1 && !arm_arch5"
f1039640 8464 "*
8465 {
150502c9 8466 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8467 return thumb_call_via_reg (operands[1]);
150502c9 8468 else if (operands[2] == const0_rtx)
f1039640 8469 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8470 else if (frame_pointer_needed)
8471 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8472 else
150502c9 8473 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8474 }"
8475 [(set_attr "type" "call")]
8476)
8477
9c08d1fa 8478;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8479;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8480
f7fbdd4a 8481(define_insn "*call_symbol"
27ed6835 8482 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8483 (match_operand 1 "" ""))
bbe777ea 8484 (use (match_operand 2 "" ""))
bd5b4116 8485 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8486 "TARGET_32BIT
cffb2a26 8487 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8488 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8489 "*
8490 {
55c1e470 8491 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8492 }"
cffb2a26 8493 [(set_attr "type" "call")]
8494)
9c08d1fa 8495
f7fbdd4a 8496(define_insn "*call_value_symbol"
ccd90aaa 8497 [(set (match_operand 0 "" "")
27ed6835 8498 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8499 (match_operand:SI 2 "" "")))
bbe777ea 8500 (use (match_operand 3 "" ""))
bd5b4116 8501 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8502 "TARGET_32BIT
cffb2a26 8503 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8504 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8505 "*
8506 {
55c1e470 8507 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8508 }"
cffb2a26 8509 [(set_attr "type" "call")]
8510)
8511
8512(define_insn "*call_insn"
27ed6835 8513 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8514 (match_operand:SI 1 "" ""))
8515 (use (match_operand 2 "" ""))
bd5b4116 8516 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8517 "TARGET_THUMB1
1675c6e9 8518 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8519 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8520 "bl\\t%a0"
8521 [(set_attr "length" "4")
8522 (set_attr "type" "call")]
8523)
8524
8525(define_insn "*call_value_insn"
ccd90aaa 8526 [(set (match_operand 0 "" "")
27ed6835 8527 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8528 (match_operand 2 "" "")))
8529 (use (match_operand 3 "" ""))
bd5b4116 8530 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8531 "TARGET_THUMB1
1675c6e9 8532 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8533 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8534 "bl\\t%a1"
8535 [(set_attr "length" "4")
8536 (set_attr "type" "call")]
8537)
9c08d1fa 8538
1c494086 8539;; We may also be able to do sibcalls for Thumb, but it's much harder...
8540(define_expand "sibcall"
8541 [(parallel [(call (match_operand 0 "memory_operand" "")
8542 (match_operand 1 "general_operand" ""))
2ba80634 8543 (return)
8544 (use (match_operand 2 "" ""))])]
d68c2c10 8545 "TARGET_32BIT"
1c494086 8546 "
8547 {
8548 if (operands[2] == NULL_RTX)
8549 operands[2] = const0_rtx;
1c494086 8550 }"
8551)
8552
8553(define_expand "sibcall_value"
ccd90aaa 8554 [(parallel [(set (match_operand 0 "" "")
1c494086 8555 (call (match_operand 1 "memory_operand" "")
8556 (match_operand 2 "general_operand" "")))
2ba80634 8557 (return)
8558 (use (match_operand 3 "" ""))])]
d68c2c10 8559 "TARGET_32BIT"
1c494086 8560 "
8561 {
8562 if (operands[3] == NULL_RTX)
8563 operands[3] = const0_rtx;
1c494086 8564 }"
8565)
8566
8567(define_insn "*sibcall_insn"
8568 [(call (mem:SI (match_operand:SI 0 "" "X"))
8569 (match_operand 1 "" ""))
2ba80634 8570 (return)
8571 (use (match_operand 2 "" ""))]
d68c2c10 8572 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8573 "*
8574 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8575 "
8576 [(set_attr "type" "call")]
8577)
8578
8579(define_insn "*sibcall_value_insn"
ccd90aaa 8580 [(set (match_operand 0 "" "")
755eb2b4 8581 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8582 (match_operand 2 "" "")))
2ba80634 8583 (return)
8584 (use (match_operand 3 "" ""))]
d68c2c10 8585 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8586 "*
8587 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8588 "
8589 [(set_attr "type" "call")]
8590)
8591
d68c2c10 8592(define_expand "return"
8593 [(return)]
8cba51a5 8594 "(TARGET_ARM || (TARGET_THUMB2
8595 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8596 && !IS_STACKALIGN (arm_current_func_type ())))
8597 && USE_RETURN_INSN (FALSE)"
8598 "
8599 {
8600 if (TARGET_THUMB2)
8601 {
8602 thumb2_expand_return ();
8603 DONE;
8604 }
8605 }
8606 "
8607)
d68c2c10 8608
9c08d1fa 8609;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8610(define_insn "*arm_return"
9c08d1fa 8611 [(return)]
cffb2a26 8612 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8613 "*
9c08d1fa 8614 {
cffb2a26 8615 if (arm_ccfsm_state == 2)
8616 {
8617 arm_ccfsm_state += 2;
8618 return \"\";
8619 }
e2549f81 8620 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8621 }"
a2cd141b 8622 [(set_attr "type" "load1")
755eb2b4 8623 (set_attr "length" "12")
0d66636f 8624 (set_attr "predicable" "yes")]
cffb2a26 8625)
9c08d1fa 8626
f7fbdd4a 8627(define_insn "*cond_return"
9c08d1fa 8628 [(set (pc)
8fa3ba89 8629 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8630 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8631 (return)
8632 (pc)))]
cffb2a26 8633 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8634 "*
8fa3ba89 8635 {
8636 if (arm_ccfsm_state == 2)
8637 {
8638 arm_ccfsm_state += 2;
8639 return \"\";
8640 }
e2549f81 8641 return output_return_instruction (operands[0], true, false, false);
8fa3ba89 8642 }"
8643 [(set_attr "conds" "use")
755eb2b4 8644 (set_attr "length" "12")
a2cd141b 8645 (set_attr "type" "load1")]
8fa3ba89 8646)
9c08d1fa 8647
f7fbdd4a 8648(define_insn "*cond_return_inverted"
9c08d1fa 8649 [(set (pc)
8fa3ba89 8650 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8651 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8652 (pc)
8653 (return)))]
cffb2a26 8654 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8655 "*
8fa3ba89 8656 {
8657 if (arm_ccfsm_state == 2)
8658 {
8659 arm_ccfsm_state += 2;
8660 return \"\";
8661 }
e2549f81 8662 return output_return_instruction (operands[0], true, true, false);
8fa3ba89 8663 }"
8664 [(set_attr "conds" "use")
37a1317b 8665 (set_attr "length" "12")
a2cd141b 8666 (set_attr "type" "load1")]
8fa3ba89 8667)
9c08d1fa 8668
e2549f81 8669(define_insn "*arm_simple_return"
8670 [(simple_return)]
8671 "TARGET_ARM"
8672 "*
8673 {
8674 if (arm_ccfsm_state == 2)
8675 {
8676 arm_ccfsm_state += 2;
8677 return \"\";
8678 }
8679 return output_return_instruction (const_true_rtx, true, false, true);
8680 }"
8681 [(set_attr "type" "branch")
8682 (set_attr "length" "4")
8683 (set_attr "predicable" "yes")]
8684)
8685
68121397 8686;; Generate a sequence of instructions to determine if the processor is
8687;; in 26-bit or 32-bit mode, and return the appropriate return address
8688;; mask.
8689
8690(define_expand "return_addr_mask"
8691 [(set (match_dup 1)
8692 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8693 (const_int 0)))
8694 (set (match_operand:SI 0 "s_register_operand" "")
8695 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8696 (const_int -1)
8697 (const_int 67108860)))] ; 0x03fffffc
8698 "TARGET_ARM"
8699 "
62eddbd4 8700 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8701 ")
8702
8703(define_insn "*check_arch2"
8704 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8705 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8706 (const_int 0)))]
8707 "TARGET_ARM"
8708 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8709 [(set_attr "length" "8")
8710 (set_attr "conds" "set")]
8711)
8712
9c08d1fa 8713;; Call subroutine returning any type.
8714
8715(define_expand "untyped_call"
8716 [(parallel [(call (match_operand 0 "" "")
8717 (const_int 0))
8718 (match_operand 1 "" "")
8719 (match_operand 2 "" "")])]
ccd90aaa 8720 "TARGET_EITHER"
9c08d1fa 8721 "
215b30b3 8722 {
8723 int i;
ccd90aaa 8724 rtx par = gen_rtx_PARALLEL (VOIDmode,
8725 rtvec_alloc (XVECLEN (operands[2], 0)));
8726 rtx addr = gen_reg_rtx (Pmode);
8727 rtx mem;
8728 int size = 0;
9c08d1fa 8729
ccd90aaa 8730 emit_move_insn (addr, XEXP (operands[1], 0));
8731 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8732
215b30b3 8733 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8734 {
ccd90aaa 8735 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8736
ccd90aaa 8737 /* Default code only uses r0 as a return value, but we could
8738 be using anything up to 4 registers. */
8739 if (REGNO (src) == R0_REGNUM)
8740 src = gen_rtx_REG (TImode, R0_REGNUM);
8741
8742 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8743 GEN_INT (size));
8744 size += GET_MODE_SIZE (GET_MODE (src));
8745 }
8746
8747 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8748 const0_rtx));
8749
8750 size = 0;
8751
8752 for (i = 0; i < XVECLEN (par, 0); i++)
8753 {
8754 HOST_WIDE_INT offset = 0;
8755 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8756
8757 if (size != 0)
29c05e22 8758 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8759
8760 mem = change_address (mem, GET_MODE (reg), NULL);
8761 if (REGNO (reg) == R0_REGNUM)
8762 {
8763 /* On thumb we have to use a write-back instruction. */
320ea44d 8764 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8765 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8766 size = TARGET_ARM ? 16 : 0;
8767 }
8768 else
8769 {
8770 emit_move_insn (mem, reg);
8771 size = GET_MODE_SIZE (GET_MODE (reg));
8772 }
215b30b3 8773 }
9c08d1fa 8774
215b30b3 8775 /* The optimizer does not know that the call sets the function value
8776 registers we stored in the result block. We avoid problems by
8777 claiming that all hard registers are used and clobbered at this
8778 point. */
8779 emit_insn (gen_blockage ());
8780
8781 DONE;
8782 }"
8783)
9c08d1fa 8784
ccd90aaa 8785(define_expand "untyped_return"
8786 [(match_operand:BLK 0 "memory_operand" "")
8787 (match_operand 1 "" "")]
8788 "TARGET_EITHER"
8789 "
8790 {
8791 int i;
8792 rtx addr = gen_reg_rtx (Pmode);
8793 rtx mem;
8794 int size = 0;
8795
8796 emit_move_insn (addr, XEXP (operands[0], 0));
8797 mem = change_address (operands[0], BLKmode, addr);
8798
8799 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8800 {
8801 HOST_WIDE_INT offset = 0;
8802 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8803
8804 if (size != 0)
29c05e22 8805 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8806
8807 mem = change_address (mem, GET_MODE (reg), NULL);
8808 if (REGNO (reg) == R0_REGNUM)
8809 {
8810 /* On thumb we have to use a write-back instruction. */
320ea44d 8811 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8812 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8813 size = TARGET_ARM ? 16 : 0;
8814 }
8815 else
8816 {
8817 emit_move_insn (reg, mem);
8818 size = GET_MODE_SIZE (GET_MODE (reg));
8819 }
8820 }
8821
8822 /* Emit USE insns before the return. */
8823 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8824 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8825
8826 /* Construct the return. */
8827 expand_naked_return ();
8828
8829 DONE;
8830 }"
8831)
8832
9c08d1fa 8833;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8834;; all of memory. This blocks insns from being moved across this point.
8835
8836(define_insn "blockage"
e1159bbe 8837 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8838 "TARGET_EITHER"
9c08d1fa 8839 ""
cffb2a26 8840 [(set_attr "length" "0")
8841 (set_attr "type" "block")]
8842)
9c08d1fa 8843
f7fbdd4a 8844(define_expand "casesi"
8845 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8846 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8847 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8848 (match_operand:SI 3 "" "") ; table label
8849 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8850 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8851 "
215b30b3 8852 {
e6ac8414 8853 enum insn_code code;
215b30b3 8854 if (operands[1] != const0_rtx)
8855 {
e6ac8414 8856 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8857
215b30b3 8858 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8859 gen_int_mode (-INTVAL (operands[1]),
8860 SImode)));
215b30b3 8861 operands[0] = reg;
8862 }
9c08d1fa 8863
25f905c2 8864 if (TARGET_ARM)
e6ac8414 8865 code = CODE_FOR_arm_casesi_internal;
3db2019b 8866 else if (TARGET_THUMB1)
e6ac8414 8867 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8868 else if (flag_pic)
e6ac8414 8869 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8870 else
e6ac8414 8871 code = CODE_FOR_thumb2_casesi_internal;
8872
8873 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8874 operands[2] = force_reg (SImode, operands[2]);
8875
8876 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8877 operands[3], operands[4]));
215b30b3 8878 DONE;
8879 }"
8880)
f7fbdd4a 8881
f082f1c4 8882;; The USE in this pattern is needed to tell flow analysis that this is
8883;; a CASESI insn. It has no other purpose.
25f905c2 8884(define_insn "arm_casesi_internal"
f082f1c4 8885 [(parallel [(set (pc)
8886 (if_then_else
8887 (leu (match_operand:SI 0 "s_register_operand" "r")
8888 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8889 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8890 (label_ref (match_operand 2 "" ""))))
8891 (label_ref (match_operand 3 "" ""))))
bd5b4116 8892 (clobber (reg:CC CC_REGNUM))
f082f1c4 8893 (use (label_ref (match_dup 2)))])]
cffb2a26 8894 "TARGET_ARM"
f7fbdd4a 8895 "*
0d66636f 8896 if (flag_pic)
8897 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8898 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8899 "
8900 [(set_attr "conds" "clob")
8901 (set_attr "length" "12")]
8902)
9c08d1fa 8903
e6ac8414 8904(define_expand "thumb1_casesi_internal_pic"
8905 [(match_operand:SI 0 "s_register_operand" "")
8906 (match_operand:SI 1 "thumb1_cmp_operand" "")
8907 (match_operand 2 "" "")
8908 (match_operand 3 "" "")]
3db2019b 8909 "TARGET_THUMB1"
e6ac8414 8910 {
8911 rtx reg0;
8912 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8913 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8914 operands[3]));
8915 reg0 = gen_rtx_REG (SImode, 0);
8916 emit_move_insn (reg0, operands[0]);
8917 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8918 DONE;
8919 }
8920)
8921
8922(define_insn "thumb1_casesi_dispatch"
8923 [(parallel [(set (pc) (unspec [(reg:SI 0)
8924 (label_ref (match_operand 0 "" ""))
8925;; (label_ref (match_operand 1 "" ""))
8926]
8927 UNSPEC_THUMB1_CASESI))
8928 (clobber (reg:SI IP_REGNUM))
8929 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8930 "TARGET_THUMB1"
e6ac8414 8931 "* return thumb1_output_casesi(operands);"
8932 [(set_attr "length" "4")]
8933)
8934
cffb2a26 8935(define_expand "indirect_jump"
9c08d1fa 8936 [(set (pc)
cffb2a26 8937 (match_operand:SI 0 "s_register_operand" ""))]
8938 "TARGET_EITHER"
25f905c2 8939 "
8940 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8941 address and use bx. */
8942 if (TARGET_THUMB2)
8943 {
8944 rtx tmp;
8945 tmp = gen_reg_rtx (SImode);
8946 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8947 operands[0] = tmp;
8948 }
8949 "
cffb2a26 8950)
8951
f1039640 8952;; NB Never uses BX.
cffb2a26 8953(define_insn "*arm_indirect_jump"
8954 [(set (pc)
8955 (match_operand:SI 0 "s_register_operand" "r"))]
8956 "TARGET_ARM"
8957 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8958 [(set_attr "predicable" "yes")]
cffb2a26 8959)
9c08d1fa 8960
f7fbdd4a 8961(define_insn "*load_indirect_jump"
9c08d1fa 8962 [(set (pc)
8963 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8964 "TARGET_ARM"
8965 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8966 [(set_attr "type" "load1")
61a2d04c 8967 (set_attr "pool_range" "4096")
8968 (set_attr "neg_pool_range" "4084")
0d66636f 8969 (set_attr "predicable" "yes")]
cffb2a26 8970)
8971
f1039640 8972;; NB Never uses BX.
25f905c2 8973(define_insn "*thumb1_indirect_jump"
cffb2a26 8974 [(set (pc)
8975 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8976 "TARGET_THUMB1"
cffb2a26 8977 "mov\\tpc, %0"
8978 [(set_attr "conds" "clob")
8979 (set_attr "length" "2")]
8980)
8981
9c08d1fa 8982\f
8983;; Misc insns
8984
8985(define_insn "nop"
8986 [(const_int 0)]
cffb2a26 8987 "TARGET_EITHER"
8988 "*
25f905c2 8989 if (TARGET_UNIFIED_ASM)
8990 return \"nop\";
cffb2a26 8991 if (TARGET_ARM)
8992 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8993 return \"mov\\tr8, r8\";
8994 "
8995 [(set (attr "length")
8996 (if_then_else (eq_attr "is_thumb" "yes")
8997 (const_int 2)
8998 (const_int 4)))]
8999)
9000
9c08d1fa 9001\f
9002;; Patterns to allow combination of arithmetic, cond code and shifts
9003
f7fbdd4a 9004(define_insn "*arith_shiftsi"
7392680c 9005 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9c08d1fa 9006 (match_operator:SI 1 "shiftable_operator"
9007 [(match_operator:SI 3 "shift_operator"
7392680c 9008 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
9009 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
9010 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
d5d4dc8d 9011 "TARGET_32BIT"
6c4c2133 9012 "%i1%?\\t%0, %2, %4%S3"
344495ea 9013 [(set_attr "predicable" "yes")
331beb1a 9014 (set_attr "shift" "4")
7392680c 9015 (set_attr "arch" "a,t2,t2,a")
9016 ;; Thumb2 doesn't allow the stack pointer to be used for
9017 ;; operand1 for all operations other than add and sub. In this case
9018 ;; the minus operation is a candidate for an rsub and hence needs
9019 ;; to be disabled.
9020 ;; We have to make sure to disable the fourth alternative if
d5d4dc8d 9021 ;; the shift_operator is MULT, since otherwise the insn will
9022 ;; also match a multiply_accumulate pattern and validate_change
9023 ;; will allow a replacement of the constant with a register
9024 ;; despite the checks done in shift_operator.
9025 (set_attr_alternative "insn_enabled"
9026 [(const_string "yes")
7392680c 9027 (if_then_else
9028 (match_operand:SI 1 "add_operator" "")
9029 (const_string "yes") (const_string "no"))
9030 (const_string "yes")
d5d4dc8d 9031 (if_then_else
9032 (match_operand:SI 3 "mult_operator" "")
9033 (const_string "no") (const_string "yes"))])
7392680c 9034 (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
9c08d1fa 9035
d7863cfe 9036(define_split
9037 [(set (match_operand:SI 0 "s_register_operand" "")
9038 (match_operator:SI 1 "shiftable_operator"
9039 [(match_operator:SI 2 "shiftable_operator"
9040 [(match_operator:SI 3 "shift_operator"
9041 [(match_operand:SI 4 "s_register_operand" "")
9042 (match_operand:SI 5 "reg_or_int_operand" "")])
9043 (match_operand:SI 6 "s_register_operand" "")])
9044 (match_operand:SI 7 "arm_rhs_operand" "")]))
9045 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 9046 "TARGET_32BIT"
d7863cfe 9047 [(set (match_dup 8)
9048 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9049 (match_dup 6)]))
9050 (set (match_dup 0)
9051 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9052 "")
9053
f7fbdd4a 9054(define_insn "*arith_shiftsi_compare0"
bd5b4116 9055 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9056 (compare:CC_NOOV
9057 (match_operator:SI 1 "shiftable_operator"
9058 [(match_operator:SI 3 "shift_operator"
9059 [(match_operand:SI 4 "s_register_operand" "r,r")
9060 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9061 (match_operand:SI 2 "s_register_operand" "r,r")])
9062 (const_int 0)))
9063 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 9064 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9065 (match_dup 2)]))]
d5d4dc8d 9066 "TARGET_32BIT"
25f905c2 9067 "%i1%.\\t%0, %2, %4%S3"
344495ea 9068 [(set_attr "conds" "set")
331beb1a 9069 (set_attr "shift" "4")
d5d4dc8d 9070 (set_attr "arch" "32,a")
9071 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9072
f7fbdd4a 9073(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9074 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9075 (compare:CC_NOOV
9076 (match_operator:SI 1 "shiftable_operator"
9077 [(match_operator:SI 3 "shift_operator"
9078 [(match_operand:SI 4 "s_register_operand" "r,r")
9079 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9080 (match_operand:SI 2 "s_register_operand" "r,r")])
9081 (const_int 0)))
9082 (clobber (match_scratch:SI 0 "=r,r"))]
9083 "TARGET_32BIT"
25f905c2 9084 "%i1%.\\t%0, %2, %4%S3"
344495ea 9085 [(set_attr "conds" "set")
331beb1a 9086 (set_attr "shift" "4")
d5d4dc8d 9087 (set_attr "arch" "32,a")
9088 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9089
f7fbdd4a 9090(define_insn "*sub_shiftsi"
d5d4dc8d 9091 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9092 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 9093 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9094 [(match_operand:SI 3 "s_register_operand" "r,r")
9095 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9096 "TARGET_32BIT"
6c4c2133 9097 "sub%?\\t%0, %1, %3%S2"
344495ea 9098 [(set_attr "predicable" "yes")
331beb1a 9099 (set_attr "shift" "3")
d5d4dc8d 9100 (set_attr "arch" "32,a")
9101 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9102
f7fbdd4a 9103(define_insn "*sub_shiftsi_compare0"
bd5b4116 9104 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9105 (compare:CC_NOOV
d5d4dc8d 9106 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9107 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9108 [(match_operand:SI 3 "s_register_operand" "r,r")
9109 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9110 (const_int 0)))
d5d4dc8d 9111 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9112 (minus:SI (match_dup 1)
9113 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9114 "TARGET_32BIT"
25f905c2 9115 "sub%.\\t%0, %1, %3%S2"
344495ea 9116 [(set_attr "conds" "set")
a2cd141b 9117 (set_attr "shift" "3")
d5d4dc8d 9118 (set_attr "arch" "32,a")
9119 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9120
f7fbdd4a 9121(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9122 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9123 (compare:CC_NOOV
d5d4dc8d 9124 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9125 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9126 [(match_operand:SI 3 "s_register_operand" "r,r")
9127 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9128 (const_int 0)))
d5d4dc8d 9129 (clobber (match_scratch:SI 0 "=r,r"))]
9130 "TARGET_32BIT"
25f905c2 9131 "sub%.\\t%0, %1, %3%S2"
344495ea 9132 [(set_attr "conds" "set")
a2cd141b 9133 (set_attr "shift" "3")
d5d4dc8d 9134 (set_attr "arch" "32,a")
9135 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9136\f
9137
f7fbdd4a 9138(define_insn "*and_scc"
9c08d1fa 9139 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9140 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9141 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9142 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9143 "TARGET_ARM"
e2348bcb 9144 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9145 [(set_attr "conds" "use")
d2a518d1 9146 (set_attr "insn" "mov")
8fa3ba89 9147 (set_attr "length" "8")]
9148)
9c08d1fa 9149
f7fbdd4a 9150(define_insn "*ior_scc"
9c08d1fa 9151 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9152 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9153 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9154 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9155 "TARGET_ARM"
e2348bcb 9156 "@
899850b0 9157 orr%d2\\t%0, %1, #1
9158 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9159 [(set_attr "conds" "use")
9160 (set_attr "length" "4,8")]
9161)
9c08d1fa 9162
2df9477b 9163; A series of splitters for the compare_scc pattern below. Note that
9164; order is important.
9165(define_split
9166 [(set (match_operand:SI 0 "s_register_operand" "")
9167 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9168 (const_int 0)))
9169 (clobber (reg:CC CC_REGNUM))]
9170 "TARGET_32BIT && reload_completed"
9171 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9172
9173(define_split
9174 [(set (match_operand:SI 0 "s_register_operand" "")
9175 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9176 (const_int 0)))
9177 (clobber (reg:CC CC_REGNUM))]
9178 "TARGET_32BIT && reload_completed"
9179 [(set (match_dup 0) (not:SI (match_dup 1)))
9180 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9181
9182(define_split
9183 [(set (match_operand:SI 0 "s_register_operand" "")
9184 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9185 (const_int 0)))
9186 (clobber (reg:CC CC_REGNUM))]
9187 "TARGET_32BIT && reload_completed"
9188 [(parallel
080c0b9a 9189 [(set (reg:CC CC_REGNUM)
9190 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9191 (set (match_dup 0)
9192 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9193 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9194 (set (match_dup 0) (const_int 0)))])
9195
9196(define_split
9197 [(set (match_operand:SI 0 "s_register_operand" "")
9198 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9199 (match_operand:SI 2 "const_int_operand" "")))
9200 (clobber (reg:CC CC_REGNUM))]
9201 "TARGET_32BIT && reload_completed"
9202 [(parallel
9203 [(set (reg:CC CC_REGNUM)
9204 (compare:CC (match_dup 1) (match_dup 2)))
9205 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9206 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9207 (set (match_dup 0) (const_int 1)))]
9208{
9209 operands[3] = GEN_INT (-INTVAL (operands[2]));
9210})
9211
9212(define_split
9213 [(set (match_operand:SI 0 "s_register_operand" "")
9214 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9215 (match_operand:SI 2 "arm_add_operand" "")))
9216 (clobber (reg:CC CC_REGNUM))]
9217 "TARGET_32BIT && reload_completed"
9218 [(parallel
9219 [(set (reg:CC_NOOV CC_REGNUM)
9220 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9221 (const_int 0)))
9222 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9223 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9224 (set (match_dup 0) (const_int 1)))])
9225
9226(define_insn_and_split "*compare_scc"
5565501b 9227 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9228 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9229 [(match_operand:SI 2 "s_register_operand" "r,r")
9230 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9231 (clobber (reg:CC CC_REGNUM))]
2df9477b 9232 "TARGET_32BIT"
9233 "#"
9234 "&& reload_completed"
9235 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9236 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9237 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9238{
9239 rtx tmp1;
9240 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9241 operands[2], operands[3]);
9242 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9243
2df9477b 9244 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9245
2df9477b 9246 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9247 if (mode == CCFPmode || mode == CCFPEmode)
9248 rc = reverse_condition_maybe_unordered (rc);
9249 else
9250 rc = reverse_condition (rc);
9251 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9252})
9c08d1fa 9253
080c0b9a 9254;; Attempt to improve the sequence generated by the compare_scc splitters
9255;; not to use conditional execution.
9256(define_peephole2
9257 [(set (reg:CC CC_REGNUM)
9258 (compare:CC (match_operand:SI 1 "register_operand" "")
9259 (match_operand:SI 2 "arm_rhs_operand" "")))
9260 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9261 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9262 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9263 (set (match_dup 0) (const_int 1)))
9264 (match_scratch:SI 3 "r")]
9265 "TARGET_32BIT"
922b6913 9266 [(parallel
9267 [(set (reg:CC CC_REGNUM)
9268 (compare:CC (match_dup 1) (match_dup 2)))
9269 (set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 9270 (parallel
9271 [(set (reg:CC CC_REGNUM)
9272 (compare:CC (const_int 0) (match_dup 3)))
9273 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
922b6913 9274 (parallel
9275 [(set (match_dup 0)
9276 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9277 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))
9278 (clobber (reg:CC CC_REGNUM))])])
080c0b9a 9279
f7fbdd4a 9280(define_insn "*cond_move"
9c08d1fa 9281 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9282 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9283 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9284 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9285 (const_int 0)])
9286 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9287 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9288 "TARGET_ARM"
9c08d1fa 9289 "*
8fa3ba89 9290 if (GET_CODE (operands[3]) == NE)
9291 {
9292 if (which_alternative != 1)
9293 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9294 if (which_alternative != 0)
9295 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9296 return \"\";
9297 }
9298 if (which_alternative != 0)
9299 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9300 if (which_alternative != 1)
9301 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9302 return \"\";
9303 "
9304 [(set_attr "conds" "use")
d2a518d1 9305 (set_attr "insn" "mov")
8fa3ba89 9306 (set_attr "length" "4,4,8")]
9307)
9c08d1fa 9308
f7fbdd4a 9309(define_insn "*cond_arith"
9c08d1fa 9310 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9311 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9312 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9313 [(match_operand:SI 2 "s_register_operand" "r,r")
9314 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9315 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9316 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9317 "TARGET_ARM"
9c08d1fa 9318 "*
8fa3ba89 9319 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9320 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9321
8fa3ba89 9322 output_asm_insn (\"cmp\\t%2, %3\", operands);
9323 if (GET_CODE (operands[5]) == AND)
9324 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9325 else if (GET_CODE (operands[5]) == MINUS)
9326 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9327 else if (which_alternative != 0)
9328 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9329 return \"%i5%d4\\t%0, %1, #1\";
9330 "
9331 [(set_attr "conds" "clob")
9332 (set_attr "length" "12")]
9333)
9c08d1fa 9334
f7fbdd4a 9335(define_insn "*cond_sub"
9c08d1fa 9336 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9337 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9338 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9339 [(match_operand:SI 2 "s_register_operand" "r,r")
9340 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9341 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9342 "TARGET_ARM"
9c08d1fa 9343 "*
8fa3ba89 9344 output_asm_insn (\"cmp\\t%2, %3\", operands);
9345 if (which_alternative != 0)
9346 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9347 return \"sub%d4\\t%0, %1, #1\";
9348 "
9349 [(set_attr "conds" "clob")
9350 (set_attr "length" "8,12")]
9351)
9c08d1fa 9352
aea4c774 9353(define_insn "*cmp_ite0"
cffb2a26 9354 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9355 (compare
9356 (if_then_else:SI
8fa3ba89 9357 (match_operator 4 "arm_comparison_operator"
2ff91fec 9358 [(match_operand:SI 0 "s_register_operand"
9359 "l,l,l,r,r,r,r,r,r")
9360 (match_operand:SI 1 "arm_add_operand"
9361 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9362 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9363 [(match_operand:SI 2 "s_register_operand"
9364 "l,r,r,l,l,r,r,r,r")
9365 (match_operand:SI 3 "arm_add_operand"
9366 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9367 (const_int 0))
9368 (const_int 0)))]
2ff91fec 9369 "TARGET_32BIT"
9c08d1fa 9370 "*
aea4c774 9371 {
2ff91fec 9372 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9373 {
9374 {\"cmp%d5\\t%0, %1\",
9375 \"cmp%d4\\t%2, %3\"},
9376 {\"cmn%d5\\t%0, #%n1\",
9377 \"cmp%d4\\t%2, %3\"},
9378 {\"cmp%d5\\t%0, %1\",
9379 \"cmn%d4\\t%2, #%n3\"},
9380 {\"cmn%d5\\t%0, #%n1\",
9381 \"cmn%d4\\t%2, #%n3\"}
9382 };
9383 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9384 {
9385 {\"cmp\\t%2, %3\",
9386 \"cmp\\t%0, %1\"},
9387 {\"cmp\\t%2, %3\",
9388 \"cmn\\t%0, #%n1\"},
9389 {\"cmn\\t%2, #%n3\",
9390 \"cmp\\t%0, %1\"},
9391 {\"cmn\\t%2, #%n3\",
9392 \"cmn\\t%0, #%n1\"}
9393 };
9394 static const char * const ite[2] =
8fa3ba89 9395 {
2ff91fec 9396 \"it\\t%d5\",
9397 \"it\\t%d4\"
8fa3ba89 9398 };
2ff91fec 9399 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9400 CMP_CMP, CMN_CMP, CMP_CMP,
9401 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9402 int swap =
9403 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9404
2ff91fec 9405 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9406 if (TARGET_THUMB2) {
9407 output_asm_insn (ite[swap], operands);
9408 }
9409 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9410 return \"\";
8fa3ba89 9411 }"
9412 [(set_attr "conds" "set")
2ff91fec 9413 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9414 (set_attr_alternative "length"
9415 [(const_int 6)
9416 (const_int 8)
9417 (const_int 8)
9418 (const_int 8)
9419 (const_int 8)
9420 (if_then_else (eq_attr "is_thumb" "no")
9421 (const_int 8)
9422 (const_int 10))
9423 (if_then_else (eq_attr "is_thumb" "no")
9424 (const_int 8)
9425 (const_int 10))
9426 (if_then_else (eq_attr "is_thumb" "no")
9427 (const_int 8)
9428 (const_int 10))
9429 (if_then_else (eq_attr "is_thumb" "no")
9430 (const_int 8)
9431 (const_int 10))])]
8fa3ba89 9432)
9c08d1fa 9433
aea4c774 9434(define_insn "*cmp_ite1"
cffb2a26 9435 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9436 (compare
9437 (if_then_else:SI
8fa3ba89 9438 (match_operator 4 "arm_comparison_operator"
2ff91fec 9439 [(match_operand:SI 0 "s_register_operand"
9440 "l,l,l,r,r,r,r,r,r")
9441 (match_operand:SI 1 "arm_add_operand"
9442 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9443 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9444 [(match_operand:SI 2 "s_register_operand"
9445 "l,r,r,l,l,r,r,r,r")
9446 (match_operand:SI 3 "arm_add_operand"
9447 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9448 (const_int 1))
9449 (const_int 0)))]
2ff91fec 9450 "TARGET_32BIT"
9c08d1fa 9451 "*
9c08d1fa 9452 {
2ff91fec 9453 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9454 {
9455 {\"cmp\\t%0, %1\",
9456 \"cmp\\t%2, %3\"},
9457 {\"cmn\\t%0, #%n1\",
9458 \"cmp\\t%2, %3\"},
9459 {\"cmp\\t%0, %1\",
9460 \"cmn\\t%2, #%n3\"},
9461 {\"cmn\\t%0, #%n1\",
9462 \"cmn\\t%2, #%n3\"}
9463 };
9464 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9465 {
2ff91fec 9466 {\"cmp%d4\\t%2, %3\",
9467 \"cmp%D5\\t%0, %1\"},
9468 {\"cmp%d4\\t%2, %3\",
9469 \"cmn%D5\\t%0, #%n1\"},
9470 {\"cmn%d4\\t%2, #%n3\",
9471 \"cmp%D5\\t%0, %1\"},
9472 {\"cmn%d4\\t%2, #%n3\",
9473 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9474 };
2ff91fec 9475 static const char * const ite[2] =
9476 {
9477 \"it\\t%d4\",
9478 \"it\\t%D5\"
9479 };
9480 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9481 CMP_CMP, CMN_CMP, CMP_CMP,
9482 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9483 int swap =
9484 comparison_dominates_p (GET_CODE (operands[5]),
9485 reverse_condition (GET_CODE (operands[4])));
9486
2ff91fec 9487 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9488 if (TARGET_THUMB2) {
9489 output_asm_insn (ite[swap], operands);
9490 }
9491 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9492 return \"\";
215b30b3 9493 }"
8fa3ba89 9494 [(set_attr "conds" "set")
2ff91fec 9495 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9496 (set_attr_alternative "length"
9497 [(const_int 6)
9498 (const_int 8)
9499 (const_int 8)
9500 (const_int 8)
9501 (const_int 8)
9502 (if_then_else (eq_attr "is_thumb" "no")
9503 (const_int 8)
9504 (const_int 10))
9505 (if_then_else (eq_attr "is_thumb" "no")
9506 (const_int 8)
9507 (const_int 10))
9508 (if_then_else (eq_attr "is_thumb" "no")
9509 (const_int 8)
9510 (const_int 10))
9511 (if_then_else (eq_attr "is_thumb" "no")
9512 (const_int 8)
9513 (const_int 10))])]
8fa3ba89 9514)
9c08d1fa 9515
f6c53574 9516(define_insn "*cmp_and"
9517 [(set (match_operand 6 "dominant_cc_register" "")
9518 (compare
9519 (and:SI
9520 (match_operator 4 "arm_comparison_operator"
2ff91fec 9521 [(match_operand:SI 0 "s_register_operand"
9522 "l,l,l,r,r,r,r,r,r")
9523 (match_operand:SI 1 "arm_add_operand"
9524 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9525 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9526 [(match_operand:SI 2 "s_register_operand"
9527 "l,r,r,l,l,r,r,r,r")
9528 (match_operand:SI 3 "arm_add_operand"
9529 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9530 (const_int 0)))]
2ff91fec 9531 "TARGET_32BIT"
f6c53574 9532 "*
9533 {
2ff91fec 9534 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9535 {
2ff91fec 9536 {\"cmp%d5\\t%0, %1\",
9537 \"cmp%d4\\t%2, %3\"},
9538 {\"cmn%d5\\t%0, #%n1\",
9539 \"cmp%d4\\t%2, %3\"},
9540 {\"cmp%d5\\t%0, %1\",
9541 \"cmn%d4\\t%2, #%n3\"},
9542 {\"cmn%d5\\t%0, #%n1\",
9543 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9544 };
2ff91fec 9545 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9546 {
9547 {\"cmp\\t%2, %3\",
9548 \"cmp\\t%0, %1\"},
9549 {\"cmp\\t%2, %3\",
9550 \"cmn\\t%0, #%n1\"},
9551 {\"cmn\\t%2, #%n3\",
9552 \"cmp\\t%0, %1\"},
9553 {\"cmn\\t%2, #%n3\",
9554 \"cmn\\t%0, #%n1\"}
9555 };
9556 static const char *const ite[2] =
9557 {
9558 \"it\\t%d5\",
9559 \"it\\t%d4\"
9560 };
9561 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9562 CMP_CMP, CMN_CMP, CMP_CMP,
9563 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9564 int swap =
9565 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9566
2ff91fec 9567 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9568 if (TARGET_THUMB2) {
9569 output_asm_insn (ite[swap], operands);
9570 }
9571 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9572 return \"\";
f6c53574 9573 }"
9574 [(set_attr "conds" "set")
9575 (set_attr "predicable" "no")
2ff91fec 9576 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9577 (set_attr_alternative "length"
9578 [(const_int 6)
9579 (const_int 8)
9580 (const_int 8)
9581 (const_int 8)
9582 (const_int 8)
9583 (if_then_else (eq_attr "is_thumb" "no")
9584 (const_int 8)
9585 (const_int 10))
9586 (if_then_else (eq_attr "is_thumb" "no")
9587 (const_int 8)
9588 (const_int 10))
9589 (if_then_else (eq_attr "is_thumb" "no")
9590 (const_int 8)
9591 (const_int 10))
9592 (if_then_else (eq_attr "is_thumb" "no")
9593 (const_int 8)
9594 (const_int 10))])]
f6c53574 9595)
9596
9597(define_insn "*cmp_ior"
9598 [(set (match_operand 6 "dominant_cc_register" "")
9599 (compare
9600 (ior:SI
9601 (match_operator 4 "arm_comparison_operator"
2ff91fec 9602 [(match_operand:SI 0 "s_register_operand"
9603 "l,l,l,r,r,r,r,r,r")
9604 (match_operand:SI 1 "arm_add_operand"
9605 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9606 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9607 [(match_operand:SI 2 "s_register_operand"
9608 "l,r,r,l,l,r,r,r,r")
9609 (match_operand:SI 3 "arm_add_operand"
9610 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9611 (const_int 0)))]
2ff91fec 9612 "TARGET_32BIT"
f6c53574 9613 "*
f6c53574 9614 {
2ff91fec 9615 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9616 {
9617 {\"cmp\\t%0, %1\",
9618 \"cmp\\t%2, %3\"},
9619 {\"cmn\\t%0, #%n1\",
9620 \"cmp\\t%2, %3\"},
9621 {\"cmp\\t%0, %1\",
9622 \"cmn\\t%2, #%n3\"},
9623 {\"cmn\\t%0, #%n1\",
9624 \"cmn\\t%2, #%n3\"}
9625 };
9626 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9627 {
9628 {\"cmp%D4\\t%2, %3\",
9629 \"cmp%D5\\t%0, %1\"},
9630 {\"cmp%D4\\t%2, %3\",
9631 \"cmn%D5\\t%0, #%n1\"},
9632 {\"cmn%D4\\t%2, #%n3\",
9633 \"cmp%D5\\t%0, %1\"},
9634 {\"cmn%D4\\t%2, #%n3\",
9635 \"cmn%D5\\t%0, #%n1\"}
9636 };
9637 static const char *const ite[2] =
9638 {
9639 \"it\\t%D4\",
9640 \"it\\t%D5\"
9641 };
9642 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9643 CMP_CMP, CMN_CMP, CMP_CMP,
9644 CMN_CMP, CMP_CMN, CMN_CMN};
9645 int swap =
9646 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9647
9648 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9649 if (TARGET_THUMB2) {
9650 output_asm_insn (ite[swap], operands);
9651 }
9652 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9653 return \"\";
9654 }
9655 "
f6c53574 9656 [(set_attr "conds" "set")
2ff91fec 9657 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9658 (set_attr_alternative "length"
9659 [(const_int 6)
9660 (const_int 8)
9661 (const_int 8)
9662 (const_int 8)
9663 (const_int 8)
9664 (if_then_else (eq_attr "is_thumb" "no")
9665 (const_int 8)
9666 (const_int 10))
9667 (if_then_else (eq_attr "is_thumb" "no")
9668 (const_int 8)
9669 (const_int 10))
9670 (if_then_else (eq_attr "is_thumb" "no")
9671 (const_int 8)
9672 (const_int 10))
9673 (if_then_else (eq_attr "is_thumb" "no")
9674 (const_int 8)
9675 (const_int 10))])]
f6c53574 9676)
9677
3c5afce6 9678(define_insn_and_split "*ior_scc_scc"
9679 [(set (match_operand:SI 0 "s_register_operand" "=r")
9680 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9681 [(match_operand:SI 1 "s_register_operand" "r")
9682 (match_operand:SI 2 "arm_add_operand" "rIL")])
9683 (match_operator:SI 6 "arm_comparison_operator"
9684 [(match_operand:SI 4 "s_register_operand" "r")
9685 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9686 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9687 "TARGET_32BIT
3c5afce6 9688 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9689 != CCmode)"
9690 "#"
2ff91fec 9691 "TARGET_32BIT && reload_completed"
3c5afce6 9692 [(set (match_dup 7)
9693 (compare
9694 (ior:SI
9695 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9696 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9697 (const_int 0)))
9698 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9699 "operands[7]
9700 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9701 DOM_CC_X_OR_Y),
601f584c 9702 CC_REGNUM);"
9703 [(set_attr "conds" "clob")
9704 (set_attr "length" "16")])
9705
9706; If the above pattern is followed by a CMP insn, then the compare is
9707; redundant, since we can rework the conditional instruction that follows.
9708(define_insn_and_split "*ior_scc_scc_cmp"
9709 [(set (match_operand 0 "dominant_cc_register" "")
9710 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9711 [(match_operand:SI 1 "s_register_operand" "r")
9712 (match_operand:SI 2 "arm_add_operand" "rIL")])
9713 (match_operator:SI 6 "arm_comparison_operator"
9714 [(match_operand:SI 4 "s_register_operand" "r")
9715 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9716 (const_int 0)))
9717 (set (match_operand:SI 7 "s_register_operand" "=r")
9718 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9719 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9720 "TARGET_32BIT"
601f584c 9721 "#"
2ff91fec 9722 "TARGET_32BIT && reload_completed"
601f584c 9723 [(set (match_dup 0)
9724 (compare
9725 (ior:SI
9726 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9727 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9728 (const_int 0)))
9729 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9730 ""
9731 [(set_attr "conds" "set")
9732 (set_attr "length" "16")])
3c5afce6 9733
9734(define_insn_and_split "*and_scc_scc"
9735 [(set (match_operand:SI 0 "s_register_operand" "=r")
9736 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9737 [(match_operand:SI 1 "s_register_operand" "r")
9738 (match_operand:SI 2 "arm_add_operand" "rIL")])
9739 (match_operator:SI 6 "arm_comparison_operator"
9740 [(match_operand:SI 4 "s_register_operand" "r")
9741 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9742 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9743 "TARGET_32BIT
3c5afce6 9744 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9745 != CCmode)"
9746 "#"
2ff91fec 9747 "TARGET_32BIT && reload_completed
601f584c 9748 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9749 != CCmode)"
3c5afce6 9750 [(set (match_dup 7)
9751 (compare
9752 (and:SI
9753 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9754 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9755 (const_int 0)))
9756 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9757 "operands[7]
9758 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9759 DOM_CC_X_AND_Y),
601f584c 9760 CC_REGNUM);"
9761 [(set_attr "conds" "clob")
9762 (set_attr "length" "16")])
9763
9764; If the above pattern is followed by a CMP insn, then the compare is
9765; redundant, since we can rework the conditional instruction that follows.
9766(define_insn_and_split "*and_scc_scc_cmp"
9767 [(set (match_operand 0 "dominant_cc_register" "")
9768 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9769 [(match_operand:SI 1 "s_register_operand" "r")
9770 (match_operand:SI 2 "arm_add_operand" "rIL")])
9771 (match_operator:SI 6 "arm_comparison_operator"
9772 [(match_operand:SI 4 "s_register_operand" "r")
9773 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9774 (const_int 0)))
9775 (set (match_operand:SI 7 "s_register_operand" "=r")
9776 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9777 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9778 "TARGET_32BIT"
601f584c 9779 "#"
2ff91fec 9780 "TARGET_32BIT && reload_completed"
601f584c 9781 [(set (match_dup 0)
9782 (compare
9783 (and:SI
9784 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9785 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9786 (const_int 0)))
9787 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9788 ""
9789 [(set_attr "conds" "set")
9790 (set_attr "length" "16")])
9791
9792;; If there is no dominance in the comparison, then we can still save an
9793;; instruction in the AND case, since we can know that the second compare
9794;; need only zero the value if false (if true, then the value is already
9795;; correct).
9796(define_insn_and_split "*and_scc_scc_nodom"
9797 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9798 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9799 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9800 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9801 (match_operator:SI 6 "arm_comparison_operator"
9802 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9803 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9804 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9805 "TARGET_32BIT
601f584c 9806 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9807 == CCmode)"
9808 "#"
2ff91fec 9809 "TARGET_32BIT && reload_completed"
601f584c 9810 [(parallel [(set (match_dup 0)
9811 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9812 (clobber (reg:CC CC_REGNUM))])
9813 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9814 (set (match_dup 0)
9815 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9816 (match_dup 0)
9817 (const_int 0)))]
9818 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9819 operands[4], operands[5]),
9820 CC_REGNUM);
9821 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9822 operands[5]);"
9823 [(set_attr "conds" "clob")
9824 (set_attr "length" "20")])
3c5afce6 9825
3a0bdee0 9826(define_split
9827 [(set (reg:CC_NOOV CC_REGNUM)
9828 (compare:CC_NOOV (ior:SI
9829 (and:SI (match_operand:SI 0 "s_register_operand" "")
9830 (const_int 1))
b0694be0 9831 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9832 [(match_operand:SI 2 "s_register_operand" "")
9833 (match_operand:SI 3 "arm_add_operand" "")]))
9834 (const_int 0)))
9835 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9836 "TARGET_ARM"
9837 [(set (match_dup 4)
9838 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9839 (match_dup 0)))
9840 (set (reg:CC_NOOV CC_REGNUM)
9841 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9842 (const_int 0)))]
9843 "")
9844
9845(define_split
9846 [(set (reg:CC_NOOV CC_REGNUM)
9847 (compare:CC_NOOV (ior:SI
b0694be0 9848 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9849 [(match_operand:SI 2 "s_register_operand" "")
9850 (match_operand:SI 3 "arm_add_operand" "")])
9851 (and:SI (match_operand:SI 0 "s_register_operand" "")
9852 (const_int 1)))
9853 (const_int 0)))
9854 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9855 "TARGET_ARM"
9856 [(set (match_dup 4)
9857 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9858 (match_dup 0)))
9859 (set (reg:CC_NOOV CC_REGNUM)
9860 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9861 (const_int 0)))]
9862 "")
25f905c2 9863;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9864
f7fbdd4a 9865(define_insn "*negscc"
9c08d1fa 9866 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9867 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9868 [(match_operand:SI 1 "s_register_operand" "r")
9869 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9870 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9871 "TARGET_ARM"
9c08d1fa 9872 "*
2ca2ec2e 9873 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9874 return \"mov\\t%0, %1, asr #31\";
9875
9c08d1fa 9876 if (GET_CODE (operands[3]) == NE)
e2348bcb 9877 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9878
e2348bcb 9879 output_asm_insn (\"cmp\\t%1, %2\", operands);
9880 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9881 return \"mvn%d3\\t%0, #0\";
215b30b3 9882 "
8fa3ba89 9883 [(set_attr "conds" "clob")
9884 (set_attr "length" "12")]
9885)
9c08d1fa 9886
9887(define_insn "movcond"
9888 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9889 (if_then_else:SI
8fa3ba89 9890 (match_operator 5 "arm_comparison_operator"
5565501b 9891 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9892 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9893 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9894 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9895 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9896 "TARGET_ARM"
9c08d1fa 9897 "*
9898 if (GET_CODE (operands[5]) == LT
9899 && (operands[4] == const0_rtx))
9900 {
0438d37f 9901 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9902 {
9c08d1fa 9903 if (operands[2] == const0_rtx)
e2348bcb 9904 return \"and\\t%0, %1, %3, asr #31\";
9905 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9906 }
0438d37f 9907 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9908 {
9c08d1fa 9909 if (operands[1] == const0_rtx)
e2348bcb 9910 return \"bic\\t%0, %2, %3, asr #31\";
9911 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9912 }
9913 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9914 are constants. */
9c08d1fa 9915 }
e2348bcb 9916
9c08d1fa 9917 if (GET_CODE (operands[5]) == GE
9918 && (operands[4] == const0_rtx))
9919 {
0438d37f 9920 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9921 {
9c08d1fa 9922 if (operands[2] == const0_rtx)
e2348bcb 9923 return \"bic\\t%0, %1, %3, asr #31\";
9924 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9925 }
0438d37f 9926 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9927 {
9c08d1fa 9928 if (operands[1] == const0_rtx)
e2348bcb 9929 return \"and\\t%0, %2, %3, asr #31\";
9930 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9931 }
9932 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9933 are constants. */
9c08d1fa 9934 }
0438d37f 9935 if (CONST_INT_P (operands[4])
9c08d1fa 9936 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9937 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9938 else
e2348bcb 9939 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9940 if (which_alternative != 0)
e2348bcb 9941 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9942 if (which_alternative != 1)
e2348bcb 9943 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9944 return \"\";
215b30b3 9945 "
8fa3ba89 9946 [(set_attr "conds" "clob")
9947 (set_attr "length" "8,8,12")]
9948)
9c08d1fa 9949
25f905c2 9950;; ??? The patterns below need checking for Thumb-2 usefulness.
9951
8a18b90c 9952(define_insn "*ifcompare_plus_move"
9953 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9954 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9955 [(match_operand:SI 4 "s_register_operand" "r,r")
9956 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9957 (plus:SI
9958 (match_operand:SI 2 "s_register_operand" "r,r")
9959 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9960 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9961 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9962 "TARGET_ARM"
8a18b90c 9963 "#"
8fa3ba89 9964 [(set_attr "conds" "clob")
9965 (set_attr "length" "8,12")]
9966)
8a18b90c 9967
9968(define_insn "*if_plus_move"
129a2fe4 9969 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9970 (if_then_else:SI
8fa3ba89 9971 (match_operator 4 "arm_comparison_operator"
8a18b90c 9972 [(match_operand 5 "cc_register" "") (const_int 0)])
9973 (plus:SI
129a2fe4 9974 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9975 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9976 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9977 "TARGET_ARM"
8a18b90c 9978 "@
9979 add%d4\\t%0, %2, %3
9980 sub%d4\\t%0, %2, #%n3
9981 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9982 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9983 [(set_attr "conds" "use")
9984 (set_attr "length" "4,4,8,8")
9985 (set_attr "type" "*,*,*,*")]
9986)
8a18b90c 9987
9988(define_insn "*ifcompare_move_plus"
5565501b 9989 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9990 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9991 [(match_operand:SI 4 "s_register_operand" "r,r")
9992 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9993 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9994 (plus:SI
9995 (match_operand:SI 2 "s_register_operand" "r,r")
9996 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9997 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9998 "TARGET_ARM"
8a18b90c 9999 "#"
8fa3ba89 10000 [(set_attr "conds" "clob")
10001 (set_attr "length" "8,12")]
10002)
8a18b90c 10003
10004(define_insn "*if_move_plus"
129a2fe4 10005 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10006 (if_then_else:SI
8fa3ba89 10007 (match_operator 4 "arm_comparison_operator"
8a18b90c 10008 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10009 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10010 (plus:SI
129a2fe4 10011 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10012 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10013 "TARGET_ARM"
8a18b90c 10014 "@
10015 add%D4\\t%0, %2, %3
10016 sub%D4\\t%0, %2, #%n3
10017 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10018 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10019 [(set_attr "conds" "use")
10020 (set_attr "length" "4,4,8,8")
10021 (set_attr "type" "*,*,*,*")]
10022)
8a18b90c 10023
10024(define_insn "*ifcompare_arith_arith"
10025 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10026 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10027 [(match_operand:SI 5 "s_register_operand" "r")
10028 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10029 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10030 [(match_operand:SI 1 "s_register_operand" "r")
10031 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10032 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10033 [(match_operand:SI 3 "s_register_operand" "r")
10034 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10035 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10036 "TARGET_ARM"
8a18b90c 10037 "#"
8fa3ba89 10038 [(set_attr "conds" "clob")
10039 (set_attr "length" "12")]
10040)
9c08d1fa 10041
8a18b90c 10042(define_insn "*if_arith_arith"
10043 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10044 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10045 [(match_operand 8 "cc_register" "") (const_int 0)])
10046 (match_operator:SI 6 "shiftable_operator"
10047 [(match_operand:SI 1 "s_register_operand" "r")
10048 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10049 (match_operator:SI 7 "shiftable_operator"
10050 [(match_operand:SI 3 "s_register_operand" "r")
10051 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10052 "TARGET_ARM"
8a18b90c 10053 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10054 [(set_attr "conds" "use")
10055 (set_attr "length" "8")]
10056)
8a18b90c 10057
f7fbdd4a 10058(define_insn "*ifcompare_arith_move"
9c08d1fa 10059 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10060 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10061 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10062 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10063 (match_operator:SI 7 "shiftable_operator"
10064 [(match_operand:SI 4 "s_register_operand" "r,r")
10065 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10066 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10067 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10068 "TARGET_ARM"
9c08d1fa 10069 "*
9c08d1fa 10070 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10071 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10072 everything is in registers then we can do this in two instructions. */
9c08d1fa 10073 if (operands[3] == const0_rtx
10074 && GET_CODE (operands[7]) != AND
0438d37f 10075 && REG_P (operands[5])
10076 && REG_P (operands[1])
9c08d1fa 10077 && REGNO (operands[1]) == REGNO (operands[4])
10078 && REGNO (operands[4]) != REGNO (operands[0]))
10079 {
10080 if (GET_CODE (operands[6]) == LT)
40dbec34 10081 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10082 else if (GET_CODE (operands[6]) == GE)
40dbec34 10083 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10084 }
0438d37f 10085 if (CONST_INT_P (operands[3])
9c08d1fa 10086 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10087 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10088 else
e2348bcb 10089 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10090 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10091 if (which_alternative != 0)
129a2fe4 10092 return \"mov%D6\\t%0, %1\";
9c08d1fa 10093 return \"\";
215b30b3 10094 "
8fa3ba89 10095 [(set_attr "conds" "clob")
10096 (set_attr "length" "8,12")]
10097)
9c08d1fa 10098
8a18b90c 10099(define_insn "*if_arith_move"
129a2fe4 10100 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10101 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10102 [(match_operand 6 "cc_register" "") (const_int 0)])
10103 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10104 [(match_operand:SI 2 "s_register_operand" "r,r")
10105 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10106 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10107 "TARGET_ARM"
8a18b90c 10108 "@
10109 %I5%d4\\t%0, %2, %3
129a2fe4 10110 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10111 [(set_attr "conds" "use")
10112 (set_attr "length" "4,8")
10113 (set_attr "type" "*,*")]
10114)
8a18b90c 10115
f7fbdd4a 10116(define_insn "*ifcompare_move_arith"
9c08d1fa 10117 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10118 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10119 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10120 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10121 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10122 (match_operator:SI 7 "shiftable_operator"
10123 [(match_operand:SI 2 "s_register_operand" "r,r")
10124 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10125 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10126 "TARGET_ARM"
9c08d1fa 10127 "*
9c08d1fa 10128 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10129 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10130 everything is in registers then we can do this in two instructions */
10131 if (operands[5] == const0_rtx
10132 && GET_CODE (operands[7]) != AND
0438d37f 10133 && REG_P (operands[3])
10134 && REG_P (operands[1])
9c08d1fa 10135 && REGNO (operands[1]) == REGNO (operands[2])
10136 && REGNO (operands[2]) != REGNO (operands[0]))
10137 {
10138 if (GET_CODE (operands[6]) == GE)
40dbec34 10139 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10140 else if (GET_CODE (operands[6]) == LT)
40dbec34 10141 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10142 }
40dbec34 10143
0438d37f 10144 if (CONST_INT_P (operands[5])
9c08d1fa 10145 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10146 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10147 else
e2348bcb 10148 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10149
9c08d1fa 10150 if (which_alternative != 0)
129a2fe4 10151 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10152 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10153 "
8fa3ba89 10154 [(set_attr "conds" "clob")
10155 (set_attr "length" "8,12")]
10156)
9c08d1fa 10157
8a18b90c 10158(define_insn "*if_move_arith"
129a2fe4 10159 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10160 (if_then_else:SI
8fa3ba89 10161 (match_operator 4 "arm_comparison_operator"
8a18b90c 10162 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10163 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10164 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10165 [(match_operand:SI 2 "s_register_operand" "r,r")
10166 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10167 "TARGET_ARM"
8a18b90c 10168 "@
10169 %I5%D4\\t%0, %2, %3
129a2fe4 10170 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10171 [(set_attr "conds" "use")
10172 (set_attr "length" "4,8")
10173 (set_attr "type" "*,*")]
10174)
8a18b90c 10175
10176(define_insn "*ifcompare_move_not"
9c08d1fa 10177 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10178 (if_then_else:SI
8fa3ba89 10179 (match_operator 5 "arm_comparison_operator"
8a18b90c 10180 [(match_operand:SI 3 "s_register_operand" "r,r")
10181 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10182 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10183 (not:SI
10184 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10185 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10186 "TARGET_ARM"
8a18b90c 10187 "#"
8fa3ba89 10188 [(set_attr "conds" "clob")
10189 (set_attr "length" "8,12")]
10190)
9c08d1fa 10191
8a18b90c 10192(define_insn "*if_move_not"
10193 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10194 (if_then_else:SI
8fa3ba89 10195 (match_operator 4 "arm_comparison_operator"
8a18b90c 10196 [(match_operand 3 "cc_register" "") (const_int 0)])
10197 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10198 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10199 "TARGET_ARM"
8a18b90c 10200 "@
10201 mvn%D4\\t%0, %2
10202 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10203 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10204 [(set_attr "conds" "use")
d2a518d1 10205 (set_attr "insn" "mvn")
8fa3ba89 10206 (set_attr "length" "4,8,8")]
10207)
8a18b90c 10208
10209(define_insn "*ifcompare_not_move"
9c08d1fa 10210 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10211 (if_then_else:SI
8fa3ba89 10212 (match_operator 5 "arm_comparison_operator"
8a18b90c 10213 [(match_operand:SI 3 "s_register_operand" "r,r")
10214 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10215 (not:SI
10216 (match_operand:SI 2 "s_register_operand" "r,r"))
10217 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10218 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10219 "TARGET_ARM"
8a18b90c 10220 "#"
8fa3ba89 10221 [(set_attr "conds" "clob")
10222 (set_attr "length" "8,12")]
10223)
9c08d1fa 10224
8a18b90c 10225(define_insn "*if_not_move"
10226 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10227 (if_then_else:SI
8fa3ba89 10228 (match_operator 4 "arm_comparison_operator"
8a18b90c 10229 [(match_operand 3 "cc_register" "") (const_int 0)])
10230 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10231 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10232 "TARGET_ARM"
8a18b90c 10233 "@
10234 mvn%d4\\t%0, %2
10235 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10236 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10237 [(set_attr "conds" "use")
d2a518d1 10238 (set_attr "insn" "mvn")
8fa3ba89 10239 (set_attr "length" "4,8,8")]
10240)
8a18b90c 10241
10242(define_insn "*ifcompare_shift_move"
9c08d1fa 10243 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10244 (if_then_else:SI
8fa3ba89 10245 (match_operator 6 "arm_comparison_operator"
8a18b90c 10246 [(match_operand:SI 4 "s_register_operand" "r,r")
10247 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10248 (match_operator:SI 7 "shift_operator"
10249 [(match_operand:SI 2 "s_register_operand" "r,r")
10250 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10251 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10252 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10253 "TARGET_ARM"
9c08d1fa 10254 "#"
8fa3ba89 10255 [(set_attr "conds" "clob")
10256 (set_attr "length" "8,12")]
10257)
9c08d1fa 10258
8a18b90c 10259(define_insn "*if_shift_move"
10260 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10261 (if_then_else:SI
8fa3ba89 10262 (match_operator 5 "arm_comparison_operator"
8a18b90c 10263 [(match_operand 6 "cc_register" "") (const_int 0)])
10264 (match_operator:SI 4 "shift_operator"
10265 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10266 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10267 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10268 "TARGET_ARM"
5565501b 10269 "@
8a18b90c 10270 mov%d5\\t%0, %2%S4
10271 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10272 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10273 [(set_attr "conds" "use")
331beb1a 10274 (set_attr "shift" "2")
a2cd141b 10275 (set_attr "length" "4,8,8")
d2a518d1 10276 (set_attr "insn" "mov")
a2cd141b 10277 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10278 (const_string "alu_shift")
10279 (const_string "alu_shift_reg")))]
8fa3ba89 10280)
5565501b 10281
8a18b90c 10282(define_insn "*ifcompare_move_shift"
10283 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10284 (if_then_else:SI
8fa3ba89 10285 (match_operator 6 "arm_comparison_operator"
8a18b90c 10286 [(match_operand:SI 4 "s_register_operand" "r,r")
10287 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10288 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10289 (match_operator:SI 7 "shift_operator"
8a18b90c 10290 [(match_operand:SI 2 "s_register_operand" "r,r")
10291 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10292 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10293 "TARGET_ARM"
8a18b90c 10294 "#"
8fa3ba89 10295 [(set_attr "conds" "clob")
10296 (set_attr "length" "8,12")]
10297)
5565501b 10298
8a18b90c 10299(define_insn "*if_move_shift"
10300 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10301 (if_then_else:SI
8fa3ba89 10302 (match_operator 5 "arm_comparison_operator"
8a18b90c 10303 [(match_operand 6 "cc_register" "") (const_int 0)])
10304 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10305 (match_operator:SI 4 "shift_operator"
10306 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10307 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10308 "TARGET_ARM"
5565501b 10309 "@
8a18b90c 10310 mov%D5\\t%0, %2%S4
10311 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10312 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10313 [(set_attr "conds" "use")
331beb1a 10314 (set_attr "shift" "2")
a2cd141b 10315 (set_attr "length" "4,8,8")
d2a518d1 10316 (set_attr "insn" "mov")
a2cd141b 10317 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10318 (const_string "alu_shift")
10319 (const_string "alu_shift_reg")))]
8fa3ba89 10320)
9c08d1fa 10321
f7fbdd4a 10322(define_insn "*ifcompare_shift_shift"
8a18b90c 10323 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10324 (if_then_else:SI
8fa3ba89 10325 (match_operator 7 "arm_comparison_operator"
8a18b90c 10326 [(match_operand:SI 5 "s_register_operand" "r")
10327 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10328 (match_operator:SI 8 "shift_operator"
8a18b90c 10329 [(match_operand:SI 1 "s_register_operand" "r")
10330 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10331 (match_operator:SI 9 "shift_operator"
8a18b90c 10332 [(match_operand:SI 3 "s_register_operand" "r")
10333 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10334 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10335 "TARGET_ARM"
8a18b90c 10336 "#"
8fa3ba89 10337 [(set_attr "conds" "clob")
10338 (set_attr "length" "12")]
10339)
9c08d1fa 10340
8a18b90c 10341(define_insn "*if_shift_shift"
10342 [(set (match_operand:SI 0 "s_register_operand" "=r")
10343 (if_then_else:SI
8fa3ba89 10344 (match_operator 5 "arm_comparison_operator"
8a18b90c 10345 [(match_operand 8 "cc_register" "") (const_int 0)])
10346 (match_operator:SI 6 "shift_operator"
10347 [(match_operand:SI 1 "s_register_operand" "r")
10348 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10349 (match_operator:SI 7 "shift_operator"
10350 [(match_operand:SI 3 "s_register_operand" "r")
10351 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10352 "TARGET_ARM"
8a18b90c 10353 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10354 [(set_attr "conds" "use")
331beb1a 10355 (set_attr "shift" "1")
a2cd141b 10356 (set_attr "length" "8")
d2a518d1 10357 (set_attr "insn" "mov")
a2cd141b 10358 (set (attr "type") (if_then_else
10359 (and (match_operand 2 "const_int_operand" "")
10360 (match_operand 4 "const_int_operand" ""))
10361 (const_string "alu_shift")
10362 (const_string "alu_shift_reg")))]
8fa3ba89 10363)
8a18b90c 10364
f7fbdd4a 10365(define_insn "*ifcompare_not_arith"
8a18b90c 10366 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10367 (if_then_else:SI
8fa3ba89 10368 (match_operator 6 "arm_comparison_operator"
8a18b90c 10369 [(match_operand:SI 4 "s_register_operand" "r")
10370 (match_operand:SI 5 "arm_add_operand" "rIL")])
10371 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10372 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10373 [(match_operand:SI 2 "s_register_operand" "r")
10374 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10375 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10376 "TARGET_ARM"
8a18b90c 10377 "#"
8fa3ba89 10378 [(set_attr "conds" "clob")
10379 (set_attr "length" "12")]
10380)
9c08d1fa 10381
8a18b90c 10382(define_insn "*if_not_arith"
10383 [(set (match_operand:SI 0 "s_register_operand" "=r")
10384 (if_then_else:SI
8fa3ba89 10385 (match_operator 5 "arm_comparison_operator"
8a18b90c 10386 [(match_operand 4 "cc_register" "") (const_int 0)])
10387 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10388 (match_operator:SI 6 "shiftable_operator"
10389 [(match_operand:SI 2 "s_register_operand" "r")
10390 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10391 "TARGET_ARM"
8a18b90c 10392 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10393 [(set_attr "conds" "use")
d2a518d1 10394 (set_attr "insn" "mvn")
8fa3ba89 10395 (set_attr "length" "8")]
10396)
8a18b90c 10397
10398(define_insn "*ifcompare_arith_not"
10399 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10400 (if_then_else:SI
8fa3ba89 10401 (match_operator 6 "arm_comparison_operator"
8a18b90c 10402 [(match_operand:SI 4 "s_register_operand" "r")
10403 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10404 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10405 [(match_operand:SI 2 "s_register_operand" "r")
10406 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10407 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10408 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10409 "TARGET_ARM"
8a18b90c 10410 "#"
8fa3ba89 10411 [(set_attr "conds" "clob")
10412 (set_attr "length" "12")]
10413)
9c08d1fa 10414
8a18b90c 10415(define_insn "*if_arith_not"
10416 [(set (match_operand:SI 0 "s_register_operand" "=r")
10417 (if_then_else:SI
8fa3ba89 10418 (match_operator 5 "arm_comparison_operator"
8a18b90c 10419 [(match_operand 4 "cc_register" "") (const_int 0)])
10420 (match_operator:SI 6 "shiftable_operator"
10421 [(match_operand:SI 2 "s_register_operand" "r")
10422 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10423 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10424 "TARGET_ARM"
8a18b90c 10425 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10426 [(set_attr "conds" "use")
d2a518d1 10427 (set_attr "insn" "mvn")
8fa3ba89 10428 (set_attr "length" "8")]
10429)
8a18b90c 10430
f7fbdd4a 10431(define_insn "*ifcompare_neg_move"
8a18b90c 10432 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10433 (if_then_else:SI
8fa3ba89 10434 (match_operator 5 "arm_comparison_operator"
8a18b90c 10435 [(match_operand:SI 3 "s_register_operand" "r,r")
10436 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10437 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10438 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10439 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10440 "TARGET_ARM"
8a18b90c 10441 "#"
8fa3ba89 10442 [(set_attr "conds" "clob")
10443 (set_attr "length" "8,12")]
10444)
8a18b90c 10445
10446(define_insn "*if_neg_move"
10447 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10448 (if_then_else:SI
8fa3ba89 10449 (match_operator 4 "arm_comparison_operator"
8a18b90c 10450 [(match_operand 3 "cc_register" "") (const_int 0)])
10451 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10452 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10453 "TARGET_ARM"
8a18b90c 10454 "@
10455 rsb%d4\\t%0, %2, #0
10456 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10457 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10458 [(set_attr "conds" "use")
10459 (set_attr "length" "4,8,8")]
10460)
9c08d1fa 10461
f7fbdd4a 10462(define_insn "*ifcompare_move_neg"
8a18b90c 10463 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10464 (if_then_else:SI
8fa3ba89 10465 (match_operator 5 "arm_comparison_operator"
8a18b90c 10466 [(match_operand:SI 3 "s_register_operand" "r,r")
10467 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10468 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10469 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10470 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10471 "TARGET_ARM"
8a18b90c 10472 "#"
8fa3ba89 10473 [(set_attr "conds" "clob")
10474 (set_attr "length" "8,12")]
10475)
8a18b90c 10476
10477(define_insn "*if_move_neg"
10478 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10479 (if_then_else:SI
8fa3ba89 10480 (match_operator 4 "arm_comparison_operator"
8a18b90c 10481 [(match_operand 3 "cc_register" "") (const_int 0)])
10482 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10483 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10484 "TARGET_ARM"
8a18b90c 10485 "@
10486 rsb%D4\\t%0, %2, #0
10487 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10488 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10489 [(set_attr "conds" "use")
10490 (set_attr "length" "4,8,8")]
10491)
9c08d1fa 10492
f7fbdd4a 10493(define_insn "*arith_adjacentmem"
9c08d1fa 10494 [(set (match_operand:SI 0 "s_register_operand" "=r")
10495 (match_operator:SI 1 "shiftable_operator"
10496 [(match_operand:SI 2 "memory_operand" "m")
10497 (match_operand:SI 3 "memory_operand" "m")]))
10498 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10499 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10500 "*
215b30b3 10501 {
10502 rtx ldm[3];
10503 rtx arith[4];
94dee231 10504 rtx base_reg;
10505 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10506
215b30b3 10507 if (REGNO (operands[0]) > REGNO (operands[4]))
10508 {
10509 ldm[1] = operands[4];
10510 ldm[2] = operands[0];
10511 }
10512 else
10513 {
10514 ldm[1] = operands[0];
10515 ldm[2] = operands[4];
10516 }
94dee231 10517
10518 base_reg = XEXP (operands[2], 0);
10519
10520 if (!REG_P (base_reg))
10521 {
10522 val1 = INTVAL (XEXP (base_reg, 1));
10523 base_reg = XEXP (base_reg, 0);
10524 }
10525
10526 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10527 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10528
215b30b3 10529 arith[0] = operands[0];
10530 arith[3] = operands[1];
94dee231 10531
215b30b3 10532 if (val1 < val2)
10533 {
10534 arith[1] = ldm[1];
10535 arith[2] = ldm[2];
10536 }
10537 else
10538 {
10539 arith[1] = ldm[2];
10540 arith[2] = ldm[1];
10541 }
94dee231 10542
10543 ldm[0] = base_reg;
10544 if (val1 !=0 && val2 != 0)
215b30b3 10545 {
cdb1295a 10546 rtx ops[3];
10547
94dee231 10548 if (val1 == 4 || val2 == 4)
10549 /* Other val must be 8, since we know they are adjacent and neither
10550 is zero. */
25f905c2 10551 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10552 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10553 {
94dee231 10554 ldm[0] = ops[0] = operands[4];
10555 ops[1] = base_reg;
10556 ops[2] = GEN_INT (val1);
10557 output_add_immediate (ops);
10558 if (val1 < val2)
25f905c2 10559 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10560 else
25f905c2 10561 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10562 }
cdb1295a 10563 else
10564 {
10565 /* Offset is out of range for a single add, so use two ldr. */
10566 ops[0] = ldm[1];
10567 ops[1] = base_reg;
10568 ops[2] = GEN_INT (val1);
10569 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10570 ops[0] = ldm[2];
10571 ops[2] = GEN_INT (val2);
10572 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10573 }
215b30b3 10574 }
94dee231 10575 else if (val1 != 0)
215b30b3 10576 {
215b30b3 10577 if (val1 < val2)
25f905c2 10578 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10579 else
25f905c2 10580 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10581 }
10582 else
10583 {
215b30b3 10584 if (val1 < val2)
25f905c2 10585 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10586 else
25f905c2 10587 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10588 }
10589 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10590 return \"\";
10591 }"
10592 [(set_attr "length" "12")
10593 (set_attr "predicable" "yes")
a2cd141b 10594 (set_attr "type" "load1")]
215b30b3 10595)
9c08d1fa 10596
9c08d1fa 10597; This pattern is never tried by combine, so do it as a peephole
10598
a0f94409 10599(define_peephole2
372575c7 10600 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10601 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10602 (set (reg:CC CC_REGNUM)
aea4c774 10603 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10604 "TARGET_ARM"
a0f94409 10605 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10606 (set (match_dup 0) (match_dup 1))])]
10607 ""
0d66636f 10608)
9c08d1fa 10609
9c08d1fa 10610(define_split
10611 [(set (match_operand:SI 0 "s_register_operand" "")
10612 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10613 (const_int 0))
8fa3ba89 10614 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10615 [(match_operand:SI 3 "s_register_operand" "")
10616 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10617 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10618 "TARGET_ARM"
9c08d1fa 10619 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10620 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10621 (match_dup 5)))]
215b30b3 10622 ""
10623)
9c08d1fa 10624
aea4c774 10625;; This split can be used because CC_Z mode implies that the following
10626;; branch will be an equality, or an unsigned inequality, so the sign
10627;; extension is not needed.
9c08d1fa 10628
aea4c774 10629(define_split
bd5b4116 10630 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10631 (compare:CC_Z
10632 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10633 (const_int 24))
aea4c774 10634 (match_operand 1 "const_int_operand" "")))
10635 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10636 "TARGET_ARM
10637 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10638 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10639 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10640 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10641 "
9c08d1fa 10642 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10643 "
10644)
25f905c2 10645;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10646
87b22bf7 10647(define_expand "prologue"
10648 [(clobber (const_int 0))]
cffb2a26 10649 "TARGET_EITHER"
25f905c2 10650 "if (TARGET_32BIT)
cffb2a26 10651 arm_expand_prologue ();
10652 else
25f905c2 10653 thumb1_expand_prologue ();
87b22bf7 10654 DONE;
cffb2a26 10655 "
10656)
87b22bf7 10657
56d27660 10658(define_expand "epilogue"
4c44712e 10659 [(clobber (const_int 0))]
cffb2a26 10660 "TARGET_EITHER"
56d27660 10661 "
18d50ae6 10662 if (crtl->calls_eh_return)
fb94f18b 10663 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10664 if (TARGET_THUMB1)
c3635784 10665 {
10666 thumb1_expand_epilogue ();
10667 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10668 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10669 }
10670 else if (HAVE_return)
10671 {
10672 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10673 no need for explicit testing again. */
10674 emit_jump_insn (gen_return ());
10675 }
10676 else if (TARGET_32BIT)
10677 {
10678 arm_expand_epilogue (true);
10679 }
cffb2a26 10680 DONE;
10681 "
10682)
56d27660 10683
7571d3f7 10684(define_insn "prologue_thumb1_interwork"
10685 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
10686 "TARGET_THUMB1"
10687 "* return thumb1_output_interwork ();"
10688 [(set_attr "length" "8")]
10689)
10690
ef5651d0 10691;; Note - although unspec_volatile's USE all hard registers,
10692;; USEs are ignored after relaod has completed. Thus we need
10693;; to add an unspec of the link register to ensure that flow
10694;; does not think that it is unused by the sibcall branch that
10695;; will replace the standard function epilogue.
c3635784 10696(define_expand "sibcall_epilogue"
fb94f18b 10697 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10698 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10699 "TARGET_32BIT"
10700 "
10701 arm_expand_epilogue (false);
10702 DONE;
10703 "
1c494086 10704)
10705
cffb2a26 10706(define_insn "*epilogue_insns"
e1159bbe 10707 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
b1324f4f 10708 "TARGET_THUMB1"
56d27660 10709 "*
e7fd8dfa 10710 return thumb1_unexpanded_epilogue ();
cffb2a26 10711 "
215b30b3 10712 ; Length is absolute worst case
cffb2a26 10713 [(set_attr "length" "44")
defc47cf 10714 (set_attr "type" "block")
10715 ;; We don't clobber the conditions, but the potential length of this
10716 ;; operation is sufficient to make conditionalizing the sequence
10717 ;; unlikely to be profitable.
10718 (set_attr "conds" "clob")]
cffb2a26 10719)
10720
10721(define_expand "eh_epilogue"
7db9af5d 10722 [(use (match_operand:SI 0 "register_operand" ""))
10723 (use (match_operand:SI 1 "register_operand" ""))
10724 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10725 "TARGET_EITHER"
10726 "
215b30b3 10727 {
10728 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10729 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10730 {
10731 rtx ra = gen_rtx_REG (Pmode, 2);
10732
10733 emit_move_insn (ra, operands[2]);
10734 operands[2] = ra;
10735 }
5cf3595a 10736 /* This is a hack -- we may have crystalized the function type too
10737 early. */
10738 cfun->machine->func_type = 0;
215b30b3 10739 }"
10740)
56d27660 10741
9c08d1fa 10742;; This split is only used during output to reduce the number of patterns
10743;; that need assembler instructions adding to them. We allowed the setting
10744;; of the conditions to be implicit during rtl generation so that
10745;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10746;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10747;; up again here.
10748
25f905c2 10749;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10750;; conditional execution sufficient?
10751
9c08d1fa 10752(define_split
10753 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10754 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10755 [(match_operand 2 "" "") (match_operand 3 "" "")])
10756 (match_dup 0)
10757 (match_operand 4 "" "")))
bd5b4116 10758 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10759 "TARGET_ARM && reload_completed"
8fa3ba89 10760 [(set (match_dup 5) (match_dup 6))
10761 (cond_exec (match_dup 7)
10762 (set (match_dup 0) (match_dup 4)))]
10763 "
10764 {
10765 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10766 operands[2], operands[3]);
10767 enum rtx_code rc = GET_CODE (operands[1]);
10768
bd5b4116 10769 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10770 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10771 if (mode == CCFPmode || mode == CCFPEmode)
10772 rc = reverse_condition_maybe_unordered (rc);
10773 else
10774 rc = reverse_condition (rc);
10775
10776 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10777 }"
10778)
10779
10780(define_split
10781 [(set (match_operand:SI 0 "s_register_operand" "")
10782 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10783 [(match_operand 2 "" "") (match_operand 3 "" "")])
10784 (match_operand 4 "" "")
10785 (match_dup 0)))
bd5b4116 10786 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10787 "TARGET_ARM && reload_completed"
8fa3ba89 10788 [(set (match_dup 5) (match_dup 6))
10789 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10790 (set (match_dup 0) (match_dup 4)))]
10791 "
10792 {
10793 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10794 operands[2], operands[3]);
10795
bd5b4116 10796 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10797 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10798 }"
10799)
10800
10801(define_split
10802 [(set (match_operand:SI 0 "s_register_operand" "")
10803 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10804 [(match_operand 2 "" "") (match_operand 3 "" "")])
10805 (match_operand 4 "" "")
10806 (match_operand 5 "" "")))
bd5b4116 10807 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10808 "TARGET_ARM && reload_completed"
8fa3ba89 10809 [(set (match_dup 6) (match_dup 7))
10810 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10811 (set (match_dup 0) (match_dup 4)))
10812 (cond_exec (match_dup 8)
10813 (set (match_dup 0) (match_dup 5)))]
10814 "
10815 {
10816 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10817 operands[2], operands[3]);
10818 enum rtx_code rc = GET_CODE (operands[1]);
10819
bd5b4116 10820 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10821 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10822 if (mode == CCFPmode || mode == CCFPEmode)
10823 rc = reverse_condition_maybe_unordered (rc);
10824 else
10825 rc = reverse_condition (rc);
10826
10827 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10828 }"
10829)
10830
cffb2a26 10831(define_split
10832 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10833 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10834 [(match_operand:SI 2 "s_register_operand" "")
10835 (match_operand:SI 3 "arm_add_operand" "")])
10836 (match_operand:SI 4 "arm_rhs_operand" "")
10837 (not:SI
10838 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10839 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10840 "TARGET_ARM && reload_completed"
cffb2a26 10841 [(set (match_dup 6) (match_dup 7))
f6c53574 10842 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10843 (set (match_dup 0) (match_dup 4)))
10844 (cond_exec (match_dup 8)
10845 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10846 "
215b30b3 10847 {
10848 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10849 operands[2], operands[3]);
f6c53574 10850 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10851
bd5b4116 10852 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10853 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10854 if (mode == CCFPmode || mode == CCFPEmode)
10855 rc = reverse_condition_maybe_unordered (rc);
10856 else
10857 rc = reverse_condition (rc);
10858
10859 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10860 }"
10861)
cffb2a26 10862
10863(define_insn "*cond_move_not"
10864 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10865 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10866 [(match_operand 3 "cc_register" "") (const_int 0)])
10867 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10868 (not:SI
10869 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10870 "TARGET_ARM"
10871 "@
10872 mvn%D4\\t%0, %2
10873 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10874 [(set_attr "conds" "use")
d2a518d1 10875 (set_attr "insn" "mvn")
0d66636f 10876 (set_attr "length" "4,8")]
10877)
cffb2a26 10878
9c08d1fa 10879;; The next two patterns occur when an AND operation is followed by a
10880;; scc insn sequence
10881
f7fbdd4a 10882(define_insn "*sign_extract_onebit"
9c08d1fa 10883 [(set (match_operand:SI 0 "s_register_operand" "=r")
10884 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10885 (const_int 1)
ed750274 10886 (match_operand:SI 2 "const_int_operand" "n")))
10887 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10888 "TARGET_ARM"
9c08d1fa 10889 "*
0d66636f 10890 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10891 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10892 return \"mvnne\\t%0, #0\";
10893 "
10894 [(set_attr "conds" "clob")
10895 (set_attr "length" "8")]
10896)
9c08d1fa 10897
f7fbdd4a 10898(define_insn "*not_signextract_onebit"
9c08d1fa 10899 [(set (match_operand:SI 0 "s_register_operand" "=r")
10900 (not:SI
10901 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10902 (const_int 1)
ed750274 10903 (match_operand:SI 2 "const_int_operand" "n"))))
10904 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10905 "TARGET_ARM"
9c08d1fa 10906 "*
0d66636f 10907 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10908 output_asm_insn (\"tst\\t%1, %2\", operands);
10909 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10910 return \"movne\\t%0, #0\";
10911 "
10912 [(set_attr "conds" "clob")
10913 (set_attr "length" "12")]
10914)
25f905c2 10915;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10916
0d66636f 10917;; Push multiple registers to the stack. Registers are in parallel (use ...)
10918;; expressions. For simplicity, the first register is also in the unspec
10919;; part.
08508cbf 10920;; To avoid the usage of GNU extension, the length attribute is computed
10921;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10922(define_insn "*push_multi"
87b22bf7 10923 [(match_parallel 2 "multi_register_push"
7571d3f7 10924 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10925 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10926 UNSPEC_PUSH_MULT))])]
7571d3f7 10927 ""
87b22bf7 10928 "*
215b30b3 10929 {
10930 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10931
215b30b3 10932 /* For the StrongARM at least it is faster to
25f905c2 10933 use STR to store only a single register.
542d5028 10934 In Thumb mode always use push, and the assembler will pick
10935 something appropriate. */
25f905c2 10936 if (num_saves == 1 && TARGET_ARM)
61309563 10937 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10938 else
10939 {
10940 int i;
10941 char pattern[100];
ed593f11 10942
25f905c2 10943 if (TARGET_ARM)
61309563 10944 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10945 else if (TARGET_THUMB2)
10946 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10947 else
10948 strcpy (pattern, \"push\\t{%1\");
215b30b3 10949
6079f055 10950 for (i = 1; i < num_saves; i++)
215b30b3 10951 {
10952 strcat (pattern, \", %|\");
10953 strcat (pattern,
10954 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10955 }
10956
10957 strcat (pattern, \"}\");
10958 output_asm_insn (pattern, operands);
10959 }
10960
10961 return \"\";
10962 }"
a6864a24 10963 [(set_attr "type" "store4")
10964 (set (attr "length")
08508cbf 10965 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10966)
f7fbdd4a 10967
4c58c898 10968(define_insn "stack_tie"
10969 [(set (mem:BLK (scratch))
aaa37ad6 10970 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10971 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10972 UNSPEC_PRLG_STK))]
10973 ""
10974 ""
10975 [(set_attr "length" "0")]
10976)
10977
426be8c5 10978;; Pop (as used in epilogue RTL)
10979;;
10980(define_insn "*load_multiple_with_writeback"
10981 [(match_parallel 0 "load_multiple_operation"
10982 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10983 (plus:SI (match_dup 1)
10984 (match_operand:SI 2 "const_int_operand" "I")))
10985 (set (match_operand:SI 3 "s_register_operand" "=rk")
10986 (mem:SI (match_dup 1)))
10987 ])]
10988 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10989 "*
10990 {
10991 arm_output_multireg_pop (operands, /*return_pc=*/false,
10992 /*cond=*/const_true_rtx,
10993 /*reverse=*/false,
10994 /*update=*/true);
10995 return \"\";
10996 }
10997 "
10998 [(set_attr "type" "load4")
10999 (set_attr "predicable" "yes")]
11000)
11001
11002;; Pop with return (as used in epilogue RTL)
11003;;
11004;; This instruction is generated when the registers are popped at the end of
11005;; epilogue. Here, instead of popping the value into LR and then generating
11006;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11007;; with (return).
11008(define_insn "*pop_multiple_with_writeback_and_return"
11009 [(match_parallel 0 "pop_multiple_return"
11010 [(return)
11011 (set (match_operand:SI 1 "s_register_operand" "+rk")
11012 (plus:SI (match_dup 1)
11013 (match_operand:SI 2 "const_int_operand" "I")))
11014 (set (match_operand:SI 3 "s_register_operand" "=rk")
11015 (mem:SI (match_dup 1)))
11016 ])]
11017 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11018 "*
11019 {
11020 arm_output_multireg_pop (operands, /*return_pc=*/true,
11021 /*cond=*/const_true_rtx,
11022 /*reverse=*/false,
11023 /*update=*/true);
11024 return \"\";
11025 }
11026 "
11027 [(set_attr "type" "load4")
11028 (set_attr "predicable" "yes")]
11029)
11030
11031(define_insn "*pop_multiple_with_return"
11032 [(match_parallel 0 "pop_multiple_return"
11033 [(return)
11034 (set (match_operand:SI 2 "s_register_operand" "=rk")
11035 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11036 ])]
11037 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11038 "*
11039 {
11040 arm_output_multireg_pop (operands, /*return_pc=*/true,
11041 /*cond=*/const_true_rtx,
11042 /*reverse=*/false,
11043 /*update=*/false);
11044 return \"\";
11045 }
11046 "
11047 [(set_attr "type" "load4")
11048 (set_attr "predicable" "yes")]
11049)
11050
11051;; Load into PC and return
11052(define_insn "*ldr_with_return"
11053 [(return)
11054 (set (reg:SI PC_REGNUM)
11055 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11056 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11057 "ldr%?\t%|pc, [%0], #4"
11058 [(set_attr "type" "load1")
11059 (set_attr "predicable" "yes")]
11060)
1a0b0f12 11061;; Pop for floating point registers (as used in epilogue RTL)
11062(define_insn "*vfp_pop_multiple_with_writeback"
11063 [(match_parallel 0 "pop_multiple_fp"
11064 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11065 (plus:SI (match_dup 1)
11066 (match_operand:SI 2 "const_int_operand" "I")))
11067 (set (match_operand:DF 3 "arm_hard_register_operand" "")
11068 (mem:DF (match_dup 1)))])]
11069 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
11070 "*
11071 {
11072 int num_regs = XVECLEN (operands[0], 0);
11073 char pattern[100];
11074 rtx op_list[2];
11075 strcpy (pattern, \"fldmfdd\\t\");
11076 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11077 strcat (pattern, \"!, {\");
11078 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11079 strcat (pattern, \"%P0\");
11080 if ((num_regs - 1) > 1)
11081 {
11082 strcat (pattern, \"-%P1\");
11083 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11084 }
11085
11086 strcat (pattern, \"}\");
11087 output_asm_insn (pattern, op_list);
11088 return \"\";
11089 }
11090 "
11091 [(set_attr "type" "load4")
11092 (set_attr "conds" "unconditional")
11093 (set_attr "predicable" "no")]
11094)
11095
f7fbdd4a 11096;; Special patterns for dealing with the constant pool
11097
cffb2a26 11098(define_insn "align_4"
e1159bbe 11099 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11100 "TARGET_EITHER"
f7fbdd4a 11101 "*
cffb2a26 11102 assemble_align (32);
f7fbdd4a 11103 return \"\";
cffb2a26 11104 "
11105)
f7fbdd4a 11106
755eb2b4 11107(define_insn "align_8"
11108 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11109 "TARGET_EITHER"
755eb2b4 11110 "*
11111 assemble_align (64);
11112 return \"\";
11113 "
11114)
11115
cffb2a26 11116(define_insn "consttable_end"
e1159bbe 11117 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11118 "TARGET_EITHER"
f7fbdd4a 11119 "*
cffb2a26 11120 making_const_table = FALSE;
f7fbdd4a 11121 return \"\";
cffb2a26 11122 "
11123)
f7fbdd4a 11124
cffb2a26 11125(define_insn "consttable_1"
e1159bbe 11126 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 11127 "TARGET_THUMB1"
f7fbdd4a 11128 "*
cffb2a26 11129 making_const_table = TRUE;
09d688ff 11130 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 11131 assemble_zeros (3);
f7fbdd4a 11132 return \"\";
cffb2a26 11133 "
11134 [(set_attr "length" "4")]
11135)
f7fbdd4a 11136
cffb2a26 11137(define_insn "consttable_2"
e1159bbe 11138 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 11139 "TARGET_THUMB1"
f7fbdd4a 11140 "*
cffb2a26 11141 making_const_table = TRUE;
9b8516be 11142 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 11143 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 11144 assemble_zeros (2);
f7fbdd4a 11145 return \"\";
cffb2a26 11146 "
11147 [(set_attr "length" "4")]
11148)
11149
11150(define_insn "consttable_4"
e1159bbe 11151 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11152 "TARGET_EITHER"
11153 "*
11154 {
9b8516be 11155 rtx x = operands[0];
cffb2a26 11156 making_const_table = TRUE;
9b8516be 11157 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 11158 {
11159 case MODE_FLOAT:
9b8516be 11160 if (GET_MODE (x) == HFmode)
11161 arm_emit_fp16_const (x);
11162 else
11163 {
11164 REAL_VALUE_TYPE r;
11165 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
11166 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
11167 }
11168 break;
cffb2a26 11169 default:
7b04c5d5 11170 /* XXX: Sometimes gcc does something really dumb and ends up with
11171 a HIGH in a constant pool entry, usually because it's trying to
11172 load into a VFP register. We know this will always be used in
11173 combination with a LO_SUM which ignores the high bits, so just
11174 strip off the HIGH. */
11175 if (GET_CODE (x) == HIGH)
11176 x = XEXP (x, 0);
9b8516be 11177 assemble_integer (x, 4, BITS_PER_WORD, 1);
11178 mark_symbol_refs_as_used (x);
cffb2a26 11179 break;
11180 }
11181 return \"\";
11182 }"
11183 [(set_attr "length" "4")]
11184)
11185
11186(define_insn "consttable_8"
e1159bbe 11187 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11188 "TARGET_EITHER"
11189 "*
11190 {
11191 making_const_table = TRUE;
11192 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11193 {
11194 case MODE_FLOAT:
11195 {
badfe841 11196 REAL_VALUE_TYPE r;
11197 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11198 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 11199 break;
11200 }
11201 default:
09d688ff 11202 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11203 break;
11204 }
11205 return \"\";
11206 }"
11207 [(set_attr "length" "8")]
11208)
11209
d98a3884 11210(define_insn "consttable_16"
11211 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11212 "TARGET_EITHER"
11213 "*
11214 {
11215 making_const_table = TRUE;
11216 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11217 {
11218 case MODE_FLOAT:
11219 {
11220 REAL_VALUE_TYPE r;
11221 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11222 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11223 break;
11224 }
11225 default:
11226 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11227 break;
11228 }
11229 return \"\";
11230 }"
11231 [(set_attr "length" "16")]
11232)
11233
cffb2a26 11234;; Miscellaneous Thumb patterns
11235
fd957ef3 11236(define_expand "tablejump"
7db9af5d 11237 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 11238 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 11239 "TARGET_THUMB1"
fd957ef3 11240 "
11241 if (flag_pic)
11242 {
11243 /* Hopefully, CSE will eliminate this copy. */
11244 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11245 rtx reg2 = gen_reg_rtx (SImode);
11246
11247 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11248 operands[0] = reg2;
11249 }
11250 "
11251)
11252
f1039640 11253;; NB never uses BX.
25f905c2 11254(define_insn "*thumb1_tablejump"
cffb2a26 11255 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11256 (use (label_ref (match_operand 1 "" "")))]
25f905c2 11257 "TARGET_THUMB1"
fd957ef3 11258 "mov\\t%|pc, %0"
cffb2a26 11259 [(set_attr "length" "2")]
11260)
0d66636f 11261
331beb1a 11262;; V5 Instructions,
11263
8f4be2be 11264(define_insn "clzsi2"
11265 [(set (match_operand:SI 0 "s_register_operand" "=r")
11266 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11267 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11268 "clz%?\\t%0, %1"
bcaec148 11269 [(set_attr "predicable" "yes")
11270 (set_attr "insn" "clz")])
331beb1a 11271
099ad98b 11272(define_insn "rbitsi2"
11273 [(set (match_operand:SI 0 "s_register_operand" "=r")
11274 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11275 "TARGET_32BIT && arm_arch_thumb2"
11276 "rbit%?\\t%0, %1"
11277 [(set_attr "predicable" "yes")
11278 (set_attr "insn" "clz")])
11279
11280(define_expand "ctzsi2"
11281 [(set (match_operand:SI 0 "s_register_operand" "")
11282 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
11283 "TARGET_32BIT && arm_arch_thumb2"
11284 "
30191172 11285 {
11286 rtx tmp = gen_reg_rtx (SImode);
11287 emit_insn (gen_rbitsi2 (tmp, operands[1]));
11288 emit_insn (gen_clzsi2 (operands[0], tmp));
11289 }
099ad98b 11290 DONE;
11291 "
11292)
11293
e1159bbe 11294;; V5E instructions.
331beb1a 11295
11296(define_insn "prefetch"
f4e79814 11297 [(prefetch (match_operand:SI 0 "address_operand" "p")
11298 (match_operand:SI 1 "" "")
11299 (match_operand:SI 2 "" ""))]
25f905c2 11300 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 11301 "pld\\t%a0")
331beb1a 11302
0d66636f 11303;; General predication pattern
11304
11305(define_cond_exec
11306 [(match_operator 0 "arm_comparison_operator"
11307 [(match_operand 1 "cc_register" "")
11308 (const_int 0)])]
25f905c2 11309 "TARGET_32BIT"
0d66636f 11310 ""
11311)
11312
fb94f18b 11313(define_insn "force_register_use"
11314 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11315 ""
fb94f18b 11316 "%@ %0 needed"
02cfc9c9 11317 [(set_attr "length" "0")]
063a05c7 11318)
7db9af5d 11319
4c44712e 11320
11321;; Patterns for exception handling
11322
11323(define_expand "eh_return"
11324 [(use (match_operand 0 "general_operand" ""))]
11325 "TARGET_EITHER"
11326 "
11327 {
25f905c2 11328 if (TARGET_32BIT)
4c44712e 11329 emit_insn (gen_arm_eh_return (operands[0]));
11330 else
11331 emit_insn (gen_thumb_eh_return (operands[0]));
11332 DONE;
11333 }"
11334)
11335
11336;; We can't expand this before we know where the link register is stored.
11337(define_insn_and_split "arm_eh_return"
11338 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11339 VUNSPEC_EH_RETURN)
11340 (clobber (match_scratch:SI 1 "=&r"))]
11341 "TARGET_ARM"
11342 "#"
11343 "&& reload_completed"
11344 [(const_int 0)]
11345 "
11346 {
11347 arm_set_return_address (operands[0], operands[1]);
11348 DONE;
11349 }"
11350)
11351
11352(define_insn_and_split "thumb_eh_return"
11353 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11354 VUNSPEC_EH_RETURN)
11355 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 11356 "TARGET_THUMB1"
4c44712e 11357 "#"
11358 "&& reload_completed"
11359 [(const_int 0)]
11360 "
11361 {
11362 thumb_set_return_address (operands[0], operands[1]);
11363 DONE;
11364 }"
11365)
11366
f655717d 11367\f
11368;; TLS support
11369
11370(define_insn "load_tp_hard"
11371 [(set (match_operand:SI 0 "register_operand" "=r")
11372 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11373 "TARGET_HARD_TP"
11374 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11375 [(set_attr "predicable" "yes")]
11376)
11377
11378;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11379(define_insn "load_tp_soft"
11380 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11381 (clobber (reg:SI LR_REGNUM))
11382 (clobber (reg:SI IP_REGNUM))
11383 (clobber (reg:CC CC_REGNUM))]
11384 "TARGET_SOFT_TP"
11385 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11386 [(set_attr "conds" "clob")]
11387)
11388
f41e4452 11389;; tls descriptor call
11390(define_insn "tlscall"
11391 [(set (reg:SI R0_REGNUM)
11392 (unspec:SI [(reg:SI R0_REGNUM)
11393 (match_operand:SI 0 "" "X")
11394 (match_operand 1 "" "")] UNSPEC_TLS))
11395 (clobber (reg:SI R1_REGNUM))
11396 (clobber (reg:SI LR_REGNUM))
11397 (clobber (reg:SI CC_REGNUM))]
11398 "TARGET_GNU2_TLS"
11399 {
11400 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11401 INTVAL (operands[1]));
11402 return "bl\\t%c0(tlscall)";
11403 }
11404 [(set_attr "conds" "clob")
11405 (set_attr "length" "4")]
11406)
11407
1fe0edab 11408;; For thread pointer builtin
11409(define_expand "get_thread_pointersi"
11410 [(match_operand:SI 0 "s_register_operand" "=r")]
11411 ""
11412 "
11413 {
11414 arm_load_tp (operands[0]);
11415 DONE;
11416 }")
11417
f41e4452 11418;;
11419
aabe09ac 11420;; We only care about the lower 16 bits of the constant
11421;; being inserted into the upper 16 bits of the register.
eca5c984 11422(define_insn "*arm_movtas_ze"
11423 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11424 (const_int 16)
11425 (const_int 16))
11426 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 11427 "arm_arch_thumb2"
aabe09ac 11428 "movt%?\t%0, %L1"
eca5c984 11429 [(set_attr "predicable" "yes")
11430 (set_attr "length" "4")]
11431)
11432
c0fc3696 11433(define_insn "*arm_rev"
a486b499 11434 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11435 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11436 "arm_arch6"
11437 "@
11438 rev\t%0, %1
11439 rev%?\t%0, %1
11440 rev%?\t%0, %1"
11441 [(set_attr "arch" "t1,t2,32")
11442 (set_attr "length" "2,2,4")]
ff82f757 11443)
11444
11445(define_expand "arm_legacy_rev"
11446 [(set (match_operand:SI 2 "s_register_operand" "")
11447 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11448 (const_int 16))
11449 (match_dup 1)))
11450 (set (match_dup 2)
11451 (lshiftrt:SI (match_dup 2)
11452 (const_int 8)))
11453 (set (match_operand:SI 3 "s_register_operand" "")
11454 (rotatert:SI (match_dup 1)
11455 (const_int 8)))
11456 (set (match_dup 2)
11457 (and:SI (match_dup 2)
11458 (const_int -65281)))
11459 (set (match_operand:SI 0 "s_register_operand" "")
11460 (xor:SI (match_dup 3)
11461 (match_dup 2)))]
11462 "TARGET_32BIT"
11463 ""
11464)
11465
11466;; Reuse temporaries to keep register pressure down.
11467(define_expand "thumb_legacy_rev"
11468 [(set (match_operand:SI 2 "s_register_operand" "")
11469 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11470 (const_int 24)))
11471 (set (match_operand:SI 3 "s_register_operand" "")
11472 (lshiftrt:SI (match_dup 1)
11473 (const_int 24)))
11474 (set (match_dup 3)
11475 (ior:SI (match_dup 3)
11476 (match_dup 2)))
11477 (set (match_operand:SI 4 "s_register_operand" "")
11478 (const_int 16))
11479 (set (match_operand:SI 5 "s_register_operand" "")
11480 (rotatert:SI (match_dup 1)
11481 (match_dup 4)))
11482 (set (match_dup 2)
11483 (ashift:SI (match_dup 5)
11484 (const_int 24)))
11485 (set (match_dup 5)
11486 (lshiftrt:SI (match_dup 5)
11487 (const_int 24)))
11488 (set (match_dup 5)
11489 (ior:SI (match_dup 5)
11490 (match_dup 2)))
11491 (set (match_dup 5)
11492 (rotatert:SI (match_dup 5)
11493 (match_dup 4)))
11494 (set (match_operand:SI 0 "s_register_operand" "")
11495 (ior:SI (match_dup 5)
11496 (match_dup 3)))]
11497 "TARGET_THUMB"
11498 ""
11499)
11500
11501(define_expand "bswapsi2"
11502 [(set (match_operand:SI 0 "s_register_operand" "=r")
11503 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11504"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11505"
8d1af482 11506 if (!arm_arch6)
11507 {
11508 rtx op2 = gen_reg_rtx (SImode);
11509 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11510
8d1af482 11511 if (TARGET_THUMB)
11512 {
11513 rtx op4 = gen_reg_rtx (SImode);
11514 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11515
8d1af482 11516 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11517 op2, op3, op4, op5));
11518 }
11519 else
11520 {
11521 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11522 op2, op3));
11523 }
ff82f757 11524
8d1af482 11525 DONE;
11526 }
ff82f757 11527 "
11528)
11529
a486b499 11530;; bswap16 patterns: use revsh and rev16 instructions for the signed
11531;; and unsigned variants, respectively. For rev16, expose
11532;; byte-swapping in the lower 16 bits only.
11533(define_insn "*arm_revsh"
11534 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11535 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11536 "arm_arch6"
11537 "@
11538 revsh\t%0, %1
11539 revsh%?\t%0, %1
11540 revsh%?\t%0, %1"
11541 [(set_attr "arch" "t1,t2,32")
11542 (set_attr "length" "2,2,4")]
11543)
11544
11545(define_insn "*arm_rev16"
11546 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11547 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11548 "arm_arch6"
11549 "@
11550 rev16\t%0, %1
11551 rev16%?\t%0, %1
11552 rev16%?\t%0, %1"
11553 [(set_attr "arch" "t1,t2,32")
11554 (set_attr "length" "2,2,4")]
11555)
11556
11557(define_expand "bswaphi2"
11558 [(set (match_operand:HI 0 "s_register_operand" "=r")
11559 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11560"arm_arch6"
11561""
11562)
11563
1653cf17 11564;; Patterns for LDRD/STRD in Thumb2 mode
11565
11566(define_insn "*thumb2_ldrd"
11567 [(set (match_operand:SI 0 "s_register_operand" "=r")
11568 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11569 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11570 (set (match_operand:SI 3 "s_register_operand" "=r")
11571 (mem:SI (plus:SI (match_dup 1)
11572 (match_operand:SI 4 "const_int_operand" ""))))]
11573 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11574 && current_tune->prefer_ldrd_strd
11575 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11576 && (operands_ok_ldrd_strd (operands[0], operands[3],
11577 operands[1], INTVAL (operands[2]),
11578 false, true))"
11579 "ldrd%?\t%0, %3, [%1, %2]"
11580 [(set_attr "type" "load2")
11581 (set_attr "predicable" "yes")])
11582
11583(define_insn "*thumb2_ldrd_base"
11584 [(set (match_operand:SI 0 "s_register_operand" "=r")
11585 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11586 (set (match_operand:SI 2 "s_register_operand" "=r")
11587 (mem:SI (plus:SI (match_dup 1)
11588 (const_int 4))))]
11589 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11590 && current_tune->prefer_ldrd_strd
11591 && (operands_ok_ldrd_strd (operands[0], operands[2],
11592 operands[1], 0, false, true))"
11593 "ldrd%?\t%0, %2, [%1]"
11594 [(set_attr "type" "load2")
11595 (set_attr "predicable" "yes")])
11596
11597(define_insn "*thumb2_ldrd_base_neg"
11598 [(set (match_operand:SI 0 "s_register_operand" "=r")
11599 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11600 (const_int -4))))
11601 (set (match_operand:SI 2 "s_register_operand" "=r")
11602 (mem:SI (match_dup 1)))]
11603 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11604 && current_tune->prefer_ldrd_strd
11605 && (operands_ok_ldrd_strd (operands[0], operands[2],
11606 operands[1], -4, false, true))"
11607 "ldrd%?\t%0, %2, [%1, #-4]"
11608 [(set_attr "type" "load2")
11609 (set_attr "predicable" "yes")])
11610
11611(define_insn "*thumb2_strd"
11612 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11613 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11614 (match_operand:SI 2 "s_register_operand" "r"))
11615 (set (mem:SI (plus:SI (match_dup 0)
11616 (match_operand:SI 3 "const_int_operand" "")))
11617 (match_operand:SI 4 "s_register_operand" "r"))]
11618 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11619 && current_tune->prefer_ldrd_strd
11620 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11621 && (operands_ok_ldrd_strd (operands[2], operands[4],
11622 operands[0], INTVAL (operands[1]),
11623 false, false))"
11624 "strd%?\t%2, %4, [%0, %1]"
11625 [(set_attr "type" "store2")
11626 (set_attr "predicable" "yes")])
11627
11628(define_insn "*thumb2_strd_base"
11629 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11630 (match_operand:SI 1 "s_register_operand" "r"))
11631 (set (mem:SI (plus:SI (match_dup 0)
11632 (const_int 4)))
11633 (match_operand:SI 2 "s_register_operand" "r"))]
11634 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11635 && current_tune->prefer_ldrd_strd
11636 && (operands_ok_ldrd_strd (operands[1], operands[2],
11637 operands[0], 0, false, false))"
11638 "strd%?\t%1, %2, [%0]"
11639 [(set_attr "type" "store2")
11640 (set_attr "predicable" "yes")])
11641
11642(define_insn "*thumb2_strd_base_neg"
11643 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11644 (const_int -4)))
11645 (match_operand:SI 1 "s_register_operand" "r"))
11646 (set (mem:SI (match_dup 0))
11647 (match_operand:SI 2 "s_register_operand" "r"))]
11648 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11649 && current_tune->prefer_ldrd_strd
11650 && (operands_ok_ldrd_strd (operands[1], operands[2],
11651 operands[0], -4, false, false))"
11652 "strd%?\t%1, %2, [%0, #-4]"
11653 [(set_attr "type" "store2")
11654 (set_attr "predicable" "yes")])
11655
11656
320ea44d 11657;; Load the load/store multiple patterns
11658(include "ldmstm.md")
426be8c5 11659
11660;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11661;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11662(define_insn "*load_multiple"
11663 [(match_parallel 0 "load_multiple_operation"
11664 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11665 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11666 ])]
11667 "TARGET_32BIT"
11668 "*
11669 {
11670 arm_output_multireg_pop (operands, /*return_pc=*/false,
11671 /*cond=*/const_true_rtx,
11672 /*reverse=*/false,
11673 /*update=*/false);
11674 return \"\";
11675 }
11676 "
11677 [(set_attr "predicable" "yes")]
11678)
11679
d98a3884 11680;; Vector bits common to IWMMXT and Neon
11681(include "vec-common.md")
755eb2b4 11682;; Load the Intel Wireless Multimedia Extension patterns
11683(include "iwmmxt.md")
a2cd141b 11684;; Load the VFP co-processor patterns
11685(include "vfp.md")
25f905c2 11686;; Thumb-2 patterns
11687(include "thumb2.md")
d98a3884 11688;; Neon patterns
11689(include "neon.md")
06df6b17 11690;; Synchronization Primitives
11691(include "sync.md")
bbbe4599 11692;; Fixed-point patterns
11693(include "arm-fixed.md")