]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* config/i386/sfp-machine.h (FP_EX_ALL): Define.
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
2d05dfad 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
934a1e72 4;; Free Software Foundation, Inc.
b11cae9e 5;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 6;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 7;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 8
acf6ed70 9;; This file is part of GCC.
b11cae9e 10
acf6ed70 11;; GCC is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published
038d1e19 13;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 14;; option) any later version.
b11cae9e 15
acf6ed70 16;; GCC is distributed in the hope that it will be useful, but WITHOUT
17;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19;; License for more details.
b11cae9e 20
21;; You should have received a copy of the GNU General Public License
038d1e19 22;; along with GCC; see the file COPYING3. If not see
23;; <http://www.gnu.org/licenses/>.
b11cae9e 24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
9c08d1fa 27\f
e1159bbe 28;;---------------------------------------------------------------------------
29;; Constants
30
bffbb863 31;; Register numbers -- All machine registers should be defined here
e1159bbe 32(define_constants
bffbb863 33 [(R0_REGNUM 0) ; First CORE register
34 (R1_REGNUM 1) ; Second CORE register
35 (IP_REGNUM 12) ; Scratch register
36 (SP_REGNUM 13) ; Stack pointer
37 (LR_REGNUM 14) ; Return address register
38 (PC_REGNUM 15) ; Program counter
39 (LAST_ARM_REGNUM 15) ;
40 (CC_REGNUM 100) ; Condition code pseudo register
41 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
2ff91fec 51;; conditional compare combination
52(define_constants
53 [(CMP_CMP 0)
54 (CMN_CMP 1)
55 (CMP_CMN 2)
56 (CMN_CMN 3)
57 (NUM_OF_COND_CMP 4)
58 ]
59)
e1159bbe 60
9c08d1fa 61;; UNSPEC Usage:
8a18b90c 62;; Note: sin and cos are no-longer used.
e7d6d136 63;; Unspec enumerators for Neon are defined in neon.md.
6b8f7c28 64;; Unspec enumerators for iwmmxt2 are defined in iwmmxt2.md
e1159bbe 65
e7d6d136 66(define_c_enum "unspec" [
e7d6d136 67 UNSPEC_PUSH_MULT ; `push multiple' operation:
68 ; operand 0 is the first register,
69 ; subsequent registers are in parallel (use ...)
70 ; expressions.
71 UNSPEC_PIC_SYM ; A symbol that has been treated properly for pic
72 ; usage, that is, we will add the pic_register
73 ; value to it before trying to dereference it.
74 UNSPEC_PIC_BASE ; Add PC and all but the last operand together,
75 ; The last operand is the number of a PIC_LABEL
76 ; that points at the containing instruction.
77 UNSPEC_PRLG_STK ; A special barrier that prevents frame accesses
78 ; being scheduled before the stack adjustment insn.
fb94f18b 79 UNSPEC_REGISTER_USE ; As USE insns are not meaningful after reload,
e7d6d136 80 ; this unspec is used to prevent the deletion of
81 ; instructions setting registers for EH handling
82 ; and stack frame generation. Operand 0 is the
83 ; register to "use".
84 UNSPEC_CHECK_ARCH ; Set CCs to indicate 26-bit or 32-bit mode.
85 UNSPEC_WSHUFH ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
86 UNSPEC_WACC ; Used by the intrinsic form of the iWMMXt WACC instruction.
87 UNSPEC_TMOVMSK ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
88 UNSPEC_WSAD ; Used by the intrinsic form of the iWMMXt WSAD instruction.
89 UNSPEC_WSADZ ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
90 UNSPEC_WMACS ; Used by the intrinsic form of the iWMMXt WMACS instruction.
91 UNSPEC_WMACU ; Used by the intrinsic form of the iWMMXt WMACU instruction.
92 UNSPEC_WMACSZ ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
93 UNSPEC_WMACUZ ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
94 UNSPEC_CLRDI ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
6b8f7c28 95 UNSPEC_WALIGNI ; Used by the intrinsic form of the iWMMXt WALIGN instruction.
e7d6d136 96 UNSPEC_TLS ; A symbol that has been treated properly for TLS usage.
97 UNSPEC_PIC_LABEL ; A label used for PIC access that does not appear in the
98 ; instruction stream.
e7d6d136 99 UNSPEC_PIC_OFFSET ; A symbolic 12-bit OFFSET that has been treated
100 ; correctly for PIC usage.
851d9296 101 UNSPEC_GOTSYM_OFF ; The offset of the start of the GOT from a
e7d6d136 102 ; a given symbolic address.
103 UNSPEC_THUMB1_CASESI ; A Thumb1 compressed dispatch-table call.
104 UNSPEC_RBIT ; rbit operation.
105 UNSPEC_SYMBOL_OFFSET ; The offset of the start of the symbol from
106 ; another symbolic address.
107 UNSPEC_MEMORY_BARRIER ; Represent a memory barrier.
eb04cafb 108 UNSPEC_UNALIGNED_LOAD ; Used to represent ldr/ldrh instructions that access
109 ; unaligned locations, on architectures which support
110 ; that.
111 UNSPEC_UNALIGNED_STORE ; Same for str/strh.
350ccca5 112 UNSPEC_PIC_UNIFIED ; Create a common pic addressing form.
ab1e18de 113 UNSPEC_LL ; Represent an unpaired load-register-exclusive.
2d391553 114 UNSPEC_VRINTZ ; Represent a float to integral float rounding
115 ; towards zero.
116 UNSPEC_VRINTP ; Represent a float to integral float rounding
117 ; towards +Inf.
118 UNSPEC_VRINTM ; Represent a float to integral float rounding
119 ; towards -Inf.
120 UNSPEC_VRINTR ; Represent a float to integral float rounding
121 ; FPSCR rounding mode.
122 UNSPEC_VRINTX ; Represent a float to integral float rounding
123 ; FPSCR rounding mode and signal inexactness.
124 UNSPEC_VRINTA ; Represent a float to integral float rounding
125 ; towards nearest, ties away from zero.
e7d6d136 126])
e1159bbe 127
215b30b3 128;; UNSPEC_VOLATILE Usage:
e1159bbe 129
e7d6d136 130(define_c_enum "unspecv" [
131 VUNSPEC_BLOCKAGE ; `blockage' insn to prevent scheduling across an
132 ; insn in the code.
133 VUNSPEC_EPILOGUE ; `epilogue' insn, used to represent any part of the
134 ; instruction epilogue sequence that isn't expanded
135 ; into normal RTL. Used for both normal and sibcall
136 ; epilogues.
7571d3f7 137 VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
138 ; modes from arm to thumb.
e7d6d136 139 VUNSPEC_ALIGN ; `align' insn. Used at the head of a minipool table
140 ; for inlined constants.
141 VUNSPEC_POOL_END ; `end-of-table'. Used to mark the end of a minipool
142 ; table.
143 VUNSPEC_POOL_1 ; `pool-entry(1)'. An entry in the constant pool for
144 ; an 8-bit object.
145 VUNSPEC_POOL_2 ; `pool-entry(2)'. An entry in the constant pool for
146 ; a 16-bit object.
147 VUNSPEC_POOL_4 ; `pool-entry(4)'. An entry in the constant pool for
148 ; a 32-bit object.
149 VUNSPEC_POOL_8 ; `pool-entry(8)'. An entry in the constant pool for
150 ; a 64-bit object.
151 VUNSPEC_POOL_16 ; `pool-entry(16)'. An entry in the constant pool for
152 ; a 128-bit object.
153 VUNSPEC_TMRC ; Used by the iWMMXt TMRC instruction.
154 VUNSPEC_TMCR ; Used by the iWMMXt TMCR instruction.
155 VUNSPEC_ALIGN8 ; 8-byte alignment version of VUNSPEC_ALIGN
156 VUNSPEC_WCMP_EQ ; Used by the iWMMXt WCMPEQ instructions
157 VUNSPEC_WCMP_GTU ; Used by the iWMMXt WCMPGTU instructions
158 VUNSPEC_WCMP_GT ; Used by the iwMMXT WCMPGT instructions
159 VUNSPEC_EH_RETURN ; Use to override the return address for exception
160 ; handling.
e1b93706 161 VUNSPEC_ATOMIC_CAS ; Represent an atomic compare swap.
162 VUNSPEC_ATOMIC_XCHG ; Represent an atomic exchange.
163 VUNSPEC_ATOMIC_OP ; Represent an atomic operation.
164 VUNSPEC_LL ; Represent a load-register-exclusive.
165 VUNSPEC_SC ; Represent a store-register-exclusive.
e7d6d136 166])
b11cae9e 167\f
e1159bbe 168;;---------------------------------------------------------------------------
9c08d1fa 169;; Attributes
170
a651f34d 171;; Processor type. This is created automatically from arm-cores.def.
172(include "arm-tune.md")
173
215b30b3 174; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
175; generating ARM code. This is used to control the length of some insn
176; patterns that share the same RTL in both ARM and Thumb code.
1c494086 177(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 178
ef51b8e1 179; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
180(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
181
747b7458 182; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
183(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
184
331beb1a 185;; Operand number of an input operand that is shifted. Zero if the
186;; given instruction does not shift one of its input operands.
331beb1a 187(define_attr "shift" "" (const_int 0))
188
3d91c5d6 189; Floating Point Unit. If we only have floating point emulation, then there
190; is no point in scheduling the floating point insns. (Well, for best
191; performance we should try and group them together).
bffbb863 192(define_attr "fpu" "none,vfp"
c7f506fd 193 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 194
094e994f 195; LENGTH of an instruction (in bytes)
06df6b17 196(define_attr "length" ""
e1b93706 197 (const_int 4))
9c08d1fa 198
d5d4dc8d 199; The architecture which supports the instruction (or alternative).
200; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
201; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
202; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
203; arm_arch6. This attribute is used to compute attribute "enabled",
204; use type "any" to enable an alternative in all cases.
6b8f7c28 205(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,neon_onlya8,nota8,neon_nota8,iwmmxt,iwmmxt2"
d5d4dc8d 206 (const_string "any"))
207
208(define_attr "arch_enabled" "no,yes"
209 (cond [(eq_attr "arch" "any")
210 (const_string "yes")
211
212 (and (eq_attr "arch" "a")
0bf497f5 213 (match_test "TARGET_ARM"))
d5d4dc8d 214 (const_string "yes")
215
216 (and (eq_attr "arch" "t")
0bf497f5 217 (match_test "TARGET_THUMB"))
d5d4dc8d 218 (const_string "yes")
219
220 (and (eq_attr "arch" "t1")
0bf497f5 221 (match_test "TARGET_THUMB1"))
d5d4dc8d 222 (const_string "yes")
223
224 (and (eq_attr "arch" "t2")
0bf497f5 225 (match_test "TARGET_THUMB2"))
d5d4dc8d 226 (const_string "yes")
227
228 (and (eq_attr "arch" "32")
0bf497f5 229 (match_test "TARGET_32BIT"))
d5d4dc8d 230 (const_string "yes")
231
232 (and (eq_attr "arch" "v6")
0bf497f5 233 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 234 (const_string "yes")
235
236 (and (eq_attr "arch" "nov6")
0bf497f5 237 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 238 (const_string "yes")
239
240 (and (eq_attr "arch" "onlya8")
241 (eq_attr "tune" "cortexa8"))
242 (const_string "yes")
243
10efb95f 244 (and (eq_attr "arch" "neon_onlya8")
245 (eq_attr "tune" "cortexa8")
246 (match_test "TARGET_NEON"))
247 (const_string "yes")
248
a651f34d 249 (and (eq_attr "arch" "nota8")
250 (not (eq_attr "tune" "cortexa8")))
10efb95f 251 (const_string "yes")
252
253 (and (eq_attr "arch" "neon_nota8")
254 (not (eq_attr "tune" "cortexa8"))
255 (match_test "TARGET_NEON"))
6b8f7c28 256 (const_string "yes")
257
258 (and (eq_attr "arch" "iwmmxt2")
259 (match_test "TARGET_REALLY_IWMMXT2"))
d5d4dc8d 260 (const_string "yes")]
6b8f7c28 261
d5d4dc8d 262 (const_string "no")))
263
aa06c51c 264(define_attr "opt" "any,speed,size"
265 (const_string "any"))
266
267(define_attr "opt_enabled" "no,yes"
268 (cond [(eq_attr "opt" "any")
269 (const_string "yes")
270
271 (and (eq_attr "opt" "speed")
272 (match_test "optimize_function_for_speed_p (cfun)"))
273 (const_string "yes")
274
275 (and (eq_attr "opt" "size")
276 (match_test "optimize_function_for_size_p (cfun)"))
277 (const_string "yes")]
278 (const_string "no")))
279
d5d4dc8d 280; Allows an insn to disable certain alternatives for reasons other than
281; arch support.
282(define_attr "insn_enabled" "no,yes"
283 (const_string "yes"))
284
285; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 286 (define_attr "enabled" "no,yes"
aa06c51c 287 (cond [(eq_attr "insn_enabled" "no")
288 (const_string "no")
289
290 (eq_attr "arch_enabled" "no")
291 (const_string "no")
292
293 (eq_attr "opt_enabled" "no")
294 (const_string "no")]
295 (const_string "yes")))
d5d4dc8d 296
56d27660 297; POOL_RANGE is how far away from a constant pool entry that this insn
298; can be placed. If the distance is zero, then this insn will never
299; reference the pool.
42e1de19 300; Note that for Thumb constant pools the PC value is rounded down to the
301; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
302; Thumb insns) should be set to <max_range> - 2.
cffb2a26 303; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 304; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 305(define_attr "arm_pool_range" "" (const_int 0))
306(define_attr "thumb2_pool_range" "" (const_int 0))
307(define_attr "arm_neg_pool_range" "" (const_int 0))
308(define_attr "thumb2_neg_pool_range" "" (const_int 0))
309
310(define_attr "pool_range" ""
311 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
312 (attr "arm_pool_range")))
313(define_attr "neg_pool_range" ""
314 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
315 (attr "arm_neg_pool_range")))
56d27660 316
215b30b3 317; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 318; If such an insn references the pool, then we have no way of knowing how,
319; so use the most conservative value for pool_range.
9c08d1fa 320(define_asm_attributes
4d7a8451 321 [(set_attr "conds" "clob")
322 (set_attr "length" "4")
323 (set_attr "pool_range" "250")])
9c08d1fa 324
a2cd141b 325;; The instruction used to implement a particular pattern. This
326;; information is used by pipeline descriptions to provide accurate
327;; scheduling information.
328
329(define_attr "insn"
b49e3742 330 "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 331 (const_string "other"))
332
9c08d1fa 333; TYPE attribute is used to detect floating point instructions which, if
334; running on a co-processor can run in parallel with other, basic instructions
335; If write-buffer scheduling is enabled then it can also be used in the
336; scheduling of writes.
337
338; Classification of each insn
607978a1 339; Note: vfp.md has different meanings for some of these, and some further
340; types as well. See that file for details.
65f68e55 341; simple_alu_imm a simple alu instruction that doesn't hit memory or fp
342; regs or have a shifted source operand and has an immediate
343; operand. This currently only tracks very basic immediate
344; alu operations.
345; alu_reg any alu instruction that doesn't hit memory or fp
346; regs or have a shifted source operand
347; and does not have an immediate operand. This is
348; also the default
a2cd141b 349; alu_shift any data instruction that doesn't hit memory or fp
350; regs, but has a source operand shifted by a constant
351; alu_shift_reg any data instruction that doesn't hit memory or fp
352; regs, but has a source operand shifted by a register value
f7fbdd4a 353; mult a multiply instruction
9c08d1fa 354; block blockage insn, this blocks all functional units
355; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 356; fdivd DFmode floating point division
357; fdivs SFmode floating point division
013b9671 358; f_load[sd] A single/double load from memory. Used for VFP unit.
359; f_store[sd] A single/double store to memory. Used for VFP unit.
c0e1af52 360; f_flag a transfer of co-processor flags to the CPSR
96854199 361; f_2_r transfer float to core (no memory needed)
362; r_2_f transfer core to float
c0e1af52 363; f_cvt convert floating<->integral
a2cd141b 364; branch a branch
9c08d1fa 365; call a subroutine call
a2cd141b 366; load_byte load byte(s) from memory to arm registers
367; load1 load 1 word from memory to arm registers
368; load2 load 2 words from memory to arm registers
369; load3 load 3 words from memory to arm registers
370; load4 load 4 words from memory to arm registers
371; store store 1 word to memory from arm registers
9c08d1fa 372; store2 store 2 words
373; store3 store 3 words
a2cd141b 374; store4 store 4 (or more) words
9c08d1fa 375;
bcaec148 376
9c08d1fa 377(define_attr "type"
65f68e55 378 "simple_alu_imm,\
379 alu_reg,\
96854199 380 alu_shift,\
381 alu_shift_reg,\
382 mult,\
383 block,\
384 float,\
385 fdivd,\
386 fdivs,\
387 fmuls,\
388 fmuld,\
389 fmacs,\
390 fmacd,\
2d391553 391 f_rints,\
392 f_rintd,\
96854199 393 f_flag,\
394 f_loads,\
395 f_loadd,\
396 f_stores,\
397 f_stored,\
398 f_2_r,\
399 r_2_f,\
400 f_cvt,\
401 branch,\
402 call,\
403 load_byte,\
404 load1,\
405 load2,\
406 load3,\
407 load4,\
408 store1,\
409 store2,\
410 store3,\
411 store4,\
412 fconsts,\
413 fconstd,\
414 fadds,\
415 faddd,\
416 ffariths,\
417 ffarithd,\
418 fcmps,\
419 fcmpd,\
420 fcpys"
421 (if_then_else
422 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,\
423 umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
424 (const_string "mult")
65f68e55 425 (const_string "alu_reg")))
9c08d1fa 426
65f2f758 427; Is this an (integer side) multiply with a 64-bit result?
428(define_attr "mul64" "no,yes"
96854199 429 (if_then_else
430 (eq_attr "insn"
431 "smlalxy,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
432 (const_string "yes")
433 (const_string "no")))
65f2f758 434
6b8f7c28 435; wtype for WMMX insn scheduling purposes.
436(define_attr "wtype"
437 "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"))
438
9888ad6d 439; Load scheduling, set from the arm_ld_sched variable
4c834714 440; initialized by arm_option_override()
9888ad6d 441(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 442
c52acdd2 443;; Classification of NEON instructions for scheduling purposes.
c52acdd2 444(define_attr "neon_type"
445 "neon_int_1,\
446 neon_int_2,\
447 neon_int_3,\
448 neon_int_4,\
449 neon_int_5,\
450 neon_vqneg_vqabs,\
451 neon_vmov,\
452 neon_vaba,\
453 neon_vsma,\
454 neon_vaba_qqq,\
455 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
456 neon_mul_qqq_8_16_32_ddd_32,\
457 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
458 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
459 neon_mla_qqq_8_16,\
460 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
461 neon_mla_qqq_32_qqd_32_scalar,\
462 neon_mul_ddd_16_scalar_32_16_long_scalar,\
463 neon_mul_qqd_32_scalar,\
464 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
465 neon_shift_1,\
466 neon_shift_2,\
467 neon_shift_3,\
468 neon_vshl_ddd,\
469 neon_vqshl_vrshl_vqrshl_qqq,\
470 neon_vsra_vrsra,\
471 neon_fp_vadd_ddd_vabs_dd,\
472 neon_fp_vadd_qqq_vabs_qq,\
473 neon_fp_vsum,\
474 neon_fp_vmul_ddd,\
475 neon_fp_vmul_qqd,\
476 neon_fp_vmla_ddd,\
477 neon_fp_vmla_qqq,\
478 neon_fp_vmla_ddd_scalar,\
479 neon_fp_vmla_qqq_scalar,\
480 neon_fp_vrecps_vrsqrts_ddd,\
481 neon_fp_vrecps_vrsqrts_qqq,\
482 neon_bp_simple,\
483 neon_bp_2cycle,\
484 neon_bp_3cycle,\
485 neon_ldr,\
486 neon_str,\
487 neon_vld1_1_2_regs,\
488 neon_vld1_3_4_regs,\
489 neon_vld2_2_regs_vld1_vld2_all_lanes,\
490 neon_vld2_4_regs,\
491 neon_vld3_vld4,\
492 neon_vst1_1_2_regs_vst2_2_regs,\
493 neon_vst1_3_4_regs,\
494 neon_vst2_4_regs_vst3_vst4,\
495 neon_vst3_vst4,\
496 neon_vld1_vld2_lane,\
497 neon_vld3_vld4_lane,\
498 neon_vst1_vst2_lane,\
499 neon_vst3_vst4_lane,\
500 neon_vld3_vld4_all_lanes,\
501 neon_mcr,\
502 neon_mcr_2_mcrr,\
503 neon_mrc,\
504 neon_mrrc,\
505 neon_ldm_2,\
506 neon_stm_2,\
507 none"
508 (const_string "none"))
509
f7fbdd4a 510; condition codes: this one is used by final_prescan_insn to speed up
511; conditionalizing instructions. It saves having to scan the rtl to see if
512; it uses or alters the condition codes.
215b30b3 513;
f7fbdd4a 514; USE means that the condition codes are used by the insn in the process of
215b30b3 515; outputting code, this means (at present) that we can't use the insn in
516; inlined branches
517;
f7fbdd4a 518; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 519; well defined manner.
520;
f7fbdd4a 521; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 522; they are altered at all
523;
ad6d3e2a 524; UNCONDITIONAL means the instruction can not be conditionally executed and
525; that the instruction does not use or alter the condition codes.
c52acdd2 526;
ad6d3e2a 527; NOCOND means that the instruction does not use or alter the condition
528; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 529
b0694be0 530(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 531 (if_then_else
532 (ior (eq_attr "is_thumb1" "yes")
533 (eq_attr "type" "call"))
c1a66faf 534 (const_string "clob")
c52acdd2 535 (if_then_else (eq_attr "neon_type" "none")
536 (const_string "nocond")
537 (const_string "unconditional"))))
f7fbdd4a 538
215b30b3 539; Predicable means that the insn can be conditionally executed based on
540; an automatically added predicate (additional patterns are generated by
541; gen...). We default to 'no' because no Thumb patterns match this rule
542; and not all ARM patterns do.
0d66636f 543(define_attr "predicable" "no,yes" (const_string "no"))
544
129a2fe4 545; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
546; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 547; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 548; affect the schedule).
74a71f7d 549(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 550
215b30b3 551; WRITE_CONFLICT implies that a read following an unrelated write is likely
552; to stall the processor. Used with model_wbuf above.
9c08d1fa 553(define_attr "write_conflict" "no,yes"
554 (if_then_else (eq_attr "type"
96854199 555 "block,call,load1")
9c08d1fa 556 (const_string "yes")
557 (const_string "no")))
558
215b30b3 559; Classify the insns into those that take one cycle and those that take more
560; than one on the main cpu execution unit.
f7fbdd4a 561(define_attr "core_cycles" "single,multi"
562 (if_then_else (eq_attr "type"
65f68e55 563 "simple_alu_imm,alu_reg,alu_shift,float,fdivd,fdivs")
f7fbdd4a 564 (const_string "single")
565 (const_string "multi")))
566
cffb2a26 567;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 568;; distant label. Only applicable to Thumb code.
cffb2a26 569(define_attr "far_jump" "yes,no" (const_string "no"))
570
d51f92df 571
25f905c2 572;; The number of machine instructions this pattern expands to.
573;; Used for Thumb-2 conditional execution.
574(define_attr "ce_count" "" (const_int 1))
575
d51f92df 576;;---------------------------------------------------------------------------
fd781bb2 577;; Mode iterators
d51f92df 578
3de0dec6 579(include "iterators.md")
03770691 580
d51f92df 581;;---------------------------------------------------------------------------
582;; Predicates
583
9c9db025 584(include "predicates.md")
234f6557 585(include "constraints.md")
9c9db025 586
a2cd141b 587;;---------------------------------------------------------------------------
588;; Pipeline descriptions
215b30b3 589
e3879fd0 590(define_attr "tune_cortexr4" "yes,no"
591 (const (if_then_else
7d3cda8c 592 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 593 (const_string "yes")
594 (const_string "no"))))
595
a2cd141b 596;; True if the generic scheduling description should be used.
597
598(define_attr "generic_sched" "yes,no"
2546d93a 599 (const (if_then_else
65f2f758 600 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexa15,cortexm4")
2546d93a 601 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 602 (const_string "no")
603 (const_string "yes"))))
604
c0e1af52 605(define_attr "generic_vfp" "yes,no"
606 (const (if_then_else
607 (and (eq_attr "fpu" "vfp")
2546d93a 608 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 609 (eq_attr "tune_cortexr4" "no"))
c0e1af52 610 (const_string "yes")
611 (const_string "no"))))
612
6b8f7c28 613(include "marvell-f-iwmmxt.md")
a2cd141b 614(include "arm-generic.md")
615(include "arm926ejs.md")
c0e1af52 616(include "arm1020e.md")
a2cd141b 617(include "arm1026ejs.md")
618(include "arm1136jfs.md")
0e266d06 619(include "fa526.md")
620(include "fa606te.md")
621(include "fa626te.md")
622(include "fmp626.md")
623(include "fa726te.md")
3f1e069f 624(include "cortex-a5.md")
bcaec148 625(include "cortex-a8.md")
036068af 626(include "cortex-a9.md")
65f2f758 627(include "cortex-a15.md")
934a1e72 628(include "cortex-r4.md")
e3879fd0 629(include "cortex-r4f.md")
2546d93a 630(include "cortex-m4.md")
631(include "cortex-m4-fpu.md")
55e3ada8 632(include "vfp11.md")
3586df96 633
9c08d1fa 634\f
215b30b3 635;;---------------------------------------------------------------------------
e1159bbe 636;; Insn patterns
637;;
a0f94409 638;; Addition insns.
215b30b3 639
9c08d1fa 640;; Note: For DImode insns, there is normally no reason why operands should
641;; not be in the same register, what we don't want is for something being
642;; written to partially overlap something that is an input.
643
cffb2a26 644(define_expand "adddi3"
645 [(parallel
215b30b3 646 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 647 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 648 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 649 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 650 "TARGET_EITHER"
651 "
25f905c2 652 if (TARGET_THUMB1)
cffb2a26 653 {
0438d37f 654 if (!REG_P (operands[1]))
bc5a93af 655 operands[1] = force_reg (DImode, operands[1]);
0438d37f 656 if (!REG_P (operands[2]))
bc5a93af 657 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 658 }
659 "
660)
661
25f905c2 662(define_insn "*thumb1_adddi3"
cffb2a26 663 [(set (match_operand:DI 0 "register_operand" "=l")
664 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 665 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 666 (clobber (reg:CC CC_REGNUM))
cffb2a26 667 ]
25f905c2 668 "TARGET_THUMB1"
cffb2a26 669 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
670 [(set_attr "length" "4")]
671)
672
a0f94409 673(define_insn_and_split "*arm_adddi3"
10e5ccd5 674 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
675 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
676 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 677 (clobber (reg:CC CC_REGNUM))]
b805622c 678 "TARGET_32BIT && !TARGET_NEON"
33782ec7 679 "#"
94829feb 680 "TARGET_32BIT && reload_completed
681 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 682 [(parallel [(set (reg:CC_C CC_REGNUM)
683 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
684 (match_dup 1)))
685 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 686 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
687 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 688 "
689 {
690 operands[3] = gen_highpart (SImode, operands[0]);
691 operands[0] = gen_lowpart (SImode, operands[0]);
692 operands[4] = gen_highpart (SImode, operands[1]);
693 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 694 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 695 operands[2] = gen_lowpart (SImode, operands[2]);
696 }"
cffb2a26 697 [(set_attr "conds" "clob")
698 (set_attr "length" "8")]
699)
9c08d1fa 700
a0f94409 701(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 702 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
703 (plus:DI (sign_extend:DI
97499065 704 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 705 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 706 (clobber (reg:CC CC_REGNUM))]
b805622c 707 "TARGET_32BIT"
33782ec7 708 "#"
25f905c2 709 "TARGET_32BIT && reload_completed"
a0f94409 710 [(parallel [(set (reg:CC_C CC_REGNUM)
711 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
712 (match_dup 1)))
713 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 714 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 715 (const_int 31))
080c0b9a 716 (match_dup 4))
717 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 718 "
719 {
720 operands[3] = gen_highpart (SImode, operands[0]);
721 operands[0] = gen_lowpart (SImode, operands[0]);
722 operands[4] = gen_highpart (SImode, operands[1]);
723 operands[1] = gen_lowpart (SImode, operands[1]);
724 operands[2] = gen_lowpart (SImode, operands[2]);
725 }"
215b30b3 726 [(set_attr "conds" "clob")
727 (set_attr "length" "8")]
728)
9c08d1fa 729
a0f94409 730(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 731 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
732 (plus:DI (zero_extend:DI
97499065 733 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 734 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 735 (clobber (reg:CC CC_REGNUM))]
b805622c 736 "TARGET_32BIT"
33782ec7 737 "#"
25f905c2 738 "TARGET_32BIT && reload_completed"
a0f94409 739 [(parallel [(set (reg:CC_C CC_REGNUM)
740 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
741 (match_dup 1)))
742 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 743 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
744 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 745 "
746 {
747 operands[3] = gen_highpart (SImode, operands[0]);
748 operands[0] = gen_lowpart (SImode, operands[0]);
749 operands[4] = gen_highpart (SImode, operands[1]);
750 operands[1] = gen_lowpart (SImode, operands[1]);
751 operands[2] = gen_lowpart (SImode, operands[2]);
752 }"
cffb2a26 753 [(set_attr "conds" "clob")
754 (set_attr "length" "8")]
755)
b11cae9e 756
87b22bf7 757(define_expand "addsi3"
cffb2a26 758 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 759 (plus:SI (match_operand:SI 1 "s_register_operand" "")
760 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 761 "TARGET_EITHER"
87b22bf7 762 "
0438d37f 763 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 764 {
96f57e36 765 arm_split_constant (PLUS, SImode, NULL_RTX,
766 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 767 optimize && can_create_pseudo_p ());
87b22bf7 768 DONE;
769 }
cffb2a26 770 "
771)
87b22bf7 772
5bd751ff 773; If there is a scratch available, this will be faster than synthesizing the
a0f94409 774; addition.
775(define_peephole2
776 [(match_scratch:SI 3 "r")
372575c7 777 (set (match_operand:SI 0 "arm_general_register_operand" "")
778 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 779 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 780 "TARGET_32BIT &&
a0f94409 781 !(const_ok_for_arm (INTVAL (operands[2]))
782 || const_ok_for_arm (-INTVAL (operands[2])))
783 && const_ok_for_arm (~INTVAL (operands[2]))"
784 [(set (match_dup 3) (match_dup 2))
785 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
786 ""
787)
87b22bf7 788
2f02c19f 789;; The r/r/k alternative is required when reloading the address
790;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
791;; put the duplicated register first, and not try the commutative version.
a0f94409 792(define_insn_and_split "*arm_addsi3"
c24d855d 793 [(set (match_operand:SI 0 "s_register_operand" "=rk, r,k, r,r, k, r, k,k,r, k, r")
794 (plus:SI (match_operand:SI 1 "s_register_operand" "%0, rk,k, r,rk,k, rk,k,r,rk,k, rk")
795 (match_operand:SI 2 "reg_or_int_operand" "rk, rI,rI,k,Pj,Pj,L, L,L,PJ,PJ,?n")))]
25f905c2 796 "TARGET_32BIT"
5565501b 797 "@
c24d855d 798 add%?\\t%0, %0, %2
5565501b 799 add%?\\t%0, %1, %2
aaa37ad6 800 add%?\\t%0, %1, %2
2f02c19f 801 add%?\\t%0, %2, %1
d5cbae34 802 addw%?\\t%0, %1, %2
803 addw%?\\t%0, %1, %2
aaa37ad6 804 sub%?\\t%0, %1, #%n2
87b22bf7 805 sub%?\\t%0, %1, #%n2
d7757711 806 sub%?\\t%0, %1, #%n2
d5cbae34 807 subw%?\\t%0, %1, #%n2
808 subw%?\\t%0, %1, #%n2
87b22bf7 809 #"
a3ffc315 810 "TARGET_32BIT
0438d37f 811 && CONST_INT_P (operands[2])
d5cbae34 812 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 813 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 814 [(clobber (const_int 0))]
815 "
96f57e36 816 arm_split_constant (PLUS, SImode, curr_insn,
817 INTVAL (operands[2]), operands[0],
a0f94409 818 operands[1], 0);
819 DONE;
820 "
c24d855d 821 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 822 (set_attr "predicable" "yes")
65f68e55 823 (set_attr "arch" "t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
824 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
825 (const_string "simple_alu_imm")
826 (const_string "alu_reg")))
827 ]
cffb2a26 828)
829
0bdb6455 830(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 831 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
832 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
833 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 834 "TARGET_THUMB1"
cffb2a26 835 "*
0d66636f 836 static const char * const asms[] =
cffb2a26 837 {
838 \"add\\t%0, %0, %2\",
839 \"sub\\t%0, %0, #%n2\",
840 \"add\\t%0, %1, %2\",
841 \"add\\t%0, %0, %2\",
842 \"add\\t%0, %0, %2\",
843 \"add\\t%0, %1, %2\",
0bdb6455 844 \"add\\t%0, %1, %2\",
845 \"#\",
bf7bc2f6 846 \"#\",
0bdb6455 847 \"#\"
cffb2a26 848 };
849 if ((which_alternative == 2 || which_alternative == 6)
0438d37f 850 && CONST_INT_P (operands[2])
cffb2a26 851 && INTVAL (operands[2]) < 0)
852 return \"sub\\t%0, %1, #%n2\";
853 return asms[which_alternative];
854 "
0bdb6455 855 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 856 && ((operands[1] != stack_pointer_rtx
857 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
858 || (operands[1] == stack_pointer_rtx
859 && INTVAL (operands[2]) > 1020))"
0bdb6455 860 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
861 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
862 {
863 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 864 if (operands[1] == stack_pointer_rtx)
865 offset -= 1020;
866 else
867 {
868 if (offset > 255)
869 offset = 255;
870 else if (offset < -255)
871 offset = -255;
872 }
0bdb6455 873 operands[3] = GEN_INT (offset);
874 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
875 }
bf7bc2f6 876 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 877)
878
879;; Reloading and elimination of the frame pointer can
880;; sometimes cause this optimization to be missed.
a0f94409 881(define_peephole2
372575c7 882 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 883 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 884 (set (match_dup 0)
372575c7 885 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 886 "TARGET_THUMB1
cffb2a26 887 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
888 && (INTVAL (operands[1]) & 3) == 0"
372575c7 889 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 890 ""
cffb2a26 891)
b11cae9e 892
90c2bcf0 893(define_insn "addsi3_compare0"
bd5b4116 894 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 895 (compare:CC_NOOV
65f68e55 896 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
897 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 898 (const_int 0)))
65f68e55 899 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 900 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 901 "TARGET_ARM"
5565501b 902 "@
25f905c2 903 add%.\\t%0, %1, %2
65f68e55 904 sub%.\\t%0, %1, #%n2
905 add%.\\t%0, %1, %2"
906 [(set_attr "conds" "set")
907 (set_attr "type" "simple_alu_imm, simple_alu_imm, *")]
cffb2a26 908)
9c08d1fa 909
aea4c774 910(define_insn "*addsi3_compare0_scratch"
bd5b4116 911 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 912 (compare:CC_NOOV
65f68e55 913 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
914 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 915 (const_int 0)))]
ec792a7b 916 "TARGET_ARM"
cffb2a26 917 "@
918 cmn%?\\t%0, %1
65f68e55 919 cmp%?\\t%0, #%n1
920 cmn%?\\t%0, %1"
596e5e8f 921 [(set_attr "conds" "set")
65f68e55 922 (set_attr "predicable" "yes")
923 (set_attr "type" "simple_alu_imm, simple_alu_imm, *")
924 ]
0d66636f 925)
cffb2a26 926
aed179ae 927(define_insn "*compare_negsi_si"
928 [(set (reg:CC_Z CC_REGNUM)
929 (compare:CC_Z
930 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
931 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 932 "TARGET_32BIT"
aed179ae 933 "cmn%?\\t%1, %0"
596e5e8f 934 [(set_attr "conds" "set")
935 (set_attr "predicable" "yes")]
0d66636f 936)
aea4c774 937
203c488f 938;; This is the canonicalization of addsi3_compare0_for_combiner when the
939;; addend is a constant.
940(define_insn "*cmpsi2_addneg"
941 [(set (reg:CC CC_REGNUM)
942 (compare:CC
943 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 944 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 945 (set (match_operand:SI 0 "s_register_operand" "=r,r")
946 (plus:SI (match_dup 1)
2a977b78 947 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 948 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 949 "@
2a977b78 950 add%.\\t%0, %1, %3
951 sub%.\\t%0, %1, #%n3"
203c488f 952 [(set_attr "conds" "set")]
953)
954
955;; Convert the sequence
956;; sub rd, rn, #1
957;; cmn rd, #1 (equivalent to cmp rd, #-1)
958;; bne dest
959;; into
960;; subs rd, rn, #1
961;; bcs dest ((unsigned)rn >= 1)
962;; similarly for the beq variant using bcc.
963;; This is a common looping idiom (while (n--))
964(define_peephole2
372575c7 965 [(set (match_operand:SI 0 "arm_general_register_operand" "")
966 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 967 (const_int -1)))
968 (set (match_operand 2 "cc_register" "")
969 (compare (match_dup 0) (const_int -1)))
970 (set (pc)
971 (if_then_else (match_operator 3 "equality_operator"
972 [(match_dup 2) (const_int 0)])
973 (match_operand 4 "" "")
974 (match_operand 5 "" "")))]
25f905c2 975 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 976 [(parallel[
977 (set (match_dup 2)
978 (compare:CC
979 (match_dup 1) (const_int 1)))
980 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
981 (set (pc)
982 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
983 (match_dup 4)
984 (match_dup 5)))]
985 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
986 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
987 ? GEU : LTU),
988 VOIDmode,
989 operands[2], const0_rtx);"
990)
991
ebcc79bc 992;; The next four insns work because they compare the result with one of
993;; the operands, and we know that the use of the condition code is
994;; either GEU or LTU, so we can use the carry flag from the addition
995;; instead of doing the compare a second time.
996(define_insn "*addsi3_compare_op1"
bd5b4116 997 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 998 (compare:CC_C
65f68e55 999 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1000 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 1001 (match_dup 1)))
65f68e55 1002 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 1003 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1004 "TARGET_32BIT"
ebcc79bc 1005 "@
25f905c2 1006 add%.\\t%0, %1, %2
65f68e55 1007 sub%.\\t%0, %1, #%n2
1008 add%.\\t%0, %1, %2"
1009 [(set_attr "conds" "set")
1010 (set_attr "type" "simple_alu_imm,simple_alu_imm,*")]
0d66636f 1011)
ebcc79bc 1012
1013(define_insn "*addsi3_compare_op2"
bd5b4116 1014 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 1015 (compare:CC_C
65f68e55 1016 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1017 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 1018 (match_dup 2)))
65f68e55 1019 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1020 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1021 "TARGET_32BIT"
5565501b 1022 "@
65f68e55 1023 add%.\\t%0, %1, %2
25f905c2 1024 add%.\\t%0, %1, %2
1025 sub%.\\t%0, %1, #%n2"
65f68e55 1026 [(set_attr "conds" "set")
1027 (set_attr "type" "simple_alu_imm,simple_alu_imm,*")]
0d66636f 1028)
9c08d1fa 1029
ebcc79bc 1030(define_insn "*compare_addsi2_op0"
bd5b4116 1031 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 1032 (compare:CC_C
65f68e55 1033 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
1034 (match_operand:SI 1 "arm_add_operand" "I,L,r"))
ebcc79bc 1035 (match_dup 0)))]
25f905c2 1036 "TARGET_32BIT"
ebcc79bc 1037 "@
1038 cmn%?\\t%0, %1
65f68e55 1039 cmp%?\\t%0, #%n1
1040 cmn%?\\t%0, %1"
596e5e8f 1041 [(set_attr "conds" "set")
65f68e55 1042 (set_attr "predicable" "yes")
1043 (set_attr "type" "simple_alu_imm,simple_alu_imm,*")]
0d66636f 1044)
ebcc79bc 1045
1046(define_insn "*compare_addsi2_op1"
bd5b4116 1047 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 1048 (compare:CC_C
65f68e55 1049 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
1050 (match_operand:SI 1 "arm_add_operand" "I,L,r"))
ebcc79bc 1051 (match_dup 1)))]
25f905c2 1052 "TARGET_32BIT"
ebcc79bc 1053 "@
1054 cmn%?\\t%0, %1
65f68e55 1055 cmp%?\\t%0, #%n1
1056 cmn%?\\t%0, %1"
596e5e8f 1057 [(set_attr "conds" "set")
65f68e55 1058 (set_attr "predicable" "yes")
1059 (set_attr "type" "simple_alu_imm,simple_alu_imm,*")]
0d66636f 1060)
ebcc79bc 1061
080c0b9a 1062(define_insn "*addsi3_carryin_<optab>"
10e5ccd5 1063 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1064 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r")
1065 (match_operand:SI 2 "arm_not_operand" "rI,K"))
080c0b9a 1066 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1067 "TARGET_32BIT"
10e5ccd5 1068 "@
1069 adc%?\\t%0, %1, %2
1070 sbc%?\\t%0, %1, #%B2"
cffb2a26 1071 [(set_attr "conds" "use")]
1072)
ebcc79bc 1073
080c0b9a 1074(define_insn "*addsi3_carryin_alt2_<optab>"
10e5ccd5 1075 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
080c0b9a 1076 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
10e5ccd5 1077 (match_operand:SI 1 "s_register_operand" "%r,r"))
1078 (match_operand:SI 2 "arm_rhs_operand" "rI,K")))]
25f905c2 1079 "TARGET_32BIT"
10e5ccd5 1080 "@
1081 adc%?\\t%0, %1, %2
1082 sbc%?\\t%0, %1, #%B2"
0d66636f 1083 [(set_attr "conds" "use")]
1084)
ebcc79bc 1085
080c0b9a 1086(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1087 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1088 (plus:SI (plus:SI
1089 (match_operator:SI 2 "shift_operator"
1090 [(match_operand:SI 3 "s_register_operand" "r")
1091 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1092 (match_operand:SI 1 "s_register_operand" "r"))
1093 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1094 "TARGET_32BIT"
080c0b9a 1095 "adc%?\\t%0, %1, %3%S2"
1096 [(set_attr "conds" "use")
1097 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1098 (const_string "alu_shift")
1099 (const_string "alu_shift_reg")))]
cffb2a26 1100)
ebcc79bc 1101
922b6913 1102(define_insn "*addsi3_carryin_clobercc_<optab>"
1103 [(set (match_operand:SI 0 "s_register_operand" "=r")
1104 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1105 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1106 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1107 (clobber (reg:CC CC_REGNUM))]
1108 "TARGET_32BIT"
1109 "adc%.\\t%0, %1, %2"
1110 [(set_attr "conds" "set")]
1111)
1112
25f905c2 1113(define_expand "incscc"
1114 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1115 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1116 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1117 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1118 "TARGET_32BIT"
1119 ""
1120)
1121
1122(define_insn "*arm_incscc"
9c08d1fa 1123 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 1124 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1125 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 1126 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 1127 "TARGET_ARM"
5565501b 1128 "@
1129 add%d2\\t%0, %1, #1
1130 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 1131 [(set_attr "conds" "use")
215b30b3 1132 (set_attr "length" "4,8")]
1133)
9c08d1fa 1134
d795fb69 1135; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1136(define_split
1137 [(set (match_operand:SI 0 "s_register_operand" "")
1138 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1139 (match_operand:SI 2 "s_register_operand" ""))
1140 (const_int -1)))
1141 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1142 "TARGET_32BIT"
d795fb69 1143 [(set (match_dup 3) (match_dup 1))
1144 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1145 "
1146 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1147")
1148
604f3a0a 1149(define_expand "addsf3"
1150 [(set (match_operand:SF 0 "s_register_operand" "")
1151 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1152 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1153 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1154 "
604f3a0a 1155")
1156
604f3a0a 1157(define_expand "adddf3"
1158 [(set (match_operand:DF 0 "s_register_operand" "")
1159 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1160 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1161 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1162 "
604f3a0a 1163")
1164
cffb2a26 1165(define_expand "subdi3"
1166 [(parallel
1167 [(set (match_operand:DI 0 "s_register_operand" "")
1168 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1169 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1170 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1171 "TARGET_EITHER"
1172 "
25f905c2 1173 if (TARGET_THUMB1)
cffb2a26 1174 {
0438d37f 1175 if (!REG_P (operands[1]))
5aa8c5f0 1176 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1177 if (!REG_P (operands[2]))
5aa8c5f0 1178 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1179 }
1180 "
1181)
1182
1183(define_insn "*arm_subdi3"
1184 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1185 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1186 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1187 (clobber (reg:CC CC_REGNUM))]
94829feb 1188 "TARGET_32BIT && !TARGET_NEON"
97499065 1189 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1190 [(set_attr "conds" "clob")
1191 (set_attr "length" "8")]
1192)
1193
1194(define_insn "*thumb_subdi3"
1195 [(set (match_operand:DI 0 "register_operand" "=l")
1196 (minus:DI (match_operand:DI 1 "register_operand" "0")
1197 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1198 (clobber (reg:CC CC_REGNUM))]
25f905c2 1199 "TARGET_THUMB1"
cffb2a26 1200 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1201 [(set_attr "length" "4")]
1202)
9c08d1fa 1203
f7fbdd4a 1204(define_insn "*subdi_di_zesidi"
cffb2a26 1205 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1206 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1207 (zero_extend:DI
cffb2a26 1208 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1209 (clobber (reg:CC CC_REGNUM))]
25f905c2 1210 "TARGET_32BIT"
97499065 1211 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1212 [(set_attr "conds" "clob")
1213 (set_attr "length" "8")]
1214)
9c08d1fa 1215
f7fbdd4a 1216(define_insn "*subdi_di_sesidi"
cffb2a26 1217 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1218 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1219 (sign_extend:DI
cffb2a26 1220 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1221 (clobber (reg:CC CC_REGNUM))]
25f905c2 1222 "TARGET_32BIT"
97499065 1223 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1224 [(set_attr "conds" "clob")
1225 (set_attr "length" "8")]
1226)
9c08d1fa 1227
f7fbdd4a 1228(define_insn "*subdi_zesidi_di"
cffb2a26 1229 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1230 (minus:DI (zero_extend:DI
cffb2a26 1231 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1232 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1233 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1234 "TARGET_ARM"
97499065 1235 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1236 [(set_attr "conds" "clob")
1237 (set_attr "length" "8")]
1238)
9c08d1fa 1239
f7fbdd4a 1240(define_insn "*subdi_sesidi_di"
cffb2a26 1241 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1242 (minus:DI (sign_extend:DI
cffb2a26 1243 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1244 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1245 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1246 "TARGET_ARM"
97499065 1247 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1248 [(set_attr "conds" "clob")
1249 (set_attr "length" "8")]
1250)
9c08d1fa 1251
f7fbdd4a 1252(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1253 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1254 (minus:DI (zero_extend:DI
cffb2a26 1255 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1256 (zero_extend:DI
cffb2a26 1257 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1258 (clobber (reg:CC CC_REGNUM))]
25f905c2 1259 "TARGET_32BIT"
1260 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1261 [(set_attr "conds" "clob")
1262 (set_attr "length" "8")]
1263)
b11cae9e 1264
87b22bf7 1265(define_expand "subsi3"
cffb2a26 1266 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1267 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1268 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1269 "TARGET_EITHER"
87b22bf7 1270 "
0438d37f 1271 if (CONST_INT_P (operands[1]))
87b22bf7 1272 {
25f905c2 1273 if (TARGET_32BIT)
cffb2a26 1274 {
96f57e36 1275 arm_split_constant (MINUS, SImode, NULL_RTX,
1276 INTVAL (operands[1]), operands[0],
e1ba4a27 1277 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1278 DONE;
1279 }
25f905c2 1280 else /* TARGET_THUMB1 */
cffb2a26 1281 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1282 }
cffb2a26 1283 "
1284)
87b22bf7 1285
747b7458 1286(define_insn "thumb1_subsi3_insn"
cffb2a26 1287 [(set (match_operand:SI 0 "register_operand" "=l")
1288 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1289 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1290 "TARGET_THUMB1"
cffb2a26 1291 "sub\\t%0, %1, %2"
747b7458 1292 [(set_attr "length" "2")
1293 (set_attr "conds" "set")])
cffb2a26 1294
25f905c2 1295; ??? Check Thumb-2 split length
a0f94409 1296(define_insn_and_split "*arm_subsi3_insn"
65f68e55 1297 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,rk,r")
1298 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,r,k,?n")
1299 (match_operand:SI 2 "reg_or_int_operand" "r,I,r,r, r")))]
25f905c2 1300 "TARGET_32BIT"
e2348bcb 1301 "@
87b22bf7 1302 rsb%?\\t%0, %2, %1
aaa37ad6 1303 sub%?\\t%0, %1, %2
080c0b9a 1304 sub%?\\t%0, %1, %2
65f68e55 1305 sub%?\\t%0, %1, %2
87b22bf7 1306 #"
0438d37f 1307 "&& (CONST_INT_P (operands[1])
91a5e339 1308 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1309 [(clobber (const_int 0))]
1310 "
96f57e36 1311 arm_split_constant (MINUS, SImode, curr_insn,
1312 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1313 DONE;
cffb2a26 1314 "
65f68e55 1315 [(set_attr "length" "4,4,4,4,16")
1316 (set_attr "predicable" "yes")
1317 (set_attr "type" "*,simple_alu_imm,*,*,*")]
a0f94409 1318)
1319
1320(define_peephole2
1321 [(match_scratch:SI 3 "r")
372575c7 1322 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1323 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1324 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1325 "TARGET_32BIT
a0f94409 1326 && !const_ok_for_arm (INTVAL (operands[1]))
1327 && const_ok_for_arm (~INTVAL (operands[1]))"
1328 [(set (match_dup 3) (match_dup 1))
1329 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1330 ""
cffb2a26 1331)
b11cae9e 1332
f7fbdd4a 1333(define_insn "*subsi3_compare0"
bd5b4116 1334 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1335 (compare:CC_NOOV
65f68e55 1336 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1337 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1338 (const_int 0)))
65f68e55 1339 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1340 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1341 "TARGET_32BIT"
e2348bcb 1342 "@
65f68e55 1343 sub%.\\t%0, %1, %2
25f905c2 1344 sub%.\\t%0, %1, %2
1345 rsb%.\\t%0, %2, %1"
65f68e55 1346 [(set_attr "conds" "set")
1347 (set_attr "type" "simple_alu_imm,*,*")]
cffb2a26 1348)
9c08d1fa 1349
080c0b9a 1350(define_insn "*subsi3_compare"
1351 [(set (reg:CC CC_REGNUM)
65f68e55 1352 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1353 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1354 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1355 (minus:SI (match_dup 1) (match_dup 2)))]
1356 "TARGET_32BIT"
1357 "@
65f68e55 1358 sub%.\\t%0, %1, %2
2df9477b 1359 sub%.\\t%0, %1, %2
1360 rsb%.\\t%0, %2, %1"
65f68e55 1361 [(set_attr "conds" "set")
1362 (set_attr "type" "simple_alu_imm,*,*")]
2df9477b 1363)
1364
25f905c2 1365(define_expand "decscc"
1366 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1367 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1368 (match_operator:SI 2 "arm_comparison_operator"
1369 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1370 "TARGET_32BIT"
1371 ""
1372)
1373
1374(define_insn "*arm_decscc"
cffb2a26 1375 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1376 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1377 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1378 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1379 "TARGET_ARM"
e2348bcb 1380 "@
215b30b3 1381 sub%d2\\t%0, %1, #1
1382 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1383 [(set_attr "conds" "use")
65f68e55 1384 (set_attr "length" "*,8")
1385 (set_attr "type" "simple_alu_imm,*")]
cffb2a26 1386)
9c08d1fa 1387
604f3a0a 1388(define_expand "subsf3"
1389 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1390 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1391 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1392 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1393 "
604f3a0a 1394")
1395
604f3a0a 1396(define_expand "subdf3"
1397 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1398 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1399 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1400 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1401 "
604f3a0a 1402")
1403
b11cae9e 1404\f
1405;; Multiplication insns
1406
cffb2a26 1407(define_expand "mulsi3"
1408 [(set (match_operand:SI 0 "s_register_operand" "")
1409 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1410 (match_operand:SI 1 "s_register_operand" "")))]
1411 "TARGET_EITHER"
1412 ""
1413)
1414
9c08d1fa 1415;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1416(define_insn "*arm_mulsi3"
1417 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1418 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1419 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1420 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1421 "mul%?\\t%0, %2, %1"
a2cd141b 1422 [(set_attr "insn" "mul")
0d66636f 1423 (set_attr "predicable" "yes")]
cffb2a26 1424)
1425
58d7d654 1426(define_insn "*arm_mulsi3_v6"
1427 [(set (match_operand:SI 0 "s_register_operand" "=r")
1428 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1429 (match_operand:SI 2 "s_register_operand" "r")))]
1430 "TARGET_32BIT && arm_arch6"
1431 "mul%?\\t%0, %1, %2"
1432 [(set_attr "insn" "mul")
1433 (set_attr "predicable" "yes")]
1434)
1435
215b30b3 1436; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1437; 1 and 2; are the same, because reload will make operand 0 match
1438; operand 1 without realizing that this conflicts with operand 2. We fix
1439; this by adding another alternative to match this case, and then `reload'
1440; it ourselves. This alternative must come first.
cffb2a26 1441(define_insn "*thumb_mulsi3"
1442 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1443 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1444 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1445 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1446 "*
1447 if (which_alternative < 2)
20c4e896 1448 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1449 else
20c4e896 1450 return \"mul\\t%0, %2\";
cffb2a26 1451 "
1452 [(set_attr "length" "4,4,2")
a2cd141b 1453 (set_attr "insn" "mul")]
cffb2a26 1454)
b11cae9e 1455
58d7d654 1456(define_insn "*thumb_mulsi3_v6"
1457 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1458 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1459 (match_operand:SI 2 "register_operand" "l,0,0")))]
1460 "TARGET_THUMB1 && arm_arch6"
1461 "@
1490694c 1462 mul\\t%0, %2
1463 mul\\t%0, %1
58d7d654 1464 mul\\t%0, %1"
1465 [(set_attr "length" "2")
1466 (set_attr "insn" "mul")]
1467)
1468
f7fbdd4a 1469(define_insn "*mulsi3_compare0"
bd5b4116 1470 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1471 (compare:CC_NOOV (mult:SI
1472 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1473 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1474 (const_int 0)))
1475 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1476 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1477 "TARGET_ARM && !arm_arch6"
1478 "mul%.\\t%0, %2, %1"
1479 [(set_attr "conds" "set")
1480 (set_attr "insn" "muls")]
1481)
1482
1483(define_insn "*mulsi3_compare0_v6"
1484 [(set (reg:CC_NOOV CC_REGNUM)
1485 (compare:CC_NOOV (mult:SI
1486 (match_operand:SI 2 "s_register_operand" "r")
1487 (match_operand:SI 1 "s_register_operand" "r"))
1488 (const_int 0)))
1489 (set (match_operand:SI 0 "s_register_operand" "=r")
1490 (mult:SI (match_dup 2) (match_dup 1)))]
1491 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1492 "mul%.\\t%0, %2, %1"
cffb2a26 1493 [(set_attr "conds" "set")
a2cd141b 1494 (set_attr "insn" "muls")]
cffb2a26 1495)
9c08d1fa 1496
f7fbdd4a 1497(define_insn "*mulsi_compare0_scratch"
bd5b4116 1498 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1499 (compare:CC_NOOV (mult:SI
1500 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1501 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1502 (const_int 0)))
1503 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1504 "TARGET_ARM && !arm_arch6"
1505 "mul%.\\t%0, %2, %1"
1506 [(set_attr "conds" "set")
1507 (set_attr "insn" "muls")]
1508)
1509
1510(define_insn "*mulsi_compare0_scratch_v6"
1511 [(set (reg:CC_NOOV CC_REGNUM)
1512 (compare:CC_NOOV (mult:SI
1513 (match_operand:SI 2 "s_register_operand" "r")
1514 (match_operand:SI 1 "s_register_operand" "r"))
1515 (const_int 0)))
1516 (clobber (match_scratch:SI 0 "=r"))]
1517 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1518 "mul%.\\t%0, %2, %1"
cffb2a26 1519 [(set_attr "conds" "set")
a2cd141b 1520 (set_attr "insn" "muls")]
cffb2a26 1521)
9c08d1fa 1522
b11cae9e 1523;; Unnamed templates to match MLA instruction.
1524
f7fbdd4a 1525(define_insn "*mulsi3addsi"
9c08d1fa 1526 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1527 (plus:SI
9c08d1fa 1528 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1529 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1530 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1531 "TARGET_32BIT && !arm_arch6"
1532 "mla%?\\t%0, %2, %1, %3"
1533 [(set_attr "insn" "mla")
1534 (set_attr "predicable" "yes")]
1535)
1536
1537(define_insn "*mulsi3addsi_v6"
1538 [(set (match_operand:SI 0 "s_register_operand" "=r")
1539 (plus:SI
1540 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1541 (match_operand:SI 1 "s_register_operand" "r"))
1542 (match_operand:SI 3 "s_register_operand" "r")))]
1543 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1544 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1545 [(set_attr "insn" "mla")
0d66636f 1546 (set_attr "predicable" "yes")]
1547)
b11cae9e 1548
f7fbdd4a 1549(define_insn "*mulsi3addsi_compare0"
bd5b4116 1550 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1551 (compare:CC_NOOV
1552 (plus:SI (mult:SI
1553 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1554 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1555 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1556 (const_int 0)))
9c08d1fa 1557 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1558 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1559 (match_dup 3)))]
58d7d654 1560 "TARGET_ARM && arm_arch6"
1561 "mla%.\\t%0, %2, %1, %3"
1562 [(set_attr "conds" "set")
1563 (set_attr "insn" "mlas")]
1564)
1565
1566(define_insn "*mulsi3addsi_compare0_v6"
1567 [(set (reg:CC_NOOV CC_REGNUM)
1568 (compare:CC_NOOV
1569 (plus:SI (mult:SI
1570 (match_operand:SI 2 "s_register_operand" "r")
1571 (match_operand:SI 1 "s_register_operand" "r"))
1572 (match_operand:SI 3 "s_register_operand" "r"))
1573 (const_int 0)))
1574 (set (match_operand:SI 0 "s_register_operand" "=r")
1575 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1576 (match_dup 3)))]
1577 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1578 "mla%.\\t%0, %2, %1, %3"
0d66636f 1579 [(set_attr "conds" "set")
a2cd141b 1580 (set_attr "insn" "mlas")]
0d66636f 1581)
9c08d1fa 1582
f7fbdd4a 1583(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1584 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1585 (compare:CC_NOOV
1586 (plus:SI (mult:SI
1587 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1588 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1589 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1590 (const_int 0)))
9c08d1fa 1591 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1592 "TARGET_ARM && !arm_arch6"
1593 "mla%.\\t%0, %2, %1, %3"
1594 [(set_attr "conds" "set")
1595 (set_attr "insn" "mlas")]
1596)
1597
1598(define_insn "*mulsi3addsi_compare0_scratch_v6"
1599 [(set (reg:CC_NOOV CC_REGNUM)
1600 (compare:CC_NOOV
1601 (plus:SI (mult:SI
1602 (match_operand:SI 2 "s_register_operand" "r")
1603 (match_operand:SI 1 "s_register_operand" "r"))
1604 (match_operand:SI 3 "s_register_operand" "r"))
1605 (const_int 0)))
1606 (clobber (match_scratch:SI 0 "=r"))]
1607 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1608 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1609 [(set_attr "conds" "set")
a2cd141b 1610 (set_attr "insn" "mlas")]
cffb2a26 1611)
f7fbdd4a 1612
89545238 1613(define_insn "*mulsi3subsi"
1614 [(set (match_operand:SI 0 "s_register_operand" "=r")
1615 (minus:SI
1616 (match_operand:SI 3 "s_register_operand" "r")
1617 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1618 (match_operand:SI 1 "s_register_operand" "r"))))]
1619 "TARGET_32BIT && arm_arch_thumb2"
1620 "mls%?\\t%0, %2, %1, %3"
1621 [(set_attr "insn" "mla")
1622 (set_attr "predicable" "yes")]
1623)
1624
5cdca009 1625(define_expand "maddsidi4"
1626 [(set (match_operand:DI 0 "s_register_operand" "")
1627 (plus:DI
1628 (mult:DI
1629 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1630 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1631 (match_operand:DI 3 "s_register_operand" "")))]
1632 "TARGET_32BIT && arm_arch3m"
1633 "")
82b85d08 1634
1635(define_insn "*mulsidi3adddi"
fe8dbf85 1636 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1637 (plus:DI
215b30b3 1638 (mult:DI
fe8dbf85 1639 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1640 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1641 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1642 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1643 "smlal%?\\t%Q0, %R0, %3, %2"
1644 [(set_attr "insn" "smlal")
1645 (set_attr "predicable" "yes")]
1646)
1647
1648(define_insn "*mulsidi3adddi_v6"
1649 [(set (match_operand:DI 0 "s_register_operand" "=r")
1650 (plus:DI
1651 (mult:DI
1652 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1653 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1654 (match_operand:DI 1 "s_register_operand" "0")))]
1655 "TARGET_32BIT && arm_arch6"
fe8dbf85 1656 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1657 [(set_attr "insn" "smlal")
0d66636f 1658 (set_attr "predicable" "yes")]
1659)
82b85d08 1660
957788b0 1661;; 32x32->64 widening multiply.
1662;; As with mulsi3, the only difference between the v3-5 and v6+
1663;; versions of these patterns is the requirement that the output not
1664;; overlap the inputs, but that still means we have to have a named
1665;; expander and two different starred insns.
1666
1667(define_expand "mulsidi3"
1668 [(set (match_operand:DI 0 "s_register_operand" "")
1669 (mult:DI
1670 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1671 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1672 "TARGET_32BIT && arm_arch3m"
1673 ""
1674)
1675
1676(define_insn "*mulsidi3_nov6"
f7fbdd4a 1677 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1678 (mult:DI
1679 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1680 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1681 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1682 "smull%?\\t%Q0, %R0, %1, %2"
1683 [(set_attr "insn" "smull")
1684 (set_attr "predicable" "yes")]
1685)
1686
957788b0 1687(define_insn "*mulsidi3_v6"
58d7d654 1688 [(set (match_operand:DI 0 "s_register_operand" "=r")
1689 (mult:DI
1690 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1691 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1692 "TARGET_32BIT && arm_arch6"
97499065 1693 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1694 [(set_attr "insn" "smull")
0d66636f 1695 (set_attr "predicable" "yes")]
1696)
f7fbdd4a 1697
957788b0 1698(define_expand "umulsidi3"
1699 [(set (match_operand:DI 0 "s_register_operand" "")
1700 (mult:DI
1701 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1702 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1703 "TARGET_32BIT && arm_arch3m"
1704 ""
1705)
1706
1707(define_insn "*umulsidi3_nov6"
f7fbdd4a 1708 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1709 (mult:DI
1710 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1711 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1712 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1713 "umull%?\\t%Q0, %R0, %1, %2"
1714 [(set_attr "insn" "umull")
1715 (set_attr "predicable" "yes")]
1716)
1717
957788b0 1718(define_insn "*umulsidi3_v6"
58d7d654 1719 [(set (match_operand:DI 0 "s_register_operand" "=r")
1720 (mult:DI
1721 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1722 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1723 "TARGET_32BIT && arm_arch6"
97499065 1724 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1725 [(set_attr "insn" "umull")
0d66636f 1726 (set_attr "predicable" "yes")]
1727)
b11cae9e 1728
5cdca009 1729(define_expand "umaddsidi4"
1730 [(set (match_operand:DI 0 "s_register_operand" "")
1731 (plus:DI
1732 (mult:DI
1733 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1734 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1735 (match_operand:DI 3 "s_register_operand" "")))]
1736 "TARGET_32BIT && arm_arch3m"
1737 "")
82b85d08 1738
1739(define_insn "*umulsidi3adddi"
8ead09f9 1740 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1741 (plus:DI
215b30b3 1742 (mult:DI
fe8dbf85 1743 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1744 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1745 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1746 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1747 "umlal%?\\t%Q0, %R0, %3, %2"
1748 [(set_attr "insn" "umlal")
1749 (set_attr "predicable" "yes")]
1750)
1751
1752(define_insn "*umulsidi3adddi_v6"
1753 [(set (match_operand:DI 0 "s_register_operand" "=r")
1754 (plus:DI
1755 (mult:DI
1756 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1757 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1758 (match_operand:DI 1 "s_register_operand" "0")))]
1759 "TARGET_32BIT && arm_arch6"
fe8dbf85 1760 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1761 [(set_attr "insn" "umlal")
0d66636f 1762 (set_attr "predicable" "yes")]
1763)
82b85d08 1764
957788b0 1765(define_expand "smulsi3_highpart"
1766 [(parallel
1767 [(set (match_operand:SI 0 "s_register_operand" "")
1768 (truncate:SI
1769 (lshiftrt:DI
1770 (mult:DI
1771 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1772 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1773 (const_int 32))))
1774 (clobber (match_scratch:SI 3 ""))])]
1775 "TARGET_32BIT && arm_arch3m"
1776 ""
1777)
1778
1779(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1780 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1781 (truncate:SI
1782 (lshiftrt:DI
215b30b3 1783 (mult:DI
e5fea38e 1784 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1785 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1786 (const_int 32))))
1787 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1788 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1789 "smull%?\\t%3, %0, %2, %1"
1790 [(set_attr "insn" "smull")
1791 (set_attr "predicable" "yes")]
1792)
1793
957788b0 1794(define_insn "*smulsi3_highpart_v6"
58d7d654 1795 [(set (match_operand:SI 0 "s_register_operand" "=r")
1796 (truncate:SI
1797 (lshiftrt:DI
1798 (mult:DI
1799 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1800 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1801 (const_int 32))))
1802 (clobber (match_scratch:SI 3 "=r"))]
1803 "TARGET_32BIT && arm_arch6"
f082f1c4 1804 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1805 [(set_attr "insn" "smull")
0d66636f 1806 (set_attr "predicable" "yes")]
cffb2a26 1807)
f082f1c4 1808
957788b0 1809(define_expand "umulsi3_highpart"
1810 [(parallel
1811 [(set (match_operand:SI 0 "s_register_operand" "")
1812 (truncate:SI
1813 (lshiftrt:DI
1814 (mult:DI
1815 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1816 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1817 (const_int 32))))
1818 (clobber (match_scratch:SI 3 ""))])]
1819 "TARGET_32BIT && arm_arch3m"
1820 ""
1821)
1822
1823(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1824 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1825 (truncate:SI
1826 (lshiftrt:DI
215b30b3 1827 (mult:DI
e5fea38e 1828 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1829 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1830 (const_int 32))))
1831 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1832 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1833 "umull%?\\t%3, %0, %2, %1"
1834 [(set_attr "insn" "umull")
1835 (set_attr "predicable" "yes")]
1836)
1837
957788b0 1838(define_insn "*umulsi3_highpart_v6"
58d7d654 1839 [(set (match_operand:SI 0 "s_register_operand" "=r")
1840 (truncate:SI
1841 (lshiftrt:DI
1842 (mult:DI
1843 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1844 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1845 (const_int 32))))
1846 (clobber (match_scratch:SI 3 "=r"))]
1847 "TARGET_32BIT && arm_arch6"
f082f1c4 1848 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1849 [(set_attr "insn" "umull")
0d66636f 1850 (set_attr "predicable" "yes")]
cffb2a26 1851)
f082f1c4 1852
331beb1a 1853(define_insn "mulhisi3"
1854 [(set (match_operand:SI 0 "s_register_operand" "=r")
1855 (mult:SI (sign_extend:SI
1856 (match_operand:HI 1 "s_register_operand" "%r"))
1857 (sign_extend:SI
1858 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1859 "TARGET_DSP_MULTIPLY"
61a2d04c 1860 "smulbb%?\\t%0, %1, %2"
a2cd141b 1861 [(set_attr "insn" "smulxy")
fec538d9 1862 (set_attr "predicable" "yes")]
1863)
1864
1865(define_insn "*mulhisi3tb"
1866 [(set (match_operand:SI 0 "s_register_operand" "=r")
1867 (mult:SI (ashiftrt:SI
1868 (match_operand:SI 1 "s_register_operand" "r")
1869 (const_int 16))
1870 (sign_extend:SI
1871 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1872 "TARGET_DSP_MULTIPLY"
fec538d9 1873 "smultb%?\\t%0, %1, %2"
a2cd141b 1874 [(set_attr "insn" "smulxy")
fec538d9 1875 (set_attr "predicable" "yes")]
1876)
1877
1878(define_insn "*mulhisi3bt"
1879 [(set (match_operand:SI 0 "s_register_operand" "=r")
1880 (mult:SI (sign_extend:SI
1881 (match_operand:HI 1 "s_register_operand" "r"))
1882 (ashiftrt:SI
1883 (match_operand:SI 2 "s_register_operand" "r")
1884 (const_int 16))))]
25f905c2 1885 "TARGET_DSP_MULTIPLY"
fec538d9 1886 "smulbt%?\\t%0, %1, %2"
a2cd141b 1887 [(set_attr "insn" "smulxy")
fec538d9 1888 (set_attr "predicable" "yes")]
1889)
1890
1891(define_insn "*mulhisi3tt"
1892 [(set (match_operand:SI 0 "s_register_operand" "=r")
1893 (mult:SI (ashiftrt:SI
1894 (match_operand:SI 1 "s_register_operand" "r")
1895 (const_int 16))
1896 (ashiftrt:SI
1897 (match_operand:SI 2 "s_register_operand" "r")
1898 (const_int 16))))]
25f905c2 1899 "TARGET_DSP_MULTIPLY"
fec538d9 1900 "smultt%?\\t%0, %1, %2"
a2cd141b 1901 [(set_attr "insn" "smulxy")
fec538d9 1902 (set_attr "predicable" "yes")]
331beb1a 1903)
1904
5cdca009 1905(define_insn "maddhisi4"
331beb1a 1906 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1907 (plus:SI (mult:SI (sign_extend:SI
1908 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1909 (sign_extend:SI
cfa6c608 1910 (match_operand:HI 2 "s_register_operand" "r")))
1911 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1912 "TARGET_DSP_MULTIPLY"
5cdca009 1913 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1914 [(set_attr "insn" "smlaxy")
fec538d9 1915 (set_attr "predicable" "yes")]
331beb1a 1916)
1917
9a92f368 1918;; Note: there is no maddhisi4ibt because this one is canonical form
1919(define_insn "*maddhisi4tb"
1920 [(set (match_operand:SI 0 "s_register_operand" "=r")
1921 (plus:SI (mult:SI (ashiftrt:SI
1922 (match_operand:SI 1 "s_register_operand" "r")
1923 (const_int 16))
1924 (sign_extend:SI
1925 (match_operand:HI 2 "s_register_operand" "r")))
1926 (match_operand:SI 3 "s_register_operand" "r")))]
1927 "TARGET_DSP_MULTIPLY"
1928 "smlatb%?\\t%0, %1, %2, %3"
1929 [(set_attr "insn" "smlaxy")
1930 (set_attr "predicable" "yes")]
1931)
1932
1933(define_insn "*maddhisi4tt"
1934 [(set (match_operand:SI 0 "s_register_operand" "=r")
1935 (plus:SI (mult:SI (ashiftrt:SI
1936 (match_operand:SI 1 "s_register_operand" "r")
1937 (const_int 16))
1938 (ashiftrt:SI
1939 (match_operand:SI 2 "s_register_operand" "r")
1940 (const_int 16)))
1941 (match_operand:SI 3 "s_register_operand" "r")))]
1942 "TARGET_DSP_MULTIPLY"
1943 "smlatt%?\\t%0, %1, %2, %3"
1944 [(set_attr "insn" "smlaxy")
1945 (set_attr "predicable" "yes")]
1946)
1947
aff5fb4d 1948(define_insn "maddhidi4"
331beb1a 1949 [(set (match_operand:DI 0 "s_register_operand" "=r")
1950 (plus:DI
331beb1a 1951 (mult:DI (sign_extend:DI
cfa6c608 1952 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1953 (sign_extend:DI
cfa6c608 1954 (match_operand:HI 2 "s_register_operand" "r")))
1955 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1956 "TARGET_DSP_MULTIPLY"
5cdca009 1957 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1958 [(set_attr "insn" "smlalxy")
fec538d9 1959 (set_attr "predicable" "yes")])
331beb1a 1960
9a92f368 1961;; Note: there is no maddhidi4ibt because this one is canonical form
1962(define_insn "*maddhidi4tb"
1963 [(set (match_operand:DI 0 "s_register_operand" "=r")
1964 (plus:DI
1965 (mult:DI (sign_extend:DI
1966 (ashiftrt:SI
1967 (match_operand:SI 1 "s_register_operand" "r")
1968 (const_int 16)))
1969 (sign_extend:DI
1970 (match_operand:HI 2 "s_register_operand" "r")))
1971 (match_operand:DI 3 "s_register_operand" "0")))]
1972 "TARGET_DSP_MULTIPLY"
1973 "smlaltb%?\\t%Q0, %R0, %1, %2"
1974 [(set_attr "insn" "smlalxy")
1975 (set_attr "predicable" "yes")])
1976
1977(define_insn "*maddhidi4tt"
1978 [(set (match_operand:DI 0 "s_register_operand" "=r")
1979 (plus:DI
1980 (mult:DI (sign_extend:DI
1981 (ashiftrt:SI
1982 (match_operand:SI 1 "s_register_operand" "r")
1983 (const_int 16)))
1984 (sign_extend:DI
1985 (ashiftrt:SI
1986 (match_operand:SI 2 "s_register_operand" "r")
1987 (const_int 16))))
1988 (match_operand:DI 3 "s_register_operand" "0")))]
1989 "TARGET_DSP_MULTIPLY"
1990 "smlaltt%?\\t%Q0, %R0, %1, %2"
1991 [(set_attr "insn" "smlalxy")
1992 (set_attr "predicable" "yes")])
1993
604f3a0a 1994(define_expand "mulsf3"
1995 [(set (match_operand:SF 0 "s_register_operand" "")
1996 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1997 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1998 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1999 "
604f3a0a 2000")
2001
604f3a0a 2002(define_expand "muldf3"
2003 [(set (match_operand:DF 0 "s_register_operand" "")
2004 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 2005 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 2006 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2007 "
604f3a0a 2008")
b11cae9e 2009\f
2010;; Division insns
2011
7db9af5d 2012(define_expand "divsf3"
2013 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 2014 (div:SF (match_operand:SF 1 "s_register_operand" "")
2015 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 2016 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 2017 "")
9c08d1fa 2018
7db9af5d 2019(define_expand "divdf3"
2020 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 2021 (div:DF (match_operand:DF 1 "s_register_operand" "")
2022 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 2023 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2024 "")
b11cae9e 2025\f
2026;; Boolean and,ior,xor insns
2027
f6ebffac 2028;; Split up double word logical operations
2029
2030;; Split up simple DImode logical operations. Simply perform the logical
2031;; operation on the upper and lower halves of the registers.
2032(define_split
2033 [(set (match_operand:DI 0 "s_register_operand" "")
2034 (match_operator:DI 6 "logical_binary_operator"
2035 [(match_operand:DI 1 "s_register_operand" "")
2036 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2037 "TARGET_32BIT && reload_completed
e2669ea7 2038 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2039 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2040 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2041 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2042 "
215b30b3 2043 {
2044 operands[3] = gen_highpart (SImode, operands[0]);
2045 operands[0] = gen_lowpart (SImode, operands[0]);
2046 operands[4] = gen_highpart (SImode, operands[1]);
2047 operands[1] = gen_lowpart (SImode, operands[1]);
2048 operands[5] = gen_highpart (SImode, operands[2]);
2049 operands[2] = gen_lowpart (SImode, operands[2]);
2050 }"
2051)
f6ebffac 2052
f6ebffac 2053(define_split
2054 [(set (match_operand:DI 0 "s_register_operand" "")
2055 (match_operator:DI 6 "logical_binary_operator"
2056 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2057 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2058 "TARGET_32BIT && reload_completed"
f6ebffac 2059 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2060 (set (match_dup 3) (match_op_dup:SI 6
2061 [(ashiftrt:SI (match_dup 2) (const_int 31))
2062 (match_dup 4)]))]
2063 "
215b30b3 2064 {
2065 operands[3] = gen_highpart (SImode, operands[0]);
2066 operands[0] = gen_lowpart (SImode, operands[0]);
2067 operands[4] = gen_highpart (SImode, operands[1]);
2068 operands[1] = gen_lowpart (SImode, operands[1]);
2069 operands[5] = gen_highpart (SImode, operands[2]);
2070 operands[2] = gen_lowpart (SImode, operands[2]);
2071 }"
2072)
f6ebffac 2073
f6ebffac 2074;; The zero extend of operand 2 means we can just copy the high part of
2075;; operand1 into operand0.
2076(define_split
2077 [(set (match_operand:DI 0 "s_register_operand" "")
2078 (ior:DI
2079 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2080 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2081 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2082 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2083 (set (match_dup 3) (match_dup 4))]
2084 "
215b30b3 2085 {
2086 operands[4] = gen_highpart (SImode, operands[1]);
2087 operands[3] = gen_highpart (SImode, operands[0]);
2088 operands[0] = gen_lowpart (SImode, operands[0]);
2089 operands[1] = gen_lowpart (SImode, operands[1]);
2090 }"
2091)
f6ebffac 2092
2093;; The zero extend of operand 2 means we can just copy the high part of
2094;; operand1 into operand0.
2095(define_split
2096 [(set (match_operand:DI 0 "s_register_operand" "")
2097 (xor:DI
2098 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2099 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2100 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2101 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2102 (set (match_dup 3) (match_dup 4))]
2103 "
215b30b3 2104 {
2105 operands[4] = gen_highpart (SImode, operands[1]);
2106 operands[3] = gen_highpart (SImode, operands[0]);
2107 operands[0] = gen_lowpart (SImode, operands[0]);
2108 operands[1] = gen_lowpart (SImode, operands[1]);
2109 }"
2110)
f6ebffac 2111
e2669ea7 2112(define_expand "anddi3"
2113 [(set (match_operand:DI 0 "s_register_operand" "")
2114 (and:DI (match_operand:DI 1 "s_register_operand" "")
2115 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2116 "TARGET_32BIT"
2117 ""
2118)
2119
2120(define_insn "*anddi3_insn"
cffb2a26 2121 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2122 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2123 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2124 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2125 "#"
215b30b3 2126 [(set_attr "length" "8")]
2127)
b11cae9e 2128
a0f94409 2129(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2130 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2131 (and:DI (zero_extend:DI
2132 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2133 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2134 "TARGET_32BIT"
f6ebffac 2135 "#"
25f905c2 2136 "TARGET_32BIT && reload_completed"
a0f94409 2137 ; The zero extend of operand 2 clears the high word of the output
2138 ; operand.
2139 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2140 (set (match_dup 3) (const_int 0))]
2141 "
2142 {
2143 operands[3] = gen_highpart (SImode, operands[0]);
2144 operands[0] = gen_lowpart (SImode, operands[0]);
2145 operands[1] = gen_lowpart (SImode, operands[1]);
2146 }"
215b30b3 2147 [(set_attr "length" "8")]
2148)
b11cae9e 2149
f7fbdd4a 2150(define_insn "*anddi_sesdi_di"
cffb2a26 2151 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2152 (and:DI (sign_extend:DI
2153 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2154 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2155 "TARGET_32BIT"
f6ebffac 2156 "#"
cffb2a26 2157 [(set_attr "length" "8")]
2158)
b11cae9e 2159
87b22bf7 2160(define_expand "andsi3"
cffb2a26 2161 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2162 (and:SI (match_operand:SI 1 "s_register_operand" "")
2163 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2164 "TARGET_EITHER"
87b22bf7 2165 "
25f905c2 2166 if (TARGET_32BIT)
87b22bf7 2167 {
0438d37f 2168 if (CONST_INT_P (operands[2]))
cffb2a26 2169 {
47b5b27b 2170 if (INTVAL (operands[2]) == 255 && arm_arch6)
2171 {
2172 operands[1] = convert_to_mode (QImode, operands[1], 1);
2173 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2174 operands[1]));
2175 }
2176 else
2177 arm_split_constant (AND, SImode, NULL_RTX,
2178 INTVAL (operands[2]), operands[0],
2179 operands[1],
2180 optimize && can_create_pseudo_p ());
615caa51 2181
cffb2a26 2182 DONE;
2183 }
87b22bf7 2184 }
25f905c2 2185 else /* TARGET_THUMB1 */
cffb2a26 2186 {
0438d37f 2187 if (!CONST_INT_P (operands[2]))
923ffadb 2188 {
2189 rtx tmp = force_reg (SImode, operands[2]);
2190 if (rtx_equal_p (operands[0], operands[1]))
2191 operands[2] = tmp;
2192 else
2193 {
2194 operands[2] = operands[1];
2195 operands[1] = tmp;
2196 }
2197 }
cffb2a26 2198 else
2199 {
2200 int i;
2201
215b30b3 2202 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2203 {
215b30b3 2204 operands[2] = force_reg (SImode,
2205 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2206
747b7458 2207 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2208
2209 DONE;
2210 }
87b22bf7 2211
cffb2a26 2212 for (i = 9; i <= 31; i++)
2213 {
2214 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2215 {
2216 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2217 const0_rtx));
2218 DONE;
2219 }
215b30b3 2220 else if ((((HOST_WIDE_INT) 1) << i) - 1
2221 == ~INTVAL (operands[2]))
cffb2a26 2222 {
2223 rtx shift = GEN_INT (i);
2224 rtx reg = gen_reg_rtx (SImode);
2225
2226 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2227 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2228
2229 DONE;
2230 }
2231 }
2232
2233 operands[2] = force_reg (SImode, operands[2]);
2234 }
215b30b3 2235 }
2236 "
cffb2a26 2237)
2238
25f905c2 2239; ??? Check split length for Thumb-2
a0f94409 2240(define_insn_and_split "*arm_andsi3_insn"
65f68e55 2241 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
2242 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r,r")
2243 (match_operand:SI 2 "reg_or_int_operand" "I,K,r,?n")))]
25f905c2 2244 "TARGET_32BIT"
5565501b 2245 "@
2246 and%?\\t%0, %1, %2
87b22bf7 2247 bic%?\\t%0, %1, #%B2
65f68e55 2248 and%?\\t%0, %1, %2
87b22bf7 2249 #"
25f905c2 2250 "TARGET_32BIT
0438d37f 2251 && CONST_INT_P (operands[2])
a0f94409 2252 && !(const_ok_for_arm (INTVAL (operands[2]))
2253 || const_ok_for_arm (~INTVAL (operands[2])))"
2254 [(clobber (const_int 0))]
2255 "
96f57e36 2256 arm_split_constant (AND, SImode, curr_insn,
2257 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2258 DONE;
2259 "
65f68e55 2260 [(set_attr "length" "4,4,4,16")
2261 (set_attr "predicable" "yes")
2262 (set_attr "type" "simple_alu_imm,simple_alu_imm,*,simple_alu_imm")]
cffb2a26 2263)
2264
25f905c2 2265(define_insn "*thumb1_andsi3_insn"
cffb2a26 2266 [(set (match_operand:SI 0 "register_operand" "=l")
2267 (and:SI (match_operand:SI 1 "register_operand" "%0")
2268 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2269 "TARGET_THUMB1"
747b7458 2270 "and\\t%0, %2"
2271 [(set_attr "length" "2")
65f68e55 2272 (set_attr "type" "simple_alu_imm")
747b7458 2273 (set_attr "conds" "set")])
87b22bf7 2274
f7fbdd4a 2275(define_insn "*andsi3_compare0"
bd5b4116 2276 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2277 (compare:CC_NOOV
65f68e55 2278 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2279 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2280 (const_int 0)))
65f68e55 2281 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2282 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2283 "TARGET_32BIT"
5565501b 2284 "@
25f905c2 2285 and%.\\t%0, %1, %2
65f68e55 2286 bic%.\\t%0, %1, #%B2
2287 and%.\\t%0, %1, %2"
2288 [(set_attr "conds" "set")
2289 (set_attr "type" "simple_alu_imm,simple_alu_imm,*")]
cffb2a26 2290)
9c08d1fa 2291
f7fbdd4a 2292(define_insn "*andsi3_compare0_scratch"
bd5b4116 2293 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2294 (compare:CC_NOOV
65f68e55 2295 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2296 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2297 (const_int 0)))
65f68e55 2298 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2299 "TARGET_32BIT"
5565501b 2300 "@
2301 tst%?\\t%0, %1
65f68e55 2302 bic%.\\t%2, %0, #%B1
2303 tst%?\\t%0, %1"
2304 [(set_attr "conds" "set")
2305 (set_attr "type" "simple_alu_imm,simple_alu_imm,*")]
0d66636f 2306)
9c08d1fa 2307
f7fbdd4a 2308(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2309 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2310 (compare:CC_NOOV (zero_extract:SI
2311 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2312 (match_operand 1 "const_int_operand" "n")
2313 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2314 (const_int 0)))]
25f905c2 2315 "TARGET_32BIT
cffb2a26 2316 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2317 && INTVAL (operands[1]) > 0
2318 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2319 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2320 "*
5c49a439 2321 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2322 << INTVAL (operands[2]));
40dbec34 2323 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2324 return \"\";
0d66636f 2325 "
596e5e8f 2326 [(set_attr "conds" "set")
65f68e55 2327 (set_attr "predicable" "yes")
2328 (set_attr "type" "simple_alu_imm")]
0d66636f 2329)
9c08d1fa 2330
f4462328 2331(define_insn_and_split "*ne_zeroextractsi"
c4034607 2332 [(set (match_operand:SI 0 "s_register_operand" "=r")
2333 (ne:SI (zero_extract:SI
2334 (match_operand:SI 1 "s_register_operand" "r")
2335 (match_operand:SI 2 "const_int_operand" "n")
2336 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2337 (const_int 0)))
2338 (clobber (reg:CC CC_REGNUM))]
25f905c2 2339 "TARGET_32BIT
cffb2a26 2340 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2341 && INTVAL (operands[2]) > 0
2342 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2343 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2344 "#"
25f905c2 2345 "TARGET_32BIT
f4462328 2346 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2347 && INTVAL (operands[2]) > 0
2348 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2349 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2350 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2351 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2352 (const_int 0)))
2353 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2354 (set (match_dup 0)
2355 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2356 (match_dup 0) (const_int 1)))]
2357 "
2358 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2359 << INTVAL (operands[3]));
2360 "
2361 [(set_attr "conds" "clob")
25f905c2 2362 (set (attr "length")
2363 (if_then_else (eq_attr "is_thumb" "yes")
2364 (const_int 12)
2365 (const_int 8)))]
f4462328 2366)
2367
2368(define_insn_and_split "*ne_zeroextractsi_shifted"
2369 [(set (match_operand:SI 0 "s_register_operand" "=r")
2370 (ne:SI (zero_extract:SI
2371 (match_operand:SI 1 "s_register_operand" "r")
2372 (match_operand:SI 2 "const_int_operand" "n")
2373 (const_int 0))
2374 (const_int 0)))
2375 (clobber (reg:CC CC_REGNUM))]
2376 "TARGET_ARM"
2377 "#"
2378 "TARGET_ARM"
2379 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2380 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2381 (const_int 0)))
2382 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2383 (set (match_dup 0)
2384 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2385 (match_dup 0) (const_int 1)))]
2386 "
2387 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2388 "
2389 [(set_attr "conds" "clob")
2390 (set_attr "length" "8")]
2391)
2392
2393(define_insn_and_split "*ite_ne_zeroextractsi"
2394 [(set (match_operand:SI 0 "s_register_operand" "=r")
2395 (if_then_else:SI (ne (zero_extract:SI
2396 (match_operand:SI 1 "s_register_operand" "r")
2397 (match_operand:SI 2 "const_int_operand" "n")
2398 (match_operand:SI 3 "const_int_operand" "n"))
2399 (const_int 0))
2400 (match_operand:SI 4 "arm_not_operand" "rIK")
2401 (const_int 0)))
2402 (clobber (reg:CC CC_REGNUM))]
2403 "TARGET_ARM
2404 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2405 && INTVAL (operands[2]) > 0
2406 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2407 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2408 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2409 "#"
2410 "TARGET_ARM
2411 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2412 && INTVAL (operands[2]) > 0
2413 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2414 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2415 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2416 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2417 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2418 (const_int 0)))
2419 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2420 (set (match_dup 0)
2421 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2422 (match_dup 0) (match_dup 4)))]
2423 "
c4034607 2424 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2425 << INTVAL (operands[3]));
2426 "
2427 [(set_attr "conds" "clob")
2428 (set_attr "length" "8")]
2429)
2430
2431(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2432 [(set (match_operand:SI 0 "s_register_operand" "=r")
2433 (if_then_else:SI (ne (zero_extract:SI
2434 (match_operand:SI 1 "s_register_operand" "r")
2435 (match_operand:SI 2 "const_int_operand" "n")
2436 (const_int 0))
2437 (const_int 0))
2438 (match_operand:SI 3 "arm_not_operand" "rIK")
2439 (const_int 0)))
2440 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2441 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2442 "#"
f8d7bf2f 2443 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2444 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2445 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2446 (const_int 0)))
2447 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2448 (set (match_dup 0)
2449 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2450 (match_dup 0) (match_dup 3)))]
2451 "
2452 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2453 "
2454 [(set_attr "conds" "clob")
215b30b3 2455 (set_attr "length" "8")]
2456)
9c08d1fa 2457
58d6528b 2458(define_split
2459 [(set (match_operand:SI 0 "s_register_operand" "")
2460 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2461 (match_operand:SI 2 "const_int_operand" "")
2462 (match_operand:SI 3 "const_int_operand" "")))
2463 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2464 "TARGET_THUMB1"
58d6528b 2465 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2466 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2467 "{
2468 HOST_WIDE_INT temp = INTVAL (operands[2]);
2469
2470 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2471 operands[3] = GEN_INT (32 - temp);
2472 }"
2473)
2474
25f905c2 2475;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2476(define_split
2477 [(set (match_operand:SI 0 "s_register_operand" "")
2478 (match_operator:SI 1 "shiftable_operator"
2479 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2480 (match_operand:SI 3 "const_int_operand" "")
2481 (match_operand:SI 4 "const_int_operand" ""))
2482 (match_operand:SI 5 "s_register_operand" "")]))
2483 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2484 "TARGET_ARM"
2485 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2486 (set (match_dup 0)
2487 (match_op_dup 1
2488 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2489 (match_dup 5)]))]
2490 "{
2491 HOST_WIDE_INT temp = INTVAL (operands[3]);
2492
2493 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2494 operands[4] = GEN_INT (32 - temp);
2495 }"
2496)
2497
58d6528b 2498(define_split
2499 [(set (match_operand:SI 0 "s_register_operand" "")
2500 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2501 (match_operand:SI 2 "const_int_operand" "")
2502 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2503 "TARGET_THUMB1"
58d6528b 2504 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2505 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2506 "{
2507 HOST_WIDE_INT temp = INTVAL (operands[2]);
2508
2509 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2510 operands[3] = GEN_INT (32 - temp);
2511 }"
2512)
2513
d7863cfe 2514(define_split
2515 [(set (match_operand:SI 0 "s_register_operand" "")
2516 (match_operator:SI 1 "shiftable_operator"
2517 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2518 (match_operand:SI 3 "const_int_operand" "")
2519 (match_operand:SI 4 "const_int_operand" ""))
2520 (match_operand:SI 5 "s_register_operand" "")]))
2521 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2522 "TARGET_ARM"
2523 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2524 (set (match_dup 0)
2525 (match_op_dup 1
2526 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2527 (match_dup 5)]))]
2528 "{
2529 HOST_WIDE_INT temp = INTVAL (operands[3]);
2530
2531 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2532 operands[4] = GEN_INT (32 - temp);
2533 }"
2534)
2535
a42059fd 2536;;; ??? This pattern is bogus. If operand3 has bits outside the range
2537;;; represented by the bitfield, then this will produce incorrect results.
2538;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2539;;; which have a real bit-field insert instruction, the truncation happens
2540;;; in the bit-field insert instruction itself. Since arm does not have a
2541;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2542;;; the value before we insert. This loses some of the advantage of having
2543;;; this insv pattern, so this pattern needs to be reevalutated.
2544
8a18b90c 2545(define_expand "insv"
eb04cafb 2546 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2547 (match_operand 1 "general_operand" "")
2548 (match_operand 2 "general_operand" ""))
2549 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2550 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2551 "
215b30b3 2552 {
2553 int start_bit = INTVAL (operands[2]);
2554 int width = INTVAL (operands[1]);
2555 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2556 rtx target, subtarget;
2557
8b054d5a 2558 if (arm_arch_thumb2)
2559 {
eb04cafb 2560 if (unaligned_access && MEM_P (operands[0])
2561 && s_register_operand (operands[3], GET_MODE (operands[3]))
2562 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2563 {
eb04cafb 2564 rtx base_addr;
2565
2566 if (BYTES_BIG_ENDIAN)
2567 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2568 - start_bit;
8b054d5a 2569
eb04cafb 2570 if (width == 32)
8b054d5a 2571 {
eb04cafb 2572 base_addr = adjust_address (operands[0], SImode,
2573 start_bit / BITS_PER_UNIT);
2574 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2575 }
eb04cafb 2576 else
2577 {
2578 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2579
eb04cafb 2580 base_addr = adjust_address (operands[0], HImode,
2581 start_bit / BITS_PER_UNIT);
2582 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2583 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2584 }
2585 DONE;
8b054d5a 2586 }
eb04cafb 2587 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2588 {
eb04cafb 2589 bool use_bfi = TRUE;
8b054d5a 2590
0438d37f 2591 if (CONST_INT_P (operands[3]))
eb04cafb 2592 {
2593 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2594
2595 if (val == 0)
2596 {
2597 emit_insn (gen_insv_zero (operands[0], operands[1],
2598 operands[2]));
2599 DONE;
2600 }
2601
2602 /* See if the set can be done with a single orr instruction. */
2603 if (val == mask && const_ok_for_arm (val << start_bit))
2604 use_bfi = FALSE;
2605 }
2606
2607 if (use_bfi)
2608 {
0438d37f 2609 if (!REG_P (operands[3]))
eb04cafb 2610 operands[3] = force_reg (SImode, operands[3]);
2611
2612 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2613 operands[3]));
2614 DONE;
2615 }
8b054d5a 2616 }
eb04cafb 2617 else
2618 FAIL;
8b054d5a 2619 }
2620
eb04cafb 2621 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2622 FAIL;
2623
3f8fde42 2624 target = copy_rtx (operands[0]);
215b30b3 2625 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2626 subreg as the final target. */
2627 if (GET_CODE (target) == SUBREG)
2628 {
2629 subtarget = gen_reg_rtx (SImode);
2630 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2631 < GET_MODE_SIZE (SImode))
2632 target = SUBREG_REG (target);
2633 }
2634 else
2635 subtarget = target;
8a18b90c 2636
0438d37f 2637 if (CONST_INT_P (operands[3]))
215b30b3 2638 {
2639 /* Since we are inserting a known constant, we may be able to
2640 reduce the number of bits that we have to clear so that
2641 the mask becomes simple. */
2642 /* ??? This code does not check to see if the new mask is actually
2643 simpler. It may not be. */
2644 rtx op1 = gen_reg_rtx (SImode);
2645 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2646 start of this pattern. */
2647 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2648 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2649
c5b3a71b 2650 emit_insn (gen_andsi3 (op1, operands[0],
2651 gen_int_mode (~mask2, SImode)));
215b30b3 2652 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2653 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2654 }
2655 else if (start_bit == 0
2656 && !(const_ok_for_arm (mask)
2657 || const_ok_for_arm (~mask)))
2658 {
2659 /* A Trick, since we are setting the bottom bits in the word,
2660 we can shift operand[3] up, operand[0] down, OR them together
2661 and rotate the result back again. This takes 3 insns, and
5910bb95 2662 the third might be mergeable into another op. */
215b30b3 2663 /* The shift up copes with the possibility that operand[3] is
2664 wider than the bitfield. */
2665 rtx op0 = gen_reg_rtx (SImode);
2666 rtx op1 = gen_reg_rtx (SImode);
2667
2668 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2669 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2670 emit_insn (gen_iorsi3 (op1, op1, op0));
2671 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2672 }
2673 else if ((width + start_bit == 32)
2674 && !(const_ok_for_arm (mask)
2675 || const_ok_for_arm (~mask)))
2676 {
2677 /* Similar trick, but slightly less efficient. */
8a18b90c 2678
215b30b3 2679 rtx op0 = gen_reg_rtx (SImode);
2680 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2681
215b30b3 2682 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2683 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2684 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2685 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2686 }
2687 else
2688 {
c5b3a71b 2689 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2690 rtx op1 = gen_reg_rtx (SImode);
2691 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2692
215b30b3 2693 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2694 {
2695 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2696
215b30b3 2697 emit_insn (gen_movsi (tmp, op0));
2698 op0 = tmp;
2699 }
8a18b90c 2700
215b30b3 2701 /* Mask out any bits in operand[3] that are not needed. */
2702 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2703
0438d37f 2704 if (CONST_INT_P (op0)
215b30b3 2705 && (const_ok_for_arm (mask << start_bit)
2706 || const_ok_for_arm (~(mask << start_bit))))
2707 {
c5b3a71b 2708 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2709 emit_insn (gen_andsi3 (op2, operands[0], op0));
2710 }
2711 else
2712 {
0438d37f 2713 if (CONST_INT_P (op0))
215b30b3 2714 {
2715 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2716
215b30b3 2717 emit_insn (gen_movsi (tmp, op0));
2718 op0 = tmp;
2719 }
2720
2721 if (start_bit != 0)
2722 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2723
215b30b3 2724 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2725 }
8a18b90c 2726
215b30b3 2727 if (start_bit != 0)
2728 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2729
215b30b3 2730 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2731 }
f082f1c4 2732
215b30b3 2733 if (subtarget != target)
2734 {
2735 /* If TARGET is still a SUBREG, then it must be wider than a word,
2736 so we must be careful only to set the subword we were asked to. */
2737 if (GET_CODE (target) == SUBREG)
2738 emit_move_insn (target, subtarget);
2739 else
2740 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2741 }
8a18b90c 2742
215b30b3 2743 DONE;
2744 }"
2745)
8a18b90c 2746
8b054d5a 2747(define_insn "insv_zero"
2748 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2749 (match_operand:SI 1 "const_int_operand" "M")
2750 (match_operand:SI 2 "const_int_operand" "M"))
2751 (const_int 0))]
2752 "arm_arch_thumb2"
2753 "bfc%?\t%0, %2, %1"
2754 [(set_attr "length" "4")
2755 (set_attr "predicable" "yes")]
2756)
2757
2758(define_insn "insv_t2"
2759 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2760 (match_operand:SI 1 "const_int_operand" "M")
2761 (match_operand:SI 2 "const_int_operand" "M"))
2762 (match_operand:SI 3 "s_register_operand" "r"))]
2763 "arm_arch_thumb2"
2764 "bfi%?\t%0, %3, %2, %1"
2765 [(set_attr "length" "4")
2766 (set_attr "predicable" "yes")]
2767)
2768
215b30b3 2769; constants for op 2 will never be given to these patterns.
a0f94409 2770(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2771 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2772 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2773 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2774 "TARGET_32BIT"
f6ebffac 2775 "#"
e2669ea7 2776 "TARGET_32BIT && reload_completed
2777 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2778 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2779 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2780 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2781 "
2782 {
2783 operands[3] = gen_highpart (SImode, operands[0]);
2784 operands[0] = gen_lowpart (SImode, operands[0]);
2785 operands[4] = gen_highpart (SImode, operands[1]);
2786 operands[1] = gen_lowpart (SImode, operands[1]);
2787 operands[5] = gen_highpart (SImode, operands[2]);
2788 operands[2] = gen_lowpart (SImode, operands[2]);
2789 }"
0d66636f 2790 [(set_attr "length" "8")
2791 (set_attr "predicable" "yes")]
2792)
9c08d1fa 2793
a0f94409 2794(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2795 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2796 (and:DI (not:DI (zero_extend:DI
2797 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2798 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2799 "TARGET_32BIT"
e2348bcb 2800 "@
97499065 2801 bic%?\\t%Q0, %Q1, %2
f6ebffac 2802 #"
a0f94409 2803 ; (not (zero_extend ...)) allows us to just copy the high word from
2804 ; operand1 to operand0.
25f905c2 2805 "TARGET_32BIT
a0f94409 2806 && reload_completed
2807 && operands[0] != operands[1]"
5a097f7d 2808 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2809 (set (match_dup 3) (match_dup 4))]
2810 "
2811 {
2812 operands[3] = gen_highpart (SImode, operands[0]);
2813 operands[0] = gen_lowpart (SImode, operands[0]);
2814 operands[4] = gen_highpart (SImode, operands[1]);
2815 operands[1] = gen_lowpart (SImode, operands[1]);
2816 }"
0d66636f 2817 [(set_attr "length" "4,8")
2818 (set_attr "predicable" "yes")]
2819)
9c08d1fa 2820
a0f94409 2821(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2822 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2823 (and:DI (not:DI (sign_extend:DI
2824 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2825 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2826 "TARGET_32BIT"
f6ebffac 2827 "#"
25f905c2 2828 "TARGET_32BIT && reload_completed"
5a097f7d 2829 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2830 (set (match_dup 3) (and:SI (not:SI
2831 (ashiftrt:SI (match_dup 2) (const_int 31)))
2832 (match_dup 4)))]
2833 "
2834 {
2835 operands[3] = gen_highpart (SImode, operands[0]);
2836 operands[0] = gen_lowpart (SImode, operands[0]);
2837 operands[4] = gen_highpart (SImode, operands[1]);
2838 operands[1] = gen_lowpart (SImode, operands[1]);
2839 }"
0d66636f 2840 [(set_attr "length" "8")
2841 (set_attr "predicable" "yes")]
2842)
9c08d1fa 2843
8a18b90c 2844(define_insn "andsi_notsi_si"
9c08d1fa 2845 [(set (match_operand:SI 0 "s_register_operand" "=r")
2846 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2847 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2848 "TARGET_32BIT"
0d66636f 2849 "bic%?\\t%0, %1, %2"
2850 [(set_attr "predicable" "yes")]
2851)
b11cae9e 2852
747b7458 2853(define_insn "thumb1_bicsi3"
cffb2a26 2854 [(set (match_operand:SI 0 "register_operand" "=l")
2855 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2856 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2857 "TARGET_THUMB1"
747b7458 2858 "bic\\t%0, %1"
2859 [(set_attr "length" "2")
2860 (set_attr "conds" "set")])
cffb2a26 2861
8a18b90c 2862(define_insn "andsi_not_shiftsi_si"
a2cd141b 2863 [(set (match_operand:SI 0 "s_register_operand" "=r")
2864 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2865 [(match_operand:SI 2 "s_register_operand" "r")
2866 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2867 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2868 "TARGET_ARM"
6c4c2133 2869 "bic%?\\t%0, %1, %2%S4"
344495ea 2870 [(set_attr "predicable" "yes")
331beb1a 2871 (set_attr "shift" "2")
a2cd141b 2872 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2873 (const_string "alu_shift")
2874 (const_string "alu_shift_reg")))]
6c4c2133 2875)
8a18b90c 2876
f7fbdd4a 2877(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2878 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2879 (compare:CC_NOOV
2880 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2881 (match_operand:SI 1 "s_register_operand" "r"))
2882 (const_int 0)))
9c08d1fa 2883 (set (match_operand:SI 0 "s_register_operand" "=r")
2884 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2885 "TARGET_32BIT"
2886 "bic%.\\t%0, %1, %2"
0d66636f 2887 [(set_attr "conds" "set")]
2888)
9c08d1fa 2889
f7fbdd4a 2890(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2891 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2892 (compare:CC_NOOV
2893 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2894 (match_operand:SI 1 "s_register_operand" "r"))
2895 (const_int 0)))
9c08d1fa 2896 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2897 "TARGET_32BIT"
2898 "bic%.\\t%0, %1, %2"
0d66636f 2899 [(set_attr "conds" "set")]
2900)
9c08d1fa 2901
e2669ea7 2902(define_expand "iordi3"
2903 [(set (match_operand:DI 0 "s_register_operand" "")
2904 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2905 (match_operand:DI 2 "neon_logic_op2" "")))]
2906 "TARGET_32BIT"
2907 ""
2908)
2909
2910(define_insn "*iordi3_insn"
cffb2a26 2911 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2912 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2913 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2914 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2915 "#"
0d66636f 2916 [(set_attr "length" "8")
2917 (set_attr "predicable" "yes")]
cffb2a26 2918)
9c08d1fa 2919
f7fbdd4a 2920(define_insn "*iordi_zesidi_di"
9c08d1fa 2921 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2922 (ior:DI (zero_extend:DI
2923 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2924 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2925 "TARGET_32BIT"
e2348bcb 2926 "@
97499065 2927 orr%?\\t%Q0, %Q1, %2
f6ebffac 2928 #"
0d66636f 2929 [(set_attr "length" "4,8")
2930 (set_attr "predicable" "yes")]
cffb2a26 2931)
9c08d1fa 2932
f7fbdd4a 2933(define_insn "*iordi_sesidi_di"
9c08d1fa 2934 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2935 (ior:DI (sign_extend:DI
2936 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2937 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2938 "TARGET_32BIT"
f6ebffac 2939 "#"
0d66636f 2940 [(set_attr "length" "8")
2941 (set_attr "predicable" "yes")]
cffb2a26 2942)
9c08d1fa 2943
87b22bf7 2944(define_expand "iorsi3"
cffb2a26 2945 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2946 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2947 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2948 "TARGET_EITHER"
87b22bf7 2949 "
0438d37f 2950 if (CONST_INT_P (operands[2]))
87b22bf7 2951 {
25f905c2 2952 if (TARGET_32BIT)
cffb2a26 2953 {
96f57e36 2954 arm_split_constant (IOR, SImode, NULL_RTX,
2955 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2956 optimize && can_create_pseudo_p ());
cffb2a26 2957 DONE;
2958 }
25f905c2 2959 else /* TARGET_THUMB1 */
923ffadb 2960 {
2961 rtx tmp = force_reg (SImode, operands[2]);
2962 if (rtx_equal_p (operands[0], operands[1]))
2963 operands[2] = tmp;
2964 else
2965 {
2966 operands[2] = operands[1];
2967 operands[1] = tmp;
2968 }
2969 }
87b22bf7 2970 }
cffb2a26 2971 "
2972)
87b22bf7 2973
d5d4dc8d 2974(define_insn_and_split "*iorsi3_insn"
65f68e55 2975 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
2976 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r,r")
2977 (match_operand:SI 2 "reg_or_int_operand" "I,K,r,?n")))]
d5d4dc8d 2978 "TARGET_32BIT"
87b22bf7 2979 "@
2980 orr%?\\t%0, %1, %2
d5d4dc8d 2981 orn%?\\t%0, %1, #%B2
65f68e55 2982 orr%?\\t%0, %1, %2
87b22bf7 2983 #"
d5d4dc8d 2984 "TARGET_32BIT
0438d37f 2985 && CONST_INT_P (operands[2])
d5d4dc8d 2986 && !(const_ok_for_arm (INTVAL (operands[2]))
2987 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2988 [(clobber (const_int 0))]
d5d4dc8d 2989{
96f57e36 2990 arm_split_constant (IOR, SImode, curr_insn,
2991 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2992 DONE;
d5d4dc8d 2993}
65f68e55 2994 [(set_attr "length" "4,4,4,16")
2995 (set_attr "arch" "32,t2,32,32")
2996 (set_attr "predicable" "yes")
2997 (set_attr "type" "simple_alu_imm,simple_alu_imm,*,*")]
2998)
cffb2a26 2999
747b7458 3000(define_insn "*thumb1_iorsi3_insn"
cffb2a26 3001 [(set (match_operand:SI 0 "register_operand" "=l")
3002 (ior:SI (match_operand:SI 1 "register_operand" "%0")
3003 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3004 "TARGET_THUMB1"
747b7458 3005 "orr\\t%0, %2"
3006 [(set_attr "length" "2")
3007 (set_attr "conds" "set")])
9c08d1fa 3008
a0f94409 3009(define_peephole2
3010 [(match_scratch:SI 3 "r")
372575c7 3011 (set (match_operand:SI 0 "arm_general_register_operand" "")
3012 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3013 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3014 "TARGET_ARM
a0f94409 3015 && !const_ok_for_arm (INTVAL (operands[2]))
3016 && const_ok_for_arm (~INTVAL (operands[2]))"
3017 [(set (match_dup 3) (match_dup 2))
3018 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3019 ""
215b30b3 3020)
a0f94409 3021
f7fbdd4a 3022(define_insn "*iorsi3_compare0"
bd5b4116 3023 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3024 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3025 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3026 (const_int 0)))
65f68e55 3027 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3028 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3029 "TARGET_32BIT"
3030 "orr%.\\t%0, %1, %2"
65f68e55 3031 [(set_attr "conds" "set")
3032 (set_attr "type" "simple_alu_imm,*")]
cffb2a26 3033)
9c08d1fa 3034
f7fbdd4a 3035(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3036 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3037 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3038 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3039 (const_int 0)))
65f68e55 3040 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3041 "TARGET_32BIT"
3042 "orr%.\\t%0, %1, %2"
65f68e55 3043 [(set_attr "conds" "set")
3044 (set_attr "type" "simple_alu_imm, *")]
0d66636f 3045)
9c08d1fa 3046
e2669ea7 3047(define_expand "xordi3"
3048 [(set (match_operand:DI 0 "s_register_operand" "")
3049 (xor:DI (match_operand:DI 1 "s_register_operand" "")
3050 (match_operand:DI 2 "s_register_operand" "")))]
3051 "TARGET_32BIT"
3052 ""
3053)
3054
3055(define_insn "*xordi3_insn"
cffb2a26 3056 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3057 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
3058 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 3059 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 3060 "#"
0d66636f 3061 [(set_attr "length" "8")
3062 (set_attr "predicable" "yes")]
cffb2a26 3063)
9c08d1fa 3064
f7fbdd4a 3065(define_insn "*xordi_zesidi_di"
9c08d1fa 3066 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3067 (xor:DI (zero_extend:DI
3068 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3069 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3070 "TARGET_32BIT"
e2348bcb 3071 "@
97499065 3072 eor%?\\t%Q0, %Q1, %2
f6ebffac 3073 #"
0d66636f 3074 [(set_attr "length" "4,8")
3075 (set_attr "predicable" "yes")]
cffb2a26 3076)
9c08d1fa 3077
f7fbdd4a 3078(define_insn "*xordi_sesidi_di"
9c08d1fa 3079 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3080 (xor:DI (sign_extend:DI
3081 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3082 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3083 "TARGET_32BIT"
f6ebffac 3084 "#"
0d66636f 3085 [(set_attr "length" "8")
3086 (set_attr "predicable" "yes")]
cffb2a26 3087)
9c08d1fa 3088
cffb2a26 3089(define_expand "xorsi3"
3090 [(set (match_operand:SI 0 "s_register_operand" "")
3091 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3092 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3093 "TARGET_EITHER"
0438d37f 3094 "if (CONST_INT_P (operands[2]))
923ffadb 3095 {
3096 if (TARGET_32BIT)
3097 {
3098 arm_split_constant (XOR, SImode, NULL_RTX,
3099 INTVAL (operands[2]), operands[0], operands[1],
3100 optimize && can_create_pseudo_p ());
3101 DONE;
3102 }
3103 else /* TARGET_THUMB1 */
3104 {
3105 rtx tmp = force_reg (SImode, operands[2]);
3106 if (rtx_equal_p (operands[0], operands[1]))
3107 operands[2] = tmp;
3108 else
3109 {
3110 operands[2] = operands[1];
3111 operands[1] = tmp;
3112 }
3113 }
3114 }"
cffb2a26 3115)
3116
5dcb35d9 3117(define_insn_and_split "*arm_xorsi3"
65f68e55 3118 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3119 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
3120 (match_operand:SI 2 "reg_or_int_operand" "I,r,?n")))]
25f905c2 3121 "TARGET_32BIT"
5dcb35d9 3122 "@
65f68e55 3123 eor%?\\t%0, %1, %2
5dcb35d9 3124 eor%?\\t%0, %1, %2
3125 #"
3126 "TARGET_32BIT
0438d37f 3127 && CONST_INT_P (operands[2])
5dcb35d9 3128 && !const_ok_for_arm (INTVAL (operands[2]))"
3129 [(clobber (const_int 0))]
3130{
3131 arm_split_constant (XOR, SImode, curr_insn,
3132 INTVAL (operands[2]), operands[0], operands[1], 0);
3133 DONE;
3134}
65f68e55 3135 [(set_attr "length" "4,4,16")
3136 (set_attr "predicable" "yes")
3137 (set_attr "type" "simple_alu_imm,*,*")]
cffb2a26 3138)
3139
747b7458 3140(define_insn "*thumb1_xorsi3_insn"
cffb2a26 3141 [(set (match_operand:SI 0 "register_operand" "=l")
3142 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3143 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3144 "TARGET_THUMB1"
747b7458 3145 "eor\\t%0, %2"
3146 [(set_attr "length" "2")
65f68e55 3147 (set_attr "conds" "set")
3148 (set_attr "type" "simple_alu_imm")]
3149)
9c08d1fa 3150
f7fbdd4a 3151(define_insn "*xorsi3_compare0"
bd5b4116 3152 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3153 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3154 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3155 (const_int 0)))
65f68e55 3156 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3157 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3158 "TARGET_32BIT"
3159 "eor%.\\t%0, %1, %2"
65f68e55 3160 [(set_attr "conds" "set")
3161 (set_attr "type" "simple_alu_imm,*")]
0d66636f 3162)
9c08d1fa 3163
f7fbdd4a 3164(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3165 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3166 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3167 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3168 (const_int 0)))]
25f905c2 3169 "TARGET_32BIT"
40dbec34 3170 "teq%?\\t%0, %1"
65f68e55 3171 [(set_attr "conds" "set")
3172 (set_attr "type" "simple_alu_imm, *")]
cffb2a26 3173)
9c08d1fa 3174
215b30b3 3175; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3176; (NOT D) we can sometimes merge the final NOT into one of the following
3177; insns.
9c08d1fa 3178
3179(define_split
a058e94a 3180 [(set (match_operand:SI 0 "s_register_operand" "")
3181 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3182 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3183 (match_operand:SI 3 "arm_rhs_operand" "")))
3184 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3185 "TARGET_32BIT"
9c08d1fa 3186 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3187 (not:SI (match_dup 3))))
3188 (set (match_dup 0) (not:SI (match_dup 4)))]
3189 ""
3190)
3191
f7fbdd4a 3192(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 3193 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3194 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3195 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3196 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3197 "TARGET_32BIT"
40dbec34 3198 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 3199 [(set_attr "length" "8")
25f905c2 3200 (set_attr "ce_count" "2")
0d66636f 3201 (set_attr "predicable" "yes")]
cffb2a26 3202)
9c08d1fa 3203
25f905c2 3204; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3205; insns are available?
d7863cfe 3206(define_split
3207 [(set (match_operand:SI 0 "s_register_operand" "")
3208 (match_operator:SI 1 "logical_binary_operator"
3209 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3210 (match_operand:SI 3 "const_int_operand" "")
3211 (match_operand:SI 4 "const_int_operand" ""))
3212 (match_operator:SI 9 "logical_binary_operator"
3213 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3214 (match_operand:SI 6 "const_int_operand" ""))
3215 (match_operand:SI 7 "s_register_operand" "")])]))
3216 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3217 "TARGET_32BIT
d7863cfe 3218 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3219 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3220 [(set (match_dup 8)
3221 (match_op_dup 1
3222 [(ashift:SI (match_dup 2) (match_dup 4))
3223 (match_dup 5)]))
3224 (set (match_dup 0)
3225 (match_op_dup 1
3226 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3227 (match_dup 7)]))]
3228 "
3229 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3230")
3231
3232(define_split
3233 [(set (match_operand:SI 0 "s_register_operand" "")
3234 (match_operator:SI 1 "logical_binary_operator"
3235 [(match_operator:SI 9 "logical_binary_operator"
3236 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3237 (match_operand:SI 6 "const_int_operand" ""))
3238 (match_operand:SI 7 "s_register_operand" "")])
3239 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3240 (match_operand:SI 3 "const_int_operand" "")
3241 (match_operand:SI 4 "const_int_operand" ""))]))
3242 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3243 "TARGET_32BIT
d7863cfe 3244 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3245 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3246 [(set (match_dup 8)
3247 (match_op_dup 1
3248 [(ashift:SI (match_dup 2) (match_dup 4))
3249 (match_dup 5)]))
3250 (set (match_dup 0)
3251 (match_op_dup 1
3252 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3253 (match_dup 7)]))]
3254 "
3255 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3256")
3257
3258(define_split
3259 [(set (match_operand:SI 0 "s_register_operand" "")
3260 (match_operator:SI 1 "logical_binary_operator"
3261 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3262 (match_operand:SI 3 "const_int_operand" "")
3263 (match_operand:SI 4 "const_int_operand" ""))
3264 (match_operator:SI 9 "logical_binary_operator"
3265 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3266 (match_operand:SI 6 "const_int_operand" ""))
3267 (match_operand:SI 7 "s_register_operand" "")])]))
3268 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3269 "TARGET_32BIT
d7863cfe 3270 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3271 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3272 [(set (match_dup 8)
3273 (match_op_dup 1
3274 [(ashift:SI (match_dup 2) (match_dup 4))
3275 (match_dup 5)]))
3276 (set (match_dup 0)
3277 (match_op_dup 1
3278 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3279 (match_dup 7)]))]
3280 "
3281 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3282")
3283
3284(define_split
3285 [(set (match_operand:SI 0 "s_register_operand" "")
3286 (match_operator:SI 1 "logical_binary_operator"
3287 [(match_operator:SI 9 "logical_binary_operator"
3288 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3289 (match_operand:SI 6 "const_int_operand" ""))
3290 (match_operand:SI 7 "s_register_operand" "")])
3291 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3292 (match_operand:SI 3 "const_int_operand" "")
3293 (match_operand:SI 4 "const_int_operand" ""))]))
3294 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3295 "TARGET_32BIT
d7863cfe 3296 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3297 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3298 [(set (match_dup 8)
3299 (match_op_dup 1
3300 [(ashift:SI (match_dup 2) (match_dup 4))
3301 (match_dup 5)]))
3302 (set (match_dup 0)
3303 (match_op_dup 1
3304 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3305 (match_dup 7)]))]
3306 "
3307 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3308")
9c08d1fa 3309\f
3310
3311;; Minimum and maximum insns
3312
8b9dc177 3313(define_expand "smaxsi3"
3314 [(parallel [
3315 (set (match_operand:SI 0 "s_register_operand" "")
3316 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3317 (match_operand:SI 2 "arm_rhs_operand" "")))
3318 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3319 "TARGET_32BIT"
8b9dc177 3320 "
8774928b 3321 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3322 {
3323 /* No need for a clobber of the condition code register here. */
3324 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3325 gen_rtx_SMAX (SImode, operands[1],
3326 operands[2])));
3327 DONE;
3328 }
3329")
3330
3331(define_insn "*smax_0"
3332 [(set (match_operand:SI 0 "s_register_operand" "=r")
3333 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3334 (const_int 0)))]
25f905c2 3335 "TARGET_32BIT"
8b9dc177 3336 "bic%?\\t%0, %1, %1, asr #31"
3337 [(set_attr "predicable" "yes")]
3338)
3339
8774928b 3340(define_insn "*smax_m1"
3341 [(set (match_operand:SI 0 "s_register_operand" "=r")
3342 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3343 (const_int -1)))]
25f905c2 3344 "TARGET_32BIT"
8774928b 3345 "orr%?\\t%0, %1, %1, asr #31"
3346 [(set_attr "predicable" "yes")]
3347)
3348
25f905c2 3349(define_insn "*arm_smax_insn"
8b9dc177 3350 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3351 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3352 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3353 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3354 "TARGET_ARM"
e2348bcb 3355 "@
3356 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3357 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3358 [(set_attr "conds" "clob")
8b9dc177 3359 (set_attr "length" "8,12")]
cffb2a26 3360)
9c08d1fa 3361
8b9dc177 3362(define_expand "sminsi3"
3363 [(parallel [
3364 (set (match_operand:SI 0 "s_register_operand" "")
3365 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3366 (match_operand:SI 2 "arm_rhs_operand" "")))
3367 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3368 "TARGET_32BIT"
8b9dc177 3369 "
3370 if (operands[2] == const0_rtx)
3371 {
3372 /* No need for a clobber of the condition code register here. */
3373 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3374 gen_rtx_SMIN (SImode, operands[1],
3375 operands[2])));
3376 DONE;
3377 }
3378")
3379
3380(define_insn "*smin_0"
3381 [(set (match_operand:SI 0 "s_register_operand" "=r")
3382 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3383 (const_int 0)))]
25f905c2 3384 "TARGET_32BIT"
8b9dc177 3385 "and%?\\t%0, %1, %1, asr #31"
3386 [(set_attr "predicable" "yes")]
3387)
3388
25f905c2 3389(define_insn "*arm_smin_insn"
8b9dc177 3390 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3391 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3392 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3393 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3394 "TARGET_ARM"
e2348bcb 3395 "@
3396 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3397 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3398 [(set_attr "conds" "clob")
8b9dc177 3399 (set_attr "length" "8,12")]
0d66636f 3400)
9c08d1fa 3401
25f905c2 3402(define_expand "umaxsi3"
3403 [(parallel [
3404 (set (match_operand:SI 0 "s_register_operand" "")
3405 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3406 (match_operand:SI 2 "arm_rhs_operand" "")))
3407 (clobber (reg:CC CC_REGNUM))])]
3408 "TARGET_32BIT"
3409 ""
3410)
3411
3412(define_insn "*arm_umaxsi3"
9c08d1fa 3413 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3414 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3415 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3416 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3417 "TARGET_ARM"
e2348bcb 3418 "@
3419 cmp\\t%1, %2\;movcc\\t%0, %2
3420 cmp\\t%1, %2\;movcs\\t%0, %1
3421 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3422 [(set_attr "conds" "clob")
3423 (set_attr "length" "8,8,12")]
3424)
9c08d1fa 3425
25f905c2 3426(define_expand "uminsi3"
3427 [(parallel [
3428 (set (match_operand:SI 0 "s_register_operand" "")
3429 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3430 (match_operand:SI 2 "arm_rhs_operand" "")))
3431 (clobber (reg:CC CC_REGNUM))])]
3432 "TARGET_32BIT"
3433 ""
3434)
3435
3436(define_insn "*arm_uminsi3"
9c08d1fa 3437 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3438 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3439 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3440 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3441 "TARGET_ARM"
e2348bcb 3442 "@
3443 cmp\\t%1, %2\;movcs\\t%0, %2
3444 cmp\\t%1, %2\;movcc\\t%0, %1
3445 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3446 [(set_attr "conds" "clob")
3447 (set_attr "length" "8,8,12")]
3448)
9c08d1fa 3449
8a18b90c 3450(define_insn "*store_minmaxsi"
9c08d1fa 3451 [(set (match_operand:SI 0 "memory_operand" "=m")
3452 (match_operator:SI 3 "minmax_operator"
3453 [(match_operand:SI 1 "s_register_operand" "r")
3454 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3455 (clobber (reg:CC CC_REGNUM))]
25f905c2 3456 "TARGET_32BIT"
9c08d1fa 3457 "*
dc55b8a9 3458 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3459 operands[1], operands[2]);
e2348bcb 3460 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3461 if (TARGET_THUMB2)
3462 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3463 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3464 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3465 return \"\";
0d66636f 3466 "
3467 [(set_attr "conds" "clob")
25f905c2 3468 (set (attr "length")
3469 (if_then_else (eq_attr "is_thumb" "yes")
3470 (const_int 14)
3471 (const_int 12)))
0d66636f 3472 (set_attr "type" "store1")]
3473)
9c08d1fa 3474
8a18b90c 3475; Reject the frame pointer in operand[1], since reloading this after
3476; it has been eliminated can cause carnage.
f7fbdd4a 3477(define_insn "*minmax_arithsi"
9c08d1fa 3478 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3479 (match_operator:SI 4 "shiftable_operator"
3480 [(match_operator:SI 5 "minmax_operator"
3481 [(match_operand:SI 2 "s_register_operand" "r,r")
3482 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3483 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3484 (clobber (reg:CC CC_REGNUM))]
25f905c2 3485 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3486 "*
0d66636f 3487 {
3488 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3489 bool need_else;
3490
3491 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3492 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3493 need_else = true;
3494 else
3495 need_else = false;
0d66636f 3496
dc55b8a9 3497 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3498 operands[2], operands[3]);
0d66636f 3499 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3500 if (TARGET_THUMB2)
3501 {
3502 if (need_else)
3503 output_asm_insn (\"ite\\t%d5\", operands);
3504 else
3505 output_asm_insn (\"it\\t%d5\", operands);
3506 }
0d66636f 3507 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3508 if (need_else)
0d66636f 3509 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3510 return \"\";
215b30b3 3511 }"
0d66636f 3512 [(set_attr "conds" "clob")
25f905c2 3513 (set (attr "length")
3514 (if_then_else (eq_attr "is_thumb" "yes")
3515 (const_int 14)
3516 (const_int 12)))]
0d66636f 3517)
9c08d1fa 3518
b49e3742 3519(define_code_iterator SAT [smin smax])
3520(define_code_iterator SATrev [smin smax])
3521(define_code_attr SATlo [(smin "1") (smax "2")])
3522(define_code_attr SAThi [(smin "2") (smax "1")])
3523
3524(define_insn "*satsi_<SAT:code>"
3525 [(set (match_operand:SI 0 "s_register_operand" "=r")
3526 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3527 (match_operand:SI 1 "const_int_operand" "i"))
3528 (match_operand:SI 2 "const_int_operand" "i")))]
3529 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3530 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3531{
3532 int mask;
3533 bool signed_sat;
3534 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3535 &mask, &signed_sat))
3536 gcc_unreachable ();
3537
3538 operands[1] = GEN_INT (mask);
3539 if (signed_sat)
3540 return "ssat%?\t%0, %1, %3";
3541 else
3542 return "usat%?\t%0, %1, %3";
3543}
3544 [(set_attr "predicable" "yes")
3545 (set_attr "insn" "sat")])
3546
3547(define_insn "*satsi_<SAT:code>_shift"
3548 [(set (match_operand:SI 0 "s_register_operand" "=r")
3549 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3550 [(match_operand:SI 4 "s_register_operand" "r")
3551 (match_operand:SI 5 "const_int_operand" "i")])
3552 (match_operand:SI 1 "const_int_operand" "i"))
3553 (match_operand:SI 2 "const_int_operand" "i")))]
3554 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3555 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3556{
3557 int mask;
3558 bool signed_sat;
3559 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3560 &mask, &signed_sat))
3561 gcc_unreachable ();
3562
3563 operands[1] = GEN_INT (mask);
3564 if (signed_sat)
3565 return "ssat%?\t%0, %1, %4%S3";
3566 else
3567 return "usat%?\t%0, %1, %4%S3";
3568}
3569 [(set_attr "predicable" "yes")
3570 (set_attr "insn" "sat")
3571 (set_attr "shift" "3")
3572 (set_attr "type" "alu_shift")])
b11cae9e 3573\f
3574;; Shift and rotation insns
3575
a2cd141b 3576(define_expand "ashldi3"
3577 [(set (match_operand:DI 0 "s_register_operand" "")
3578 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3579 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3580 "TARGET_32BIT"
a2cd141b 3581 "
aa06c51c 3582 if (TARGET_NEON)
3583 {
3584 /* Delay the decision whether to use NEON or core-regs until
3585 register allocation. */
3586 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3587 DONE;
3588 }
3589 else
3590 {
3591 /* Only the NEON case can handle in-memory shift counts. */
3592 if (!reg_or_int_operand (operands[2], SImode))
3593 operands[2] = force_reg (SImode, operands[2]);
3594 }
3595
b805622c 3596 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3597 ; /* No special preparation statements; expand pattern as above. */
3598 else
a2cd141b 3599 {
ffcc986d 3600 rtx scratch1, scratch2;
3601
3602 if (CONST_INT_P (operands[2])
3603 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3604 {
3605 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3606 DONE;
3607 }
ffcc986d 3608
3609 /* Ideally we should use iwmmxt here if we could know that operands[1]
3610 ends up already living in an iwmmxt register. Otherwise it's
3611 cheaper to have the alternate code being generated than moving
3612 values to iwmmxt regs and back. */
3613
3614 /* If we're optimizing for size, we prefer the libgcc calls. */
3615 if (optimize_function_for_size_p (cfun))
3616 FAIL;
3617
3618 /* Expand operation using core-registers.
3619 'FAIL' would achieve the same thing, but this is a bit smarter. */
3620 scratch1 = gen_reg_rtx (SImode);
3621 scratch2 = gen_reg_rtx (SImode);
3622 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3623 operands[2], scratch1, scratch2);
3624 DONE;
a2cd141b 3625 }
a2cd141b 3626 "
3627)
3628
3629(define_insn "arm_ashldi3_1bit"
50ad1bf9 3630 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3631 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3632 (const_int 1)))
3633 (clobber (reg:CC CC_REGNUM))]
25f905c2 3634 "TARGET_32BIT"
a2cd141b 3635 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3636 [(set_attr "conds" "clob")
3637 (set_attr "length" "8")]
3638)
3639
87b22bf7 3640(define_expand "ashlsi3"
cffb2a26 3641 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3642 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3643 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3644 "TARGET_EITHER"
87b22bf7 3645 "
0438d37f 3646 if (CONST_INT_P (operands[2])
87b22bf7 3647 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3648 {
3649 emit_insn (gen_movsi (operands[0], const0_rtx));
3650 DONE;
3651 }
cffb2a26 3652 "
3653)
3654
25f905c2 3655(define_insn "*thumb1_ashlsi3"
cffb2a26 3656 [(set (match_operand:SI 0 "register_operand" "=l,l")
3657 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3658 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3659 "TARGET_THUMB1"
cffb2a26 3660 "lsl\\t%0, %1, %2"
747b7458 3661 [(set_attr "length" "2")
3662 (set_attr "conds" "set")])
b11cae9e 3663
a2cd141b 3664(define_expand "ashrdi3"
3665 [(set (match_operand:DI 0 "s_register_operand" "")
3666 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3667 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3668 "TARGET_32BIT"
a2cd141b 3669 "
aa06c51c 3670 if (TARGET_NEON)
3671 {
3672 /* Delay the decision whether to use NEON or core-regs until
3673 register allocation. */
3674 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3675 DONE;
3676 }
3677
b805622c 3678 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3679 ; /* No special preparation statements; expand pattern as above. */
3680 else
a2cd141b 3681 {
ffcc986d 3682 rtx scratch1, scratch2;
3683
3684 if (CONST_INT_P (operands[2])
3685 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3686 {
3687 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3688 DONE;
3689 }
ffcc986d 3690
3691 /* Ideally we should use iwmmxt here if we could know that operands[1]
3692 ends up already living in an iwmmxt register. Otherwise it's
3693 cheaper to have the alternate code being generated than moving
3694 values to iwmmxt regs and back. */
3695
3696 /* If we're optimizing for size, we prefer the libgcc calls. */
3697 if (optimize_function_for_size_p (cfun))
3698 FAIL;
3699
3700 /* Expand operation using core-registers.
3701 'FAIL' would achieve the same thing, but this is a bit smarter. */
3702 scratch1 = gen_reg_rtx (SImode);
3703 scratch2 = gen_reg_rtx (SImode);
3704 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3705 operands[2], scratch1, scratch2);
3706 DONE;
a2cd141b 3707 }
a2cd141b 3708 "
3709)
3710
3711(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3712 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3713 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3714 (const_int 1)))
3715 (clobber (reg:CC CC_REGNUM))]
25f905c2 3716 "TARGET_32BIT"
a2cd141b 3717 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3718 [(set_attr "conds" "clob")
d2a518d1 3719 (set_attr "insn" "mov")
a2cd141b 3720 (set_attr "length" "8")]
3721)
3722
87b22bf7 3723(define_expand "ashrsi3"
cffb2a26 3724 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3725 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3726 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3727 "TARGET_EITHER"
87b22bf7 3728 "
0438d37f 3729 if (CONST_INT_P (operands[2])
87b22bf7 3730 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3731 operands[2] = GEN_INT (31);
cffb2a26 3732 "
3733)
3734
25f905c2 3735(define_insn "*thumb1_ashrsi3"
cffb2a26 3736 [(set (match_operand:SI 0 "register_operand" "=l,l")
3737 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3738 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3739 "TARGET_THUMB1"
cffb2a26 3740 "asr\\t%0, %1, %2"
747b7458 3741 [(set_attr "length" "2")
3742 (set_attr "conds" "set")])
b11cae9e 3743
a2cd141b 3744(define_expand "lshrdi3"
3745 [(set (match_operand:DI 0 "s_register_operand" "")
3746 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3747 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3748 "TARGET_32BIT"
a2cd141b 3749 "
aa06c51c 3750 if (TARGET_NEON)
3751 {
3752 /* Delay the decision whether to use NEON or core-regs until
3753 register allocation. */
3754 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3755 DONE;
3756 }
3757
b805622c 3758 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3759 ; /* No special preparation statements; expand pattern as above. */
3760 else
a2cd141b 3761 {
ffcc986d 3762 rtx scratch1, scratch2;
3763
3764 if (CONST_INT_P (operands[2])
3765 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3766 {
3767 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3768 DONE;
3769 }
ffcc986d 3770
3771 /* Ideally we should use iwmmxt here if we could know that operands[1]
3772 ends up already living in an iwmmxt register. Otherwise it's
3773 cheaper to have the alternate code being generated than moving
3774 values to iwmmxt regs and back. */
3775
3776 /* If we're optimizing for size, we prefer the libgcc calls. */
3777 if (optimize_function_for_size_p (cfun))
3778 FAIL;
3779
3780 /* Expand operation using core-registers.
3781 'FAIL' would achieve the same thing, but this is a bit smarter. */
3782 scratch1 = gen_reg_rtx (SImode);
3783 scratch2 = gen_reg_rtx (SImode);
3784 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3785 operands[2], scratch1, scratch2);
3786 DONE;
a2cd141b 3787 }
a2cd141b 3788 "
3789)
3790
3791(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3792 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3793 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3794 (const_int 1)))
3795 (clobber (reg:CC CC_REGNUM))]
25f905c2 3796 "TARGET_32BIT"
a2cd141b 3797 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3798 [(set_attr "conds" "clob")
d2a518d1 3799 (set_attr "insn" "mov")
a2cd141b 3800 (set_attr "length" "8")]
3801)
3802
87b22bf7 3803(define_expand "lshrsi3"
cffb2a26 3804 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3805 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3806 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3807 "TARGET_EITHER"
87b22bf7 3808 "
0438d37f 3809 if (CONST_INT_P (operands[2])
87b22bf7 3810 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3811 {
3812 emit_insn (gen_movsi (operands[0], const0_rtx));
3813 DONE;
3814 }
cffb2a26 3815 "
3816)
3817
25f905c2 3818(define_insn "*thumb1_lshrsi3"
cffb2a26 3819 [(set (match_operand:SI 0 "register_operand" "=l,l")
3820 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3821 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3822 "TARGET_THUMB1"
cffb2a26 3823 "lsr\\t%0, %1, %2"
747b7458 3824 [(set_attr "length" "2")
3825 (set_attr "conds" "set")])
b11cae9e 3826
87b22bf7 3827(define_expand "rotlsi3"
cffb2a26 3828 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3829 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3830 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3831 "TARGET_32BIT"
87b22bf7 3832 "
0438d37f 3833 if (CONST_INT_P (operands[2]))
87b22bf7 3834 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3835 else
b11cae9e 3836 {
87b22bf7 3837 rtx reg = gen_reg_rtx (SImode);
3838 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3839 operands[2] = reg;
b11cae9e 3840 }
cffb2a26 3841 "
3842)
9c08d1fa 3843
87b22bf7 3844(define_expand "rotrsi3"
cffb2a26 3845 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3846 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3847 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3848 "TARGET_EITHER"
87b22bf7 3849 "
25f905c2 3850 if (TARGET_32BIT)
cffb2a26 3851 {
0438d37f 3852 if (CONST_INT_P (operands[2])
cffb2a26 3853 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3854 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3855 }
25f905c2 3856 else /* TARGET_THUMB1 */
cffb2a26 3857 {
0438d37f 3858 if (CONST_INT_P (operands [2]))
cffb2a26 3859 operands [2] = force_reg (SImode, operands[2]);
3860 }
3861 "
3862)
87b22bf7 3863
25f905c2 3864(define_insn "*thumb1_rotrsi3"
cffb2a26 3865 [(set (match_operand:SI 0 "register_operand" "=l")
3866 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3867 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3868 "TARGET_THUMB1"
cffb2a26 3869 "ror\\t%0, %0, %2"
3870 [(set_attr "length" "2")]
3871)
3872
3873(define_insn "*arm_shiftsi3"
3874 [(set (match_operand:SI 0 "s_register_operand" "=r")
3875 (match_operator:SI 3 "shift_operator"
3876 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3877 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3878 "TARGET_32BIT"
3879 "* return arm_output_shift(operands, 0);"
344495ea 3880 [(set_attr "predicable" "yes")
331beb1a 3881 (set_attr "shift" "1")
a2cd141b 3882 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3883 (const_string "alu_shift")
3884 (const_string "alu_shift_reg")))]
6c4c2133 3885)
87b22bf7 3886
f7fbdd4a 3887(define_insn "*shiftsi3_compare0"
bd5b4116 3888 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3889 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3890 [(match_operand:SI 1 "s_register_operand" "r")
3891 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3892 (const_int 0)))
3893 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3894 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3895 "TARGET_32BIT"
3896 "* return arm_output_shift(operands, 1);"
344495ea 3897 [(set_attr "conds" "set")
331beb1a 3898 (set_attr "shift" "1")
a2cd141b 3899 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3900 (const_string "alu_shift")
3901 (const_string "alu_shift_reg")))]
0d66636f 3902)
9c08d1fa 3903
f7fbdd4a 3904(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3905 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3906 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3907 [(match_operand:SI 1 "s_register_operand" "r")
3908 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3909 (const_int 0)))
3910 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3911 "TARGET_32BIT"
3912 "* return arm_output_shift(operands, 1);"
344495ea 3913 [(set_attr "conds" "set")
a2cd141b 3914 (set_attr "shift" "1")]
0d66636f 3915)
9c08d1fa 3916
d5d4dc8d 3917(define_insn "*not_shiftsi"
3918 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3919 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3920 [(match_operand:SI 1 "s_register_operand" "r,r")
3921 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3922 "TARGET_32BIT"
6c4c2133 3923 "mvn%?\\t%0, %1%S3"
344495ea 3924 [(set_attr "predicable" "yes")
331beb1a 3925 (set_attr "shift" "1")
d2a518d1 3926 (set_attr "insn" "mvn")
d5d4dc8d 3927 (set_attr "arch" "32,a")
3928 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3929
d5d4dc8d 3930(define_insn "*not_shiftsi_compare0"
bd5b4116 3931 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3932 (compare:CC_NOOV
3933 (not:SI (match_operator:SI 3 "shift_operator"
3934 [(match_operand:SI 1 "s_register_operand" "r,r")
3935 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3936 (const_int 0)))
3937 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3938 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3939 "TARGET_32BIT"
25f905c2 3940 "mvn%.\\t%0, %1%S3"
344495ea 3941 [(set_attr "conds" "set")
331beb1a 3942 (set_attr "shift" "1")
d2a518d1 3943 (set_attr "insn" "mvn")
d5d4dc8d 3944 (set_attr "arch" "32,a")
3945 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3946
d5d4dc8d 3947(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3948 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3949 (compare:CC_NOOV
3950 (not:SI (match_operator:SI 3 "shift_operator"
3951 [(match_operand:SI 1 "s_register_operand" "r,r")
3952 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3953 (const_int 0)))
3954 (clobber (match_scratch:SI 0 "=r,r"))]
3955 "TARGET_32BIT"
25f905c2 3956 "mvn%.\\t%0, %1%S3"
344495ea 3957 [(set_attr "conds" "set")
331beb1a 3958 (set_attr "shift" "1")
d2a518d1 3959 (set_attr "insn" "mvn")
d5d4dc8d 3960 (set_attr "arch" "32,a")
3961 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3962
cffb2a26 3963;; We don't really have extzv, but defining this using shifts helps
3964;; to reduce register pressure later on.
3965
3966(define_expand "extzv"
eb04cafb 3967 [(set (match_operand 0 "s_register_operand" "")
3968 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3969 (match_operand 2 "const_int_operand" "")
3970 (match_operand 3 "const_int_operand" "")))]
8b054d5a 3971 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3972 "
3973 {
3974 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3975 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3976
8b054d5a 3977 if (arm_arch_thumb2)
3978 {
eb04cafb 3979 HOST_WIDE_INT width = INTVAL (operands[2]);
3980 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3981
3982 if (unaligned_access && MEM_P (operands[1])
3983 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3984 {
3985 rtx base_addr;
3986
3987 if (BYTES_BIG_ENDIAN)
3988 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3989 - bitpos;
3990
3991 if (width == 32)
3992 {
3993 base_addr = adjust_address (operands[1], SImode,
3994 bitpos / BITS_PER_UNIT);
3995 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3996 }
3997 else
3998 {
3999 rtx dest = operands[0];
4000 rtx tmp = gen_reg_rtx (SImode);
4001
4002 /* We may get a paradoxical subreg here. Strip it off. */
4003 if (GET_CODE (dest) == SUBREG
4004 && GET_MODE (dest) == SImode
4005 && GET_MODE (SUBREG_REG (dest)) == HImode)
4006 dest = SUBREG_REG (dest);
4007
4008 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4009 FAIL;
4010
4011 base_addr = adjust_address (operands[1], HImode,
4012 bitpos / BITS_PER_UNIT);
4013 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4014 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4015 }
4016 DONE;
4017 }
4018 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4019 {
4020 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4021 operands[3]));
4022 DONE;
4023 }
4024 else
4025 FAIL;
8b054d5a 4026 }
eb04cafb 4027
4028 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4029 FAIL;
8b054d5a 4030
cffb2a26 4031 operands[3] = GEN_INT (rshift);
4032
4033 if (lshift == 0)
4034 {
4035 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4036 DONE;
4037 }
4038
eb04cafb 4039 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4040 operands[3], gen_reg_rtx (SImode)));
4041 DONE;
215b30b3 4042 }"
cffb2a26 4043)
4044
eb04cafb 4045;; Helper for extzv, for the Thumb-1 register-shifts case.
4046
4047(define_expand "extzv_t1"
4048 [(set (match_operand:SI 4 "s_register_operand" "")
4049 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4050 (match_operand:SI 2 "const_int_operand" "")))
4051 (set (match_operand:SI 0 "s_register_operand" "")
4052 (lshiftrt:SI (match_dup 4)
4053 (match_operand:SI 3 "const_int_operand" "")))]
4054 "TARGET_THUMB1"
4055 "")
4056
4057(define_expand "extv"
4058 [(set (match_operand 0 "s_register_operand" "")
4059 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4060 (match_operand 2 "const_int_operand" "")
4061 (match_operand 3 "const_int_operand" "")))]
4062 "arm_arch_thumb2"
4063{
4064 HOST_WIDE_INT width = INTVAL (operands[2]);
4065 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4066
4067 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4068 && (bitpos % BITS_PER_UNIT) == 0)
4069 {
4070 rtx base_addr;
4071
4072 if (BYTES_BIG_ENDIAN)
4073 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4074
4075 if (width == 32)
4076 {
4077 base_addr = adjust_address (operands[1], SImode,
4078 bitpos / BITS_PER_UNIT);
4079 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4080 }
4081 else
4082 {
4083 rtx dest = operands[0];
4084 rtx tmp = gen_reg_rtx (SImode);
4085
4086 /* We may get a paradoxical subreg here. Strip it off. */
4087 if (GET_CODE (dest) == SUBREG
4088 && GET_MODE (dest) == SImode
4089 && GET_MODE (SUBREG_REG (dest)) == HImode)
4090 dest = SUBREG_REG (dest);
4091
4092 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4093 FAIL;
4094
4095 base_addr = adjust_address (operands[1], HImode,
4096 bitpos / BITS_PER_UNIT);
4097 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4098 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4099 }
4100
4101 DONE;
4102 }
4103 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4104 FAIL;
4105 else if (GET_MODE (operands[0]) == SImode
4106 && GET_MODE (operands[1]) == SImode)
4107 {
4108 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4109 operands[3]));
4110 DONE;
4111 }
4112
4113 FAIL;
4114})
4115
4116; Helper to expand register forms of extv with the proper modes.
4117
4118(define_expand "extv_regsi"
4119 [(set (match_operand:SI 0 "s_register_operand" "")
4120 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4121 (match_operand 2 "const_int_operand" "")
4122 (match_operand 3 "const_int_operand" "")))]
4123 ""
4124{
4125})
4126
4127; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4128
4129(define_insn "unaligned_loadsi"
4130 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4131 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4132 UNSPEC_UNALIGNED_LOAD))]
4133 "unaligned_access && TARGET_32BIT"
4134 "ldr%?\t%0, %1\t@ unaligned"
4135 [(set_attr "arch" "t2,any")
4136 (set_attr "length" "2,4")
4137 (set_attr "predicable" "yes")
4138 (set_attr "type" "load1")])
4139
4140(define_insn "unaligned_loadhis"
4141 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4142 (sign_extend:SI
4143 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4144 UNSPEC_UNALIGNED_LOAD)))]
4145 "unaligned_access && TARGET_32BIT"
4146 "ldr%(sh%)\t%0, %1\t@ unaligned"
4147 [(set_attr "arch" "t2,any")
4148 (set_attr "length" "2,4")
4149 (set_attr "predicable" "yes")
4150 (set_attr "type" "load_byte")])
4151
4152(define_insn "unaligned_loadhiu"
4153 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4154 (zero_extend:SI
4155 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4156 UNSPEC_UNALIGNED_LOAD)))]
4157 "unaligned_access && TARGET_32BIT"
4158 "ldr%(h%)\t%0, %1\t@ unaligned"
4159 [(set_attr "arch" "t2,any")
4160 (set_attr "length" "2,4")
4161 (set_attr "predicable" "yes")
4162 (set_attr "type" "load_byte")])
4163
4164(define_insn "unaligned_storesi"
4165 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4166 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4167 UNSPEC_UNALIGNED_STORE))]
4168 "unaligned_access && TARGET_32BIT"
4169 "str%?\t%1, %0\t@ unaligned"
4170 [(set_attr "arch" "t2,any")
4171 (set_attr "length" "2,4")
4172 (set_attr "predicable" "yes")
4173 (set_attr "type" "store1")])
4174
4175(define_insn "unaligned_storehi"
4176 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4177 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4178 UNSPEC_UNALIGNED_STORE))]
4179 "unaligned_access && TARGET_32BIT"
4180 "str%(h%)\t%1, %0\t@ unaligned"
4181 [(set_attr "arch" "t2,any")
4182 (set_attr "length" "2,4")
4183 (set_attr "predicable" "yes")
4184 (set_attr "type" "store1")])
4185
4186(define_insn "*extv_reg"
8b054d5a 4187 [(set (match_operand:SI 0 "s_register_operand" "=r")
4188 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4189 (match_operand:SI 2 "const_int_operand" "M")
4190 (match_operand:SI 3 "const_int_operand" "M")))]
4191 "arm_arch_thumb2"
4192 "sbfx%?\t%0, %1, %3, %2"
4193 [(set_attr "length" "4")
4194 (set_attr "predicable" "yes")]
4195)
4196
4197(define_insn "extzv_t2"
4198 [(set (match_operand:SI 0 "s_register_operand" "=r")
4199 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4200 (match_operand:SI 2 "const_int_operand" "M")
4201 (match_operand:SI 3 "const_int_operand" "M")))]
4202 "arm_arch_thumb2"
4203 "ubfx%?\t%0, %1, %3, %2"
4204 [(set_attr "length" "4")
4205 (set_attr "predicable" "yes")]
4206)
4207
7d3cda8c 4208
4209;; Division instructions
4210(define_insn "divsi3"
4211 [(set (match_operand:SI 0 "s_register_operand" "=r")
4212 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4213 (match_operand:SI 2 "s_register_operand" "r")))]
4214 "TARGET_IDIV"
4215 "sdiv%?\t%0, %1, %2"
4216 [(set_attr "predicable" "yes")
4217 (set_attr "insn" "sdiv")]
4218)
4219
4220(define_insn "udivsi3"
4221 [(set (match_operand:SI 0 "s_register_operand" "=r")
4222 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4223 (match_operand:SI 2 "s_register_operand" "r")))]
4224 "TARGET_IDIV"
4225 "udiv%?\t%0, %1, %2"
4226 [(set_attr "predicable" "yes")
4227 (set_attr "insn" "udiv")]
4228)
4229
b11cae9e 4230\f
4231;; Unary arithmetic insns
4232
cffb2a26 4233(define_expand "negdi2"
4234 [(parallel
8135a42b 4235 [(set (match_operand:DI 0 "s_register_operand" "")
4236 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4237 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4238 "TARGET_EITHER"
774d2fbb 4239 {
4240 if (TARGET_NEON)
4241 {
4242 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4243 DONE;
4244 }
4245 }
cffb2a26 4246)
4247
4248;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4249;; The first alternative allows the common case of a *full* overlap.
cffb2a26 4250(define_insn "*arm_negdi2"
458a8706 4251 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4252 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4253 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4254 "TARGET_ARM"
97499065 4255 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 4256 [(set_attr "conds" "clob")
4257 (set_attr "length" "8")]
4258)
b11cae9e 4259
25f905c2 4260(define_insn "*thumb1_negdi2"
8135a42b 4261 [(set (match_operand:DI 0 "register_operand" "=&l")
4262 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 4263 (clobber (reg:CC CC_REGNUM))]
25f905c2 4264 "TARGET_THUMB1"
cffb2a26 4265 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
4266 [(set_attr "length" "6")]
4267)
4268
4269(define_expand "negsi2"
4270 [(set (match_operand:SI 0 "s_register_operand" "")
4271 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4272 "TARGET_EITHER"
b11cae9e 4273 ""
cffb2a26 4274)
4275
4276(define_insn "*arm_negsi2"
4277 [(set (match_operand:SI 0 "s_register_operand" "=r")
4278 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4279 "TARGET_32BIT"
cffb2a26 4280 "rsb%?\\t%0, %1, #0"
0d66636f 4281 [(set_attr "predicable" "yes")]
cffb2a26 4282)
4283
25f905c2 4284(define_insn "*thumb1_negsi2"
cffb2a26 4285 [(set (match_operand:SI 0 "register_operand" "=l")
4286 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4287 "TARGET_THUMB1"
cffb2a26 4288 "neg\\t%0, %1"
4289 [(set_attr "length" "2")]
4290)
b11cae9e 4291
604f3a0a 4292(define_expand "negsf2"
4293 [(set (match_operand:SF 0 "s_register_operand" "")
4294 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4295 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4296 ""
4297)
4298
4299(define_expand "negdf2"
4300 [(set (match_operand:DF 0 "s_register_operand" "")
4301 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4302 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4303 "")
4304
9c08d1fa 4305;; abssi2 doesn't really clobber the condition codes if a different register
4306;; is being set. To keep things simple, assume during rtl manipulations that
4307;; it does, but tell the final scan operator the truth. Similarly for
4308;; (neg (abs...))
4309
604f3a0a 4310(define_expand "abssi2"
4311 [(parallel
4312 [(set (match_operand:SI 0 "s_register_operand" "")
4313 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4314 (clobber (match_dup 2))])]
4315 "TARGET_EITHER"
4316 "
25f905c2 4317 if (TARGET_THUMB1)
ba156559 4318 operands[2] = gen_rtx_SCRATCH (SImode);
4319 else
4320 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4321")
604f3a0a 4322
7d57ec45 4323(define_insn "*arm_abssi2"
ba156559 4324 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4325 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4326 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4327 "TARGET_ARM"
e2348bcb 4328 "@
4329 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 4330 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 4331 [(set_attr "conds" "clob,*")
331beb1a 4332 (set_attr "shift" "1")
2ad08b65 4333 (set_attr "predicable" "no, yes")
cffb2a26 4334 (set_attr "length" "8")]
4335)
9c08d1fa 4336
25f905c2 4337(define_insn_and_split "*thumb1_abssi2"
ba156559 4338 [(set (match_operand:SI 0 "s_register_operand" "=l")
4339 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
4340 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4341 "TARGET_THUMB1"
ba156559 4342 "#"
25f905c2 4343 "TARGET_THUMB1 && reload_completed"
ba156559 4344 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4345 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
4346 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4347 ""
4348 [(set_attr "length" "6")]
4349)
4350
4351(define_insn "*arm_neg_abssi2"
9c08d1fa 4352 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4353 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4354 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4355 "TARGET_ARM"
e2348bcb 4356 "@
4357 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 4358 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 4359 [(set_attr "conds" "clob,*")
331beb1a 4360 (set_attr "shift" "1")
2ad08b65 4361 (set_attr "predicable" "no, yes")
cffb2a26 4362 (set_attr "length" "8")]
4363)
b11cae9e 4364
25f905c2 4365(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 4366 [(set (match_operand:SI 0 "s_register_operand" "=l")
4367 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
4368 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4369 "TARGET_THUMB1"
ba156559 4370 "#"
25f905c2 4371 "TARGET_THUMB1 && reload_completed"
ba156559 4372 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4373 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
4374 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4375 ""
4376 [(set_attr "length" "6")]
4377)
4378
604f3a0a 4379(define_expand "abssf2"
4380 [(set (match_operand:SF 0 "s_register_operand" "")
4381 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4382 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4383 "")
4384
604f3a0a 4385(define_expand "absdf2"
4386 [(set (match_operand:DF 0 "s_register_operand" "")
4387 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4388 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4389 "")
4390
7db9af5d 4391(define_expand "sqrtsf2"
4392 [(set (match_operand:SF 0 "s_register_operand" "")
4393 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4394 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4395 "")
9c08d1fa 4396
7db9af5d 4397(define_expand "sqrtdf2"
4398 [(set (match_operand:DF 0 "s_register_operand" "")
4399 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4400 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4401 "")
9c08d1fa 4402
a0f94409 4403(define_insn_and_split "one_cmpldi2"
10efb95f 4404 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4405 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4406 "TARGET_32BIT"
10efb95f 4407 "@
4408 vmvn\t%P0, %P1
4409 #
4410 #
4411 vmvn\t%P0, %P1"
4412 "TARGET_32BIT && reload_completed
4413 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4414 [(set (match_dup 0) (not:SI (match_dup 1)))
4415 (set (match_dup 2) (not:SI (match_dup 3)))]
4416 "
4417 {
4418 operands[2] = gen_highpart (SImode, operands[0]);
4419 operands[0] = gen_lowpart (SImode, operands[0]);
4420 operands[3] = gen_highpart (SImode, operands[1]);
4421 operands[1] = gen_lowpart (SImode, operands[1]);
4422 }"
10efb95f 4423 [(set_attr "length" "*,8,8,*")
4424 (set_attr "predicable" "no,yes,yes,no")
4425 (set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
4426 (set_attr "arch" "neon_nota8,*,*,neon_onlya8")]
cffb2a26 4427)
b11cae9e 4428
cffb2a26 4429(define_expand "one_cmplsi2"
4430 [(set (match_operand:SI 0 "s_register_operand" "")
4431 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4432 "TARGET_EITHER"
b11cae9e 4433 ""
cffb2a26 4434)
4435
4436(define_insn "*arm_one_cmplsi2"
4437 [(set (match_operand:SI 0 "s_register_operand" "=r")
4438 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4439 "TARGET_32BIT"
cffb2a26 4440 "mvn%?\\t%0, %1"
d2a518d1 4441 [(set_attr "predicable" "yes")
4442 (set_attr "insn" "mvn")]
cffb2a26 4443)
4444
25f905c2 4445(define_insn "*thumb1_one_cmplsi2"
cffb2a26 4446 [(set (match_operand:SI 0 "register_operand" "=l")
4447 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4448 "TARGET_THUMB1"
cffb2a26 4449 "mvn\\t%0, %1"
d2a518d1 4450 [(set_attr "length" "2")
4451 (set_attr "insn" "mvn")]
cffb2a26 4452)
9c08d1fa 4453
f7fbdd4a 4454(define_insn "*notsi_compare0"
bd5b4116 4455 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4456 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4457 (const_int 0)))
4458 (set (match_operand:SI 0 "s_register_operand" "=r")
4459 (not:SI (match_dup 1)))]
25f905c2 4460 "TARGET_32BIT"
4461 "mvn%.\\t%0, %1"
d2a518d1 4462 [(set_attr "conds" "set")
4463 (set_attr "insn" "mvn")]
cffb2a26 4464)
9c08d1fa 4465
f7fbdd4a 4466(define_insn "*notsi_compare0_scratch"
bd5b4116 4467 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4468 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4469 (const_int 0)))
4470 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4471 "TARGET_32BIT"
4472 "mvn%.\\t%0, %1"
d2a518d1 4473 [(set_attr "conds" "set")
4474 (set_attr "insn" "mvn")]
cffb2a26 4475)
b11cae9e 4476\f
4477;; Fixed <--> Floating conversion insns
4478
9b8516be 4479(define_expand "floatsihf2"
4480 [(set (match_operand:HF 0 "general_operand" "")
4481 (float:HF (match_operand:SI 1 "general_operand" "")))]
4482 "TARGET_EITHER"
4483 "
4484 {
4485 rtx op1 = gen_reg_rtx (SFmode);
4486 expand_float (op1, operands[1], 0);
4487 op1 = convert_to_mode (HFmode, op1, 0);
4488 emit_move_insn (operands[0], op1);
4489 DONE;
4490 }"
4491)
4492
4493(define_expand "floatdihf2"
4494 [(set (match_operand:HF 0 "general_operand" "")
4495 (float:HF (match_operand:DI 1 "general_operand" "")))]
4496 "TARGET_EITHER"
4497 "
4498 {
4499 rtx op1 = gen_reg_rtx (SFmode);
4500 expand_float (op1, operands[1], 0);
4501 op1 = convert_to_mode (HFmode, op1, 0);
4502 emit_move_insn (operands[0], op1);
4503 DONE;
4504 }"
4505)
4506
604f3a0a 4507(define_expand "floatsisf2"
4508 [(set (match_operand:SF 0 "s_register_operand" "")
4509 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4510 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4511 "
604f3a0a 4512")
4513
604f3a0a 4514(define_expand "floatsidf2"
4515 [(set (match_operand:DF 0 "s_register_operand" "")
4516 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4517 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4518 "
604f3a0a 4519")
4520
9b8516be 4521(define_expand "fix_trunchfsi2"
4522 [(set (match_operand:SI 0 "general_operand" "")
4523 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4524 "TARGET_EITHER"
4525 "
4526 {
4527 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4528 expand_fix (operands[0], op1, 0);
4529 DONE;
4530 }"
4531)
4532
4533(define_expand "fix_trunchfdi2"
4534 [(set (match_operand:DI 0 "general_operand" "")
4535 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4536 "TARGET_EITHER"
4537 "
4538 {
4539 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4540 expand_fix (operands[0], op1, 0);
4541 DONE;
4542 }"
4543)
4544
604f3a0a 4545(define_expand "fix_truncsfsi2"
4546 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4547 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4548 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4549 "
604f3a0a 4550")
4551
604f3a0a 4552(define_expand "fix_truncdfsi2"
4553 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4554 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4555 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4556 "
604f3a0a 4557")
4558
f544c6d2 4559;; Truncation insns
b11cae9e 4560
604f3a0a 4561(define_expand "truncdfsf2"
4562 [(set (match_operand:SF 0 "s_register_operand" "")
4563 (float_truncate:SF
4564 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4565 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4566 ""
4567)
9b8516be 4568
4569/* DFmode -> HFmode conversions have to go through SFmode. */
4570(define_expand "truncdfhf2"
4571 [(set (match_operand:HF 0 "general_operand" "")
4572 (float_truncate:HF
4573 (match_operand:DF 1 "general_operand" "")))]
4574 "TARGET_EITHER"
4575 "
4576 {
4577 rtx op1;
4578 op1 = convert_to_mode (SFmode, operands[1], 0);
4579 op1 = convert_to_mode (HFmode, op1, 0);
4580 emit_move_insn (operands[0], op1);
4581 DONE;
4582 }"
4583)
b11cae9e 4584\f
9c08d1fa 4585;; Zero and sign extension instructions.
b11cae9e 4586
848e66ac 4587(define_insn "zero_extend<mode>di2"
4588 [(set (match_operand:DI 0 "s_register_operand" "=r")
6d97728e 4589 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4590 "<qhs_zextenddi_cstr>")))]
848e66ac 4591 "TARGET_32BIT <qhs_zextenddi_cond>"
4592 "#"
4593 [(set_attr "length" "8")
4594 (set_attr "ce_count" "2")
4595 (set_attr "predicable" "yes")]
25f905c2 4596)
4597
848e66ac 4598(define_insn "extend<mode>di2"
9c08d1fa 4599 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4600 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4601 "<qhs_extenddi_cstr>")))]
848e66ac 4602 "TARGET_32BIT <qhs_sextenddi_cond>"
4603 "#"
0d66636f 4604 [(set_attr "length" "8")
848e66ac 4605 (set_attr "ce_count" "2")
4606 (set_attr "shift" "1")
0d66636f 4607 (set_attr "predicable" "yes")]
4608)
9c08d1fa 4609
848e66ac 4610;; Splits for all extensions to DImode
4611(define_split
4612 [(set (match_operand:DI 0 "s_register_operand" "")
4613 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4614 "TARGET_32BIT"
848e66ac 4615 [(set (match_dup 0) (match_dup 1))]
4616{
848e66ac 4617 rtx lo_part = gen_lowpart (SImode, operands[0]);
4618 enum machine_mode src_mode = GET_MODE (operands[1]);
4619
4620 if (REG_P (operands[0])
4621 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4622 emit_clobber (operands[0]);
4623 if (!REG_P (lo_part) || src_mode != SImode
4624 || !rtx_equal_p (lo_part, operands[1]))
4625 {
4626 if (src_mode == SImode)
4627 emit_move_insn (lo_part, operands[1]);
4628 else
4629 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4630 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4631 operands[1] = lo_part;
4632 }
4633 operands[0] = gen_highpart (SImode, operands[0]);
4634 operands[1] = const0_rtx;
4635})
9c08d1fa 4636
848e66ac 4637(define_split
25f905c2 4638 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4639 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4640 "TARGET_32BIT"
848e66ac 4641 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4642{
4643 rtx lo_part = gen_lowpart (SImode, operands[0]);
4644 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4645
848e66ac 4646 if (REG_P (operands[0])
4647 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4648 emit_clobber (operands[0]);
4649
4650 if (!REG_P (lo_part) || src_mode != SImode
4651 || !rtx_equal_p (lo_part, operands[1]))
4652 {
4653 if (src_mode == SImode)
4654 emit_move_insn (lo_part, operands[1]);
4655 else
4656 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4657 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4658 operands[1] = lo_part;
4659 }
4660 operands[0] = gen_highpart (SImode, operands[0]);
4661})
9c08d1fa 4662
4663(define_expand "zero_extendhisi2"
ef51b8e1 4664 [(set (match_operand:SI 0 "s_register_operand" "")
4665 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4666 "TARGET_EITHER"
ef51b8e1 4667{
4668 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4669 {
ef51b8e1 4670 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4671 DONE;
25f7a26e 4672 }
ef51b8e1 4673 if (!arm_arch6 && !MEM_P (operands[1]))
4674 {
4675 rtx t = gen_lowpart (SImode, operands[1]);
4676 rtx tmp = gen_reg_rtx (SImode);
4677 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4678 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4679 DONE;
4680 }
4681})
9c08d1fa 4682
ef51b8e1 4683(define_split
b146458f 4684 [(set (match_operand:SI 0 "s_register_operand" "")
4685 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4686 "!TARGET_THUMB2 && !arm_arch6"
4687 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4688 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4689{
4690 operands[2] = gen_lowpart (SImode, operands[1]);
4691})
4692
4693(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4694 [(set (match_operand:SI 0 "register_operand" "=l,l")
4695 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4696 "TARGET_THUMB1"
848e66ac 4697{
a2cd141b 4698 rtx mem;
4699
ef51b8e1 4700 if (which_alternative == 0 && arm_arch6)
848e66ac 4701 return "uxth\t%0, %1";
ef51b8e1 4702 if (which_alternative == 0)
848e66ac 4703 return "#";
a2cd141b 4704
4705 mem = XEXP (operands[1], 0);
4706
4707 if (GET_CODE (mem) == CONST)
4708 mem = XEXP (mem, 0);
4709
a2cd141b 4710 if (GET_CODE (mem) == PLUS)
4711 {
4712 rtx a = XEXP (mem, 0);
a2cd141b 4713
4714 /* This can happen due to bugs in reload. */
0438d37f 4715 if (REG_P (a) && REGNO (a) == SP_REGNUM)
a2cd141b 4716 {
4717 rtx ops[2];
4718 ops[0] = operands[0];
4719 ops[1] = a;
4720
848e66ac 4721 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4722
4723 XEXP (mem, 0) = operands[0];
4724 }
a2cd141b 4725 }
4726
848e66ac 4727 return "ldrh\t%0, %1";
4728}
ef51b8e1 4729 [(set_attr_alternative "length"
4730 [(if_then_else (eq_attr "is_arch6" "yes")
4731 (const_int 2) (const_int 4))
4732 (const_int 4)])
65f68e55 4733 (set_attr_alternative "type"
4734 [(if_then_else (eq_attr "tune" "cortexa7")
4735 (const_string "simple_alu_imm")
4736 (const_string "alu_shift"))
4737 (const_string "load_byte")])]
a2cd141b 4738)
4739
cffb2a26 4740(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4741 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4742 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4743 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4744 "@
4745 #
4746 ldr%(h%)\\t%0, %1"
4747 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4748 (set_attr "predicable" "yes")]
cffb2a26 4749)
f7fbdd4a 4750
a2cd141b 4751(define_insn "*arm_zero_extendhisi2_v6"
4752 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4753 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4754 "TARGET_ARM && arm_arch6"
4755 "@
4756 uxth%?\\t%0, %1
25f905c2 4757 ldr%(h%)\\t%0, %1"
65f68e55 4758 [(set_attr "predicable" "yes")
4759 (set_attr_alternative "type"
4760 [(if_then_else (eq_attr "tune" "cortexa7")
4761 (const_string "simple_alu_imm")
4762 (const_string "alu_shift"))
4763 (const_string "load_byte")])]
a2cd141b 4764)
4765
4766(define_insn "*arm_zero_extendhisi2addsi"
4767 [(set (match_operand:SI 0 "s_register_operand" "=r")
4768 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4769 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4770 "TARGET_INT_SIMD"
a2cd141b 4771 "uxtah%?\\t%0, %2, %1"
4772 [(set_attr "type" "alu_shift")
4773 (set_attr "predicable" "yes")]
4774)
4775
87b22bf7 4776(define_expand "zero_extendqisi2"
cffb2a26 4777 [(set (match_operand:SI 0 "s_register_operand" "")
4778 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4779 "TARGET_EITHER"
ef51b8e1 4780{
0438d37f 4781 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 4782 {
ef51b8e1 4783 emit_insn (gen_andsi3 (operands[0],
4784 gen_lowpart (SImode, operands[1]),
4785 GEN_INT (255)));
4786 DONE;
4787 }
4788 if (!arm_arch6 && !MEM_P (operands[1]))
4789 {
4790 rtx t = gen_lowpart (SImode, operands[1]);
4791 rtx tmp = gen_reg_rtx (SImode);
4792 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4793 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4794 DONE;
4795 }
4796})
cffb2a26 4797
ef51b8e1 4798(define_split
b146458f 4799 [(set (match_operand:SI 0 "s_register_operand" "")
4800 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4801 "!arm_arch6"
4802 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4803 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4804{
4805 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4806 if (TARGET_ARM)
4807 {
4808 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4809 DONE;
4810 }
ef51b8e1 4811})
9c08d1fa 4812
25f905c2 4813(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4814 [(set (match_operand:SI 0 "register_operand" "=l,l")
4815 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4816 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4817 "@
4818 #
4819 ldrb\\t%0, %1"
4820 [(set_attr "length" "4,2")
4821 (set_attr "type" "alu_shift,load_byte")
4822 (set_attr "pool_range" "*,32")]
cffb2a26 4823)
4824
25f905c2 4825(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4826 [(set (match_operand:SI 0 "register_operand" "=l,l")
4827 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4828 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4829 "@
4830 uxtb\\t%0, %1
4831 ldrb\\t%0, %1"
848e66ac 4832 [(set_attr "length" "2")
65f68e55 4833 (set_attr_alternative "type"
4834 [(if_then_else (eq_attr "tune" "cortexa7")
4835 (const_string "simple_alu_imm")
4836 (const_string "alu_shift"))
4837 (const_string "load_byte")])]
a2cd141b 4838)
4839
cffb2a26 4840(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4841 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4842 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4843 "TARGET_ARM && !arm_arch6"
ef51b8e1 4844 "@
4845 #
4846 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4847 [(set_attr "length" "8,4")
4848 (set_attr "type" "alu_shift,load_byte")
848e66ac 4849 (set_attr "predicable" "yes")]
cffb2a26 4850)
87b22bf7 4851
a2cd141b 4852(define_insn "*arm_zero_extendqisi2_v6"
4853 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4854 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4855 "TARGET_ARM && arm_arch6"
4856 "@
25f905c2 4857 uxtb%(%)\\t%0, %1
4858 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
65f68e55 4859 [(set_attr_alternative "type"
4860 [(if_then_else (eq_attr "tune" "cortexa7")
4861 (const_string "simple_alu_imm")
4862 (const_string "alu_shift"))
4863 (const_string "load_byte")])
848e66ac 4864 (set_attr "predicable" "yes")]
a2cd141b 4865)
4866
4867(define_insn "*arm_zero_extendqisi2addsi"
4868 [(set (match_operand:SI 0 "s_register_operand" "=r")
4869 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4870 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4871 "TARGET_INT_SIMD"
a2cd141b 4872 "uxtab%?\\t%0, %2, %1"
4873 [(set_attr "predicable" "yes")
bcaec148 4874 (set_attr "insn" "xtab")
a2cd141b 4875 (set_attr "type" "alu_shift")]
4876)
4877
87b22bf7 4878(define_split
4879 [(set (match_operand:SI 0 "s_register_operand" "")
4880 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4881 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4882 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 4883 [(set (match_dup 2) (match_dup 1))
4884 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4885 ""
4886)
9c08d1fa 4887
8a4d25d6 4888(define_split
4889 [(set (match_operand:SI 0 "s_register_operand" "")
4890 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4891 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4892 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 4893 [(set (match_dup 2) (match_dup 1))
4894 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4895 ""
4896)
4897
1c274529 4898
4899(define_split
4900 [(set (match_operand:SI 0 "s_register_operand" "")
4901 (ior_xor:SI (and:SI (ashift:SI
4902 (match_operand:SI 1 "s_register_operand" "")
4903 (match_operand:SI 2 "const_int_operand" ""))
4904 (match_operand:SI 3 "const_int_operand" ""))
4905 (zero_extend:SI
4906 (match_operator 5 "subreg_lowpart_operator"
4907 [(match_operand:SI 4 "s_register_operand" "")]))))]
4908 "TARGET_32BIT
63787642 4909 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4910 == (GET_MODE_MASK (GET_MODE (operands[5]))
4911 & (GET_MODE_MASK (GET_MODE (operands[5]))
4912 << (INTVAL (operands[2])))))"
4913 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4914 (match_dup 4)))
4915 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4916 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4917)
4918
f7fbdd4a 4919(define_insn "*compareqi_eq0"
bd5b4116 4920 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4921 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4922 (const_int 0)))]
25f905c2 4923 "TARGET_32BIT"
596e5e8f 4924 "tst%?\\t%0, #255"
4925 [(set_attr "conds" "set")
4926 (set_attr "predicable" "yes")]
cffb2a26 4927)
b11cae9e 4928
b11cae9e 4929(define_expand "extendhisi2"
ef51b8e1 4930 [(set (match_operand:SI 0 "s_register_operand" "")
4931 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4932 "TARGET_EITHER"
ef51b8e1 4933{
4934 if (TARGET_THUMB1)
4935 {
4936 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4937 DONE;
4938 }
4939 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4940 {
4941 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4942 DONE;
4943 }
ed29c566 4944
ef51b8e1 4945 if (!arm_arch6 && !MEM_P (operands[1]))
4946 {
4947 rtx t = gen_lowpart (SImode, operands[1]);
4948 rtx tmp = gen_reg_rtx (SImode);
4949 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4950 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4951 DONE;
4952 }
4953})
cffb2a26 4954
ef51b8e1 4955(define_split
4956 [(parallel
4957 [(set (match_operand:SI 0 "register_operand" "")
4958 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4959 (clobber (match_scratch:SI 2 ""))])]
4960 "!arm_arch6"
4961 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4962 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4963{
4964 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4965})
25f7a26e 4966
a2cd141b 4967;; We used to have an early-clobber on the scratch register here.
4968;; However, there's a bug somewhere in reload which means that this
4969;; can be partially ignored during spill allocation if the memory
ed29c566 4970;; address also needs reloading; this causes us to die later on when
a2cd141b 4971;; we try to verify the operands. Fortunately, we don't really need
4972;; the early-clobber: we can always use operand 0 if operand 2
4973;; overlaps the address.
ef51b8e1 4974(define_insn "thumb1_extendhisi2"
a2cd141b 4975 [(set (match_operand:SI 0 "register_operand" "=l,l")
4976 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4977 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4978 "TARGET_THUMB1"
a2cd141b 4979 "*
4980 {
4981 rtx ops[4];
4982 rtx mem;
4983
ef51b8e1 4984 if (which_alternative == 0 && !arm_arch6)
4985 return \"#\";
a2cd141b 4986 if (which_alternative == 0)
4987 return \"sxth\\t%0, %1\";
4988
4989 mem = XEXP (operands[1], 0);
4990
4991 /* This code used to try to use 'V', and fix the address only if it was
4992 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4993 range of QImode offsets, and offsettable_address_p does a QImode
4994 address check. */
4995
4996 if (GET_CODE (mem) == CONST)
4997 mem = XEXP (mem, 0);
4998
4999 if (GET_CODE (mem) == LABEL_REF)
5000 return \"ldr\\t%0, %1\";
5001
5002 if (GET_CODE (mem) == PLUS)
5003 {
5004 rtx a = XEXP (mem, 0);
5005 rtx b = XEXP (mem, 1);
5006
5007 if (GET_CODE (a) == LABEL_REF
0438d37f 5008 && CONST_INT_P (b))
a2cd141b 5009 return \"ldr\\t%0, %1\";
5010
0438d37f 5011 if (REG_P (b))
a2cd141b 5012 return \"ldrsh\\t%0, %1\";
5013
5014 ops[1] = a;
5015 ops[2] = b;
5016 }
5017 else
5018 {
5019 ops[1] = mem;
5020 ops[2] = const0_rtx;
5021 }
5022
0438d37f 5023 gcc_assert (REG_P (ops[1]));
a2cd141b 5024
5025 ops[0] = operands[0];
5026 if (reg_mentioned_p (operands[2], ops[1]))
5027 ops[3] = ops[0];
5028 else
5029 ops[3] = operands[2];
5030 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
5031 return \"\";
5032 }"
ef51b8e1 5033 [(set_attr_alternative "length"
5034 [(if_then_else (eq_attr "is_arch6" "yes")
5035 (const_int 2) (const_int 4))
5036 (const_int 4)])
65f68e55 5037 (set_attr_alternative "type"
5038 [(if_then_else (eq_attr "tune" "cortexa7")
5039 (const_string "simple_alu_imm")
5040 (const_string "alu_shift"))
5041 (const_string "load_byte")])
42e1de19 5042 (set_attr "pool_range" "*,1018")]
a2cd141b 5043)
5044
25f905c2 5045;; This pattern will only be used when ldsh is not available
25f7a26e 5046(define_expand "extendhisi2_mem"
eab14235 5047 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5048 (set (match_dup 3)
eab14235 5049 (zero_extend:SI (match_dup 7)))
25f7a26e 5050 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5051 (set (match_operand:SI 0 "" "")
5052 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5053 "TARGET_ARM"
25f7a26e 5054 "
215b30b3 5055 {
5056 rtx mem1, mem2;
5057 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5058
788fcce0 5059 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5060 mem2 = change_address (operands[1], QImode,
5061 plus_constant (Pmode, addr, 1));
215b30b3 5062 operands[0] = gen_lowpart (SImode, operands[0]);
5063 operands[1] = mem1;
5064 operands[2] = gen_reg_rtx (SImode);
5065 operands[3] = gen_reg_rtx (SImode);
5066 operands[6] = gen_reg_rtx (SImode);
5067 operands[7] = mem2;
25f7a26e 5068
215b30b3 5069 if (BYTES_BIG_ENDIAN)
5070 {
5071 operands[4] = operands[2];
5072 operands[5] = operands[3];
5073 }
5074 else
5075 {
5076 operands[4] = operands[3];
5077 operands[5] = operands[2];
5078 }
5079 }"
5080)
b11cae9e 5081
ef51b8e1 5082(define_split
5083 [(set (match_operand:SI 0 "register_operand" "")
5084 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5085 "!arm_arch6"
5086 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5087 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5088{
5089 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5090})
5091
a2cd141b 5092(define_insn "*arm_extendhisi2"
ef51b8e1 5093 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5094 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5095 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5096 "@
5097 #
5098 ldr%(sh%)\\t%0, %1"
5099 [(set_attr "length" "8,4")
5100 (set_attr "type" "alu_shift,load_byte")
0d66636f 5101 (set_attr "predicable" "yes")
ef51b8e1 5102 (set_attr "pool_range" "*,256")
5103 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5104)
f7fbdd4a 5105
25f905c2 5106;; ??? Check Thumb-2 pool range
a2cd141b 5107(define_insn "*arm_extendhisi2_v6"
5108 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5109 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 5110 "TARGET_32BIT && arm_arch6"
a2cd141b 5111 "@
5112 sxth%?\\t%0, %1
25f905c2 5113 ldr%(sh%)\\t%0, %1"
65f68e55 5114 [(set_attr_alternative "type"
5115 [(if_then_else (eq_attr "tune" "cortexa7")
5116 (const_string "simple_alu_imm")
5117 (const_string "alu_shift"))
5118 (const_string "load_byte")])
a2cd141b 5119 (set_attr "predicable" "yes")
5120 (set_attr "pool_range" "*,256")
5121 (set_attr "neg_pool_range" "*,244")]
5122)
5123
5124(define_insn "*arm_extendhisi2addsi"
5125 [(set (match_operand:SI 0 "s_register_operand" "=r")
5126 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5127 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5128 "TARGET_INT_SIMD"
a2cd141b 5129 "sxtah%?\\t%0, %2, %1"
5130)
5131
c8f69309 5132(define_expand "extendqihi2"
5133 [(set (match_dup 2)
bed7d9a5 5134 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5135 (const_int 24)))
9c08d1fa 5136 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5137 (ashiftrt:SI (match_dup 2)
5138 (const_int 24)))]
cffb2a26 5139 "TARGET_ARM"
c8f69309 5140 "
215b30b3 5141 {
0438d37f 5142 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5143 {
5144 emit_insn (gen_rtx_SET (VOIDmode,
5145 operands[0],
5146 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5147 DONE;
5148 }
5149 if (!s_register_operand (operands[1], QImode))
5150 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5151 operands[0] = gen_lowpart (SImode, operands[0]);
5152 operands[1] = gen_lowpart (SImode, operands[1]);
5153 operands[2] = gen_reg_rtx (SImode);
5154 }"
5155)
f7fbdd4a 5156
25f905c2 5157(define_insn "*arm_extendqihi_insn"
b4e8a300 5158 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5159 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5160 "TARGET_ARM && arm_arch4"
25f905c2 5161 "ldr%(sb%)\\t%0, %1"
a2cd141b 5162 [(set_attr "type" "load_byte")
0d66636f 5163 (set_attr "predicable" "yes")
cffb2a26 5164 (set_attr "pool_range" "256")
5165 (set_attr "neg_pool_range" "244")]
5166)
3fc2009e 5167
b11cae9e 5168(define_expand "extendqisi2"
ef51b8e1 5169 [(set (match_operand:SI 0 "s_register_operand" "")
5170 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5171 "TARGET_EITHER"
ef51b8e1 5172{
5173 if (!arm_arch4 && MEM_P (operands[1]))
5174 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5175
ef51b8e1 5176 if (!arm_arch6 && !MEM_P (operands[1]))
5177 {
5178 rtx t = gen_lowpart (SImode, operands[1]);
5179 rtx tmp = gen_reg_rtx (SImode);
5180 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5181 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5182 DONE;
5183 }
5184})
a2cd141b 5185
ef51b8e1 5186(define_split
5187 [(set (match_operand:SI 0 "register_operand" "")
5188 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5189 "!arm_arch6"
5190 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5191 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5192{
5193 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5194})
f7fbdd4a 5195
a2cd141b 5196(define_insn "*arm_extendqisi"
ef51b8e1 5197 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5198 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5199 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5200 "@
5201 #
5202 ldr%(sb%)\\t%0, %1"
5203 [(set_attr "length" "8,4")
5204 (set_attr "type" "alu_shift,load_byte")
0d66636f 5205 (set_attr "predicable" "yes")
ef51b8e1 5206 (set_attr "pool_range" "*,256")
5207 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5208)
3fc2009e 5209
a2cd141b 5210(define_insn "*arm_extendqisi_v6"
5211 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5212 (sign_extend:SI
5213 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5214 "TARGET_ARM && arm_arch6"
b4e8a300 5215 "@
5216 sxtb%?\\t%0, %1
25f905c2 5217 ldr%(sb%)\\t%0, %1"
65f68e55 5218 [(set_attr_alternative "type"
5219 [(if_then_else (eq_attr "tune" "cortexa7")
5220 (const_string "simple_alu_imm")
5221 (const_string "alu_shift"))
5222 (const_string "load_byte")])
a2cd141b 5223 (set_attr "predicable" "yes")
a2cd141b 5224 (set_attr "pool_range" "*,256")
5225 (set_attr "neg_pool_range" "*,244")]
5226)
5227
5228(define_insn "*arm_extendqisi2addsi"
5229 [(set (match_operand:SI 0 "s_register_operand" "=r")
5230 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5231 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5232 "TARGET_INT_SIMD"
a2cd141b 5233 "sxtab%?\\t%0, %2, %1"
5234 [(set_attr "type" "alu_shift")
bcaec148 5235 (set_attr "insn" "xtab")
a2cd141b 5236 (set_attr "predicable" "yes")]
5237)
5238
ef51b8e1 5239(define_split
5240 [(set (match_operand:SI 0 "register_operand" "")
5241 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
5242 "TARGET_THUMB1 && reload_completed"
5243 [(set (match_dup 0) (match_dup 2))
5244 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
5245{
5246 rtx addr = XEXP (operands[1], 0);
cffb2a26 5247
ef51b8e1 5248 if (GET_CODE (addr) == CONST)
5249 addr = XEXP (addr, 0);
cffb2a26 5250
ef51b8e1 5251 if (GET_CODE (addr) == PLUS
5252 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5253 /* No split necessary. */
5254 FAIL;
5255
5256 if (GET_CODE (addr) == PLUS
5257 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
5258 FAIL;
5259
5260 if (reg_overlap_mentioned_p (operands[0], addr))
5261 {
5262 rtx t = gen_lowpart (QImode, operands[0]);
5263 emit_move_insn (t, operands[1]);
5264 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
5265 DONE;
5266 }
5267
5268 if (REG_P (addr))
5269 {
5270 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
5271 operands[2] = const0_rtx;
5272 }
5273 else if (GET_CODE (addr) != PLUS)
5274 FAIL;
5275 else if (REG_P (XEXP (addr, 0)))
5276 {
5277 operands[2] = XEXP (addr, 1);
5278 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
5279 }
5280 else
5281 {
5282 operands[2] = XEXP (addr, 0);
5283 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
5284 }
cffb2a26 5285
ef51b8e1 5286 operands[3] = change_address (operands[1], QImode, addr);
5287})
5288
8a3b73a1 5289(define_peephole2
5290 [(set (match_operand:SI 0 "register_operand" "")
5291 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
5292 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
5293 (set (match_operand:SI 3 "register_operand" "")
5294 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
5295 "TARGET_THUMB1
5296 && GET_CODE (XEXP (operands[4], 0)) == PLUS
5297 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
5298 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
5299 && (peep2_reg_dead_p (3, operands[0])
5300 || rtx_equal_p (operands[0], operands[3]))
5301 && (peep2_reg_dead_p (3, operands[2])
5302 || rtx_equal_p (operands[2], operands[3]))"
5303 [(set (match_dup 2) (match_dup 1))
5304 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
5305{
5306 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
5307 operands[4] = change_address (operands[4], QImode, addr);
5308})
5309
ef51b8e1 5310(define_insn "thumb1_extendqisi2"
a2cd141b 5311 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5312 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 5313 "TARGET_THUMB1"
5314{
5315 rtx addr;
a2cd141b 5316
ef51b8e1 5317 if (which_alternative == 0 && arm_arch6)
5318 return "sxtb\\t%0, %1";
5319 if (which_alternative == 0)
5320 return "#";
a2cd141b 5321
ef51b8e1 5322 addr = XEXP (operands[1], 0);
5323 if (GET_CODE (addr) == PLUS
5324 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5325 return "ldrsb\\t%0, %1";
a2cd141b 5326
ef51b8e1 5327 return "#";
5328}
5329 [(set_attr_alternative "length"
5330 [(if_then_else (eq_attr "is_arch6" "yes")
5331 (const_int 2) (const_int 4))
5332 (const_int 2)
5333 (if_then_else (eq_attr "is_arch6" "yes")
5334 (const_int 4) (const_int 6))])
65f68e55 5335 (set_attr_alternative "type"
5336 [(if_then_else (eq_attr "tune" "cortexa7")
5337 (const_string "simple_alu_imm")
5338 (const_string "alu_shift"))
5339 (const_string "load_byte")
5340 (const_string "load_byte")])]
a2cd141b 5341)
5342
caedf871 5343(define_expand "extendsfdf2"
5344 [(set (match_operand:DF 0 "s_register_operand" "")
5345 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5346 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5347 ""
5348)
9b8516be 5349
5350/* HFmode -> DFmode conversions have to go through SFmode. */
5351(define_expand "extendhfdf2"
5352 [(set (match_operand:DF 0 "general_operand" "")
5353 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5354 "TARGET_EITHER"
5355 "
5356 {
5357 rtx op1;
5358 op1 = convert_to_mode (SFmode, operands[1], 0);
5359 op1 = convert_to_mode (DFmode, op1, 0);
5360 emit_insn (gen_movdf (operands[0], op1));
5361 DONE;
5362 }"
5363)
b11cae9e 5364\f
5365;; Move insns (including loads and stores)
5366
5367;; XXX Just some ideas about movti.
9c08d1fa 5368;; I don't think these are a good idea on the arm, there just aren't enough
5369;; registers
b11cae9e 5370;;(define_expand "loadti"
9c08d1fa 5371;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5372;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5373;; "" "")
5374
5375;;(define_expand "storeti"
5376;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5377;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5378;; "" "")
5379
5380;;(define_expand "movti"
5381;; [(set (match_operand:TI 0 "general_operand" "")
5382;; (match_operand:TI 1 "general_operand" ""))]
5383;; ""
5384;; "
5385;;{
5386;; rtx insn;
5387;;
0438d37f 5388;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5389;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5390;; if (MEM_P (operands[0]))
b11cae9e 5391;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5392;; else if (MEM_P (operands[1]))
b11cae9e 5393;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5394;; else
5395;; FAIL;
5396;;
5397;; emit_insn (insn);
5398;; DONE;
5399;;}")
5400
a2f10574 5401;; Recognize garbage generated above.
b11cae9e 5402
5403;;(define_insn ""
5404;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5405;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5406;; ""
5407;; "*
5408;; {
5409;; register mem = (which_alternative < 3);
0d66636f 5410;; register const char *template;
b11cae9e 5411;;
5412;; operands[mem] = XEXP (operands[mem], 0);
5413;; switch (which_alternative)
5414;; {
5415;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5416;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5417;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5418;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5419;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5420;; case 5: template = \"stmia\\t%0, %M1\"; break;
5421;; }
e2348bcb 5422;; output_asm_insn (template, operands);
5423;; return \"\";
b11cae9e 5424;; }")
5425
cffb2a26 5426(define_expand "movdi"
5427 [(set (match_operand:DI 0 "general_operand" "")
5428 (match_operand:DI 1 "general_operand" ""))]
5429 "TARGET_EITHER"
5430 "
e1ba4a27 5431 if (can_create_pseudo_p ())
cffb2a26 5432 {
0438d37f 5433 if (!REG_P (operands[0]))
b2778788 5434 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5435 }
5436 "
5437)
b11cae9e 5438
cffb2a26 5439(define_insn "*arm_movdi"
d51f92df 5440 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5441 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 5442 "TARGET_32BIT
b805622c 5443 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5444 && !TARGET_IWMMXT
5445 && ( register_operand (operands[0], DImode)
5446 || register_operand (operands[1], DImode))"
b11cae9e 5447 "*
d51f92df 5448 switch (which_alternative)
5449 {
5450 case 0:
5451 case 1:
5452 case 2:
5453 return \"#\";
5454 default:
26ff80c0 5455 return output_move_double (operands, true, NULL);
d51f92df 5456 }
cffb2a26 5457 "
359a6e9f 5458 [(set_attr "length" "8,12,16,8,8")
5459 (set_attr "type" "*,*,*,load2,store2")
cde1623a 5460 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5461 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5462 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5463 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5464)
5465
d51f92df 5466(define_split
5467 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5468 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 5469 "TARGET_32BIT
d51f92df 5470 && reload_completed
5471 && (arm_const_double_inline_cost (operands[1])
5472 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
5473 [(const_int 0)]
5474 "
5475 arm_split_constant (SET, SImode, curr_insn,
5476 INTVAL (gen_lowpart (SImode, operands[1])),
5477 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5478 arm_split_constant (SET, SImode, curr_insn,
5479 INTVAL (gen_highpart_mode (SImode,
5480 GET_MODE (operands[0]),
5481 operands[1])),
5482 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5483 DONE;
5484 "
5485)
5486
e5ba9289 5487; If optimizing for size, or if we have load delay slots, then
5488; we want to split the constant into two separate operations.
5489; In both cases this may split a trivial part into a single data op
5490; leaving a single complex constant to load. We can also get longer
5491; offsets in a LDR which means we get better chances of sharing the pool
5492; entries. Finally, we can normally do a better job of scheduling
5493; LDR instructions than we can with LDM.
5494; This pattern will only match if the one above did not.
5495(define_split
5496 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5497 (match_operand:ANY64 1 "const_double_operand" ""))]
5498 "TARGET_ARM && reload_completed
5499 && arm_const_double_by_parts (operands[1])"
5500 [(set (match_dup 0) (match_dup 1))
5501 (set (match_dup 2) (match_dup 3))]
5502 "
5503 operands[2] = gen_highpart (SImode, operands[0]);
5504 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5505 operands[1]);
5506 operands[0] = gen_lowpart (SImode, operands[0]);
5507 operands[1] = gen_lowpart (SImode, operands[1]);
5508 "
5509)
5510
d51f92df 5511(define_split
5512 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5513 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5514 "TARGET_EITHER && reload_completed"
5515 [(set (match_dup 0) (match_dup 1))
5516 (set (match_dup 2) (match_dup 3))]
5517 "
5518 operands[2] = gen_highpart (SImode, operands[0]);
5519 operands[3] = gen_highpart (SImode, operands[1]);
5520 operands[0] = gen_lowpart (SImode, operands[0]);
5521 operands[1] = gen_lowpart (SImode, operands[1]);
5522
5523 /* Handle a partial overlap. */
5524 if (rtx_equal_p (operands[0], operands[3]))
5525 {
5526 rtx tmp0 = operands[0];
5527 rtx tmp1 = operands[1];
5528
5529 operands[0] = operands[2];
5530 operands[1] = operands[3];
5531 operands[2] = tmp0;
5532 operands[3] = tmp1;
5533 }
5534 "
5535)
5536
a8a3b539 5537;; We can't actually do base+index doubleword loads if the index and
5538;; destination overlap. Split here so that we at least have chance to
5539;; schedule.
5540(define_split
5541 [(set (match_operand:DI 0 "s_register_operand" "")
5542 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5543 (match_operand:SI 2 "s_register_operand" ""))))]
5544 "TARGET_LDRD
5545 && reg_overlap_mentioned_p (operands[0], operands[1])
5546 && reg_overlap_mentioned_p (operands[0], operands[2])"
5547 [(set (match_dup 4)
5548 (plus:SI (match_dup 1)
5549 (match_dup 2)))
5550 (set (match_dup 0)
5551 (mem:DI (match_dup 4)))]
5552 "
5553 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5554 "
5555)
5556
cffb2a26 5557;;; ??? This should have alternatives for constants.
5558;;; ??? This was originally identical to the movdf_insn pattern.
5559;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5560;;; thumb_reorg with a memory reference.
25f905c2 5561(define_insn "*thumb1_movdi_insn"
215b30b3 5562 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5563 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 5564 "TARGET_THUMB1
cffb2a26 5565 && ( register_operand (operands[0], DImode)
5566 || register_operand (operands[1], DImode))"
5567 "*
5568 {
5569 switch (which_alternative)
5570 {
5571 default:
5572 case 0:
5573 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5574 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5575 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5576 case 1:
5577 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5578 case 2:
5579 operands[1] = GEN_INT (- INTVAL (operands[1]));
5580 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5581 case 3:
5582 return \"ldmia\\t%1, {%0, %H0}\";
5583 case 4:
5584 return \"stmia\\t%0, {%1, %H1}\";
5585 case 5:
5586 return thumb_load_double_from_address (operands);
5587 case 6:
1a83b3ff 5588 operands[2] = gen_rtx_MEM (SImode,
29c05e22 5589 plus_constant (Pmode, XEXP (operands[0], 0), 4));
cffb2a26 5590 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5591 return \"\";
5592 case 7:
5593 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5594 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5595 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5596 }
5597 }"
5598 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5599 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5600 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
42e1de19 5601 (set_attr "pool_range" "*,*,*,*,*,1018,*,*")]
cffb2a26 5602)
b11cae9e 5603
9c08d1fa 5604(define_expand "movsi"
5605 [(set (match_operand:SI 0 "general_operand" "")
5606 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5607 "TARGET_EITHER"
9c08d1fa 5608 "
befb0bac 5609 {
e348ff3e 5610 rtx base, offset, tmp;
5611
25f905c2 5612 if (TARGET_32BIT)
9c08d1fa 5613 {
674a8f0b 5614 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5615 if (MEM_P (operands[0]))
cffb2a26 5616 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5617 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5618 && CONST_INT_P (operands[1])
cffb2a26 5619 && !(const_ok_for_arm (INTVAL (operands[1]))
5620 || const_ok_for_arm (~INTVAL (operands[1]))))
5621 {
96f57e36 5622 arm_split_constant (SET, SImode, NULL_RTX,
5623 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5624 optimize && can_create_pseudo_p ());
cffb2a26 5625 DONE;
5626 }
5627 }
25f905c2 5628 else /* TARGET_THUMB1... */
cffb2a26 5629 {
e1ba4a27 5630 if (can_create_pseudo_p ())
cffb2a26 5631 {
0438d37f 5632 if (!REG_P (operands[0]))
cffb2a26 5633 operands[1] = force_reg (SImode, operands[1]);
5634 }
9c08d1fa 5635 }
f655717d 5636
e348ff3e 5637 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5638 {
5639 split_const (operands[1], &base, &offset);
5640 if (GET_CODE (base) == SYMBOL_REF
5641 && !offset_within_block_p (base, INTVAL (offset)))
5642 {
b308ddcf 5643 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5644 emit_move_insn (tmp, base);
5645 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5646 DONE;
5647 }
5648 }
5649
f655717d 5650 /* Recognize the case where operand[1] is a reference to thread-local
5651 data and load its address to a register. */
5652 if (arm_tls_referenced_p (operands[1]))
5653 {
5654 rtx tmp = operands[1];
5655 rtx addend = NULL;
5656
5657 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5658 {
5659 addend = XEXP (XEXP (tmp, 0), 1);
5660 tmp = XEXP (XEXP (tmp, 0), 0);
5661 }
5662
5663 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5664 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5665
e1ba4a27 5666 tmp = legitimize_tls_address (tmp,
5667 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5668 if (addend)
5669 {
5670 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5671 tmp = force_operand (tmp, operands[0]);
5672 }
5673 operands[1] = tmp;
5674 }
5675 else if (flag_pic
5676 && (CONSTANT_P (operands[1])
5677 || symbol_mentioned_p (operands[1])
5678 || label_mentioned_p (operands[1])))
5679 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5680 (!can_create_pseudo_p ()
5681 ? operands[0]
5682 : 0));
befb0bac 5683 }
215b30b3 5684 "
5685)
9c08d1fa 5686
d0e6a121 5687;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5688;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5689;; so this does not matter.
5690(define_insn "*arm_movt"
5691 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5692 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5693 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5694 "arm_arch_thumb2"
d0e6a121 5695 "movt%?\t%0, #:upper16:%c2"
5696 [(set_attr "predicable" "yes")
5697 (set_attr "length" "4")]
5698)
5699
cffb2a26 5700(define_insn "*arm_movsi_insn"
aaa37ad6 5701 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5702 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5703 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5704 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5705 && ( register_operand (operands[0], SImode)
5706 || register_operand (operands[1], SImode))"
f7fbdd4a 5707 "@
aaa37ad6 5708 mov%?\\t%0, %1
f7fbdd4a 5709 mov%?\\t%0, %1
5710 mvn%?\\t%0, #%B1
25f905c2 5711 movw%?\\t%0, %1
f7fbdd4a 5712 ldr%?\\t%0, %1
5713 str%?\\t%1, %0"
65f68e55 5714 [(set_attr "type" "*,simple_alu_imm,simple_alu_imm,simple_alu_imm,load1,store1")
d2a518d1 5715 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5716 (set_attr "predicable" "yes")
aaa37ad6 5717 (set_attr "pool_range" "*,*,*,*,4096,*")
5718 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5719)
87b22bf7 5720
5721(define_split
a2cd141b 5722 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5723 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5724 "TARGET_32BIT
215b30b3 5725 && (!(const_ok_for_arm (INTVAL (operands[1]))
5726 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5727 [(clobber (const_int 0))]
5728 "
96f57e36 5729 arm_split_constant (SET, SImode, NULL_RTX,
5730 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5731 DONE;
215b30b3 5732 "
5733)
9c08d1fa 5734
b8d5d078 5735;; Split symbol_refs at the later stage (after cprop), instead of generating
5736;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5737;; and lo_sum would be merged back into memory load at cprop. However,
5738;; if the default is to prefer movt/movw rather than a load from the constant
5739;; pool, the performance is better.
5740(define_split
5741 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5742 (match_operand:SI 1 "general_operand" ""))]
5743 "TARGET_32BIT
5744 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5745 && !flag_pic && !target_word_relocations
5746 && !arm_tls_referenced_p (operands[1])"
5747 [(clobber (const_int 0))]
5748{
5749 arm_emit_movpair (operands[0], operands[1]);
5750 DONE;
5751})
5752
25f905c2 5753(define_insn "*thumb1_movsi_insn"
55a0d64c 5754 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5755 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 5756 "TARGET_THUMB1
cffb2a26 5757 && ( register_operand (operands[0], SImode)
5758 || register_operand (operands[1], SImode))"
5759 "@
5760 mov %0, %1
5761 mov %0, %1
5762 #
5763 #
5764 ldmia\\t%1, {%0}
5765 stmia\\t%0, {%1}
5766 ldr\\t%0, %1
5767 str\\t%1, %0
5768 mov\\t%0, %1"
5769 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5770 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
42e1de19 5771 (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")
747b7458 5772 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5773
5774(define_split
5775 [(set (match_operand:SI 0 "register_operand" "")
5776 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5777 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5778 [(set (match_dup 2) (match_dup 1))
5779 (set (match_dup 0) (neg:SI (match_dup 2)))]
5780 "
5781 {
5782 operands[1] = GEN_INT (- INTVAL (operands[1]));
5783 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5784 }"
cffb2a26 5785)
5786
5787(define_split
5788 [(set (match_operand:SI 0 "register_operand" "")
5789 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5790 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5791 [(set (match_dup 2) (match_dup 1))
5792 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5793 "
5794 {
e4aeee53 5795 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5796 unsigned HOST_WIDE_INT mask = 0xff;
5797 int i;
5798
5799 for (i = 0; i < 25; i++)
5800 if ((val & (mask << i)) == val)
5801 break;
5802
1276f1b8 5803 /* Don't split if the shift is zero. */
cffb2a26 5804 if (i == 0)
5805 FAIL;
5806
5807 operands[1] = GEN_INT (val >> i);
1276f1b8 5808 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5809 operands[3] = GEN_INT (i);
cffb2a26 5810 }"
5811)
5812
c5b75283 5813;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
5814(define_split
5815 [(set (match_operand:SI 0 "register_operand" "")
5816 (match_operand:SI 1 "const_int_operand" ""))]
5817 "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
5818 [(set (match_dup 2) (match_dup 1))
5819 (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
5820 "
5821 {
5822 operands[1] = GEN_INT (INTVAL (operands[1]) - 255);
5823 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5824 operands[3] = GEN_INT (255);
5825 }"
5826)
5827
67336bcf 5828;; When generating pic, we need to load the symbol offset into a register.
5829;; So that the optimizer does not confuse this with a normal symbol load
5830;; we use an unspec. The offset will be loaded from a constant pool entry,
5831;; since that is the only type of relocation we can use.
5832
94f8caca 5833;; Wrap calculation of the whole PIC address in a single pattern for the
5834;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5835;; a PIC address involves two loads from memory, so we want to CSE it
5836;; as often as possible.
5837;; This pattern will be split into one of the pic_load_addr_* patterns
5838;; and a move after GCSE optimizations.
5839;;
5840;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5841(define_expand "calculate_pic_address"
5842 [(set (match_operand:SI 0 "register_operand" "")
5843 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5844 (unspec:SI [(match_operand:SI 2 "" "")]
5845 UNSPEC_PIC_SYM))))]
5846 "flag_pic"
5847)
5848
5849;; Split calculate_pic_address into pic_load_addr_* and a move.
5850(define_split
5851 [(set (match_operand:SI 0 "register_operand" "")
5852 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5853 (unspec:SI [(match_operand:SI 2 "" "")]
5854 UNSPEC_PIC_SYM))))]
5855 "flag_pic"
5856 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5857 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5858 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5859)
5860
350ccca5 5861;; operand1 is the memory address to go into
5862;; pic_load_addr_32bit.
5863;; operand2 is the PIC label to be emitted
5864;; from pic_add_dot_plus_eight.
5865;; We do this to allow hoisting of the entire insn.
5866(define_insn_and_split "pic_load_addr_unified"
5867 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5868 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5869 (match_operand:SI 2 "" "")]
5870 UNSPEC_PIC_UNIFIED))]
5871 "flag_pic"
5872 "#"
5873 "&& reload_completed"
5874 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5875 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5876 (match_dup 2)] UNSPEC_PIC_BASE))]
5877 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5878 [(set_attr "type" "load1,load1,load1")
42e1de19 5879 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5880 (set_attr "neg_pool_range" "4084,0,0")
5881 (set_attr "arch" "a,t2,t1")
5882 (set_attr "length" "8,6,4")]
5883)
5884
67336bcf 5885;; The rather odd constraints on the following are to force reload to leave
5886;; the insn alone, and to force the minipool generation pass to then move
5887;; the GOT symbol to memory.
849170fd 5888
b3cd5f55 5889(define_insn "pic_load_addr_32bit"
849170fd 5890 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5891 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5892 "TARGET_32BIT && flag_pic"
67336bcf 5893 "ldr%?\\t%0, %1"
a2cd141b 5894 [(set_attr "type" "load1")
42e1de19 5895 (set (attr "pool_range")
5896 (if_then_else (eq_attr "is_thumb" "no")
5897 (const_int 4096)
5898 (const_int 4094)))
b3cd5f55 5899 (set (attr "neg_pool_range")
5900 (if_then_else (eq_attr "is_thumb" "no")
5901 (const_int 4084)
5902 (const_int 0)))]
8c4d8060 5903)
5904
25f905c2 5905(define_insn "pic_load_addr_thumb1"
8c4d8060 5906 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5907 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5908 "TARGET_THUMB1 && flag_pic"
8c4d8060 5909 "ldr\\t%0, %1"
a2cd141b 5910 [(set_attr "type" "load1")
42e1de19 5911 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5912)
849170fd 5913
cffb2a26 5914(define_insn "pic_add_dot_plus_four"
15d5d060 5915 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5916 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5917 (const_int 4)
beef0fb5 5918 (match_operand 2 "" "")]
5919 UNSPEC_PIC_BASE))]
b3cd5f55 5920 "TARGET_THUMB"
cffb2a26 5921 "*
6cdcb15c 5922 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5923 INTVAL (operands[2]));
cffb2a26 5924 return \"add\\t%0, %|pc\";
5925 "
5926 [(set_attr "length" "2")]
5927)
849170fd 5928
5929(define_insn "pic_add_dot_plus_eight"
15d5d060 5930 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5931 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5932 (const_int 8)
beef0fb5 5933 (match_operand 2 "" "")]
5934 UNSPEC_PIC_BASE))]
f655717d 5935 "TARGET_ARM"
c4034607 5936 "*
6cdcb15c 5937 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5938 INTVAL (operands[2]));
15d5d060 5939 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5940 "
0d66636f 5941 [(set_attr "predicable" "yes")]
cffb2a26 5942)
849170fd 5943
f655717d 5944(define_insn "tls_load_dot_plus_eight"
cc071db6 5945 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5946 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5947 (const_int 8)
beef0fb5 5948 (match_operand 2 "" "")]
5949 UNSPEC_PIC_BASE)))]
f655717d 5950 "TARGET_ARM"
5951 "*
6cdcb15c 5952 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5953 INTVAL (operands[2]));
f655717d 5954 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5955 "
5956 [(set_attr "predicable" "yes")]
5957)
5958
5959;; PIC references to local variables can generate pic_add_dot_plus_eight
5960;; followed by a load. These sequences can be crunched down to
5961;; tls_load_dot_plus_eight by a peephole.
5962
5963(define_peephole2
c0c1fba5 5964 [(set (match_operand:SI 0 "register_operand" "")
5965 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5966 (const_int 8)
5967 (match_operand 1 "" "")]
5968 UNSPEC_PIC_BASE))
2d05dfad 5969 (set (match_operand:SI 2 "arm_general_register_operand" "")
5970 (mem:SI (match_dup 0)))]
f655717d 5971 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5972 [(set (match_dup 2)
5973 (mem:SI (unspec:SI [(match_dup 3)
5974 (const_int 8)
5975 (match_dup 1)]
5976 UNSPEC_PIC_BASE)))]
f655717d 5977 ""
5978)
5979
bac7fc85 5980(define_insn "pic_offset_arm"
5981 [(set (match_operand:SI 0 "register_operand" "=r")
5982 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5983 (unspec:SI [(match_operand:SI 2 "" "X")]
5984 UNSPEC_PIC_OFFSET))))]
5985 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5986 "ldr%?\\t%0, [%1,%2]"
5987 [(set_attr "type" "load1")]
5988)
5989
95373f08 5990(define_expand "builtin_setjmp_receiver"
5991 [(label_ref (match_operand 0 "" ""))]
5992 "flag_pic"
5993 "
5994{
b935b306 5995 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5996 register. */
2cb7d577 5997 if (arm_pic_register != INVALID_REGNUM)
5998 arm_load_pic_register (1UL << 3);
95373f08 5999 DONE;
6000}")
6001
9c08d1fa 6002;; If copying one reg to another we can set the condition codes according to
6003;; its value. Such a move is common after a return from subroutine and the
6004;; result is being tested against zero.
6005
f7fbdd4a 6006(define_insn "*movsi_compare0"
bd5b4116 6007 [(set (reg:CC CC_REGNUM)
cffb2a26 6008 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6009 (const_int 0)))
6010 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6011 (match_dup 1))]
25f905c2 6012 "TARGET_32BIT"
e2348bcb 6013 "@
40dbec34 6014 cmp%?\\t%0, #0
25f905c2 6015 sub%.\\t%0, %1, #0"
65f68e55 6016 [(set_attr "conds" "set")
6017 (set_attr "type" "simple_alu_imm,simple_alu_imm")]
cffb2a26 6018)
b11cae9e 6019
b11cae9e 6020;; Subroutine to store a half word from a register into memory.
6021;; Operand 0 is the source register (HImode)
c8f69309 6022;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6023
9c08d1fa 6024;; In both this routine and the next, we must be careful not to spill
01cc3b75 6025;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6026;; can generate unrecognizable rtl.
6027
b11cae9e 6028(define_expand "storehi"
c8f69309 6029 [;; store the low byte
f082f1c4 6030 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6031 ;; extract the high byte
c8f69309 6032 (set (match_dup 2)
6033 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6034 ;; store the high byte
787f8210 6035 (set (match_dup 4) (match_dup 5))]
cffb2a26 6036 "TARGET_ARM"
b11cae9e 6037 "
215b30b3 6038 {
537ffcfc 6039 rtx op1 = operands[1];
6040 rtx addr = XEXP (op1, 0);
215b30b3 6041 enum rtx_code code = GET_CODE (addr);
6042
0438d37f 6043 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6044 || code == MINUS)
537ffcfc 6045 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6046
537ffcfc 6047 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6048 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6049 operands[3] = gen_lowpart (QImode, operands[0]);
6050 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6051 operands[2] = gen_reg_rtx (SImode);
6052 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6053 }"
6054)
b11cae9e 6055
c7597b5d 6056(define_expand "storehi_bigend"
f082f1c4 6057 [(set (match_dup 4) (match_dup 3))
c7597b5d 6058 (set (match_dup 2)
6059 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6060 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6061 "TARGET_ARM"
b11cae9e 6062 "
215b30b3 6063 {
537ffcfc 6064 rtx op1 = operands[1];
6065 rtx addr = XEXP (op1, 0);
215b30b3 6066 enum rtx_code code = GET_CODE (addr);
6067
0438d37f 6068 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6069 || code == MINUS)
537ffcfc 6070 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6071
537ffcfc 6072 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6073 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6074 operands[3] = gen_lowpart (QImode, operands[0]);
6075 operands[0] = gen_lowpart (SImode, operands[0]);
6076 operands[2] = gen_reg_rtx (SImode);
787f8210 6077 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6078 }"
6079)
c7597b5d 6080
6081;; Subroutine to store a half word integer constant into memory.
6082(define_expand "storeinthi"
f082f1c4 6083 [(set (match_operand 0 "" "")
787f8210 6084 (match_operand 1 "" ""))
9e8503e6 6085 (set (match_dup 3) (match_dup 2))]
cffb2a26 6086 "TARGET_ARM"
c7597b5d 6087 "
215b30b3 6088 {
6089 HOST_WIDE_INT value = INTVAL (operands[1]);
6090 rtx addr = XEXP (operands[0], 0);
537ffcfc 6091 rtx op0 = operands[0];
215b30b3 6092 enum rtx_code code = GET_CODE (addr);
c7597b5d 6093
0438d37f 6094 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6095 || code == MINUS)
537ffcfc 6096 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6097
215b30b3 6098 operands[1] = gen_reg_rtx (SImode);
6099 if (BYTES_BIG_ENDIAN)
6100 {
6101 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6102 if ((value & 255) == ((value >> 8) & 255))
6103 operands[2] = operands[1];
6104 else
6105 {
6106 operands[2] = gen_reg_rtx (SImode);
6107 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6108 }
6109 }
6110 else
6111 {
6112 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6113 if ((value & 255) == ((value >> 8) & 255))
6114 operands[2] = operands[1];
6115 else
6116 {
6117 operands[2] = gen_reg_rtx (SImode);
6118 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6119 }
6120 }
c7597b5d 6121
537ffcfc 6122 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6123 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6124 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6125 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6126 }"
6127)
b11cae9e 6128
f7fbdd4a 6129(define_expand "storehi_single_op"
6130 [(set (match_operand:HI 0 "memory_operand" "")
6131 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6132 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6133 "
215b30b3 6134 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6135 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6136 "
6137)
f7fbdd4a 6138
b11cae9e 6139(define_expand "movhi"
6140 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6141 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6142 "TARGET_EITHER"
b11cae9e 6143 "
cffb2a26 6144 if (TARGET_ARM)
b11cae9e 6145 {
e1ba4a27 6146 if (can_create_pseudo_p ())
cffb2a26 6147 {
0438d37f 6148 if (MEM_P (operands[0]))
b11cae9e 6149 {
cffb2a26 6150 if (arm_arch4)
6151 {
6152 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6153 DONE;
6154 }
0438d37f 6155 if (CONST_INT_P (operands[1]))
cffb2a26 6156 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6157 else
cffb2a26 6158 {
0438d37f 6159 if (MEM_P (operands[1]))
cffb2a26 6160 operands[1] = force_reg (HImode, operands[1]);
6161 if (BYTES_BIG_ENDIAN)
6162 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6163 else
6164 emit_insn (gen_storehi (operands[1], operands[0]));
6165 }
6166 DONE;
b11cae9e 6167 }
cffb2a26 6168 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6169 else if (CONST_INT_P (operands[1]))
9c08d1fa 6170 {
cffb2a26 6171 rtx reg = gen_reg_rtx (SImode);
6172 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6173
6174 /* If the constant is already valid, leave it alone. */
215b30b3 6175 if (!const_ok_for_arm (val))
cffb2a26 6176 {
6177 /* If setting all the top bits will make the constant
6178 loadable in a single instruction, then set them.
6179 Otherwise, sign extend the number. */
6180
215b30b3 6181 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6182 val |= ~0xffff;
6183 else if (val & 0x8000)
6184 val |= ~0xffff;
6185 }
6186
6187 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6188 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6189 }
e1ba4a27 6190 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6191 && MEM_P (operands[1]))
0045890a 6192 {
6193 rtx reg = gen_reg_rtx (SImode);
6194
6195 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6196 operands[1] = gen_lowpart (HImode, reg);
6197 }
215b30b3 6198 else if (!arm_arch4)
f7fbdd4a 6199 {
0438d37f 6200 if (MEM_P (operands[1]))
cffb2a26 6201 {
c1a66faf 6202 rtx base;
6203 rtx offset = const0_rtx;
6204 rtx reg = gen_reg_rtx (SImode);
6205
0438d37f 6206 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6207 || (GET_CODE (base) == PLUS
0438d37f 6208 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6209 && ((INTVAL(offset) & 1) != 1)
0438d37f 6210 && REG_P (base = XEXP (base, 0))))
c1a66faf 6211 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6212 {
8deb3959 6213 rtx new_rtx;
c1a66faf 6214
8deb3959 6215 new_rtx = widen_memory_access (operands[1], SImode,
6216 ((INTVAL (offset) & ~3)
6217 - INTVAL (offset)));
6218 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6219 if (((INTVAL (offset) & 2) != 0)
6220 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6221 {
6222 rtx reg2 = gen_reg_rtx (SImode);
6223
6224 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6225 reg = reg2;
6226 }
206ee9a2 6227 }
c1a66faf 6228 else
6229 emit_insn (gen_movhi_bytes (reg, operands[1]));
6230
6231 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6232 }
6233 }
6234 }
674a8f0b 6235 /* Handle loading a large integer during reload. */
0438d37f 6236 else if (CONST_INT_P (operands[1])
215b30b3 6237 && !const_ok_for_arm (INTVAL (operands[1]))
6238 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6239 {
6240 /* Writing a constant to memory needs a scratch, which should
6241 be handled with SECONDARY_RELOADs. */
0438d37f 6242 gcc_assert (REG_P (operands[0]));
cffb2a26 6243
6244 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6245 emit_insn (gen_movsi (operands[0], operands[1]));
6246 DONE;
6247 }
6248 }
25f905c2 6249 else if (TARGET_THUMB2)
6250 {
6251 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6252 if (can_create_pseudo_p ())
25f905c2 6253 {
0438d37f 6254 if (!REG_P (operands[0]))
25f905c2 6255 operands[1] = force_reg (HImode, operands[1]);
6256 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6257 else if (CONST_INT_P (operands[1]))
25f905c2 6258 {
6259 rtx reg = gen_reg_rtx (SImode);
6260 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6261
6262 emit_insn (gen_movsi (reg, GEN_INT (val)));
6263 operands[1] = gen_lowpart (HImode, reg);
6264 }
6265 }
6266 }
6267 else /* TARGET_THUMB1 */
cffb2a26 6268 {
e1ba4a27 6269 if (can_create_pseudo_p ())
cffb2a26 6270 {
0438d37f 6271 if (CONST_INT_P (operands[1]))
6cffc037 6272 {
6273 rtx reg = gen_reg_rtx (SImode);
6274
6275 emit_insn (gen_movsi (reg, operands[1]));
6276 operands[1] = gen_lowpart (HImode, reg);
6277 }
cffb2a26 6278
6279 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6280 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6281 virtual register (also rejected as illegitimate for HImode/QImode)
6282 relative address. */
cffb2a26 6283 /* ??? This should perhaps be fixed elsewhere, for instance, in
6284 fixup_stack_1, by checking for other kinds of invalid addresses,
6285 e.g. a bare reference to a virtual register. This may confuse the
6286 alpha though, which must handle this case differently. */
0438d37f 6287 if (MEM_P (operands[0])
215b30b3 6288 && !memory_address_p (GET_MODE (operands[0]),
6289 XEXP (operands[0], 0)))
537ffcfc 6290 operands[0]
6291 = replace_equiv_address (operands[0],
6292 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6293
0438d37f 6294 if (MEM_P (operands[1])
215b30b3 6295 && !memory_address_p (GET_MODE (operands[1]),
6296 XEXP (operands[1], 0)))
537ffcfc 6297 operands[1]
6298 = replace_equiv_address (operands[1],
6299 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6300
0438d37f 6301 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6302 {
6303 rtx reg = gen_reg_rtx (SImode);
6304
6305 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6306 operands[1] = gen_lowpart (HImode, reg);
6307 }
6308
0438d37f 6309 if (MEM_P (operands[0]))
6cffc037 6310 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6311 }
0438d37f 6312 else if (CONST_INT_P (operands[1])
234f6557 6313 && !satisfies_constraint_I (operands[1]))
cffb2a26 6314 {
6cffc037 6315 /* Handle loading a large integer during reload. */
6316
cffb2a26 6317 /* Writing a constant to memory needs a scratch, which should
6318 be handled with SECONDARY_RELOADs. */
0438d37f 6319 gcc_assert (REG_P (operands[0]));
cffb2a26 6320
1a83b3ff 6321 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6322 emit_insn (gen_movsi (operands[0], operands[1]));
6323 DONE;
6324 }
b11cae9e 6325 }
cffb2a26 6326 "
6327)
6328
25f905c2 6329(define_insn "*thumb1_movhi_insn"
a941568e 6330 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6331 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 6332 "TARGET_THUMB1
cffb2a26 6333 && ( register_operand (operands[0], HImode)
6334 || register_operand (operands[1], HImode))"
6335 "*
6336 switch (which_alternative)
d79300ac 6337 {
cffb2a26 6338 case 0: return \"add %0, %1, #0\";
6339 case 2: return \"strh %1, %0\";
6340 case 3: return \"mov %0, %1\";
6341 case 4: return \"mov %0, %1\";
6342 case 5: return \"mov %0, %1\";
ed29c566 6343 default: gcc_unreachable ();
cffb2a26 6344 case 1:
6345 /* The stack pointer can end up being taken as an index register.
6346 Catch this case here and deal with it. */
6347 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
0438d37f 6348 && REG_P (XEXP (XEXP (operands[1], 0), 0))
cffb2a26 6349 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
6350 {
6351 rtx ops[2];
6352 ops[0] = operands[0];
6353 ops[1] = XEXP (XEXP (operands[1], 0), 0);
6354
6355 output_asm_insn (\"mov %0, %1\", ops);
6356
6357 XEXP (XEXP (operands[1], 0), 0) = operands[0];
6358
6359 }
6360 return \"ldrh %0, %1\";
6361 }"
6362 [(set_attr "length" "2,4,2,2,2,2")
747b7458 6363 (set_attr "type" "*,load1,store1,*,*,*")
6364 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 6365
b11cae9e 6366
25f7a26e 6367(define_expand "movhi_bytes"
eab14235 6368 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6369 (set (match_dup 3)
eab14235 6370 (zero_extend:SI (match_dup 6)))
25f7a26e 6371 (set (match_operand:SI 0 "" "")
6372 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6373 "TARGET_ARM"
25f7a26e 6374 "
215b30b3 6375 {
6376 rtx mem1, mem2;
6377 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6378
788fcce0 6379 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6380 mem2 = change_address (operands[1], QImode,
6381 plus_constant (Pmode, addr, 1));
215b30b3 6382 operands[0] = gen_lowpart (SImode, operands[0]);
6383 operands[1] = mem1;
6384 operands[2] = gen_reg_rtx (SImode);
6385 operands[3] = gen_reg_rtx (SImode);
6386 operands[6] = mem2;
25f7a26e 6387
215b30b3 6388 if (BYTES_BIG_ENDIAN)
6389 {
6390 operands[4] = operands[2];
6391 operands[5] = operands[3];
6392 }
6393 else
6394 {
6395 operands[4] = operands[3];
6396 operands[5] = operands[2];
6397 }
6398 }"
6399)
25f7a26e 6400
c7597b5d 6401(define_expand "movhi_bigend"
6402 [(set (match_dup 2)
6403 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6404 (const_int 16)))
6405 (set (match_dup 3)
6406 (ashiftrt:SI (match_dup 2) (const_int 16)))
6407 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6408 (match_dup 4))]
cffb2a26 6409 "TARGET_ARM"
c7597b5d 6410 "
6411 operands[2] = gen_reg_rtx (SImode);
6412 operands[3] = gen_reg_rtx (SImode);
787f8210 6413 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6414 "
6415)
b11cae9e 6416
a2f10574 6417;; Pattern to recognize insn generated default case above
f7fbdd4a 6418(define_insn "*movhi_insn_arch4"
cde1623a 6419 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 6420 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 6421 "TARGET_ARM
6422 && arm_arch4
85e02ccb 6423 && (register_operand (operands[0], HImode)
6424 || register_operand (operands[1], HImode))"
f7fbdd4a 6425 "@
6426 mov%?\\t%0, %1\\t%@ movhi
6427 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 6428 str%(h%)\\t%1, %0\\t%@ movhi
6429 ldr%(h%)\\t%0, %1\\t%@ movhi"
65f68e55 6430 [(set_attr "predicable" "yes")
d2a518d1 6431 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 6432 (set_attr "pool_range" "*,*,*,256")
65f68e55 6433 (set_attr "neg_pool_range" "*,*,*,244")
6434 (set_attr_alternative "type"
6435 [(if_then_else (match_operand 1 "const_int_operand" "")
6436 (const_string "simple_alu_imm" )
6437 (const_string "*"))
6438 (const_string "simple_alu_imm")
6439 (const_string "store1")
6440 (const_string "load1")])]
cffb2a26 6441)
f7fbdd4a 6442
f7fbdd4a 6443(define_insn "*movhi_bytes"
65f68e55 6444 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
6445 (match_operand:HI 1 "arm_rhs_operand" "I,r,K"))]
c1a66faf 6446 "TARGET_ARM"
25f7a26e 6447 "@
65f68e55 6448 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6449 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6450 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6451 [(set_attr "predicable" "yes")
65f68e55 6452 (set_attr "insn" "mov, mov,mvn")
6453 (set_attr "type" "simple_alu_imm,*,simple_alu_imm")]
0d66636f 6454)
25f7a26e 6455
f90b51f1 6456(define_expand "thumb_movhi_clobber"
6457 [(set (match_operand:HI 0 "memory_operand" "")
6458 (match_operand:HI 1 "register_operand" ""))
6459 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 6460 "TARGET_THUMB1"
f90b51f1 6461 "
6462 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
6463 && REGNO (operands[1]) <= LAST_LO_REGNUM)
6464 {
6465 emit_insn (gen_movhi (operands[0], operands[1]));
6466 DONE;
6467 }
6468 /* XXX Fixme, need to handle other cases here as well. */
6469 gcc_unreachable ();
6470 "
cffb2a26 6471)
6472
bc5c7e08 6473;; We use a DImode scratch because we may occasionally need an additional
6474;; temporary if the address isn't offsettable -- push_reload doesn't seem
6475;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6476(define_expand "reload_outhi"
cffb2a26 6477 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6478 (match_operand:HI 1 "s_register_operand" "r")
6479 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6480 "TARGET_EITHER"
6481 "if (TARGET_ARM)
6482 arm_reload_out_hi (operands);
6483 else
6484 thumb_reload_out_hi (operands);
d3373b54 6485 DONE;
cffb2a26 6486 "
6487)
d3373b54 6488
25f7a26e 6489(define_expand "reload_inhi"
6490 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6491 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6492 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6493 "TARGET_EITHER"
25f7a26e 6494 "
cffb2a26 6495 if (TARGET_ARM)
6496 arm_reload_in_hi (operands);
6497 else
6498 thumb_reload_out_hi (operands);
25f7a26e 6499 DONE;
6500")
6501
9c08d1fa 6502(define_expand "movqi"
6503 [(set (match_operand:QI 0 "general_operand" "")
6504 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6505 "TARGET_EITHER"
9c08d1fa 6506 "
6cffc037 6507 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6508
e1ba4a27 6509 if (can_create_pseudo_p ())
cffb2a26 6510 {
0438d37f 6511 if (CONST_INT_P (operands[1]))
6cffc037 6512 {
6513 rtx reg = gen_reg_rtx (SImode);
6514
03770691 6515 /* For thumb we want an unsigned immediate, then we are more likely
6516 to be able to use a movs insn. */
6517 if (TARGET_THUMB)
6518 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6519
6cffc037 6520 emit_insn (gen_movsi (reg, operands[1]));
6521 operands[1] = gen_lowpart (QImode, reg);
6522 }
cffb2a26 6523
6cffc037 6524 if (TARGET_THUMB)
6525 {
cffb2a26 6526 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6527 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6528 virtual register (also rejected as illegitimate for HImode/QImode)
6529 relative address. */
cffb2a26 6530 /* ??? This should perhaps be fixed elsewhere, for instance, in
6531 fixup_stack_1, by checking for other kinds of invalid addresses,
6532 e.g. a bare reference to a virtual register. This may confuse the
6533 alpha though, which must handle this case differently. */
0438d37f 6534 if (MEM_P (operands[0])
215b30b3 6535 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6536 XEXP (operands[0], 0)))
537ffcfc 6537 operands[0]
6538 = replace_equiv_address (operands[0],
6539 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6540 if (MEM_P (operands[1])
215b30b3 6541 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6542 XEXP (operands[1], 0)))
537ffcfc 6543 operands[1]
6544 = replace_equiv_address (operands[1],
6545 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6546 }
6547
0438d37f 6548 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6549 {
6550 rtx reg = gen_reg_rtx (SImode);
6551
6552 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6553 operands[1] = gen_lowpart (QImode, reg);
6554 }
6555
0438d37f 6556 if (MEM_P (operands[0]))
6cffc037 6557 operands[1] = force_reg (QImode, operands[1]);
6558 }
6559 else if (TARGET_THUMB
0438d37f 6560 && CONST_INT_P (operands[1])
234f6557 6561 && !satisfies_constraint_I (operands[1]))
6cffc037 6562 {
674a8f0b 6563 /* Handle loading a large integer during reload. */
cffb2a26 6564
6cffc037 6565 /* Writing a constant to memory needs a scratch, which should
6566 be handled with SECONDARY_RELOADs. */
0438d37f 6567 gcc_assert (REG_P (operands[0]));
6cffc037 6568
6569 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6570 emit_insn (gen_movsi (operands[0], operands[1]));
6571 DONE;
cffb2a26 6572 }
6573 "
6574)
b11cae9e 6575
9c08d1fa 6576
cffb2a26 6577(define_insn "*arm_movqi_insn"
65f68e55 6578 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,Uu,r,m")
6579 (match_operand:QI 1 "general_operand" "r,I,K,Uu,l,m,r"))]
25f905c2 6580 "TARGET_32BIT
cffb2a26 6581 && ( register_operand (operands[0], QImode)
6582 || register_operand (operands[1], QImode))"
5565501b 6583 "@
65f68e55 6584 mov%?\\t%0, %1
5565501b 6585 mov%?\\t%0, %1
6586 mvn%?\\t%0, #%B1
25f905c2 6587 ldr%(b%)\\t%0, %1
a54e3e7b 6588 str%(b%)\\t%1, %0
6589 ldr%(b%)\\t%0, %1
25f905c2 6590 str%(b%)\\t%1, %0"
65f68e55 6591 [(set_attr "type" "*,simple_alu_imm,simple_alu_imm,load1, store1, load1, store1")
6592 (set_attr "insn" "mov,mov,mvn,*,*,*,*")
a54e3e7b 6593 (set_attr "predicable" "yes")
65f68e55 6594 (set_attr "arch" "any,any,any,t2,t2,any,any")
6595 (set_attr "length" "4,4,4,2,2,4,4")]
cffb2a26 6596)
6597
25f905c2 6598(define_insn "*thumb1_movqi_insn"
cffb2a26 6599 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 6600 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 6601 "TARGET_THUMB1
cffb2a26 6602 && ( register_operand (operands[0], QImode)
6603 || register_operand (operands[1], QImode))"
6604 "@
6605 add\\t%0, %1, #0
6606 ldrb\\t%0, %1
6607 strb\\t%1, %0
6608 mov\\t%0, %1
6609 mov\\t%0, %1
6610 mov\\t%0, %1"
6611 [(set_attr "length" "2")
65f68e55 6612 (set_attr "type" "simple_alu_imm,load1,store1,*,*,simple_alu_imm")
d2a518d1 6613 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 6614 (set_attr "pool_range" "*,32,*,*,*,*")
6615 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 6616
9b8516be 6617;; HFmode moves
6618(define_expand "movhf"
6619 [(set (match_operand:HF 0 "general_operand" "")
6620 (match_operand:HF 1 "general_operand" ""))]
6621 "TARGET_EITHER"
6622 "
6623 if (TARGET_32BIT)
6624 {
0438d37f 6625 if (MEM_P (operands[0]))
9b8516be 6626 operands[1] = force_reg (HFmode, operands[1]);
6627 }
6628 else /* TARGET_THUMB1 */
6629 {
6630 if (can_create_pseudo_p ())
6631 {
0438d37f 6632 if (!REG_P (operands[0]))
9b8516be 6633 operands[1] = force_reg (HFmode, operands[1]);
6634 }
6635 }
6636 "
6637)
6638
6639(define_insn "*arm32_movhf"
6640 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6641 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 6642 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6643 && ( s_register_operand (operands[0], HFmode)
6644 || s_register_operand (operands[1], HFmode))"
6645 "*
6646 switch (which_alternative)
6647 {
6648 case 0: /* ARM register from memory */
6649 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6650 case 1: /* memory from ARM register */
6651 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6652 case 2: /* ARM register from ARM register */
6653 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6654 case 3: /* ARM register from constant */
6655 {
6656 REAL_VALUE_TYPE r;
6657 long bits;
6658 rtx ops[4];
6659
6660 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6661 bits = real_to_target (NULL, &r, HFmode);
6662 ops[0] = operands[0];
6663 ops[1] = GEN_INT (bits);
6664 ops[2] = GEN_INT (bits & 0xff00);
6665 ops[3] = GEN_INT (bits & 0x00ff);
6666
6667 if (arm_arch_thumb2)
6668 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6669 else
6670 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6671 return \"\";
6672 }
6673 default:
6674 gcc_unreachable ();
6675 }
6676 "
6677 [(set_attr "conds" "unconditional")
6678 (set_attr "type" "load1,store1,*,*")
d2a518d1 6679 (set_attr "insn" "*,*,mov,mov")
9b8516be 6680 (set_attr "length" "4,4,4,8")
d2a518d1 6681 (set_attr "predicable" "yes")]
9b8516be 6682)
6683
6684(define_insn "*thumb1_movhf"
6685 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6686 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6687 "TARGET_THUMB1
6688 && ( s_register_operand (operands[0], HFmode)
6689 || s_register_operand (operands[1], HFmode))"
6690 "*
6691 switch (which_alternative)
6692 {
6693 case 1:
6694 {
6695 rtx addr;
0438d37f 6696 gcc_assert (MEM_P (operands[1]));
9b8516be 6697 addr = XEXP (operands[1], 0);
6698 if (GET_CODE (addr) == LABEL_REF
6699 || (GET_CODE (addr) == CONST
6700 && GET_CODE (XEXP (addr, 0)) == PLUS
6701 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
0438d37f 6702 && CONST_INT_P (XEXP (XEXP (addr, 0), 1))))
9b8516be 6703 {
6704 /* Constant pool entry. */
6705 return \"ldr\\t%0, %1\";
6706 }
6707 return \"ldrh\\t%0, %1\";
6708 }
6709 case 2: return \"strh\\t%1, %0\";
6710 default: return \"mov\\t%0, %1\";
6711 }
6712 "
6713 [(set_attr "length" "2")
6714 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6715 (set_attr "insn" "mov,*,*,mov,mov")
42e1de19 6716 (set_attr "pool_range" "*,1018,*,*,*")
747b7458 6717 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6718
87b22bf7 6719(define_expand "movsf"
6720 [(set (match_operand:SF 0 "general_operand" "")
6721 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6722 "TARGET_EITHER"
87b22bf7 6723 "
25f905c2 6724 if (TARGET_32BIT)
cffb2a26 6725 {
0438d37f 6726 if (MEM_P (operands[0]))
cffb2a26 6727 operands[1] = force_reg (SFmode, operands[1]);
6728 }
25f905c2 6729 else /* TARGET_THUMB1 */
cffb2a26 6730 {
e1ba4a27 6731 if (can_create_pseudo_p ())
cffb2a26 6732 {
0438d37f 6733 if (!REG_P (operands[0]))
cffb2a26 6734 operands[1] = force_reg (SFmode, operands[1]);
6735 }
6736 }
6737 "
6738)
6739
03d440a6 6740;; Transform a floating-point move of a constant into a core register into
6741;; an SImode operation.
cffb2a26 6742(define_split
03d440a6 6743 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6744 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6745 "TARGET_EITHER
cffb2a26 6746 && reload_completed
0438d37f 6747 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6748 [(set (match_dup 2) (match_dup 3))]
6749 "
6750 operands[2] = gen_lowpart (SImode, operands[0]);
6751 operands[3] = gen_lowpart (SImode, operands[1]);
6752 if (operands[2] == 0 || operands[3] == 0)
6753 FAIL;
215b30b3 6754 "
6755)
87b22bf7 6756
cffb2a26 6757(define_insn "*arm_movsf_soft_insn"
6758 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6759 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6760 "TARGET_32BIT
cffb2a26 6761 && TARGET_SOFT_FLOAT
0438d37f 6762 && (!MEM_P (operands[0])
215b30b3 6763 || register_operand (operands[1], SFmode))"
9a1112d7 6764 "@
6765 mov%?\\t%0, %1
6766 ldr%?\\t%0, %1\\t%@ float
6767 str%?\\t%1, %0\\t%@ float"
cde1623a 6768 [(set_attr "predicable" "yes")
a2cd141b 6769 (set_attr "type" "*,load1,store1")
d2a518d1 6770 (set_attr "insn" "mov,*,*")
42e1de19 6771 (set_attr "arm_pool_range" "*,4096,*")
6772 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6773 (set_attr "arm_neg_pool_range" "*,4084,*")
6774 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6775)
6776
6777;;; ??? This should have alternatives for constants.
25f905c2 6778(define_insn "*thumb1_movsf_insn"
215b30b3 6779 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6780 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6781 "TARGET_THUMB1
cffb2a26 6782 && ( register_operand (operands[0], SFmode)
6783 || register_operand (operands[1], SFmode))"
6784 "@
6785 add\\t%0, %1, #0
6786 ldmia\\t%1, {%0}
6787 stmia\\t%0, {%1}
6788 ldr\\t%0, %1
6789 str\\t%1, %0
6790 mov\\t%0, %1
6791 mov\\t%0, %1"
6792 [(set_attr "length" "2")
a2cd141b 6793 (set_attr "type" "*,load1,store1,load1,store1,*,*")
42e1de19 6794 (set_attr "pool_range" "*,*,*,1018,*,*,*")
d2a518d1 6795 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6796 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6797)
9a1112d7 6798
9c08d1fa 6799(define_expand "movdf"
87b22bf7 6800 [(set (match_operand:DF 0 "general_operand" "")
6801 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6802 "TARGET_EITHER"
9c08d1fa 6803 "
25f905c2 6804 if (TARGET_32BIT)
cffb2a26 6805 {
0438d37f 6806 if (MEM_P (operands[0]))
cffb2a26 6807 operands[1] = force_reg (DFmode, operands[1]);
6808 }
6809 else /* TARGET_THUMB */
6810 {
e1ba4a27 6811 if (can_create_pseudo_p ())
cffb2a26 6812 {
0438d37f 6813 if (!REG_P (operands[0]))
cffb2a26 6814 operands[1] = force_reg (DFmode, operands[1]);
6815 }
6816 }
6817 "
6818)
b11cae9e 6819
9c08d1fa 6820;; Reloading a df mode value stored in integer regs to memory can require a
6821;; scratch reg.
6822(define_expand "reload_outdf"
cffb2a26 6823 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6824 (match_operand:DF 1 "s_register_operand" "r")
6825 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6826 "TARGET_THUMB2"
87b22bf7 6827 "
215b30b3 6828 {
6829 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6830
215b30b3 6831 if (code == REG)
6832 operands[2] = XEXP (operands[0], 0);
6833 else if (code == POST_INC || code == PRE_DEC)
6834 {
6835 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6836 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6837 emit_insn (gen_movdi (operands[0], operands[1]));
6838 DONE;
6839 }
6840 else if (code == PRE_INC)
6841 {
6842 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6843
215b30b3 6844 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6845 operands[2] = reg;
6846 }
6847 else if (code == POST_DEC)
6848 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6849 else
6850 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6851 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6852
788fcce0 6853 emit_insn (gen_rtx_SET (VOIDmode,
6854 replace_equiv_address (operands[0], operands[2]),
215b30b3 6855 operands[1]));
f7fbdd4a 6856
215b30b3 6857 if (code == POST_DEC)
6858 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6859
6860 DONE;
6861 }"
6862)
9c08d1fa 6863
9a1112d7 6864(define_insn "*movdf_soft_insn"
359a6e9f 6865 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6866 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6867 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6868 && ( register_operand (operands[0], DFmode)
6869 || register_operand (operands[1], DFmode))"
d51f92df 6870 "*
6871 switch (which_alternative)
6872 {
6873 case 0:
6874 case 1:
6875 case 2:
6876 return \"#\";
6877 default:
26ff80c0 6878 return output_move_double (operands, true, NULL);
d51f92df 6879 }
6880 "
359a6e9f 6881 [(set_attr "length" "8,12,16,8,8")
6882 (set_attr "type" "*,*,*,load2,store2")
42e1de19 6883 (set_attr "arm_pool_range" "*,*,*,1020,*")
6884 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6885 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6886 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6887)
6888
6889;;; ??? This should have alternatives for constants.
6890;;; ??? This was originally identical to the movdi_insn pattern.
6891;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6892;;; thumb_reorg with a memory reference.
6893(define_insn "*thumb_movdf_insn"
215b30b3 6894 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6895 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6896 "TARGET_THUMB1
cffb2a26 6897 && ( register_operand (operands[0], DFmode)
6898 || register_operand (operands[1], DFmode))"
6899 "*
6900 switch (which_alternative)
6901 {
6902 default:
6903 case 0:
6904 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6905 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6906 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6907 case 1:
6908 return \"ldmia\\t%1, {%0, %H0}\";
6909 case 2:
6910 return \"stmia\\t%0, {%1, %H1}\";
6911 case 3:
6912 return thumb_load_double_from_address (operands);
6913 case 4:
1a83b3ff 6914 operands[2] = gen_rtx_MEM (SImode,
29c05e22 6915 plus_constant (Pmode,
6916 XEXP (operands[0], 0), 4));
cffb2a26 6917 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6918 return \"\";
6919 case 5:
6920 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6921 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6922 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6923 }
6924 "
6925 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6926 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6927 (set_attr "insn" "*,*,*,*,*,mov")
42e1de19 6928 (set_attr "pool_range" "*,*,*,1018,*,*")]
cffb2a26 6929)
b11cae9e 6930\f
b11cae9e 6931
9c08d1fa 6932;; load- and store-multiple insns
6933;; The arm can load/store any set of registers, provided that they are in
320ea44d 6934;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6935
9c08d1fa 6936(define_expand "load_multiple"
6937 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6938 (match_operand:SI 1 "" ""))
6939 (use (match_operand:SI 2 "" ""))])]
25f905c2 6940 "TARGET_32BIT"
9580c25f 6941{
6942 HOST_WIDE_INT offset = 0;
6943
bd5b4116 6944 /* Support only fixed point registers. */
0438d37f 6945 if (!CONST_INT_P (operands[2])
9c08d1fa 6946 || INTVAL (operands[2]) > 14
6947 || INTVAL (operands[2]) < 2
0438d37f 6948 || !MEM_P (operands[1])
6949 || !REG_P (operands[0])
bd5b4116 6950 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6951 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6952 FAIL;
6953
6954 operands[3]
320ea44d 6955 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6956 INTVAL (operands[2]),
f082f1c4 6957 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6958 FALSE, operands[1], &offset);
9580c25f 6959})
b11cae9e 6960
9c08d1fa 6961(define_expand "store_multiple"
6962 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6963 (match_operand:SI 1 "" ""))
6964 (use (match_operand:SI 2 "" ""))])]
25f905c2 6965 "TARGET_32BIT"
9580c25f 6966{
6967 HOST_WIDE_INT offset = 0;
6968
674a8f0b 6969 /* Support only fixed point registers. */
0438d37f 6970 if (!CONST_INT_P (operands[2])
9c08d1fa 6971 || INTVAL (operands[2]) > 14
6972 || INTVAL (operands[2]) < 2
0438d37f 6973 || !REG_P (operands[1])
6974 || !MEM_P (operands[0])
bd5b4116 6975 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6976 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6977 FAIL;
6978
6979 operands[3]
320ea44d 6980 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6981 INTVAL (operands[2]),
f082f1c4 6982 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6983 FALSE, operands[0], &offset);
9580c25f 6984})
b11cae9e 6985
9c08d1fa 6986
6987;; Move a block of memory if it is word aligned and MORE than 2 words long.
6988;; We could let this apply for blocks of less than this, but it clobbers so
6989;; many registers that there is then probably a better way.
6990
008c057d 6991(define_expand "movmemqi"
34191dd1 6992 [(match_operand:BLK 0 "general_operand" "")
6993 (match_operand:BLK 1 "general_operand" "")
6994 (match_operand:SI 2 "const_int_operand" "")
6995 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6996 "TARGET_EITHER"
9c08d1fa 6997 "
25f905c2 6998 if (TARGET_32BIT)
cffb2a26 6999 {
008c057d 7000 if (arm_gen_movmemqi (operands))
cffb2a26 7001 DONE;
7002 FAIL;
7003 }
25f905c2 7004 else /* TARGET_THUMB1 */
cffb2a26 7005 {
7006 if ( INTVAL (operands[3]) != 4
7007 || INTVAL (operands[2]) > 48)
7008 FAIL;
7009
008c057d 7010 thumb_expand_movmemqi (operands);
cffb2a26 7011 DONE;
7012 }
7013 "
7014)
7015
2162064c 7016;; Thumb block-move insns
cffb2a26 7017
7018(define_insn "movmem12b"
960f3acf 7019 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
7020 (mem:SI (match_operand:SI 3 "register_operand" "1")))
7021 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
7022 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
7023 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
7024 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
7025 (set (match_operand:SI 0 "register_operand" "=l")
7026 (plus:SI (match_dup 2) (const_int 12)))
7027 (set (match_operand:SI 1 "register_operand" "=l")
7028 (plus:SI (match_dup 3) (const_int 12)))
7029 (clobber (match_scratch:SI 4 "=&l"))
7030 (clobber (match_scratch:SI 5 "=&l"))
7031 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 7032 "TARGET_THUMB1"
cffb2a26 7033 "* return thumb_output_move_mem_multiple (3, operands);"
7034 [(set_attr "length" "4")
215b30b3 7035 ; This isn't entirely accurate... It loads as well, but in terms of
7036 ; scheduling the following insn it is better to consider it as a store
cffb2a26 7037 (set_attr "type" "store3")]
7038)
7039
7040(define_insn "movmem8b"
960f3acf 7041 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
7042 (mem:SI (match_operand:SI 3 "register_operand" "1")))
7043 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
7044 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
7045 (set (match_operand:SI 0 "register_operand" "=l")
7046 (plus:SI (match_dup 2) (const_int 8)))
7047 (set (match_operand:SI 1 "register_operand" "=l")
7048 (plus:SI (match_dup 3) (const_int 8)))
7049 (clobber (match_scratch:SI 4 "=&l"))
7050 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 7051 "TARGET_THUMB1"
cffb2a26 7052 "* return thumb_output_move_mem_multiple (2, operands);"
7053 [(set_attr "length" "4")
215b30b3 7054 ; This isn't entirely accurate... It loads as well, but in terms of
7055 ; scheduling the following insn it is better to consider it as a store
cffb2a26 7056 (set_attr "type" "store2")]
7057)
7058
9c08d1fa 7059\f
b11cae9e 7060
341940e8 7061;; Compare & branch insns
8d232dc7 7062;; The range calculations are based as follows:
341940e8 7063;; For forward branches, the address calculation returns the address of
7064;; the next instruction. This is 2 beyond the branch instruction.
7065;; For backward branches, the address calculation returns the address of
7066;; the first instruction in this pattern (cmp). This is 2 before the branch
7067;; instruction for the shortest sequence, and 4 before the branch instruction
7068;; if we have to jump around an unconditional branch.
7069;; To the basic branch range the PC offset must be added (this is +4).
7070;; So for forward branches we have
7071;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7072;; And for backward branches we have
7073;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7074;;
7075;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7076;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7077
aeac46d4 7078(define_expand "cbranchsi4"
7079 [(set (pc) (if_then_else
aa06947a 7080 (match_operator 0 "expandable_comparison_operator"
aeac46d4 7081 [(match_operand:SI 1 "s_register_operand" "")
7082 (match_operand:SI 2 "nonmemory_operand" "")])
7083 (label_ref (match_operand 3 "" ""))
7084 (pc)))]
f9aa4160 7085 "TARGET_EITHER"
aeac46d4 7086 "
74f4459c 7087 if (!TARGET_THUMB1)
7088 {
f9aa4160 7089 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7090 FAIL;
74f4459c 7091 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7092 operands[3]));
7093 DONE;
7094 }
25f905c2 7095 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7096 {
7097 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7098 operands[3], operands[0]));
7099 DONE;
7100 }
25f905c2 7101 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7102 operands[2] = force_reg (SImode, operands[2]);
7103 ")
7104
a8e6c15d 7105;; A pattern to recognize a special situation and optimize for it.
7106;; On the thumb, zero-extension from memory is preferrable to sign-extension
7107;; due to the available addressing modes. Hence, convert a signed comparison
7108;; with zero into an unsigned comparison with 127 if possible.
7109(define_expand "cbranchqi4"
7110 [(set (pc) (if_then_else
7111 (match_operator 0 "lt_ge_comparison_operator"
7112 [(match_operand:QI 1 "memory_operand" "")
7113 (match_operand:QI 2 "const0_operand" "")])
7114 (label_ref (match_operand 3 "" ""))
7115 (pc)))]
7116 "TARGET_THUMB1"
7117{
d0f6c30d 7118 rtx xops[4];
a8e6c15d 7119 xops[1] = gen_reg_rtx (SImode);
7120 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
7121 xops[2] = GEN_INT (127);
7122 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
7123 VOIDmode, xops[1], xops[2]);
7124 xops[3] = operands[3];
7125 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
7126 DONE;
7127})
7128
74f4459c 7129(define_expand "cbranchsf4"
7130 [(set (pc) (if_then_else
aa06947a 7131 (match_operator 0 "expandable_comparison_operator"
74f4459c 7132 [(match_operand:SF 1 "s_register_operand" "")
7133 (match_operand:SF 2 "arm_float_compare_operand" "")])
7134 (label_ref (match_operand 3 "" ""))
7135 (pc)))]
7136 "TARGET_32BIT && TARGET_HARD_FLOAT"
7137 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7138 operands[3])); DONE;"
7139)
7140
7141(define_expand "cbranchdf4"
7142 [(set (pc) (if_then_else
aa06947a 7143 (match_operator 0 "expandable_comparison_operator"
74f4459c 7144 [(match_operand:DF 1 "s_register_operand" "")
7145 (match_operand:DF 2 "arm_float_compare_operand" "")])
7146 (label_ref (match_operand 3 "" ""))
7147 (pc)))]
a50d7267 7148 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7149 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7150 operands[3])); DONE;"
7151)
7152
74f4459c 7153(define_expand "cbranchdi4"
7154 [(set (pc) (if_then_else
aa06947a 7155 (match_operator 0 "expandable_comparison_operator"
a8045a4f 7156 [(match_operand:DI 1 "cmpdi_operand" "")
7157 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7158 (label_ref (match_operand 3 "" ""))
7159 (pc)))]
a8045a4f 7160 "TARGET_32BIT"
7161 "{
a8045a4f 7162 /* We should not have two constants. */
7163 gcc_assert (GET_MODE (operands[1]) == DImode
7164 || GET_MODE (operands[2]) == DImode);
7165
0438d37f 7166 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7167 FAIL;
7168 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7169 operands[3]));
7170 DONE;
7171 }"
74f4459c 7172)
7173
d60047aa 7174(define_insn "cbranchsi4_insn"
aeac46d4 7175 [(set (pc) (if_then_else
7176 (match_operator 0 "arm_comparison_operator"
747b7458 7177 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 7178 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 7179 (label_ref (match_operand 3 "" ""))
7180 (pc)))]
25f905c2 7181 "TARGET_THUMB1"
747b7458 7182{
7183 rtx t = cfun->machine->thumb1_cc_insn;
7184 if (t != NULL_RTX)
d60047aa 7185 {
747b7458 7186 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
7187 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
7188 t = NULL_RTX;
7189 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
7190 {
7191 if (!noov_comparison_operator (operands[0], VOIDmode))
7192 t = NULL_RTX;
7193 }
7194 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 7195 t = NULL_RTX;
7196 }
d60047aa 7197 if (t == NULL_RTX)
747b7458 7198 {
7199 output_asm_insn ("cmp\t%1, %2", operands);
7200 cfun->machine->thumb1_cc_insn = insn;
7201 cfun->machine->thumb1_cc_op0 = operands[1];
7202 cfun->machine->thumb1_cc_op1 = operands[2];
7203 cfun->machine->thumb1_cc_mode = CCmode;
7204 }
7205 else
7206 /* Ensure we emit the right type of condition code on the jump. */
7207 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
7208 CC_REGNUM);
aeac46d4 7209
cffb2a26 7210 switch (get_attr_length (insn))
7211 {
7212 case 4: return \"b%d0\\t%l3\";
7213 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7214 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7215 }
747b7458 7216}
cffb2a26 7217 [(set (attr "far_jump")
7218 (if_then_else
7219 (eq_attr "length" "8")
7220 (const_string "yes")
7221 (const_string "no")))
7222 (set (attr "length")
7223 (if_then_else
7224 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7225 (le (minus (match_dup 3) (pc)) (const_int 256)))
7226 (const_int 4)
7227 (if_then_else
7228 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 7229 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7230 (const_int 6)
7231 (const_int 8))))]
7232)
7233
aeac46d4 7234(define_insn "cbranchsi4_scratch"
7235 [(set (pc) (if_then_else
7236 (match_operator 4 "arm_comparison_operator"
7237 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 7238 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 7239 (label_ref (match_operand 3 "" ""))
7240 (pc)))
7241 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 7242 "TARGET_THUMB1"
aeac46d4 7243 "*
7244 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
7245
7246 switch (get_attr_length (insn))
7247 {
7248 case 4: return \"b%d4\\t%l3\";
7249 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7250 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7251 }
7252 "
7253 [(set (attr "far_jump")
7254 (if_then_else
7255 (eq_attr "length" "8")
7256 (const_string "yes")
7257 (const_string "no")))
7258 (set (attr "length")
7259 (if_then_else
7260 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7261 (le (minus (match_dup 3) (pc)) (const_int 256)))
7262 (const_int 4)
7263 (if_then_else
7264 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7265 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7266 (const_int 6)
7267 (const_int 8))))]
7268)
446a1e96 7269
cffb2a26 7270(define_insn "*negated_cbranchsi4"
7271 [(set (pc)
7272 (if_then_else
aed179ae 7273 (match_operator 0 "equality_operator"
aeac46d4 7274 [(match_operand:SI 1 "s_register_operand" "l")
7275 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
7276 (label_ref (match_operand 3 "" ""))
215b30b3 7277 (pc)))]
25f905c2 7278 "TARGET_THUMB1"
cffb2a26 7279 "*
7280 output_asm_insn (\"cmn\\t%1, %2\", operands);
7281 switch (get_attr_length (insn))
7282 {
7283 case 4: return \"b%d0\\t%l3\";
7284 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7285 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7286 }
7287 "
7288 [(set (attr "far_jump")
7289 (if_then_else
7290 (eq_attr "length" "8")
7291 (const_string "yes")
7292 (const_string "no")))
7293 (set (attr "length")
7294 (if_then_else
7295 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 7296 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 7297 (const_int 4)
7298 (if_then_else
341940e8 7299 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7300 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7301 (const_int 6)
7302 (const_int 8))))]
7303)
7304
58d6528b 7305(define_insn "*tbit_cbranch"
7306 [(set (pc)
7307 (if_then_else
7308 (match_operator 0 "equality_operator"
7309 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7310 (const_int 1)
7311 (match_operand:SI 2 "const_int_operand" "i"))
7312 (const_int 0)])
7313 (label_ref (match_operand 3 "" ""))
7314 (pc)))
7315 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7316 "TARGET_THUMB1"
58d6528b 7317 "*
7318 {
7319 rtx op[3];
7320 op[0] = operands[4];
7321 op[1] = operands[1];
7322 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
7323
86efa74d 7324 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7325 switch (get_attr_length (insn))
7326 {
7327 case 4: return \"b%d0\\t%l3\";
7328 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7329 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7330 }
7331 }"
7332 [(set (attr "far_jump")
7333 (if_then_else
7334 (eq_attr "length" "8")
7335 (const_string "yes")
7336 (const_string "no")))
7337 (set (attr "length")
7338 (if_then_else
7339 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7340 (le (minus (match_dup 3) (pc)) (const_int 256)))
7341 (const_int 4)
7342 (if_then_else
7343 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7344 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7345 (const_int 6)
7346 (const_int 8))))]
7347)
7348
7349(define_insn "*tlobits_cbranch"
7350 [(set (pc)
7351 (if_then_else
7352 (match_operator 0 "equality_operator"
7353 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7354 (match_operand:SI 2 "const_int_operand" "i")
7355 (const_int 0))
7356 (const_int 0)])
7357 (label_ref (match_operand 3 "" ""))
7358 (pc)))
7359 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7360 "TARGET_THUMB1"
86efa74d 7361 "*
7362 {
7363 rtx op[3];
7364 op[0] = operands[4];
7365 op[1] = operands[1];
7366 op[2] = GEN_INT (32 - INTVAL (operands[2]));
7367
58d6528b 7368 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7369 switch (get_attr_length (insn))
7370 {
7371 case 4: return \"b%d0\\t%l3\";
7372 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7373 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7374 }
7375 }"
7376 [(set (attr "far_jump")
7377 (if_then_else
7378 (eq_attr "length" "8")
7379 (const_string "yes")
7380 (const_string "no")))
7381 (set (attr "length")
7382 (if_then_else
7383 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7384 (le (minus (match_dup 3) (pc)) (const_int 256)))
7385 (const_int 4)
7386 (if_then_else
7387 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7388 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7389 (const_int 6)
7390 (const_int 8))))]
7391)
747b7458 7392
aeac46d4 7393(define_insn "*tstsi3_cbranch"
58d6528b 7394 [(set (pc)
7395 (if_then_else
aeac46d4 7396 (match_operator 3 "equality_operator"
7397 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7398 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 7399 (const_int 0)])
aeac46d4 7400 (label_ref (match_operand 2 "" ""))
7401 (pc)))]
25f905c2 7402 "TARGET_THUMB1"
58d6528b 7403 "*
7404 {
aeac46d4 7405 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 7406 switch (get_attr_length (insn))
7407 {
aeac46d4 7408 case 4: return \"b%d3\\t%l2\";
7409 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7410 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 7411 }
7412 }"
7413 [(set (attr "far_jump")
7414 (if_then_else
7415 (eq_attr "length" "8")
7416 (const_string "yes")
7417 (const_string "no")))
7418 (set (attr "length")
7419 (if_then_else
aeac46d4 7420 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7421 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 7422 (const_int 4)
7423 (if_then_else
aeac46d4 7424 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7425 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 7426 (const_int 6)
7427 (const_int 8))))]
7428)
7429
203c488f 7430(define_insn "*cbranchne_decr1"
7431 [(set (pc)
7432 (if_then_else (match_operator 3 "equality_operator"
7433 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7434 (const_int 0)])
7435 (label_ref (match_operand 4 "" ""))
7436 (pc)))
aeac46d4 7437 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7438 (plus:SI (match_dup 2) (const_int -1)))
7439 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7440 "TARGET_THUMB1"
203c488f 7441 "*
7442 {
7443 rtx cond[2];
7444 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7445 ? GEU : LTU),
58d6528b 7446 VOIDmode, operands[2], const1_rtx);
203c488f 7447 cond[1] = operands[4];
7448
7449 if (which_alternative == 0)
7450 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7451 else if (which_alternative == 1)
7452 {
7453 /* We must provide an alternative for a hi reg because reload
7454 cannot handle output reloads on a jump instruction, but we
7455 can't subtract into that. Fortunately a mov from lo to hi
7456 does not clobber the condition codes. */
7457 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7458 output_asm_insn (\"mov\\t%0, %1\", operands);
7459 }
7460 else
7461 {
7462 /* Similarly, but the target is memory. */
7463 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7464 output_asm_insn (\"str\\t%1, %0\", operands);
7465 }
7466
7467 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7468 {
7469 case 4:
8aea555f 7470 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7471 return \"\";
7472 case 6:
8aea555f 7473 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7474 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7475 default:
8aea555f 7476 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7477 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7478 }
7479 }
7480 "
7481 [(set (attr "far_jump")
7482 (if_then_else
7483 (ior (and (eq (symbol_ref ("which_alternative"))
7484 (const_int 0))
7485 (eq_attr "length" "8"))
7486 (eq_attr "length" "10"))
7487 (const_string "yes")
7488 (const_string "no")))
7489 (set_attr_alternative "length"
7490 [
7491 ;; Alternative 0
7492 (if_then_else
7493 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7494 (le (minus (match_dup 4) (pc)) (const_int 256)))
7495 (const_int 4)
7496 (if_then_else
7497 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7498 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7499 (const_int 6)
7500 (const_int 8)))
7501 ;; Alternative 1
7502 (if_then_else
7503 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7504 (le (minus (match_dup 4) (pc)) (const_int 256)))
7505 (const_int 6)
7506 (if_then_else
7507 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7508 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7509 (const_int 8)
7510 (const_int 10)))
7511 ;; Alternative 2
7512 (if_then_else
7513 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7514 (le (minus (match_dup 4) (pc)) (const_int 256)))
7515 (const_int 6)
7516 (if_then_else
7517 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7518 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7519 (const_int 8)
7520 (const_int 10)))
7521 ;; Alternative 3
7522 (if_then_else
7523 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7524 (le (minus (match_dup 4) (pc)) (const_int 256)))
7525 (const_int 6)
7526 (if_then_else
7527 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7528 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7529 (const_int 8)
7530 (const_int 10)))])]
7531)
cffb2a26 7532
58d6528b 7533(define_insn "*addsi3_cbranch"
7534 [(set (pc)
7535 (if_then_else
b0694be0 7536 (match_operator 4 "arm_comparison_operator"
58d6528b 7537 [(plus:SI
e54011cb 7538 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7539 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 7540 (const_int 0)])
7541 (label_ref (match_operand 5 "" ""))
7542 (pc)))
aeac46d4 7543 (set
7544 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7545 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 7546 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 7547 "TARGET_THUMB1
58d6528b 7548 && (GET_CODE (operands[4]) == EQ
7549 || GET_CODE (operands[4]) == NE
7550 || GET_CODE (operands[4]) == GE
7551 || GET_CODE (operands[4]) == LT)"
7552 "*
7553 {
7554 rtx cond[3];
7555
956a6170 7556 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 7557 cond[1] = operands[2];
7558 cond[2] = operands[3];
7559
0438d37f 7560 if (CONST_INT_P (cond[2]) && INTVAL (cond[2]) < 0)
58d6528b 7561 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7562 else
7563 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7564
956a6170 7565 if (which_alternative >= 2
58d6528b 7566 && which_alternative < 4)
7567 output_asm_insn (\"mov\\t%0, %1\", operands);
7568 else if (which_alternative >= 4)
7569 output_asm_insn (\"str\\t%1, %0\", operands);
7570
d0f6c30d 7571 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 7572 {
7573 case 4:
7574 return \"b%d4\\t%l5\";
7575 case 6:
7576 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7577 default:
7578 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7579 }
7580 }
7581 "
7582 [(set (attr "far_jump")
7583 (if_then_else
7584 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7585 (const_int 2))
58d6528b 7586 (eq_attr "length" "8"))
7587 (eq_attr "length" "10"))
7588 (const_string "yes")
7589 (const_string "no")))
7590 (set (attr "length")
7591 (if_then_else
7592 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7593 (const_int 2))
58d6528b 7594 (if_then_else
7595 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7596 (le (minus (match_dup 5) (pc)) (const_int 256)))
7597 (const_int 4)
7598 (if_then_else
7599 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7600 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7601 (const_int 6)
7602 (const_int 8)))
7603 (if_then_else
7604 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7605 (le (minus (match_dup 5) (pc)) (const_int 256)))
7606 (const_int 6)
7607 (if_then_else
7608 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7609 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7610 (const_int 8)
7611 (const_int 10)))))]
7612)
7613
7614(define_insn "*addsi3_cbranch_scratch"
7615 [(set (pc)
7616 (if_then_else
b0694be0 7617 (match_operator 3 "arm_comparison_operator"
58d6528b 7618 [(plus:SI
7619 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7620 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7621 (const_int 0)])
7622 (label_ref (match_operand 4 "" ""))
7623 (pc)))
7624 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7625 "TARGET_THUMB1
58d6528b 7626 && (GET_CODE (operands[3]) == EQ
7627 || GET_CODE (operands[3]) == NE
7628 || GET_CODE (operands[3]) == GE
7629 || GET_CODE (operands[3]) == LT)"
7630 "*
7631 {
7632 switch (which_alternative)
7633 {
7634 case 0:
7635 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7636 break;
7637 case 1:
7638 output_asm_insn (\"cmn\t%1, %2\", operands);
7639 break;
0f5e9701 7640 case 2:
3a445a04 7641 if (INTVAL (operands[2]) < 0)
7642 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7643 else
7644 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7645 break;
0f5e9701 7646 case 3:
3a445a04 7647 if (INTVAL (operands[2]) < 0)
7648 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7649 else
7650 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7651 break;
7652 }
7653
7654 switch (get_attr_length (insn))
7655 {
7656 case 4:
7657 return \"b%d3\\t%l4\";
7658 case 6:
7659 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7660 default:
7661 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7662 }
7663 }
7664 "
7665 [(set (attr "far_jump")
7666 (if_then_else
7667 (eq_attr "length" "8")
7668 (const_string "yes")
7669 (const_string "no")))
7670 (set (attr "length")
7671 (if_then_else
7672 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7673 (le (minus (match_dup 4) (pc)) (const_int 256)))
7674 (const_int 4)
7675 (if_then_else
7676 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7677 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7678 (const_int 6)
7679 (const_int 8))))]
7680)
7681
58d6528b 7682
9c08d1fa 7683;; Comparison and test insns
7684
cffb2a26 7685(define_insn "*arm_cmpsi_insn"
bd5b4116 7686 [(set (reg:CC CC_REGNUM)
a6864a24 7687 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7688 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
25f905c2 7689 "TARGET_32BIT"
5565501b 7690 "@
a6864a24 7691 cmp%?\\t%0, %1
7692 cmp%?\\t%0, %1
aea4c774 7693 cmp%?\\t%0, %1
7694 cmn%?\\t%0, #%n1"
a6864a24 7695 [(set_attr "conds" "set")
7696 (set_attr "arch" "t2,t2,any,any")
596e5e8f 7697 (set_attr "length" "2,2,4,4")
65f68e55 7698 (set_attr "predicable" "yes")
7699 (set_attr "type" "*,*,*,simple_alu_imm")]
cffb2a26 7700)
b11cae9e 7701
d5d4dc8d 7702(define_insn "*cmpsi_shiftsi"
bd5b4116 7703 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7704 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7705 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7706 [(match_operand:SI 1 "s_register_operand" "r,r")
7707 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7708 "TARGET_32BIT"
aea4c774 7709 "cmp%?\\t%0, %1%S3"
344495ea 7710 [(set_attr "conds" "set")
331beb1a 7711 (set_attr "shift" "1")
d5d4dc8d 7712 (set_attr "arch" "32,a")
7713 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7714
d5d4dc8d 7715(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7716 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7717 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7718 [(match_operand:SI 1 "s_register_operand" "r,r")
7719 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7720 (match_operand:SI 0 "s_register_operand" "r,r")))]
7721 "TARGET_32BIT"
aea4c774 7722 "cmp%?\\t%0, %1%S3"
344495ea 7723 [(set_attr "conds" "set")
331beb1a 7724 (set_attr "shift" "1")
d5d4dc8d 7725 (set_attr "arch" "32,a")
7726 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7727
25f905c2 7728(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7729 [(set (reg:CC_Z CC_REGNUM)
7730 (compare:CC_Z
7731 (neg:SI (match_operator:SI 1 "shift_operator"
7732 [(match_operand:SI 2 "s_register_operand" "r")
7733 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7734 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7735 "TARGET_ARM"
aed179ae 7736 "cmn%?\\t%0, %2%S1"
344495ea 7737 [(set_attr "conds" "set")
aed179ae 7738 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7739 (const_string "alu_shift")
596e5e8f 7740 (const_string "alu_shift_reg")))
7741 (set_attr "predicable" "yes")]
0d66636f 7742)
b11cae9e 7743
a8045a4f 7744;; DImode comparisons. The generic code generates branches that
7745;; if-conversion can not reduce to a conditional compare, so we do
7746;; that directly.
7747
7748(define_insn "*arm_cmpdi_insn"
7749 [(set (reg:CC_NCV CC_REGNUM)
7750 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7751 (match_operand:DI 1 "arm_di_operand" "rDi")))
7752 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7753 "TARGET_32BIT"
a8045a4f 7754 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7755 [(set_attr "conds" "set")
7756 (set_attr "length" "8")]
7757)
7758
7759(define_insn "*arm_cmpdi_unsigned"
7760 [(set (reg:CC_CZ CC_REGNUM)
7761 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7762 (match_operand:DI 1 "arm_di_operand" "rDi")))]
48a98053 7763 "TARGET_32BIT"
7764 "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
a8045a4f 7765 [(set_attr "conds" "set")
7766 (set_attr "length" "8")]
7767)
7768
7769(define_insn "*arm_cmpdi_zero"
7770 [(set (reg:CC_Z CC_REGNUM)
7771 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7772 (const_int 0)))
7773 (clobber (match_scratch:SI 1 "=r"))]
7774 "TARGET_32BIT"
7775 "orr%.\\t%1, %Q0, %R0"
7776 [(set_attr "conds" "set")]
7777)
7778
7779(define_insn "*thumb_cmpdi_zero"
7780 [(set (reg:CC_Z CC_REGNUM)
7781 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7782 (const_int 0)))
7783 (clobber (match_scratch:SI 1 "=l"))]
7784 "TARGET_THUMB1"
7785 "orr\\t%1, %Q0, %R0"
7786 [(set_attr "conds" "set")
7787 (set_attr "length" "2")]
7788)
7789
9c08d1fa 7790; This insn allows redundant compares to be removed by cse, nothing should
7791; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7792; is deleted later on. The match_dup will match the mode here, so that
7793; mode changes of the condition codes aren't lost by this even though we don't
7794; specify what they are.
7795
8a18b90c 7796(define_insn "*deleted_compare"
9c08d1fa 7797 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7798 "TARGET_32BIT"
40dbec34 7799 "\\t%@ deleted compare"
cffb2a26 7800 [(set_attr "conds" "set")
7801 (set_attr "length" "0")]
7802)
9c08d1fa 7803
7804\f
7805;; Conditional branch insns
7806
74f4459c 7807(define_expand "cbranch_cc"
9c08d1fa 7808 [(set (pc)
74f4459c 7809 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7810 (match_operand 2 "" "")])
7811 (label_ref (match_operand 3 "" ""))
9c08d1fa 7812 (pc)))]
25f905c2 7813 "TARGET_32BIT"
74f4459c 7814 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7815 operands[1], operands[2], NULL_RTX);
74f4459c 7816 operands[2] = const0_rtx;"
8fa3ba89 7817)
7818
7819;;
7820;; Patterns to match conditional branch insns.
7821;;
7822
ffcc986d 7823(define_insn "arm_cond_branch"
9c08d1fa 7824 [(set (pc)
8fa3ba89 7825 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7826 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7827 (label_ref (match_operand 0 "" ""))
7828 (pc)))]
25f905c2 7829 "TARGET_32BIT"
d75350ce 7830 "*
9c08d1fa 7831 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7832 {
7833 arm_ccfsm_state += 2;
7834 return \"\";
7835 }
e2348bcb 7836 return \"b%d1\\t%l0\";
cffb2a26 7837 "
a2cd141b 7838 [(set_attr "conds" "use")
a6864a24 7839 (set_attr "type" "branch")
7840 (set (attr "length")
7841 (if_then_else
0bf497f5 7842 (and (match_test "TARGET_THUMB2")
a6864a24 7843 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7844 (le (minus (match_dup 0) (pc)) (const_int 256))))
7845 (const_int 2)
7846 (const_int 4)))]
cffb2a26 7847)
d75350ce 7848
cffb2a26 7849(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7850 [(set (pc)
8fa3ba89 7851 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7852 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7853 (pc)
7854 (label_ref (match_operand 0 "" ""))))]
25f905c2 7855 "TARGET_32BIT"
d75350ce 7856 "*
9c08d1fa 7857 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7858 {
7859 arm_ccfsm_state += 2;
7860 return \"\";
7861 }
e2348bcb 7862 return \"b%D1\\t%l0\";
cffb2a26 7863 "
a2cd141b 7864 [(set_attr "conds" "use")
a6864a24 7865 (set_attr "type" "branch")
7866 (set (attr "length")
7867 (if_then_else
0bf497f5 7868 (and (match_test "TARGET_THUMB2")
a6864a24 7869 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7870 (le (minus (match_dup 0) (pc)) (const_int 256))))
7871 (const_int 2)
7872 (const_int 4)))]
cffb2a26 7873)
7874
b11cae9e 7875\f
9c08d1fa 7876
7877; scc insns
7878
74f4459c 7879(define_expand "cstore_cc"
7db9af5d 7880 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7881 (match_operator:SI 1 "" [(match_operand 2 "" "")
7882 (match_operand 3 "" "")]))]
25f905c2 7883 "TARGET_32BIT"
74f4459c 7884 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7885 operands[2], operands[3], NULL_RTX);
74f4459c 7886 operands[3] = const0_rtx;"
8fa3ba89 7887)
7888
f7fbdd4a 7889(define_insn "*mov_scc"
9c08d1fa 7890 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7891 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7892 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7893 "TARGET_ARM"
4d61e570 7894 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7895 [(set_attr "conds" "use")
d2a518d1 7896 (set_attr "insn" "mov")
cffb2a26 7897 (set_attr "length" "8")]
7898)
9c08d1fa 7899
f7fbdd4a 7900(define_insn "*mov_negscc"
9c08d1fa 7901 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7902 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7903 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7904 "TARGET_ARM"
4d61e570 7905 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7906 [(set_attr "conds" "use")
d2a518d1 7907 (set_attr "insn" "mov")
cffb2a26 7908 (set_attr "length" "8")]
7909)
9c08d1fa 7910
f7fbdd4a 7911(define_insn "*mov_notscc"
9c08d1fa 7912 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7913 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7914 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7915 "TARGET_ARM"
7d0a3bab 7916 "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7917 [(set_attr "conds" "use")
d2a518d1 7918 (set_attr "insn" "mov")
cffb2a26 7919 (set_attr "length" "8")]
7920)
9c08d1fa 7921
595d88b5 7922(define_expand "cstoresi4"
7923 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7924 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7925 [(match_operand:SI 2 "s_register_operand" "")
7926 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7927 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7928 "{
7929 rtx op3, scratch, scratch2;
7930
74f4459c 7931 if (!TARGET_THUMB1)
7932 {
7933 if (!arm_add_operand (operands[3], SImode))
7934 operands[3] = force_reg (SImode, operands[3]);
7935 emit_insn (gen_cstore_cc (operands[0], operands[1],
7936 operands[2], operands[3]));
7937 DONE;
7938 }
7939
595d88b5 7940 if (operands[3] == const0_rtx)
7941 {
7942 switch (GET_CODE (operands[1]))
7943 {
7944 case EQ:
25f905c2 7945 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7946 break;
7947
7948 case NE:
25f905c2 7949 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7950 break;
7951
7952 case LE:
7953 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7954 NULL_RTX, 0, OPTAB_WIDEN);
7955 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7956 NULL_RTX, 0, OPTAB_WIDEN);
7957 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7958 operands[0], 1, OPTAB_WIDEN);
7959 break;
7960
7961 case GE:
7962 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7963 NULL_RTX, 1);
7964 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7965 NULL_RTX, 1, OPTAB_WIDEN);
7966 break;
7967
7968 case GT:
7969 scratch = expand_binop (SImode, ashr_optab, operands[2],
7970 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7971 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7972 NULL_RTX, 0, OPTAB_WIDEN);
7973 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7974 0, OPTAB_WIDEN);
7975 break;
7976
7977 /* LT is handled by generic code. No need for unsigned with 0. */
7978 default:
7979 FAIL;
7980 }
7981 DONE;
7982 }
7983
7984 switch (GET_CODE (operands[1]))
7985 {
7986 case EQ:
7987 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7988 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7989 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7990 break;
7991
7992 case NE:
7993 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7994 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7995 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7996 break;
7997
7998 case LE:
7999 op3 = force_reg (SImode, operands[3]);
8000
8001 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8002 NULL_RTX, 1, OPTAB_WIDEN);
8003 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8004 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8005 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8006 op3, operands[2]));
8007 break;
8008
8009 case GE:
8010 op3 = operands[3];
25f905c2 8011 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8012 op3 = force_reg (SImode, op3);
8013 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8014 NULL_RTX, 0, OPTAB_WIDEN);
8015 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8016 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 8017 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8018 operands[2], op3));
8019 break;
8020
8021 case LEU:
8022 op3 = force_reg (SImode, operands[3]);
8023 scratch = force_reg (SImode, const0_rtx);
25f905c2 8024 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8025 op3, operands[2]));
8026 break;
8027
8028 case GEU:
8029 op3 = operands[3];
25f905c2 8030 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8031 op3 = force_reg (SImode, op3);
8032 scratch = force_reg (SImode, const0_rtx);
25f905c2 8033 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8034 operands[2], op3));
8035 break;
8036
8037 case LTU:
8038 op3 = operands[3];
25f905c2 8039 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8040 op3 = force_reg (SImode, op3);
8041 scratch = gen_reg_rtx (SImode);
408b7ae5 8042 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 8043 break;
8044
8045 case GTU:
8046 op3 = force_reg (SImode, operands[3]);
8047 scratch = gen_reg_rtx (SImode);
408b7ae5 8048 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 8049 break;
8050
8051 /* No good sequences for GT, LT. */
8052 default:
8053 FAIL;
8054 }
8055 DONE;
8056}")
8057
74f4459c 8058(define_expand "cstoresf4"
8059 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8060 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 8061 [(match_operand:SF 2 "s_register_operand" "")
8062 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8063 "TARGET_32BIT && TARGET_HARD_FLOAT"
8064 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8065 operands[2], operands[3])); DONE;"
8066)
8067
8068(define_expand "cstoredf4"
8069 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8070 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 8071 [(match_operand:DF 2 "s_register_operand" "")
8072 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 8073 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 8074 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8075 operands[2], operands[3])); DONE;"
8076)
8077
74f4459c 8078(define_expand "cstoredi4"
8079 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8080 (match_operator:SI 1 "expandable_comparison_operator"
a8045a4f 8081 [(match_operand:DI 2 "cmpdi_operand" "")
8082 (match_operand:DI 3 "cmpdi_operand" "")]))]
8083 "TARGET_32BIT"
8084 "{
a8045a4f 8085 /* We should not have two constants. */
8086 gcc_assert (GET_MODE (operands[2]) == DImode
8087 || GET_MODE (operands[3]) == DImode);
8088
f9aa4160 8089 if (!arm_validize_comparison (&operands[1],
8090 &operands[2],
8091 &operands[3]))
8092 FAIL;
8093 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 8094 operands[3]));
8095 DONE;
8096 }"
74f4459c 8097)
8098
25f905c2 8099(define_expand "cstoresi_eq0_thumb1"
595d88b5 8100 [(parallel
8101 [(set (match_operand:SI 0 "s_register_operand" "")
8102 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8103 (const_int 0)))
8104 (clobber (match_dup:SI 2))])]
25f905c2 8105 "TARGET_THUMB1"
595d88b5 8106 "operands[2] = gen_reg_rtx (SImode);"
8107)
8108
25f905c2 8109(define_expand "cstoresi_ne0_thumb1"
595d88b5 8110 [(parallel
8111 [(set (match_operand:SI 0 "s_register_operand" "")
8112 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8113 (const_int 0)))
8114 (clobber (match_dup:SI 2))])]
25f905c2 8115 "TARGET_THUMB1"
595d88b5 8116 "operands[2] = gen_reg_rtx (SImode);"
8117)
8118
25f905c2 8119(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 8120 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8121 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8122 (const_int 0)))
8123 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 8124 "TARGET_THUMB1"
595d88b5 8125 "@
8126 neg\\t%0, %1\;adc\\t%0, %0, %1
8127 neg\\t%2, %1\;adc\\t%0, %1, %2"
8128 [(set_attr "length" "4")]
8129)
8130
25f905c2 8131(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 8132 [(set (match_operand:SI 0 "s_register_operand" "=l")
8133 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8134 (const_int 0)))
8135 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8136 "TARGET_THUMB1"
595d88b5 8137 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8138 [(set_attr "length" "4")]
8139)
8140
408b7ae5 8141;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 8142(define_insn "cstoresi_nltu_thumb1"
595d88b5 8143 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8144 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8145 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8146 "TARGET_THUMB1"
595d88b5 8147 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8148 [(set_attr "length" "4")]
8149)
8150
408b7ae5 8151(define_insn_and_split "cstoresi_ltu_thumb1"
8152 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8153 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8154 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8155 "TARGET_THUMB1"
8156 "#"
8157 "TARGET_THUMB1"
8158 [(set (match_dup 3)
8159 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8160 (set (match_dup 0) (neg:SI (match_dup 3)))]
8161 "operands[3] = gen_reg_rtx (SImode);"
8162 [(set_attr "length" "4")]
8163)
8164
595d88b5 8165;; Used as part of the expansion of thumb les sequence.
25f905c2 8166(define_insn "thumb1_addsi3_addgeu"
595d88b5 8167 [(set (match_operand:SI 0 "s_register_operand" "=l")
8168 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8169 (match_operand:SI 2 "s_register_operand" "l"))
8170 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8171 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8172 "TARGET_THUMB1"
595d88b5 8173 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8174 [(set_attr "length" "4")]
8175)
8176
9c08d1fa 8177\f
39b5e676 8178;; Conditional move insns
8179
8180(define_expand "movsicc"
8a18b90c 8181 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8182 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 8183 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8184 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8185 "TARGET_32BIT"
39b5e676 8186 "
215b30b3 8187 {
f9aa4160 8188 enum rtx_code code;
278b301d 8189 rtx ccreg;
8190
f9aa4160 8191 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8192 &XEXP (operands[1], 1)))
278b301d 8193 FAIL;
f9aa4160 8194
8195 code = GET_CODE (operands[1]);
74f4459c 8196 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8197 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8198 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8199 }"
8200)
39b5e676 8201
8202(define_expand "movsfcc"
8a18b90c 8203 [(set (match_operand:SF 0 "s_register_operand" "")
aa06947a 8204 (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8205 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 8206 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 8207 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8208 "
215b30b3 8209 {
8210 enum rtx_code code = GET_CODE (operands[1]);
8211 rtx ccreg;
f082f1c4 8212
f9aa4160 8213 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8214 &XEXP (operands[1], 1)))
8215 FAIL;
39b5e676 8216
f9aa4160 8217 code = GET_CODE (operands[1]);
74f4459c 8218 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8219 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8220 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8221 }"
8222)
39b5e676 8223
8224(define_expand "movdfcc"
8a18b90c 8225 [(set (match_operand:DF 0 "s_register_operand" "")
aa06947a 8226 (if_then_else:DF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8227 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 8228 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 8229 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 8230 "
215b30b3 8231 {
8232 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8233 rtx ccreg;
39b5e676 8234
f9aa4160 8235 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8236 &XEXP (operands[1], 1)))
8237 FAIL;
8238 code = GET_CODE (operands[1]);
74f4459c 8239 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8240 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8241 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8242 }"
8243)
39b5e676 8244
8245(define_insn "*movsicc_insn"
f082f1c4 8246 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8247 (if_then_else:SI
8fa3ba89 8248 (match_operator 3 "arm_comparison_operator"
8a18b90c 8249 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8250 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8251 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8252 "TARGET_ARM"
39b5e676 8253 "@
8a18b90c 8254 mov%D3\\t%0, %2
8255 mvn%D3\\t%0, #%B2
f082f1c4 8256 mov%d3\\t%0, %1
8257 mvn%d3\\t%0, #%B1
8a18b90c 8258 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8259 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8260 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8261 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8262 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8263 (set_attr "conds" "use")
65f68e55 8264 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")
8265 (set_attr_alternative "type"
8266 [(if_then_else (match_operand 2 "const_int_operand" "")
8267 (const_string "simple_alu_imm")
8268 (const_string "*"))
8269 (const_string "simple_alu_imm")
8270 (if_then_else (match_operand 1 "const_int_operand" "")
8271 (const_string "simple_alu_imm")
8272 (const_string "*"))
8273 (const_string "simple_alu_imm")
8274 (const_string "*")
8275 (const_string "*")
8276 (const_string "*")
8277 (const_string "*")])]
215b30b3 8278)
39b5e676 8279
39b5e676 8280(define_insn "*movsfcc_soft_insn"
f082f1c4 8281 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8282 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8283 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8284 (match_operand:SF 1 "s_register_operand" "0,r")
8285 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8286 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8287 "@
8288 mov%D3\\t%0, %2
8289 mov%d3\\t%0, %1"
d2a518d1 8290 [(set_attr "conds" "use")
8291 (set_attr "insn" "mov")]
8fa3ba89 8292)
39b5e676 8293
39b5e676 8294\f
9c08d1fa 8295;; Jump and linkage insns
8296
cffb2a26 8297(define_expand "jump"
9c08d1fa 8298 [(set (pc)
8299 (label_ref (match_operand 0 "" "")))]
cffb2a26 8300 "TARGET_EITHER"
9c08d1fa 8301 ""
cffb2a26 8302)
8303
8304(define_insn "*arm_jump"
8305 [(set (pc)
8306 (label_ref (match_operand 0 "" "")))]
25f905c2 8307 "TARGET_32BIT"
9c08d1fa 8308 "*
0d66636f 8309 {
8310 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8311 {
8312 arm_ccfsm_state += 2;
8313 return \"\";
8314 }
8315 return \"b%?\\t%l0\";
8316 }
8317 "
a6864a24 8318 [(set_attr "predicable" "yes")
8319 (set (attr "length")
8320 (if_then_else
0bf497f5 8321 (and (match_test "TARGET_THUMB2")
a6864a24 8322 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8323 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8324 (const_int 2)
8325 (const_int 4)))]
0d66636f 8326)
9c08d1fa 8327
cffb2a26 8328(define_insn "*thumb_jump"
8329 [(set (pc)
8330 (label_ref (match_operand 0 "" "")))]
25f905c2 8331 "TARGET_THUMB1"
cffb2a26 8332 "*
8333 if (get_attr_length (insn) == 2)
8334 return \"b\\t%l0\";
8335 return \"bl\\t%l0\\t%@ far jump\";
8336 "
8337 [(set (attr "far_jump")
8338 (if_then_else
8339 (eq_attr "length" "4")
8340 (const_string "yes")
8341 (const_string "no")))
8342 (set (attr "length")
8343 (if_then_else
911ed8af 8344 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8345 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8346 (const_int 2)
8347 (const_int 4)))]
8348)
8349
d3373b54 8350(define_expand "call"
8351 [(parallel [(call (match_operand 0 "memory_operand" "")
8352 (match_operand 1 "general_operand" ""))
cffb2a26 8353 (use (match_operand 2 "" ""))
bd5b4116 8354 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8355 "TARGET_EITHER"
6c4c2133 8356 "
8357 {
bac7fc85 8358 rtx callee, pat;
bbe777ea 8359
bbe777ea 8360 /* In an untyped call, we can get NULL for operand 2. */
8361 if (operands[2] == NULL_RTX)
8362 operands[2] = const0_rtx;
8363
de55252a 8364 /* Decide if we should generate indirect calls by loading the
85c36fd1 8365 32-bit address of the callee into a register before performing the
de55252a 8366 branch and link. */
8367 callee = XEXP (operands[0], 0);
8368 if (GET_CODE (callee) == SYMBOL_REF
8369 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8370 : !REG_P (callee))
bbe777ea 8371 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8372
8373 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8374 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8375 DONE;
6c4c2133 8376 }"
8377)
d3373b54 8378
bac7fc85 8379(define_expand "call_internal"
8380 [(parallel [(call (match_operand 0 "memory_operand" "")
8381 (match_operand 1 "general_operand" ""))
8382 (use (match_operand 2 "" ""))
8383 (clobber (reg:SI LR_REGNUM))])])
8384
f1039640 8385(define_insn "*call_reg_armv5"
d3373b54 8386 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8387 (match_operand 1 "" ""))
8388 (use (match_operand 2 "" ""))
bd5b4116 8389 (clobber (reg:SI LR_REGNUM))]
f1039640 8390 "TARGET_ARM && arm_arch5"
8391 "blx%?\\t%0"
8392 [(set_attr "type" "call")]
8393)
8394
8395(define_insn "*call_reg_arm"
8396 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8397 (match_operand 1 "" ""))
8398 (use (match_operand 2 "" ""))
8399 (clobber (reg:SI LR_REGNUM))]
8400 "TARGET_ARM && !arm_arch5"
9c08d1fa 8401 "*
5565501b 8402 return output_call (operands);
cffb2a26 8403 "
8404 ;; length is worst case, normally it is only two
8405 [(set_attr "length" "12")
8406 (set_attr "type" "call")]
8407)
9c08d1fa 8408
89504fc1 8409
8410;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8411;; considered a function call by the branch predictor of some cores (PR40887).
8412;; Falls back to blx rN (*call_reg_armv5).
8413
f7fbdd4a 8414(define_insn "*call_mem"
a3c63a9d 8415 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8416 (match_operand 1 "" ""))
8417 (use (match_operand 2 "" ""))
bd5b4116 8418 (clobber (reg:SI LR_REGNUM))]
89504fc1 8419 "TARGET_ARM && !arm_arch5"
9c08d1fa 8420 "*
5565501b 8421 return output_call_mem (operands);
cffb2a26 8422 "
8423 [(set_attr "length" "12")
8424 (set_attr "type" "call")]
8425)
8426
25f905c2 8427(define_insn "*call_reg_thumb1_v5"
cffb2a26 8428 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8429 (match_operand 1 "" ""))
8430 (use (match_operand 2 "" ""))
bd5b4116 8431 (clobber (reg:SI LR_REGNUM))]
25f905c2 8432 "TARGET_THUMB1 && arm_arch5"
f1039640 8433 "blx\\t%0"
8434 [(set_attr "length" "2")
8435 (set_attr "type" "call")]
cffb2a26 8436)
8437
25f905c2 8438(define_insn "*call_reg_thumb1"
f1039640 8439 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8440 (match_operand 1 "" ""))
8441 (use (match_operand 2 "" ""))
bd5b4116 8442 (clobber (reg:SI LR_REGNUM))]
25f905c2 8443 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8444 "*
8445 {
150502c9 8446 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8447 return thumb_call_via_reg (operands[0]);
150502c9 8448 else if (operands[1] == const0_rtx)
f1039640 8449 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8450 else if (frame_pointer_needed)
8451 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8452 else
150502c9 8453 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8454 }"
8455 [(set_attr "type" "call")]
8456)
9c08d1fa 8457
d3373b54 8458(define_expand "call_value"
e0698af7 8459 [(parallel [(set (match_operand 0 "" "")
8460 (call (match_operand 1 "memory_operand" "")
8461 (match_operand 2 "general_operand" "")))
cffb2a26 8462 (use (match_operand 3 "" ""))
bd5b4116 8463 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8464 "TARGET_EITHER"
6c4c2133 8465 "
8466 {
bac7fc85 8467 rtx pat, callee;
bbe777ea 8468
8469 /* In an untyped call, we can get NULL for operand 2. */
8470 if (operands[3] == 0)
8471 operands[3] = const0_rtx;
8472
de55252a 8473 /* Decide if we should generate indirect calls by loading the
8474 32-bit address of the callee into a register before performing the
8475 branch and link. */
8476 callee = XEXP (operands[1], 0);
8477 if (GET_CODE (callee) == SYMBOL_REF
8478 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8479 : !REG_P (callee))
78fe751b 8480 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8481
8482 pat = gen_call_value_internal (operands[0], operands[1],
8483 operands[2], operands[3]);
8484 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8485 DONE;
6c4c2133 8486 }"
8487)
d3373b54 8488
bac7fc85 8489(define_expand "call_value_internal"
8490 [(parallel [(set (match_operand 0 "" "")
8491 (call (match_operand 1 "memory_operand" "")
8492 (match_operand 2 "general_operand" "")))
8493 (use (match_operand 3 "" ""))
8494 (clobber (reg:SI LR_REGNUM))])])
8495
f1039640 8496(define_insn "*call_value_reg_armv5"
27ed6835 8497 [(set (match_operand 0 "" "")
755eb2b4 8498 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8499 (match_operand 2 "" "")))
bbe777ea 8500 (use (match_operand 3 "" ""))
bd5b4116 8501 (clobber (reg:SI LR_REGNUM))]
f1039640 8502 "TARGET_ARM && arm_arch5"
8503 "blx%?\\t%1"
8504 [(set_attr "type" "call")]
8505)
8506
8507(define_insn "*call_value_reg_arm"
8508 [(set (match_operand 0 "" "")
8509 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8510 (match_operand 2 "" "")))
8511 (use (match_operand 3 "" ""))
8512 (clobber (reg:SI LR_REGNUM))]
8513 "TARGET_ARM && !arm_arch5"
9c08d1fa 8514 "*
215b30b3 8515 return output_call (&operands[1]);
cffb2a26 8516 "
8517 [(set_attr "length" "12")
8518 (set_attr "type" "call")]
8519)
9c08d1fa 8520
89504fc1 8521;; Note: see *call_mem
8522
f7fbdd4a 8523(define_insn "*call_value_mem"
27ed6835 8524 [(set (match_operand 0 "" "")
a3c63a9d 8525 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8526 (match_operand 2 "" "")))
bbe777ea 8527 (use (match_operand 3 "" ""))
bd5b4116 8528 (clobber (reg:SI LR_REGNUM))]
89504fc1 8529 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8530 "*
215b30b3 8531 return output_call_mem (&operands[1]);
cffb2a26 8532 "
8533 [(set_attr "length" "12")
8534 (set_attr "type" "call")]
8535)
9c08d1fa 8536
25f905c2 8537(define_insn "*call_value_reg_thumb1_v5"
f1039640 8538 [(set (match_operand 0 "" "")
8539 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8540 (match_operand 2 "" "")))
8541 (use (match_operand 3 "" ""))
8542 (clobber (reg:SI LR_REGNUM))]
25f905c2 8543 "TARGET_THUMB1 && arm_arch5"
f1039640 8544 "blx\\t%1"
8545 [(set_attr "length" "2")
8546 (set_attr "type" "call")]
8547)
8548
25f905c2 8549(define_insn "*call_value_reg_thumb1"
f1039640 8550 [(set (match_operand 0 "" "")
8551 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8552 (match_operand 2 "" "")))
8553 (use (match_operand 3 "" ""))
8554 (clobber (reg:SI LR_REGNUM))]
25f905c2 8555 "TARGET_THUMB1 && !arm_arch5"
f1039640 8556 "*
8557 {
150502c9 8558 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8559 return thumb_call_via_reg (operands[1]);
150502c9 8560 else if (operands[2] == const0_rtx)
f1039640 8561 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8562 else if (frame_pointer_needed)
8563 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8564 else
150502c9 8565 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8566 }"
8567 [(set_attr "type" "call")]
8568)
8569
9c08d1fa 8570;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8571;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8572
f7fbdd4a 8573(define_insn "*call_symbol"
27ed6835 8574 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8575 (match_operand 1 "" ""))
bbe777ea 8576 (use (match_operand 2 "" ""))
bd5b4116 8577 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8578 "TARGET_32BIT
cffb2a26 8579 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8580 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8581 "*
8582 {
55c1e470 8583 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8584 }"
cffb2a26 8585 [(set_attr "type" "call")]
8586)
9c08d1fa 8587
f7fbdd4a 8588(define_insn "*call_value_symbol"
ccd90aaa 8589 [(set (match_operand 0 "" "")
27ed6835 8590 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8591 (match_operand:SI 2 "" "")))
bbe777ea 8592 (use (match_operand 3 "" ""))
bd5b4116 8593 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8594 "TARGET_32BIT
cffb2a26 8595 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8596 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8597 "*
8598 {
55c1e470 8599 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8600 }"
cffb2a26 8601 [(set_attr "type" "call")]
8602)
8603
8604(define_insn "*call_insn"
27ed6835 8605 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8606 (match_operand:SI 1 "" ""))
8607 (use (match_operand 2 "" ""))
bd5b4116 8608 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8609 "TARGET_THUMB1
1675c6e9 8610 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8611 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8612 "bl\\t%a0"
8613 [(set_attr "length" "4")
8614 (set_attr "type" "call")]
8615)
8616
8617(define_insn "*call_value_insn"
ccd90aaa 8618 [(set (match_operand 0 "" "")
27ed6835 8619 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8620 (match_operand 2 "" "")))
8621 (use (match_operand 3 "" ""))
bd5b4116 8622 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8623 "TARGET_THUMB1
1675c6e9 8624 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8625 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8626 "bl\\t%a1"
8627 [(set_attr "length" "4")
8628 (set_attr "type" "call")]
8629)
9c08d1fa 8630
1c494086 8631;; We may also be able to do sibcalls for Thumb, but it's much harder...
8632(define_expand "sibcall"
8633 [(parallel [(call (match_operand 0 "memory_operand" "")
8634 (match_operand 1 "general_operand" ""))
2ba80634 8635 (return)
8636 (use (match_operand 2 "" ""))])]
d68c2c10 8637 "TARGET_32BIT"
1c494086 8638 "
8639 {
8640 if (operands[2] == NULL_RTX)
8641 operands[2] = const0_rtx;
1c494086 8642 }"
8643)
8644
8645(define_expand "sibcall_value"
ccd90aaa 8646 [(parallel [(set (match_operand 0 "" "")
1c494086 8647 (call (match_operand 1 "memory_operand" "")
8648 (match_operand 2 "general_operand" "")))
2ba80634 8649 (return)
8650 (use (match_operand 3 "" ""))])]
d68c2c10 8651 "TARGET_32BIT"
1c494086 8652 "
8653 {
8654 if (operands[3] == NULL_RTX)
8655 operands[3] = const0_rtx;
1c494086 8656 }"
8657)
8658
8659(define_insn "*sibcall_insn"
8660 [(call (mem:SI (match_operand:SI 0 "" "X"))
8661 (match_operand 1 "" ""))
2ba80634 8662 (return)
8663 (use (match_operand 2 "" ""))]
d68c2c10 8664 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8665 "*
8666 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8667 "
8668 [(set_attr "type" "call")]
8669)
8670
8671(define_insn "*sibcall_value_insn"
ccd90aaa 8672 [(set (match_operand 0 "" "")
755eb2b4 8673 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8674 (match_operand 2 "" "")))
2ba80634 8675 (return)
8676 (use (match_operand 3 "" ""))]
d68c2c10 8677 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8678 "*
8679 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8680 "
8681 [(set_attr "type" "call")]
8682)
8683
d68c2c10 8684(define_expand "return"
8685 [(return)]
8cba51a5 8686 "(TARGET_ARM || (TARGET_THUMB2
8687 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8688 && !IS_STACKALIGN (arm_current_func_type ())))
8689 && USE_RETURN_INSN (FALSE)"
8690 "
8691 {
8692 if (TARGET_THUMB2)
8693 {
8694 thumb2_expand_return ();
8695 DONE;
8696 }
8697 }
8698 "
8699)
d68c2c10 8700
9c08d1fa 8701;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8702(define_insn "*arm_return"
9c08d1fa 8703 [(return)]
cffb2a26 8704 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8705 "*
9c08d1fa 8706 {
cffb2a26 8707 if (arm_ccfsm_state == 2)
8708 {
8709 arm_ccfsm_state += 2;
8710 return \"\";
8711 }
e2549f81 8712 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8713 }"
a2cd141b 8714 [(set_attr "type" "load1")
755eb2b4 8715 (set_attr "length" "12")
0d66636f 8716 (set_attr "predicable" "yes")]
cffb2a26 8717)
9c08d1fa 8718
f7fbdd4a 8719(define_insn "*cond_return"
9c08d1fa 8720 [(set (pc)
8fa3ba89 8721 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8722 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8723 (return)
8724 (pc)))]
cffb2a26 8725 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8726 "*
8fa3ba89 8727 {
8728 if (arm_ccfsm_state == 2)
8729 {
8730 arm_ccfsm_state += 2;
8731 return \"\";
8732 }
e2549f81 8733 return output_return_instruction (operands[0], true, false, false);
8fa3ba89 8734 }"
8735 [(set_attr "conds" "use")
755eb2b4 8736 (set_attr "length" "12")
a2cd141b 8737 (set_attr "type" "load1")]
8fa3ba89 8738)
9c08d1fa 8739
f7fbdd4a 8740(define_insn "*cond_return_inverted"
9c08d1fa 8741 [(set (pc)
8fa3ba89 8742 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8743 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8744 (pc)
8745 (return)))]
cffb2a26 8746 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8747 "*
8fa3ba89 8748 {
8749 if (arm_ccfsm_state == 2)
8750 {
8751 arm_ccfsm_state += 2;
8752 return \"\";
8753 }
e2549f81 8754 return output_return_instruction (operands[0], true, true, false);
8fa3ba89 8755 }"
8756 [(set_attr "conds" "use")
37a1317b 8757 (set_attr "length" "12")
a2cd141b 8758 (set_attr "type" "load1")]
8fa3ba89 8759)
9c08d1fa 8760
e2549f81 8761(define_insn "*arm_simple_return"
8762 [(simple_return)]
8763 "TARGET_ARM"
8764 "*
8765 {
8766 if (arm_ccfsm_state == 2)
8767 {
8768 arm_ccfsm_state += 2;
8769 return \"\";
8770 }
8771 return output_return_instruction (const_true_rtx, true, false, true);
8772 }"
8773 [(set_attr "type" "branch")
8774 (set_attr "length" "4")
8775 (set_attr "predicable" "yes")]
8776)
8777
68121397 8778;; Generate a sequence of instructions to determine if the processor is
8779;; in 26-bit or 32-bit mode, and return the appropriate return address
8780;; mask.
8781
8782(define_expand "return_addr_mask"
8783 [(set (match_dup 1)
8784 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8785 (const_int 0)))
8786 (set (match_operand:SI 0 "s_register_operand" "")
8787 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8788 (const_int -1)
8789 (const_int 67108860)))] ; 0x03fffffc
8790 "TARGET_ARM"
8791 "
62eddbd4 8792 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8793 ")
8794
8795(define_insn "*check_arch2"
8796 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8797 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8798 (const_int 0)))]
8799 "TARGET_ARM"
8800 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8801 [(set_attr "length" "8")
8802 (set_attr "conds" "set")]
8803)
8804
9c08d1fa 8805;; Call subroutine returning any type.
8806
8807(define_expand "untyped_call"
8808 [(parallel [(call (match_operand 0 "" "")
8809 (const_int 0))
8810 (match_operand 1 "" "")
8811 (match_operand 2 "" "")])]
ccd90aaa 8812 "TARGET_EITHER"
9c08d1fa 8813 "
215b30b3 8814 {
8815 int i;
ccd90aaa 8816 rtx par = gen_rtx_PARALLEL (VOIDmode,
8817 rtvec_alloc (XVECLEN (operands[2], 0)));
8818 rtx addr = gen_reg_rtx (Pmode);
8819 rtx mem;
8820 int size = 0;
9c08d1fa 8821
ccd90aaa 8822 emit_move_insn (addr, XEXP (operands[1], 0));
8823 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8824
215b30b3 8825 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8826 {
ccd90aaa 8827 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8828
ccd90aaa 8829 /* Default code only uses r0 as a return value, but we could
8830 be using anything up to 4 registers. */
8831 if (REGNO (src) == R0_REGNUM)
8832 src = gen_rtx_REG (TImode, R0_REGNUM);
8833
8834 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8835 GEN_INT (size));
8836 size += GET_MODE_SIZE (GET_MODE (src));
8837 }
8838
8839 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8840 const0_rtx));
8841
8842 size = 0;
8843
8844 for (i = 0; i < XVECLEN (par, 0); i++)
8845 {
8846 HOST_WIDE_INT offset = 0;
8847 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8848
8849 if (size != 0)
29c05e22 8850 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8851
8852 mem = change_address (mem, GET_MODE (reg), NULL);
8853 if (REGNO (reg) == R0_REGNUM)
8854 {
8855 /* On thumb we have to use a write-back instruction. */
320ea44d 8856 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8857 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8858 size = TARGET_ARM ? 16 : 0;
8859 }
8860 else
8861 {
8862 emit_move_insn (mem, reg);
8863 size = GET_MODE_SIZE (GET_MODE (reg));
8864 }
215b30b3 8865 }
9c08d1fa 8866
215b30b3 8867 /* The optimizer does not know that the call sets the function value
8868 registers we stored in the result block. We avoid problems by
8869 claiming that all hard registers are used and clobbered at this
8870 point. */
8871 emit_insn (gen_blockage ());
8872
8873 DONE;
8874 }"
8875)
9c08d1fa 8876
ccd90aaa 8877(define_expand "untyped_return"
8878 [(match_operand:BLK 0 "memory_operand" "")
8879 (match_operand 1 "" "")]
8880 "TARGET_EITHER"
8881 "
8882 {
8883 int i;
8884 rtx addr = gen_reg_rtx (Pmode);
8885 rtx mem;
8886 int size = 0;
8887
8888 emit_move_insn (addr, XEXP (operands[0], 0));
8889 mem = change_address (operands[0], BLKmode, addr);
8890
8891 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8892 {
8893 HOST_WIDE_INT offset = 0;
8894 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8895
8896 if (size != 0)
29c05e22 8897 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8898
8899 mem = change_address (mem, GET_MODE (reg), NULL);
8900 if (REGNO (reg) == R0_REGNUM)
8901 {
8902 /* On thumb we have to use a write-back instruction. */
320ea44d 8903 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8904 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8905 size = TARGET_ARM ? 16 : 0;
8906 }
8907 else
8908 {
8909 emit_move_insn (reg, mem);
8910 size = GET_MODE_SIZE (GET_MODE (reg));
8911 }
8912 }
8913
8914 /* Emit USE insns before the return. */
8915 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8916 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8917
8918 /* Construct the return. */
8919 expand_naked_return ();
8920
8921 DONE;
8922 }"
8923)
8924
9c08d1fa 8925;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8926;; all of memory. This blocks insns from being moved across this point.
8927
8928(define_insn "blockage"
e1159bbe 8929 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8930 "TARGET_EITHER"
9c08d1fa 8931 ""
cffb2a26 8932 [(set_attr "length" "0")
8933 (set_attr "type" "block")]
8934)
9c08d1fa 8935
f7fbdd4a 8936(define_expand "casesi"
8937 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8938 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8939 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8940 (match_operand:SI 3 "" "") ; table label
8941 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8942 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8943 "
215b30b3 8944 {
e6ac8414 8945 enum insn_code code;
215b30b3 8946 if (operands[1] != const0_rtx)
8947 {
e6ac8414 8948 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8949
215b30b3 8950 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8951 gen_int_mode (-INTVAL (operands[1]),
8952 SImode)));
215b30b3 8953 operands[0] = reg;
8954 }
9c08d1fa 8955
25f905c2 8956 if (TARGET_ARM)
e6ac8414 8957 code = CODE_FOR_arm_casesi_internal;
3db2019b 8958 else if (TARGET_THUMB1)
e6ac8414 8959 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8960 else if (flag_pic)
e6ac8414 8961 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8962 else
e6ac8414 8963 code = CODE_FOR_thumb2_casesi_internal;
8964
8965 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8966 operands[2] = force_reg (SImode, operands[2]);
8967
8968 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8969 operands[3], operands[4]));
215b30b3 8970 DONE;
8971 }"
8972)
f7fbdd4a 8973
f082f1c4 8974;; The USE in this pattern is needed to tell flow analysis that this is
8975;; a CASESI insn. It has no other purpose.
25f905c2 8976(define_insn "arm_casesi_internal"
f082f1c4 8977 [(parallel [(set (pc)
8978 (if_then_else
8979 (leu (match_operand:SI 0 "s_register_operand" "r")
8980 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8981 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8982 (label_ref (match_operand 2 "" ""))))
8983 (label_ref (match_operand 3 "" ""))))
bd5b4116 8984 (clobber (reg:CC CC_REGNUM))
f082f1c4 8985 (use (label_ref (match_dup 2)))])]
cffb2a26 8986 "TARGET_ARM"
f7fbdd4a 8987 "*
0d66636f 8988 if (flag_pic)
8989 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8990 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8991 "
8992 [(set_attr "conds" "clob")
8993 (set_attr "length" "12")]
8994)
9c08d1fa 8995
e6ac8414 8996(define_expand "thumb1_casesi_internal_pic"
8997 [(match_operand:SI 0 "s_register_operand" "")
8998 (match_operand:SI 1 "thumb1_cmp_operand" "")
8999 (match_operand 2 "" "")
9000 (match_operand 3 "" "")]
3db2019b 9001 "TARGET_THUMB1"
e6ac8414 9002 {
9003 rtx reg0;
9004 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9005 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9006 operands[3]));
9007 reg0 = gen_rtx_REG (SImode, 0);
9008 emit_move_insn (reg0, operands[0]);
9009 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9010 DONE;
9011 }
9012)
9013
9014(define_insn "thumb1_casesi_dispatch"
9015 [(parallel [(set (pc) (unspec [(reg:SI 0)
9016 (label_ref (match_operand 0 "" ""))
9017;; (label_ref (match_operand 1 "" ""))
9018]
9019 UNSPEC_THUMB1_CASESI))
9020 (clobber (reg:SI IP_REGNUM))
9021 (clobber (reg:SI LR_REGNUM))])]
3db2019b 9022 "TARGET_THUMB1"
e6ac8414 9023 "* return thumb1_output_casesi(operands);"
9024 [(set_attr "length" "4")]
9025)
9026
cffb2a26 9027(define_expand "indirect_jump"
9c08d1fa 9028 [(set (pc)
cffb2a26 9029 (match_operand:SI 0 "s_register_operand" ""))]
9030 "TARGET_EITHER"
25f905c2 9031 "
9032 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
9033 address and use bx. */
9034 if (TARGET_THUMB2)
9035 {
9036 rtx tmp;
9037 tmp = gen_reg_rtx (SImode);
9038 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9039 operands[0] = tmp;
9040 }
9041 "
cffb2a26 9042)
9043
f1039640 9044;; NB Never uses BX.
cffb2a26 9045(define_insn "*arm_indirect_jump"
9046 [(set (pc)
9047 (match_operand:SI 0 "s_register_operand" "r"))]
9048 "TARGET_ARM"
9049 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 9050 [(set_attr "predicable" "yes")]
cffb2a26 9051)
9c08d1fa 9052
f7fbdd4a 9053(define_insn "*load_indirect_jump"
9c08d1fa 9054 [(set (pc)
9055 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 9056 "TARGET_ARM"
9057 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 9058 [(set_attr "type" "load1")
61a2d04c 9059 (set_attr "pool_range" "4096")
9060 (set_attr "neg_pool_range" "4084")
0d66636f 9061 (set_attr "predicable" "yes")]
cffb2a26 9062)
9063
f1039640 9064;; NB Never uses BX.
25f905c2 9065(define_insn "*thumb1_indirect_jump"
cffb2a26 9066 [(set (pc)
9067 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 9068 "TARGET_THUMB1"
cffb2a26 9069 "mov\\tpc, %0"
9070 [(set_attr "conds" "clob")
9071 (set_attr "length" "2")]
9072)
9073
9c08d1fa 9074\f
9075;; Misc insns
9076
9077(define_insn "nop"
9078 [(const_int 0)]
cffb2a26 9079 "TARGET_EITHER"
9080 "*
25f905c2 9081 if (TARGET_UNIFIED_ASM)
9082 return \"nop\";
cffb2a26 9083 if (TARGET_ARM)
9084 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9085 return \"mov\\tr8, r8\";
9086 "
9087 [(set (attr "length")
9088 (if_then_else (eq_attr "is_thumb" "yes")
9089 (const_int 2)
9090 (const_int 4)))]
9091)
9092
9c08d1fa 9093\f
9094;; Patterns to allow combination of arithmetic, cond code and shifts
9095
f7fbdd4a 9096(define_insn "*arith_shiftsi"
7392680c 9097 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9c08d1fa 9098 (match_operator:SI 1 "shiftable_operator"
9099 [(match_operator:SI 3 "shift_operator"
7392680c 9100 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
9101 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
9102 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
d5d4dc8d 9103 "TARGET_32BIT"
6c4c2133 9104 "%i1%?\\t%0, %2, %4%S3"
344495ea 9105 [(set_attr "predicable" "yes")
331beb1a 9106 (set_attr "shift" "4")
7392680c 9107 (set_attr "arch" "a,t2,t2,a")
9108 ;; Thumb2 doesn't allow the stack pointer to be used for
9109 ;; operand1 for all operations other than add and sub. In this case
9110 ;; the minus operation is a candidate for an rsub and hence needs
9111 ;; to be disabled.
9112 ;; We have to make sure to disable the fourth alternative if
d5d4dc8d 9113 ;; the shift_operator is MULT, since otherwise the insn will
9114 ;; also match a multiply_accumulate pattern and validate_change
9115 ;; will allow a replacement of the constant with a register
9116 ;; despite the checks done in shift_operator.
9117 (set_attr_alternative "insn_enabled"
9118 [(const_string "yes")
7392680c 9119 (if_then_else
9120 (match_operand:SI 1 "add_operator" "")
9121 (const_string "yes") (const_string "no"))
9122 (const_string "yes")
d5d4dc8d 9123 (if_then_else
9124 (match_operand:SI 3 "mult_operator" "")
9125 (const_string "no") (const_string "yes"))])
7392680c 9126 (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
9c08d1fa 9127
d7863cfe 9128(define_split
9129 [(set (match_operand:SI 0 "s_register_operand" "")
9130 (match_operator:SI 1 "shiftable_operator"
9131 [(match_operator:SI 2 "shiftable_operator"
9132 [(match_operator:SI 3 "shift_operator"
9133 [(match_operand:SI 4 "s_register_operand" "")
9134 (match_operand:SI 5 "reg_or_int_operand" "")])
9135 (match_operand:SI 6 "s_register_operand" "")])
9136 (match_operand:SI 7 "arm_rhs_operand" "")]))
9137 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 9138 "TARGET_32BIT"
d7863cfe 9139 [(set (match_dup 8)
9140 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9141 (match_dup 6)]))
9142 (set (match_dup 0)
9143 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9144 "")
9145
f7fbdd4a 9146(define_insn "*arith_shiftsi_compare0"
bd5b4116 9147 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9148 (compare:CC_NOOV
9149 (match_operator:SI 1 "shiftable_operator"
9150 [(match_operator:SI 3 "shift_operator"
9151 [(match_operand:SI 4 "s_register_operand" "r,r")
9152 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9153 (match_operand:SI 2 "s_register_operand" "r,r")])
9154 (const_int 0)))
9155 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 9156 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9157 (match_dup 2)]))]
d5d4dc8d 9158 "TARGET_32BIT"
25f905c2 9159 "%i1%.\\t%0, %2, %4%S3"
344495ea 9160 [(set_attr "conds" "set")
331beb1a 9161 (set_attr "shift" "4")
d5d4dc8d 9162 (set_attr "arch" "32,a")
9163 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9164
f7fbdd4a 9165(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9166 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9167 (compare:CC_NOOV
9168 (match_operator:SI 1 "shiftable_operator"
9169 [(match_operator:SI 3 "shift_operator"
9170 [(match_operand:SI 4 "s_register_operand" "r,r")
9171 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9172 (match_operand:SI 2 "s_register_operand" "r,r")])
9173 (const_int 0)))
9174 (clobber (match_scratch:SI 0 "=r,r"))]
9175 "TARGET_32BIT"
25f905c2 9176 "%i1%.\\t%0, %2, %4%S3"
344495ea 9177 [(set_attr "conds" "set")
331beb1a 9178 (set_attr "shift" "4")
d5d4dc8d 9179 (set_attr "arch" "32,a")
9180 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9181
f7fbdd4a 9182(define_insn "*sub_shiftsi"
d5d4dc8d 9183 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9184 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 9185 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9186 [(match_operand:SI 3 "s_register_operand" "r,r")
9187 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9188 "TARGET_32BIT"
6c4c2133 9189 "sub%?\\t%0, %1, %3%S2"
344495ea 9190 [(set_attr "predicable" "yes")
331beb1a 9191 (set_attr "shift" "3")
d5d4dc8d 9192 (set_attr "arch" "32,a")
9193 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9194
f7fbdd4a 9195(define_insn "*sub_shiftsi_compare0"
bd5b4116 9196 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9197 (compare:CC_NOOV
d5d4dc8d 9198 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9199 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9200 [(match_operand:SI 3 "s_register_operand" "r,r")
9201 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9202 (const_int 0)))
d5d4dc8d 9203 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9204 (minus:SI (match_dup 1)
9205 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9206 "TARGET_32BIT"
25f905c2 9207 "sub%.\\t%0, %1, %3%S2"
344495ea 9208 [(set_attr "conds" "set")
a2cd141b 9209 (set_attr "shift" "3")
d5d4dc8d 9210 (set_attr "arch" "32,a")
9211 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9212
f7fbdd4a 9213(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9214 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9215 (compare:CC_NOOV
d5d4dc8d 9216 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9217 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9218 [(match_operand:SI 3 "s_register_operand" "r,r")
9219 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9220 (const_int 0)))
d5d4dc8d 9221 (clobber (match_scratch:SI 0 "=r,r"))]
9222 "TARGET_32BIT"
25f905c2 9223 "sub%.\\t%0, %1, %3%S2"
344495ea 9224 [(set_attr "conds" "set")
a2cd141b 9225 (set_attr "shift" "3")
d5d4dc8d 9226 (set_attr "arch" "32,a")
9227 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9228\f
9229
f7fbdd4a 9230(define_insn "*and_scc"
9c08d1fa 9231 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9232 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9233 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9234 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9235 "TARGET_ARM"
e2348bcb 9236 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9237 [(set_attr "conds" "use")
d2a518d1 9238 (set_attr "insn" "mov")
8fa3ba89 9239 (set_attr "length" "8")]
9240)
9c08d1fa 9241
f7fbdd4a 9242(define_insn "*ior_scc"
9c08d1fa 9243 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9244 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9245 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9246 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9247 "TARGET_ARM"
e2348bcb 9248 "@
899850b0 9249 orr%d2\\t%0, %1, #1
9250 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9251 [(set_attr "conds" "use")
9252 (set_attr "length" "4,8")]
9253)
9c08d1fa 9254
2df9477b 9255; A series of splitters for the compare_scc pattern below. Note that
9256; order is important.
9257(define_split
9258 [(set (match_operand:SI 0 "s_register_operand" "")
9259 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9260 (const_int 0)))
9261 (clobber (reg:CC CC_REGNUM))]
9262 "TARGET_32BIT && reload_completed"
9263 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9264
9265(define_split
9266 [(set (match_operand:SI 0 "s_register_operand" "")
9267 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9268 (const_int 0)))
9269 (clobber (reg:CC CC_REGNUM))]
9270 "TARGET_32BIT && reload_completed"
9271 [(set (match_dup 0) (not:SI (match_dup 1)))
9272 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9273
9274(define_split
9275 [(set (match_operand:SI 0 "s_register_operand" "")
9276 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9277 (const_int 0)))
9278 (clobber (reg:CC CC_REGNUM))]
9279 "TARGET_32BIT && reload_completed"
9280 [(parallel
080c0b9a 9281 [(set (reg:CC CC_REGNUM)
9282 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9283 (set (match_dup 0)
9284 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9285 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9286 (set (match_dup 0) (const_int 0)))])
9287
9288(define_split
9289 [(set (match_operand:SI 0 "s_register_operand" "")
9290 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9291 (match_operand:SI 2 "const_int_operand" "")))
9292 (clobber (reg:CC CC_REGNUM))]
9293 "TARGET_32BIT && reload_completed"
9294 [(parallel
9295 [(set (reg:CC CC_REGNUM)
9296 (compare:CC (match_dup 1) (match_dup 2)))
9297 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9298 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9299 (set (match_dup 0) (const_int 1)))]
9300{
9301 operands[3] = GEN_INT (-INTVAL (operands[2]));
9302})
9303
9304(define_split
9305 [(set (match_operand:SI 0 "s_register_operand" "")
9306 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9307 (match_operand:SI 2 "arm_add_operand" "")))
9308 (clobber (reg:CC CC_REGNUM))]
9309 "TARGET_32BIT && reload_completed"
9310 [(parallel
9311 [(set (reg:CC_NOOV CC_REGNUM)
9312 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9313 (const_int 0)))
9314 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9315 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9316 (set (match_dup 0) (const_int 1)))])
9317
9318(define_insn_and_split "*compare_scc"
5565501b 9319 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9320 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9321 [(match_operand:SI 2 "s_register_operand" "r,r")
9322 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9323 (clobber (reg:CC CC_REGNUM))]
2df9477b 9324 "TARGET_32BIT"
9325 "#"
9326 "&& reload_completed"
9327 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9328 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9329 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9330{
9331 rtx tmp1;
9332 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9333 operands[2], operands[3]);
9334 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9335
2df9477b 9336 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9337
2df9477b 9338 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9339 if (mode == CCFPmode || mode == CCFPEmode)
9340 rc = reverse_condition_maybe_unordered (rc);
9341 else
9342 rc = reverse_condition (rc);
9343 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9344})
9c08d1fa 9345
080c0b9a 9346;; Attempt to improve the sequence generated by the compare_scc splitters
9347;; not to use conditional execution.
9348(define_peephole2
9349 [(set (reg:CC CC_REGNUM)
9350 (compare:CC (match_operand:SI 1 "register_operand" "")
9351 (match_operand:SI 2 "arm_rhs_operand" "")))
9352 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9353 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9354 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9355 (set (match_dup 0) (const_int 1)))
9356 (match_scratch:SI 3 "r")]
9357 "TARGET_32BIT"
922b6913 9358 [(parallel
9359 [(set (reg:CC CC_REGNUM)
9360 (compare:CC (match_dup 1) (match_dup 2)))
9361 (set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 9362 (parallel
9363 [(set (reg:CC CC_REGNUM)
9364 (compare:CC (const_int 0) (match_dup 3)))
9365 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
922b6913 9366 (parallel
9367 [(set (match_dup 0)
9368 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9369 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))
9370 (clobber (reg:CC CC_REGNUM))])])
080c0b9a 9371
f7fbdd4a 9372(define_insn "*cond_move"
9c08d1fa 9373 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9374 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9375 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9376 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9377 (const_int 0)])
9378 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9379 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9380 "TARGET_ARM"
9c08d1fa 9381 "*
8fa3ba89 9382 if (GET_CODE (operands[3]) == NE)
9383 {
9384 if (which_alternative != 1)
9385 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9386 if (which_alternative != 0)
9387 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9388 return \"\";
9389 }
9390 if (which_alternative != 0)
9391 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9392 if (which_alternative != 1)
9393 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9394 return \"\";
9395 "
9396 [(set_attr "conds" "use")
d2a518d1 9397 (set_attr "insn" "mov")
8fa3ba89 9398 (set_attr "length" "4,4,8")]
9399)
9c08d1fa 9400
f7fbdd4a 9401(define_insn "*cond_arith"
9c08d1fa 9402 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9403 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9404 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9405 [(match_operand:SI 2 "s_register_operand" "r,r")
9406 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9407 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9408 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9409 "TARGET_ARM"
9c08d1fa 9410 "*
8fa3ba89 9411 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9412 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9413
8fa3ba89 9414 output_asm_insn (\"cmp\\t%2, %3\", operands);
9415 if (GET_CODE (operands[5]) == AND)
9416 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9417 else if (GET_CODE (operands[5]) == MINUS)
9418 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9419 else if (which_alternative != 0)
9420 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9421 return \"%i5%d4\\t%0, %1, #1\";
9422 "
9423 [(set_attr "conds" "clob")
9424 (set_attr "length" "12")]
9425)
9c08d1fa 9426
f7fbdd4a 9427(define_insn "*cond_sub"
9c08d1fa 9428 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9429 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9430 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9431 [(match_operand:SI 2 "s_register_operand" "r,r")
9432 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9433 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9434 "TARGET_ARM"
9c08d1fa 9435 "*
8fa3ba89 9436 output_asm_insn (\"cmp\\t%2, %3\", operands);
9437 if (which_alternative != 0)
9438 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9439 return \"sub%d4\\t%0, %1, #1\";
9440 "
9441 [(set_attr "conds" "clob")
9442 (set_attr "length" "8,12")]
9443)
9c08d1fa 9444
aea4c774 9445(define_insn "*cmp_ite0"
cffb2a26 9446 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9447 (compare
9448 (if_then_else:SI
8fa3ba89 9449 (match_operator 4 "arm_comparison_operator"
2ff91fec 9450 [(match_operand:SI 0 "s_register_operand"
9451 "l,l,l,r,r,r,r,r,r")
9452 (match_operand:SI 1 "arm_add_operand"
9453 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9454 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9455 [(match_operand:SI 2 "s_register_operand"
9456 "l,r,r,l,l,r,r,r,r")
9457 (match_operand:SI 3 "arm_add_operand"
9458 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9459 (const_int 0))
9460 (const_int 0)))]
2ff91fec 9461 "TARGET_32BIT"
9c08d1fa 9462 "*
aea4c774 9463 {
2ff91fec 9464 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9465 {
9466 {\"cmp%d5\\t%0, %1\",
9467 \"cmp%d4\\t%2, %3\"},
9468 {\"cmn%d5\\t%0, #%n1\",
9469 \"cmp%d4\\t%2, %3\"},
9470 {\"cmp%d5\\t%0, %1\",
9471 \"cmn%d4\\t%2, #%n3\"},
9472 {\"cmn%d5\\t%0, #%n1\",
9473 \"cmn%d4\\t%2, #%n3\"}
9474 };
9475 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9476 {
9477 {\"cmp\\t%2, %3\",
9478 \"cmp\\t%0, %1\"},
9479 {\"cmp\\t%2, %3\",
9480 \"cmn\\t%0, #%n1\"},
9481 {\"cmn\\t%2, #%n3\",
9482 \"cmp\\t%0, %1\"},
9483 {\"cmn\\t%2, #%n3\",
9484 \"cmn\\t%0, #%n1\"}
9485 };
9486 static const char * const ite[2] =
8fa3ba89 9487 {
2ff91fec 9488 \"it\\t%d5\",
9489 \"it\\t%d4\"
8fa3ba89 9490 };
2ff91fec 9491 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9492 CMP_CMP, CMN_CMP, CMP_CMP,
9493 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9494 int swap =
9495 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9496
2ff91fec 9497 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9498 if (TARGET_THUMB2) {
9499 output_asm_insn (ite[swap], operands);
9500 }
9501 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9502 return \"\";
8fa3ba89 9503 }"
9504 [(set_attr "conds" "set")
2ff91fec 9505 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9506 (set_attr_alternative "length"
9507 [(const_int 6)
9508 (const_int 8)
9509 (const_int 8)
9510 (const_int 8)
9511 (const_int 8)
9512 (if_then_else (eq_attr "is_thumb" "no")
9513 (const_int 8)
9514 (const_int 10))
9515 (if_then_else (eq_attr "is_thumb" "no")
9516 (const_int 8)
9517 (const_int 10))
9518 (if_then_else (eq_attr "is_thumb" "no")
9519 (const_int 8)
9520 (const_int 10))
9521 (if_then_else (eq_attr "is_thumb" "no")
9522 (const_int 8)
9523 (const_int 10))])]
8fa3ba89 9524)
9c08d1fa 9525
aea4c774 9526(define_insn "*cmp_ite1"
cffb2a26 9527 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9528 (compare
9529 (if_then_else:SI
8fa3ba89 9530 (match_operator 4 "arm_comparison_operator"
2ff91fec 9531 [(match_operand:SI 0 "s_register_operand"
9532 "l,l,l,r,r,r,r,r,r")
9533 (match_operand:SI 1 "arm_add_operand"
9534 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9535 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9536 [(match_operand:SI 2 "s_register_operand"
9537 "l,r,r,l,l,r,r,r,r")
9538 (match_operand:SI 3 "arm_add_operand"
9539 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9540 (const_int 1))
9541 (const_int 0)))]
2ff91fec 9542 "TARGET_32BIT"
9c08d1fa 9543 "*
9c08d1fa 9544 {
2ff91fec 9545 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9546 {
9547 {\"cmp\\t%0, %1\",
9548 \"cmp\\t%2, %3\"},
9549 {\"cmn\\t%0, #%n1\",
9550 \"cmp\\t%2, %3\"},
9551 {\"cmp\\t%0, %1\",
9552 \"cmn\\t%2, #%n3\"},
9553 {\"cmn\\t%0, #%n1\",
9554 \"cmn\\t%2, #%n3\"}
9555 };
9556 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9557 {
2ff91fec 9558 {\"cmp%d4\\t%2, %3\",
9559 \"cmp%D5\\t%0, %1\"},
9560 {\"cmp%d4\\t%2, %3\",
9561 \"cmn%D5\\t%0, #%n1\"},
9562 {\"cmn%d4\\t%2, #%n3\",
9563 \"cmp%D5\\t%0, %1\"},
9564 {\"cmn%d4\\t%2, #%n3\",
9565 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9566 };
2ff91fec 9567 static const char * const ite[2] =
9568 {
9569 \"it\\t%d4\",
9570 \"it\\t%D5\"
9571 };
9572 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9573 CMP_CMP, CMN_CMP, CMP_CMP,
9574 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9575 int swap =
9576 comparison_dominates_p (GET_CODE (operands[5]),
9577 reverse_condition (GET_CODE (operands[4])));
9578
2ff91fec 9579 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9580 if (TARGET_THUMB2) {
9581 output_asm_insn (ite[swap], operands);
9582 }
9583 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9584 return \"\";
215b30b3 9585 }"
8fa3ba89 9586 [(set_attr "conds" "set")
2ff91fec 9587 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9588 (set_attr_alternative "length"
9589 [(const_int 6)
9590 (const_int 8)
9591 (const_int 8)
9592 (const_int 8)
9593 (const_int 8)
9594 (if_then_else (eq_attr "is_thumb" "no")
9595 (const_int 8)
9596 (const_int 10))
9597 (if_then_else (eq_attr "is_thumb" "no")
9598 (const_int 8)
9599 (const_int 10))
9600 (if_then_else (eq_attr "is_thumb" "no")
9601 (const_int 8)
9602 (const_int 10))
9603 (if_then_else (eq_attr "is_thumb" "no")
9604 (const_int 8)
9605 (const_int 10))])]
8fa3ba89 9606)
9c08d1fa 9607
f6c53574 9608(define_insn "*cmp_and"
9609 [(set (match_operand 6 "dominant_cc_register" "")
9610 (compare
9611 (and:SI
9612 (match_operator 4 "arm_comparison_operator"
2ff91fec 9613 [(match_operand:SI 0 "s_register_operand"
9614 "l,l,l,r,r,r,r,r,r")
9615 (match_operand:SI 1 "arm_add_operand"
9616 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9617 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9618 [(match_operand:SI 2 "s_register_operand"
9619 "l,r,r,l,l,r,r,r,r")
9620 (match_operand:SI 3 "arm_add_operand"
9621 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9622 (const_int 0)))]
2ff91fec 9623 "TARGET_32BIT"
f6c53574 9624 "*
9625 {
2ff91fec 9626 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9627 {
2ff91fec 9628 {\"cmp%d5\\t%0, %1\",
9629 \"cmp%d4\\t%2, %3\"},
9630 {\"cmn%d5\\t%0, #%n1\",
9631 \"cmp%d4\\t%2, %3\"},
9632 {\"cmp%d5\\t%0, %1\",
9633 \"cmn%d4\\t%2, #%n3\"},
9634 {\"cmn%d5\\t%0, #%n1\",
9635 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9636 };
2ff91fec 9637 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9638 {
9639 {\"cmp\\t%2, %3\",
9640 \"cmp\\t%0, %1\"},
9641 {\"cmp\\t%2, %3\",
9642 \"cmn\\t%0, #%n1\"},
9643 {\"cmn\\t%2, #%n3\",
9644 \"cmp\\t%0, %1\"},
9645 {\"cmn\\t%2, #%n3\",
9646 \"cmn\\t%0, #%n1\"}
9647 };
9648 static const char *const ite[2] =
9649 {
9650 \"it\\t%d5\",
9651 \"it\\t%d4\"
9652 };
9653 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9654 CMP_CMP, CMN_CMP, CMP_CMP,
9655 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9656 int swap =
9657 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9658
2ff91fec 9659 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9660 if (TARGET_THUMB2) {
9661 output_asm_insn (ite[swap], operands);
9662 }
9663 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9664 return \"\";
f6c53574 9665 }"
9666 [(set_attr "conds" "set")
9667 (set_attr "predicable" "no")
2ff91fec 9668 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9669 (set_attr_alternative "length"
9670 [(const_int 6)
9671 (const_int 8)
9672 (const_int 8)
9673 (const_int 8)
9674 (const_int 8)
9675 (if_then_else (eq_attr "is_thumb" "no")
9676 (const_int 8)
9677 (const_int 10))
9678 (if_then_else (eq_attr "is_thumb" "no")
9679 (const_int 8)
9680 (const_int 10))
9681 (if_then_else (eq_attr "is_thumb" "no")
9682 (const_int 8)
9683 (const_int 10))
9684 (if_then_else (eq_attr "is_thumb" "no")
9685 (const_int 8)
9686 (const_int 10))])]
f6c53574 9687)
9688
9689(define_insn "*cmp_ior"
9690 [(set (match_operand 6 "dominant_cc_register" "")
9691 (compare
9692 (ior:SI
9693 (match_operator 4 "arm_comparison_operator"
2ff91fec 9694 [(match_operand:SI 0 "s_register_operand"
9695 "l,l,l,r,r,r,r,r,r")
9696 (match_operand:SI 1 "arm_add_operand"
9697 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9698 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9699 [(match_operand:SI 2 "s_register_operand"
9700 "l,r,r,l,l,r,r,r,r")
9701 (match_operand:SI 3 "arm_add_operand"
9702 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9703 (const_int 0)))]
2ff91fec 9704 "TARGET_32BIT"
f6c53574 9705 "*
f6c53574 9706 {
2ff91fec 9707 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9708 {
9709 {\"cmp\\t%0, %1\",
9710 \"cmp\\t%2, %3\"},
9711 {\"cmn\\t%0, #%n1\",
9712 \"cmp\\t%2, %3\"},
9713 {\"cmp\\t%0, %1\",
9714 \"cmn\\t%2, #%n3\"},
9715 {\"cmn\\t%0, #%n1\",
9716 \"cmn\\t%2, #%n3\"}
9717 };
9718 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9719 {
9720 {\"cmp%D4\\t%2, %3\",
9721 \"cmp%D5\\t%0, %1\"},
9722 {\"cmp%D4\\t%2, %3\",
9723 \"cmn%D5\\t%0, #%n1\"},
9724 {\"cmn%D4\\t%2, #%n3\",
9725 \"cmp%D5\\t%0, %1\"},
9726 {\"cmn%D4\\t%2, #%n3\",
9727 \"cmn%D5\\t%0, #%n1\"}
9728 };
9729 static const char *const ite[2] =
9730 {
9731 \"it\\t%D4\",
9732 \"it\\t%D5\"
9733 };
9734 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9735 CMP_CMP, CMN_CMP, CMP_CMP,
9736 CMN_CMP, CMP_CMN, CMN_CMN};
9737 int swap =
9738 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9739
9740 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9741 if (TARGET_THUMB2) {
9742 output_asm_insn (ite[swap], operands);
9743 }
9744 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9745 return \"\";
9746 }
9747 "
f6c53574 9748 [(set_attr "conds" "set")
2ff91fec 9749 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9750 (set_attr_alternative "length"
9751 [(const_int 6)
9752 (const_int 8)
9753 (const_int 8)
9754 (const_int 8)
9755 (const_int 8)
9756 (if_then_else (eq_attr "is_thumb" "no")
9757 (const_int 8)
9758 (const_int 10))
9759 (if_then_else (eq_attr "is_thumb" "no")
9760 (const_int 8)
9761 (const_int 10))
9762 (if_then_else (eq_attr "is_thumb" "no")
9763 (const_int 8)
9764 (const_int 10))
9765 (if_then_else (eq_attr "is_thumb" "no")
9766 (const_int 8)
9767 (const_int 10))])]
f6c53574 9768)
9769
3c5afce6 9770(define_insn_and_split "*ior_scc_scc"
9771 [(set (match_operand:SI 0 "s_register_operand" "=r")
9772 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9773 [(match_operand:SI 1 "s_register_operand" "r")
9774 (match_operand:SI 2 "arm_add_operand" "rIL")])
9775 (match_operator:SI 6 "arm_comparison_operator"
9776 [(match_operand:SI 4 "s_register_operand" "r")
9777 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9778 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9779 "TARGET_32BIT
3c5afce6 9780 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9781 != CCmode)"
9782 "#"
2ff91fec 9783 "TARGET_32BIT && reload_completed"
3c5afce6 9784 [(set (match_dup 7)
9785 (compare
9786 (ior:SI
9787 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9788 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9789 (const_int 0)))
9790 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9791 "operands[7]
9792 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9793 DOM_CC_X_OR_Y),
601f584c 9794 CC_REGNUM);"
9795 [(set_attr "conds" "clob")
9796 (set_attr "length" "16")])
9797
9798; If the above pattern is followed by a CMP insn, then the compare is
9799; redundant, since we can rework the conditional instruction that follows.
9800(define_insn_and_split "*ior_scc_scc_cmp"
9801 [(set (match_operand 0 "dominant_cc_register" "")
9802 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9803 [(match_operand:SI 1 "s_register_operand" "r")
9804 (match_operand:SI 2 "arm_add_operand" "rIL")])
9805 (match_operator:SI 6 "arm_comparison_operator"
9806 [(match_operand:SI 4 "s_register_operand" "r")
9807 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9808 (const_int 0)))
9809 (set (match_operand:SI 7 "s_register_operand" "=r")
9810 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9811 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9812 "TARGET_32BIT"
601f584c 9813 "#"
2ff91fec 9814 "TARGET_32BIT && reload_completed"
601f584c 9815 [(set (match_dup 0)
9816 (compare
9817 (ior:SI
9818 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9819 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9820 (const_int 0)))
9821 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9822 ""
9823 [(set_attr "conds" "set")
9824 (set_attr "length" "16")])
3c5afce6 9825
9826(define_insn_and_split "*and_scc_scc"
9827 [(set (match_operand:SI 0 "s_register_operand" "=r")
9828 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9829 [(match_operand:SI 1 "s_register_operand" "r")
9830 (match_operand:SI 2 "arm_add_operand" "rIL")])
9831 (match_operator:SI 6 "arm_comparison_operator"
9832 [(match_operand:SI 4 "s_register_operand" "r")
9833 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9834 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9835 "TARGET_32BIT
3c5afce6 9836 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9837 != CCmode)"
9838 "#"
2ff91fec 9839 "TARGET_32BIT && reload_completed
601f584c 9840 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9841 != CCmode)"
3c5afce6 9842 [(set (match_dup 7)
9843 (compare
9844 (and:SI
9845 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9846 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9847 (const_int 0)))
9848 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9849 "operands[7]
9850 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9851 DOM_CC_X_AND_Y),
601f584c 9852 CC_REGNUM);"
9853 [(set_attr "conds" "clob")
9854 (set_attr "length" "16")])
9855
9856; If the above pattern is followed by a CMP insn, then the compare is
9857; redundant, since we can rework the conditional instruction that follows.
9858(define_insn_and_split "*and_scc_scc_cmp"
9859 [(set (match_operand 0 "dominant_cc_register" "")
9860 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9861 [(match_operand:SI 1 "s_register_operand" "r")
9862 (match_operand:SI 2 "arm_add_operand" "rIL")])
9863 (match_operator:SI 6 "arm_comparison_operator"
9864 [(match_operand:SI 4 "s_register_operand" "r")
9865 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9866 (const_int 0)))
9867 (set (match_operand:SI 7 "s_register_operand" "=r")
9868 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9869 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9870 "TARGET_32BIT"
601f584c 9871 "#"
2ff91fec 9872 "TARGET_32BIT && reload_completed"
601f584c 9873 [(set (match_dup 0)
9874 (compare
9875 (and:SI
9876 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9877 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9878 (const_int 0)))
9879 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9880 ""
9881 [(set_attr "conds" "set")
9882 (set_attr "length" "16")])
9883
9884;; If there is no dominance in the comparison, then we can still save an
9885;; instruction in the AND case, since we can know that the second compare
9886;; need only zero the value if false (if true, then the value is already
9887;; correct).
9888(define_insn_and_split "*and_scc_scc_nodom"
9889 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9890 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9891 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9892 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9893 (match_operator:SI 6 "arm_comparison_operator"
9894 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9895 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9896 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9897 "TARGET_32BIT
601f584c 9898 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9899 == CCmode)"
9900 "#"
2ff91fec 9901 "TARGET_32BIT && reload_completed"
601f584c 9902 [(parallel [(set (match_dup 0)
9903 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9904 (clobber (reg:CC CC_REGNUM))])
9905 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9906 (set (match_dup 0)
9907 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9908 (match_dup 0)
9909 (const_int 0)))]
9910 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9911 operands[4], operands[5]),
9912 CC_REGNUM);
9913 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9914 operands[5]);"
9915 [(set_attr "conds" "clob")
9916 (set_attr "length" "20")])
3c5afce6 9917
3a0bdee0 9918(define_split
9919 [(set (reg:CC_NOOV CC_REGNUM)
9920 (compare:CC_NOOV (ior:SI
9921 (and:SI (match_operand:SI 0 "s_register_operand" "")
9922 (const_int 1))
b0694be0 9923 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9924 [(match_operand:SI 2 "s_register_operand" "")
9925 (match_operand:SI 3 "arm_add_operand" "")]))
9926 (const_int 0)))
9927 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9928 "TARGET_ARM"
9929 [(set (match_dup 4)
9930 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9931 (match_dup 0)))
9932 (set (reg:CC_NOOV CC_REGNUM)
9933 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9934 (const_int 0)))]
9935 "")
9936
9937(define_split
9938 [(set (reg:CC_NOOV CC_REGNUM)
9939 (compare:CC_NOOV (ior:SI
b0694be0 9940 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9941 [(match_operand:SI 2 "s_register_operand" "")
9942 (match_operand:SI 3 "arm_add_operand" "")])
9943 (and:SI (match_operand:SI 0 "s_register_operand" "")
9944 (const_int 1)))
9945 (const_int 0)))
9946 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9947 "TARGET_ARM"
9948 [(set (match_dup 4)
9949 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9950 (match_dup 0)))
9951 (set (reg:CC_NOOV CC_REGNUM)
9952 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9953 (const_int 0)))]
9954 "")
25f905c2 9955;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9956
f7fbdd4a 9957(define_insn "*negscc"
9c08d1fa 9958 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9959 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9960 [(match_operand:SI 1 "s_register_operand" "r")
9961 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9962 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9963 "TARGET_ARM"
9c08d1fa 9964 "*
2ca2ec2e 9965 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9966 return \"mov\\t%0, %1, asr #31\";
9967
9c08d1fa 9968 if (GET_CODE (operands[3]) == NE)
e2348bcb 9969 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9970
e2348bcb 9971 output_asm_insn (\"cmp\\t%1, %2\", operands);
9972 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9973 return \"mvn%d3\\t%0, #0\";
215b30b3 9974 "
8fa3ba89 9975 [(set_attr "conds" "clob")
9976 (set_attr "length" "12")]
9977)
9c08d1fa 9978
9979(define_insn "movcond"
9980 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9981 (if_then_else:SI
8fa3ba89 9982 (match_operator 5 "arm_comparison_operator"
5565501b 9983 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9984 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9985 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9986 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9987 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9988 "TARGET_ARM"
9c08d1fa 9989 "*
9990 if (GET_CODE (operands[5]) == LT
9991 && (operands[4] == const0_rtx))
9992 {
0438d37f 9993 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9994 {
9c08d1fa 9995 if (operands[2] == const0_rtx)
e2348bcb 9996 return \"and\\t%0, %1, %3, asr #31\";
9997 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9998 }
0438d37f 9999 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 10000 {
9c08d1fa 10001 if (operands[1] == const0_rtx)
e2348bcb 10002 return \"bic\\t%0, %2, %3, asr #31\";
10003 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 10004 }
10005 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 10006 are constants. */
9c08d1fa 10007 }
e2348bcb 10008
9c08d1fa 10009 if (GET_CODE (operands[5]) == GE
10010 && (operands[4] == const0_rtx))
10011 {
0438d37f 10012 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 10013 {
9c08d1fa 10014 if (operands[2] == const0_rtx)
e2348bcb 10015 return \"bic\\t%0, %1, %3, asr #31\";
10016 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 10017 }
0438d37f 10018 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 10019 {
9c08d1fa 10020 if (operands[1] == const0_rtx)
e2348bcb 10021 return \"and\\t%0, %2, %3, asr #31\";
10022 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 10023 }
10024 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 10025 are constants. */
9c08d1fa 10026 }
0438d37f 10027 if (CONST_INT_P (operands[4])
9c08d1fa 10028 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 10029 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 10030 else
e2348bcb 10031 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 10032 if (which_alternative != 0)
e2348bcb 10033 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 10034 if (which_alternative != 1)
e2348bcb 10035 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 10036 return \"\";
215b30b3 10037 "
8fa3ba89 10038 [(set_attr "conds" "clob")
10039 (set_attr "length" "8,8,12")]
10040)
9c08d1fa 10041
25f905c2 10042;; ??? The patterns below need checking for Thumb-2 usefulness.
10043
8a18b90c 10044(define_insn "*ifcompare_plus_move"
10045 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10046 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10047 [(match_operand:SI 4 "s_register_operand" "r,r")
10048 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10049 (plus:SI
10050 (match_operand:SI 2 "s_register_operand" "r,r")
10051 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 10052 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10053 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10054 "TARGET_ARM"
8a18b90c 10055 "#"
8fa3ba89 10056 [(set_attr "conds" "clob")
10057 (set_attr "length" "8,12")]
10058)
8a18b90c 10059
10060(define_insn "*if_plus_move"
129a2fe4 10061 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10062 (if_then_else:SI
8fa3ba89 10063 (match_operator 4 "arm_comparison_operator"
8a18b90c 10064 [(match_operand 5 "cc_register" "") (const_int 0)])
10065 (plus:SI
129a2fe4 10066 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10067 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
10068 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 10069 "TARGET_ARM"
8a18b90c 10070 "@
10071 add%d4\\t%0, %2, %3
10072 sub%d4\\t%0, %2, #%n3
10073 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 10074 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 10075 [(set_attr "conds" "use")
10076 (set_attr "length" "4,4,8,8")
65f68e55 10077 (set_attr_alternative "type"
10078 [(if_then_else (match_operand 3 "const_int_operand" "")
10079 (const_string "simple_alu_imm" )
10080 (const_string "*"))
10081 (const_string "simple_alu_imm")
10082 (const_string "*")
10083 (const_string "*")])]
8fa3ba89 10084)
8a18b90c 10085
10086(define_insn "*ifcompare_move_plus"
5565501b 10087 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10088 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10089 [(match_operand:SI 4 "s_register_operand" "r,r")
10090 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10091 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10092 (plus:SI
10093 (match_operand:SI 2 "s_register_operand" "r,r")
10094 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 10095 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10096 "TARGET_ARM"
8a18b90c 10097 "#"
8fa3ba89 10098 [(set_attr "conds" "clob")
10099 (set_attr "length" "8,12")]
10100)
8a18b90c 10101
10102(define_insn "*if_move_plus"
129a2fe4 10103 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10104 (if_then_else:SI
8fa3ba89 10105 (match_operator 4 "arm_comparison_operator"
8a18b90c 10106 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10107 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10108 (plus:SI
129a2fe4 10109 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10110 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10111 "TARGET_ARM"
8a18b90c 10112 "@
10113 add%D4\\t%0, %2, %3
10114 sub%D4\\t%0, %2, #%n3
10115 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10116 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10117 [(set_attr "conds" "use")
10118 (set_attr "length" "4,4,8,8")
65f68e55 10119 (set_attr_alternative "type"
10120 [(if_then_else (match_operand 3 "const_int_operand" "")
10121 (const_string "simple_alu_imm" )
10122 (const_string "*"))
10123 (const_string "simple_alu_imm")
10124 (const_string "*")
10125 (const_string "*")])]
8fa3ba89 10126)
8a18b90c 10127
10128(define_insn "*ifcompare_arith_arith"
10129 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10130 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10131 [(match_operand:SI 5 "s_register_operand" "r")
10132 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10133 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10134 [(match_operand:SI 1 "s_register_operand" "r")
10135 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10136 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10137 [(match_operand:SI 3 "s_register_operand" "r")
10138 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10139 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10140 "TARGET_ARM"
8a18b90c 10141 "#"
8fa3ba89 10142 [(set_attr "conds" "clob")
10143 (set_attr "length" "12")]
10144)
9c08d1fa 10145
8a18b90c 10146(define_insn "*if_arith_arith"
10147 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10148 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10149 [(match_operand 8 "cc_register" "") (const_int 0)])
10150 (match_operator:SI 6 "shiftable_operator"
10151 [(match_operand:SI 1 "s_register_operand" "r")
10152 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10153 (match_operator:SI 7 "shiftable_operator"
10154 [(match_operand:SI 3 "s_register_operand" "r")
10155 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10156 "TARGET_ARM"
8a18b90c 10157 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10158 [(set_attr "conds" "use")
10159 (set_attr "length" "8")]
10160)
8a18b90c 10161
f7fbdd4a 10162(define_insn "*ifcompare_arith_move"
9c08d1fa 10163 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10164 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10165 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10166 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10167 (match_operator:SI 7 "shiftable_operator"
10168 [(match_operand:SI 4 "s_register_operand" "r,r")
10169 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10170 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10171 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10172 "TARGET_ARM"
9c08d1fa 10173 "*
9c08d1fa 10174 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10175 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10176 everything is in registers then we can do this in two instructions. */
9c08d1fa 10177 if (operands[3] == const0_rtx
10178 && GET_CODE (operands[7]) != AND
0438d37f 10179 && REG_P (operands[5])
10180 && REG_P (operands[1])
9c08d1fa 10181 && REGNO (operands[1]) == REGNO (operands[4])
10182 && REGNO (operands[4]) != REGNO (operands[0]))
10183 {
10184 if (GET_CODE (operands[6]) == LT)
40dbec34 10185 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10186 else if (GET_CODE (operands[6]) == GE)
40dbec34 10187 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10188 }
0438d37f 10189 if (CONST_INT_P (operands[3])
9c08d1fa 10190 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10191 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10192 else
e2348bcb 10193 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10194 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10195 if (which_alternative != 0)
129a2fe4 10196 return \"mov%D6\\t%0, %1\";
9c08d1fa 10197 return \"\";
215b30b3 10198 "
8fa3ba89 10199 [(set_attr "conds" "clob")
10200 (set_attr "length" "8,12")]
10201)
9c08d1fa 10202
8a18b90c 10203(define_insn "*if_arith_move"
129a2fe4 10204 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10205 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10206 [(match_operand 6 "cc_register" "") (const_int 0)])
10207 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10208 [(match_operand:SI 2 "s_register_operand" "r,r")
10209 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10210 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10211 "TARGET_ARM"
8a18b90c 10212 "@
10213 %I5%d4\\t%0, %2, %3
129a2fe4 10214 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10215 [(set_attr "conds" "use")
10216 (set_attr "length" "4,8")
10217 (set_attr "type" "*,*")]
10218)
8a18b90c 10219
f7fbdd4a 10220(define_insn "*ifcompare_move_arith"
9c08d1fa 10221 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10222 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10223 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10224 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10225 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10226 (match_operator:SI 7 "shiftable_operator"
10227 [(match_operand:SI 2 "s_register_operand" "r,r")
10228 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10229 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10230 "TARGET_ARM"
9c08d1fa 10231 "*
9c08d1fa 10232 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10233 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10234 everything is in registers then we can do this in two instructions */
10235 if (operands[5] == const0_rtx
10236 && GET_CODE (operands[7]) != AND
0438d37f 10237 && REG_P (operands[3])
10238 && REG_P (operands[1])
9c08d1fa 10239 && REGNO (operands[1]) == REGNO (operands[2])
10240 && REGNO (operands[2]) != REGNO (operands[0]))
10241 {
10242 if (GET_CODE (operands[6]) == GE)
40dbec34 10243 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10244 else if (GET_CODE (operands[6]) == LT)
40dbec34 10245 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10246 }
40dbec34 10247
0438d37f 10248 if (CONST_INT_P (operands[5])
9c08d1fa 10249 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10250 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10251 else
e2348bcb 10252 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10253
9c08d1fa 10254 if (which_alternative != 0)
129a2fe4 10255 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10256 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10257 "
8fa3ba89 10258 [(set_attr "conds" "clob")
10259 (set_attr "length" "8,12")]
10260)
9c08d1fa 10261
8a18b90c 10262(define_insn "*if_move_arith"
129a2fe4 10263 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10264 (if_then_else:SI
8fa3ba89 10265 (match_operator 4 "arm_comparison_operator"
8a18b90c 10266 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10267 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10268 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10269 [(match_operand:SI 2 "s_register_operand" "r,r")
10270 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10271 "TARGET_ARM"
8a18b90c 10272 "@
10273 %I5%D4\\t%0, %2, %3
129a2fe4 10274 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10275 [(set_attr "conds" "use")
10276 (set_attr "length" "4,8")
10277 (set_attr "type" "*,*")]
10278)
8a18b90c 10279
10280(define_insn "*ifcompare_move_not"
9c08d1fa 10281 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10282 (if_then_else:SI
8fa3ba89 10283 (match_operator 5 "arm_comparison_operator"
8a18b90c 10284 [(match_operand:SI 3 "s_register_operand" "r,r")
10285 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10286 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10287 (not:SI
10288 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10289 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10290 "TARGET_ARM"
8a18b90c 10291 "#"
8fa3ba89 10292 [(set_attr "conds" "clob")
10293 (set_attr "length" "8,12")]
10294)
9c08d1fa 10295
8a18b90c 10296(define_insn "*if_move_not"
10297 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10298 (if_then_else:SI
8fa3ba89 10299 (match_operator 4 "arm_comparison_operator"
8a18b90c 10300 [(match_operand 3 "cc_register" "") (const_int 0)])
10301 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10302 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10303 "TARGET_ARM"
8a18b90c 10304 "@
10305 mvn%D4\\t%0, %2
10306 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10307 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10308 [(set_attr "conds" "use")
d2a518d1 10309 (set_attr "insn" "mvn")
8fa3ba89 10310 (set_attr "length" "4,8,8")]
10311)
8a18b90c 10312
10313(define_insn "*ifcompare_not_move"
9c08d1fa 10314 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10315 (if_then_else:SI
8fa3ba89 10316 (match_operator 5 "arm_comparison_operator"
8a18b90c 10317 [(match_operand:SI 3 "s_register_operand" "r,r")
10318 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10319 (not:SI
10320 (match_operand:SI 2 "s_register_operand" "r,r"))
10321 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10322 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10323 "TARGET_ARM"
8a18b90c 10324 "#"
8fa3ba89 10325 [(set_attr "conds" "clob")
10326 (set_attr "length" "8,12")]
10327)
9c08d1fa 10328
8a18b90c 10329(define_insn "*if_not_move"
10330 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10331 (if_then_else:SI
8fa3ba89 10332 (match_operator 4 "arm_comparison_operator"
8a18b90c 10333 [(match_operand 3 "cc_register" "") (const_int 0)])
10334 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10335 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10336 "TARGET_ARM"
8a18b90c 10337 "@
10338 mvn%d4\\t%0, %2
10339 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10340 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10341 [(set_attr "conds" "use")
d2a518d1 10342 (set_attr "insn" "mvn")
8fa3ba89 10343 (set_attr "length" "4,8,8")]
10344)
8a18b90c 10345
10346(define_insn "*ifcompare_shift_move"
9c08d1fa 10347 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10348 (if_then_else:SI
8fa3ba89 10349 (match_operator 6 "arm_comparison_operator"
8a18b90c 10350 [(match_operand:SI 4 "s_register_operand" "r,r")
10351 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10352 (match_operator:SI 7 "shift_operator"
10353 [(match_operand:SI 2 "s_register_operand" "r,r")
10354 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10355 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10356 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10357 "TARGET_ARM"
9c08d1fa 10358 "#"
8fa3ba89 10359 [(set_attr "conds" "clob")
10360 (set_attr "length" "8,12")]
10361)
9c08d1fa 10362
8a18b90c 10363(define_insn "*if_shift_move"
10364 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10365 (if_then_else:SI
8fa3ba89 10366 (match_operator 5 "arm_comparison_operator"
8a18b90c 10367 [(match_operand 6 "cc_register" "") (const_int 0)])
10368 (match_operator:SI 4 "shift_operator"
10369 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10370 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10371 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10372 "TARGET_ARM"
5565501b 10373 "@
8a18b90c 10374 mov%d5\\t%0, %2%S4
10375 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10376 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10377 [(set_attr "conds" "use")
331beb1a 10378 (set_attr "shift" "2")
a2cd141b 10379 (set_attr "length" "4,8,8")
d2a518d1 10380 (set_attr "insn" "mov")
a2cd141b 10381 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10382 (const_string "alu_shift")
10383 (const_string "alu_shift_reg")))]
8fa3ba89 10384)
5565501b 10385
8a18b90c 10386(define_insn "*ifcompare_move_shift"
10387 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10388 (if_then_else:SI
8fa3ba89 10389 (match_operator 6 "arm_comparison_operator"
8a18b90c 10390 [(match_operand:SI 4 "s_register_operand" "r,r")
10391 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10392 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10393 (match_operator:SI 7 "shift_operator"
8a18b90c 10394 [(match_operand:SI 2 "s_register_operand" "r,r")
10395 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10396 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10397 "TARGET_ARM"
8a18b90c 10398 "#"
8fa3ba89 10399 [(set_attr "conds" "clob")
10400 (set_attr "length" "8,12")]
10401)
5565501b 10402
8a18b90c 10403(define_insn "*if_move_shift"
10404 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10405 (if_then_else:SI
8fa3ba89 10406 (match_operator 5 "arm_comparison_operator"
8a18b90c 10407 [(match_operand 6 "cc_register" "") (const_int 0)])
10408 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10409 (match_operator:SI 4 "shift_operator"
10410 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10411 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10412 "TARGET_ARM"
5565501b 10413 "@
8a18b90c 10414 mov%D5\\t%0, %2%S4
10415 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10416 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10417 [(set_attr "conds" "use")
331beb1a 10418 (set_attr "shift" "2")
a2cd141b 10419 (set_attr "length" "4,8,8")
d2a518d1 10420 (set_attr "insn" "mov")
a2cd141b 10421 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10422 (const_string "alu_shift")
10423 (const_string "alu_shift_reg")))]
8fa3ba89 10424)
9c08d1fa 10425
f7fbdd4a 10426(define_insn "*ifcompare_shift_shift"
8a18b90c 10427 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10428 (if_then_else:SI
8fa3ba89 10429 (match_operator 7 "arm_comparison_operator"
8a18b90c 10430 [(match_operand:SI 5 "s_register_operand" "r")
10431 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10432 (match_operator:SI 8 "shift_operator"
8a18b90c 10433 [(match_operand:SI 1 "s_register_operand" "r")
10434 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10435 (match_operator:SI 9 "shift_operator"
8a18b90c 10436 [(match_operand:SI 3 "s_register_operand" "r")
10437 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10438 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10439 "TARGET_ARM"
8a18b90c 10440 "#"
8fa3ba89 10441 [(set_attr "conds" "clob")
10442 (set_attr "length" "12")]
10443)
9c08d1fa 10444
8a18b90c 10445(define_insn "*if_shift_shift"
10446 [(set (match_operand:SI 0 "s_register_operand" "=r")
10447 (if_then_else:SI
8fa3ba89 10448 (match_operator 5 "arm_comparison_operator"
8a18b90c 10449 [(match_operand 8 "cc_register" "") (const_int 0)])
10450 (match_operator:SI 6 "shift_operator"
10451 [(match_operand:SI 1 "s_register_operand" "r")
10452 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10453 (match_operator:SI 7 "shift_operator"
10454 [(match_operand:SI 3 "s_register_operand" "r")
10455 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10456 "TARGET_ARM"
8a18b90c 10457 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10458 [(set_attr "conds" "use")
331beb1a 10459 (set_attr "shift" "1")
a2cd141b 10460 (set_attr "length" "8")
d2a518d1 10461 (set_attr "insn" "mov")
a2cd141b 10462 (set (attr "type") (if_then_else
10463 (and (match_operand 2 "const_int_operand" "")
10464 (match_operand 4 "const_int_operand" ""))
10465 (const_string "alu_shift")
10466 (const_string "alu_shift_reg")))]
8fa3ba89 10467)
8a18b90c 10468
f7fbdd4a 10469(define_insn "*ifcompare_not_arith"
8a18b90c 10470 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10471 (if_then_else:SI
8fa3ba89 10472 (match_operator 6 "arm_comparison_operator"
8a18b90c 10473 [(match_operand:SI 4 "s_register_operand" "r")
10474 (match_operand:SI 5 "arm_add_operand" "rIL")])
10475 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10476 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10477 [(match_operand:SI 2 "s_register_operand" "r")
10478 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10479 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10480 "TARGET_ARM"
8a18b90c 10481 "#"
8fa3ba89 10482 [(set_attr "conds" "clob")
10483 (set_attr "length" "12")]
10484)
9c08d1fa 10485
8a18b90c 10486(define_insn "*if_not_arith"
10487 [(set (match_operand:SI 0 "s_register_operand" "=r")
10488 (if_then_else:SI
8fa3ba89 10489 (match_operator 5 "arm_comparison_operator"
8a18b90c 10490 [(match_operand 4 "cc_register" "") (const_int 0)])
10491 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10492 (match_operator:SI 6 "shiftable_operator"
10493 [(match_operand:SI 2 "s_register_operand" "r")
10494 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10495 "TARGET_ARM"
8a18b90c 10496 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10497 [(set_attr "conds" "use")
d2a518d1 10498 (set_attr "insn" "mvn")
8fa3ba89 10499 (set_attr "length" "8")]
10500)
8a18b90c 10501
10502(define_insn "*ifcompare_arith_not"
10503 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10504 (if_then_else:SI
8fa3ba89 10505 (match_operator 6 "arm_comparison_operator"
8a18b90c 10506 [(match_operand:SI 4 "s_register_operand" "r")
10507 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10508 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10509 [(match_operand:SI 2 "s_register_operand" "r")
10510 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10511 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10512 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10513 "TARGET_ARM"
8a18b90c 10514 "#"
8fa3ba89 10515 [(set_attr "conds" "clob")
10516 (set_attr "length" "12")]
10517)
9c08d1fa 10518
8a18b90c 10519(define_insn "*if_arith_not"
10520 [(set (match_operand:SI 0 "s_register_operand" "=r")
10521 (if_then_else:SI
8fa3ba89 10522 (match_operator 5 "arm_comparison_operator"
8a18b90c 10523 [(match_operand 4 "cc_register" "") (const_int 0)])
10524 (match_operator:SI 6 "shiftable_operator"
10525 [(match_operand:SI 2 "s_register_operand" "r")
10526 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10527 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10528 "TARGET_ARM"
8a18b90c 10529 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10530 [(set_attr "conds" "use")
d2a518d1 10531 (set_attr "insn" "mvn")
8fa3ba89 10532 (set_attr "length" "8")]
10533)
8a18b90c 10534
f7fbdd4a 10535(define_insn "*ifcompare_neg_move"
8a18b90c 10536 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10537 (if_then_else:SI
8fa3ba89 10538 (match_operator 5 "arm_comparison_operator"
8a18b90c 10539 [(match_operand:SI 3 "s_register_operand" "r,r")
10540 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10541 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10542 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10543 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10544 "TARGET_ARM"
8a18b90c 10545 "#"
8fa3ba89 10546 [(set_attr "conds" "clob")
10547 (set_attr "length" "8,12")]
10548)
8a18b90c 10549
10550(define_insn "*if_neg_move"
10551 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10552 (if_then_else:SI
8fa3ba89 10553 (match_operator 4 "arm_comparison_operator"
8a18b90c 10554 [(match_operand 3 "cc_register" "") (const_int 0)])
10555 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10556 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10557 "TARGET_ARM"
8a18b90c 10558 "@
10559 rsb%d4\\t%0, %2, #0
10560 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10561 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10562 [(set_attr "conds" "use")
10563 (set_attr "length" "4,8,8")]
10564)
9c08d1fa 10565
f7fbdd4a 10566(define_insn "*ifcompare_move_neg"
8a18b90c 10567 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10568 (if_then_else:SI
8fa3ba89 10569 (match_operator 5 "arm_comparison_operator"
8a18b90c 10570 [(match_operand:SI 3 "s_register_operand" "r,r")
10571 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10572 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10573 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10574 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10575 "TARGET_ARM"
8a18b90c 10576 "#"
8fa3ba89 10577 [(set_attr "conds" "clob")
10578 (set_attr "length" "8,12")]
10579)
8a18b90c 10580
10581(define_insn "*if_move_neg"
10582 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10583 (if_then_else:SI
8fa3ba89 10584 (match_operator 4 "arm_comparison_operator"
8a18b90c 10585 [(match_operand 3 "cc_register" "") (const_int 0)])
10586 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10587 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10588 "TARGET_ARM"
8a18b90c 10589 "@
10590 rsb%D4\\t%0, %2, #0
10591 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10592 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10593 [(set_attr "conds" "use")
10594 (set_attr "length" "4,8,8")]
10595)
9c08d1fa 10596
f7fbdd4a 10597(define_insn "*arith_adjacentmem"
9c08d1fa 10598 [(set (match_operand:SI 0 "s_register_operand" "=r")
10599 (match_operator:SI 1 "shiftable_operator"
10600 [(match_operand:SI 2 "memory_operand" "m")
10601 (match_operand:SI 3 "memory_operand" "m")]))
10602 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10603 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10604 "*
215b30b3 10605 {
10606 rtx ldm[3];
10607 rtx arith[4];
94dee231 10608 rtx base_reg;
10609 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10610
215b30b3 10611 if (REGNO (operands[0]) > REGNO (operands[4]))
10612 {
10613 ldm[1] = operands[4];
10614 ldm[2] = operands[0];
10615 }
10616 else
10617 {
10618 ldm[1] = operands[0];
10619 ldm[2] = operands[4];
10620 }
94dee231 10621
10622 base_reg = XEXP (operands[2], 0);
10623
10624 if (!REG_P (base_reg))
10625 {
10626 val1 = INTVAL (XEXP (base_reg, 1));
10627 base_reg = XEXP (base_reg, 0);
10628 }
10629
10630 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10631 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10632
215b30b3 10633 arith[0] = operands[0];
10634 arith[3] = operands[1];
94dee231 10635
215b30b3 10636 if (val1 < val2)
10637 {
10638 arith[1] = ldm[1];
10639 arith[2] = ldm[2];
10640 }
10641 else
10642 {
10643 arith[1] = ldm[2];
10644 arith[2] = ldm[1];
10645 }
94dee231 10646
10647 ldm[0] = base_reg;
10648 if (val1 !=0 && val2 != 0)
215b30b3 10649 {
cdb1295a 10650 rtx ops[3];
10651
94dee231 10652 if (val1 == 4 || val2 == 4)
10653 /* Other val must be 8, since we know they are adjacent and neither
10654 is zero. */
25f905c2 10655 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10656 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10657 {
94dee231 10658 ldm[0] = ops[0] = operands[4];
10659 ops[1] = base_reg;
10660 ops[2] = GEN_INT (val1);
10661 output_add_immediate (ops);
10662 if (val1 < val2)
25f905c2 10663 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10664 else
25f905c2 10665 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10666 }
cdb1295a 10667 else
10668 {
10669 /* Offset is out of range for a single add, so use two ldr. */
10670 ops[0] = ldm[1];
10671 ops[1] = base_reg;
10672 ops[2] = GEN_INT (val1);
10673 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10674 ops[0] = ldm[2];
10675 ops[2] = GEN_INT (val2);
10676 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10677 }
215b30b3 10678 }
94dee231 10679 else if (val1 != 0)
215b30b3 10680 {
215b30b3 10681 if (val1 < val2)
25f905c2 10682 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10683 else
25f905c2 10684 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10685 }
10686 else
10687 {
215b30b3 10688 if (val1 < val2)
25f905c2 10689 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10690 else
25f905c2 10691 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10692 }
10693 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10694 return \"\";
10695 }"
10696 [(set_attr "length" "12")
10697 (set_attr "predicable" "yes")
a2cd141b 10698 (set_attr "type" "load1")]
215b30b3 10699)
9c08d1fa 10700
9c08d1fa 10701; This pattern is never tried by combine, so do it as a peephole
10702
a0f94409 10703(define_peephole2
372575c7 10704 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10705 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10706 (set (reg:CC CC_REGNUM)
aea4c774 10707 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10708 "TARGET_ARM"
a0f94409 10709 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10710 (set (match_dup 0) (match_dup 1))])]
10711 ""
0d66636f 10712)
9c08d1fa 10713
9c08d1fa 10714(define_split
10715 [(set (match_operand:SI 0 "s_register_operand" "")
10716 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10717 (const_int 0))
8fa3ba89 10718 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10719 [(match_operand:SI 3 "s_register_operand" "")
10720 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10721 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10722 "TARGET_ARM"
9c08d1fa 10723 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10724 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10725 (match_dup 5)))]
215b30b3 10726 ""
10727)
9c08d1fa 10728
aea4c774 10729;; This split can be used because CC_Z mode implies that the following
10730;; branch will be an equality, or an unsigned inequality, so the sign
10731;; extension is not needed.
9c08d1fa 10732
aea4c774 10733(define_split
bd5b4116 10734 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10735 (compare:CC_Z
10736 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10737 (const_int 24))
aea4c774 10738 (match_operand 1 "const_int_operand" "")))
10739 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10740 "TARGET_ARM
10741 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10742 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10743 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10744 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10745 "
9c08d1fa 10746 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10747 "
10748)
25f905c2 10749;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10750
87b22bf7 10751(define_expand "prologue"
10752 [(clobber (const_int 0))]
cffb2a26 10753 "TARGET_EITHER"
25f905c2 10754 "if (TARGET_32BIT)
cffb2a26 10755 arm_expand_prologue ();
10756 else
25f905c2 10757 thumb1_expand_prologue ();
87b22bf7 10758 DONE;
cffb2a26 10759 "
10760)
87b22bf7 10761
56d27660 10762(define_expand "epilogue"
4c44712e 10763 [(clobber (const_int 0))]
cffb2a26 10764 "TARGET_EITHER"
56d27660 10765 "
18d50ae6 10766 if (crtl->calls_eh_return)
fb94f18b 10767 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10768 if (TARGET_THUMB1)
c3635784 10769 {
10770 thumb1_expand_epilogue ();
10771 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10772 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10773 }
10774 else if (HAVE_return)
10775 {
10776 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10777 no need for explicit testing again. */
10778 emit_jump_insn (gen_return ());
10779 }
10780 else if (TARGET_32BIT)
10781 {
10782 arm_expand_epilogue (true);
10783 }
cffb2a26 10784 DONE;
10785 "
10786)
56d27660 10787
7571d3f7 10788(define_insn "prologue_thumb1_interwork"
10789 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
10790 "TARGET_THUMB1"
10791 "* return thumb1_output_interwork ();"
10792 [(set_attr "length" "8")]
10793)
10794
ef5651d0 10795;; Note - although unspec_volatile's USE all hard registers,
10796;; USEs are ignored after relaod has completed. Thus we need
10797;; to add an unspec of the link register to ensure that flow
10798;; does not think that it is unused by the sibcall branch that
10799;; will replace the standard function epilogue.
c3635784 10800(define_expand "sibcall_epilogue"
fb94f18b 10801 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10802 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10803 "TARGET_32BIT"
10804 "
10805 arm_expand_epilogue (false);
10806 DONE;
10807 "
1c494086 10808)
10809
cffb2a26 10810(define_insn "*epilogue_insns"
e1159bbe 10811 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
b1324f4f 10812 "TARGET_THUMB1"
56d27660 10813 "*
e7fd8dfa 10814 return thumb1_unexpanded_epilogue ();
cffb2a26 10815 "
215b30b3 10816 ; Length is absolute worst case
cffb2a26 10817 [(set_attr "length" "44")
defc47cf 10818 (set_attr "type" "block")
10819 ;; We don't clobber the conditions, but the potential length of this
10820 ;; operation is sufficient to make conditionalizing the sequence
10821 ;; unlikely to be profitable.
10822 (set_attr "conds" "clob")]
cffb2a26 10823)
10824
10825(define_expand "eh_epilogue"
7db9af5d 10826 [(use (match_operand:SI 0 "register_operand" ""))
10827 (use (match_operand:SI 1 "register_operand" ""))
10828 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10829 "TARGET_EITHER"
10830 "
215b30b3 10831 {
10832 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10833 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10834 {
10835 rtx ra = gen_rtx_REG (Pmode, 2);
10836
10837 emit_move_insn (ra, operands[2]);
10838 operands[2] = ra;
10839 }
5cf3595a 10840 /* This is a hack -- we may have crystalized the function type too
10841 early. */
10842 cfun->machine->func_type = 0;
215b30b3 10843 }"
10844)
56d27660 10845
9c08d1fa 10846;; This split is only used during output to reduce the number of patterns
10847;; that need assembler instructions adding to them. We allowed the setting
10848;; of the conditions to be implicit during rtl generation so that
10849;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10850;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10851;; up again here.
10852
25f905c2 10853;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10854;; conditional execution sufficient?
10855
9c08d1fa 10856(define_split
10857 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10858 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10859 [(match_operand 2 "" "") (match_operand 3 "" "")])
10860 (match_dup 0)
10861 (match_operand 4 "" "")))
bd5b4116 10862 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10863 "TARGET_ARM && reload_completed"
8fa3ba89 10864 [(set (match_dup 5) (match_dup 6))
10865 (cond_exec (match_dup 7)
10866 (set (match_dup 0) (match_dup 4)))]
10867 "
10868 {
10869 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10870 operands[2], operands[3]);
10871 enum rtx_code rc = GET_CODE (operands[1]);
10872
bd5b4116 10873 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10874 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10875 if (mode == CCFPmode || mode == CCFPEmode)
10876 rc = reverse_condition_maybe_unordered (rc);
10877 else
10878 rc = reverse_condition (rc);
10879
10880 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10881 }"
10882)
10883
10884(define_split
10885 [(set (match_operand:SI 0 "s_register_operand" "")
10886 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10887 [(match_operand 2 "" "") (match_operand 3 "" "")])
10888 (match_operand 4 "" "")
10889 (match_dup 0)))
bd5b4116 10890 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10891 "TARGET_ARM && reload_completed"
8fa3ba89 10892 [(set (match_dup 5) (match_dup 6))
10893 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10894 (set (match_dup 0) (match_dup 4)))]
10895 "
10896 {
10897 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10898 operands[2], operands[3]);
10899
bd5b4116 10900 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10901 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10902 }"
10903)
10904
10905(define_split
10906 [(set (match_operand:SI 0 "s_register_operand" "")
10907 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10908 [(match_operand 2 "" "") (match_operand 3 "" "")])
10909 (match_operand 4 "" "")
10910 (match_operand 5 "" "")))
bd5b4116 10911 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10912 "TARGET_ARM && reload_completed"
8fa3ba89 10913 [(set (match_dup 6) (match_dup 7))
10914 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10915 (set (match_dup 0) (match_dup 4)))
10916 (cond_exec (match_dup 8)
10917 (set (match_dup 0) (match_dup 5)))]
10918 "
10919 {
10920 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10921 operands[2], operands[3]);
10922 enum rtx_code rc = GET_CODE (operands[1]);
10923
bd5b4116 10924 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10925 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10926 if (mode == CCFPmode || mode == CCFPEmode)
10927 rc = reverse_condition_maybe_unordered (rc);
10928 else
10929 rc = reverse_condition (rc);
10930
10931 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10932 }"
10933)
10934
cffb2a26 10935(define_split
10936 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10937 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10938 [(match_operand:SI 2 "s_register_operand" "")
10939 (match_operand:SI 3 "arm_add_operand" "")])
10940 (match_operand:SI 4 "arm_rhs_operand" "")
10941 (not:SI
10942 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10943 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10944 "TARGET_ARM && reload_completed"
cffb2a26 10945 [(set (match_dup 6) (match_dup 7))
f6c53574 10946 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10947 (set (match_dup 0) (match_dup 4)))
10948 (cond_exec (match_dup 8)
10949 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10950 "
215b30b3 10951 {
10952 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10953 operands[2], operands[3]);
f6c53574 10954 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10955
bd5b4116 10956 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10957 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10958 if (mode == CCFPmode || mode == CCFPEmode)
10959 rc = reverse_condition_maybe_unordered (rc);
10960 else
10961 rc = reverse_condition (rc);
10962
10963 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10964 }"
10965)
cffb2a26 10966
10967(define_insn "*cond_move_not"
10968 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10969 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10970 [(match_operand 3 "cc_register" "") (const_int 0)])
10971 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10972 (not:SI
10973 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10974 "TARGET_ARM"
10975 "@
10976 mvn%D4\\t%0, %2
10977 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10978 [(set_attr "conds" "use")
d2a518d1 10979 (set_attr "insn" "mvn")
0d66636f 10980 (set_attr "length" "4,8")]
10981)
cffb2a26 10982
9c08d1fa 10983;; The next two patterns occur when an AND operation is followed by a
10984;; scc insn sequence
10985
f7fbdd4a 10986(define_insn "*sign_extract_onebit"
9c08d1fa 10987 [(set (match_operand:SI 0 "s_register_operand" "=r")
10988 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10989 (const_int 1)
ed750274 10990 (match_operand:SI 2 "const_int_operand" "n")))
10991 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10992 "TARGET_ARM"
9c08d1fa 10993 "*
0d66636f 10994 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10995 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10996 return \"mvnne\\t%0, #0\";
10997 "
10998 [(set_attr "conds" "clob")
10999 (set_attr "length" "8")]
11000)
9c08d1fa 11001
f7fbdd4a 11002(define_insn "*not_signextract_onebit"
9c08d1fa 11003 [(set (match_operand:SI 0 "s_register_operand" "=r")
11004 (not:SI
11005 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
11006 (const_int 1)
ed750274 11007 (match_operand:SI 2 "const_int_operand" "n"))))
11008 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11009 "TARGET_ARM"
9c08d1fa 11010 "*
0d66636f 11011 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
11012 output_asm_insn (\"tst\\t%1, %2\", operands);
11013 output_asm_insn (\"mvneq\\t%0, #0\", operands);
11014 return \"movne\\t%0, #0\";
11015 "
11016 [(set_attr "conds" "clob")
11017 (set_attr "length" "12")]
11018)
25f905c2 11019;; ??? The above patterns need auditing for Thumb-2
87b22bf7 11020
0d66636f 11021;; Push multiple registers to the stack. Registers are in parallel (use ...)
11022;; expressions. For simplicity, the first register is also in the unspec
11023;; part.
08508cbf 11024;; To avoid the usage of GNU extension, the length attribute is computed
11025;; in a C function arm_attr_length_push_multi.
f7fbdd4a 11026(define_insn "*push_multi"
87b22bf7 11027 [(match_parallel 2 "multi_register_push"
7571d3f7 11028 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 11029 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 11030 UNSPEC_PUSH_MULT))])]
7571d3f7 11031 ""
87b22bf7 11032 "*
215b30b3 11033 {
11034 int num_saves = XVECLEN (operands[2], 0);
ed593f11 11035
215b30b3 11036 /* For the StrongARM at least it is faster to
25f905c2 11037 use STR to store only a single register.
542d5028 11038 In Thumb mode always use push, and the assembler will pick
11039 something appropriate. */
25f905c2 11040 if (num_saves == 1 && TARGET_ARM)
61309563 11041 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 11042 else
11043 {
11044 int i;
11045 char pattern[100];
ed593f11 11046
25f905c2 11047 if (TARGET_ARM)
61309563 11048 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
11049 else if (TARGET_THUMB2)
11050 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 11051 else
11052 strcpy (pattern, \"push\\t{%1\");
215b30b3 11053
6079f055 11054 for (i = 1; i < num_saves; i++)
215b30b3 11055 {
11056 strcat (pattern, \", %|\");
11057 strcat (pattern,
11058 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11059 }
11060
11061 strcat (pattern, \"}\");
11062 output_asm_insn (pattern, operands);
11063 }
11064
11065 return \"\";
11066 }"
a6864a24 11067 [(set_attr "type" "store4")
11068 (set (attr "length")
08508cbf 11069 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 11070)
f7fbdd4a 11071
4c58c898 11072(define_insn "stack_tie"
11073 [(set (mem:BLK (scratch))
aaa37ad6 11074 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11075 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 11076 UNSPEC_PRLG_STK))]
11077 ""
11078 ""
11079 [(set_attr "length" "0")]
11080)
11081
426be8c5 11082;; Pop (as used in epilogue RTL)
11083;;
11084(define_insn "*load_multiple_with_writeback"
11085 [(match_parallel 0 "load_multiple_operation"
11086 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11087 (plus:SI (match_dup 1)
11088 (match_operand:SI 2 "const_int_operand" "I")))
11089 (set (match_operand:SI 3 "s_register_operand" "=rk")
11090 (mem:SI (match_dup 1)))
11091 ])]
11092 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11093 "*
11094 {
11095 arm_output_multireg_pop (operands, /*return_pc=*/false,
11096 /*cond=*/const_true_rtx,
11097 /*reverse=*/false,
11098 /*update=*/true);
11099 return \"\";
11100 }
11101 "
11102 [(set_attr "type" "load4")
11103 (set_attr "predicable" "yes")]
11104)
11105
11106;; Pop with return (as used in epilogue RTL)
11107;;
11108;; This instruction is generated when the registers are popped at the end of
11109;; epilogue. Here, instead of popping the value into LR and then generating
11110;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11111;; with (return).
11112(define_insn "*pop_multiple_with_writeback_and_return"
11113 [(match_parallel 0 "pop_multiple_return"
11114 [(return)
11115 (set (match_operand:SI 1 "s_register_operand" "+rk")
11116 (plus:SI (match_dup 1)
11117 (match_operand:SI 2 "const_int_operand" "I")))
11118 (set (match_operand:SI 3 "s_register_operand" "=rk")
11119 (mem:SI (match_dup 1)))
11120 ])]
11121 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11122 "*
11123 {
11124 arm_output_multireg_pop (operands, /*return_pc=*/true,
11125 /*cond=*/const_true_rtx,
11126 /*reverse=*/false,
11127 /*update=*/true);
11128 return \"\";
11129 }
11130 "
11131 [(set_attr "type" "load4")
11132 (set_attr "predicable" "yes")]
11133)
11134
11135(define_insn "*pop_multiple_with_return"
11136 [(match_parallel 0 "pop_multiple_return"
11137 [(return)
11138 (set (match_operand:SI 2 "s_register_operand" "=rk")
11139 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11140 ])]
11141 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11142 "*
11143 {
11144 arm_output_multireg_pop (operands, /*return_pc=*/true,
11145 /*cond=*/const_true_rtx,
11146 /*reverse=*/false,
11147 /*update=*/false);
11148 return \"\";
11149 }
11150 "
11151 [(set_attr "type" "load4")
11152 (set_attr "predicable" "yes")]
11153)
11154
11155;; Load into PC and return
11156(define_insn "*ldr_with_return"
11157 [(return)
11158 (set (reg:SI PC_REGNUM)
11159 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11160 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11161 "ldr%?\t%|pc, [%0], #4"
11162 [(set_attr "type" "load1")
11163 (set_attr "predicable" "yes")]
11164)
1a0b0f12 11165;; Pop for floating point registers (as used in epilogue RTL)
11166(define_insn "*vfp_pop_multiple_with_writeback"
11167 [(match_parallel 0 "pop_multiple_fp"
11168 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11169 (plus:SI (match_dup 1)
11170 (match_operand:SI 2 "const_int_operand" "I")))
11171 (set (match_operand:DF 3 "arm_hard_register_operand" "")
11172 (mem:DF (match_dup 1)))])]
11173 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
11174 "*
11175 {
11176 int num_regs = XVECLEN (operands[0], 0);
11177 char pattern[100];
11178 rtx op_list[2];
11179 strcpy (pattern, \"fldmfdd\\t\");
11180 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11181 strcat (pattern, \"!, {\");
11182 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11183 strcat (pattern, \"%P0\");
11184 if ((num_regs - 1) > 1)
11185 {
11186 strcat (pattern, \"-%P1\");
11187 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11188 }
11189
11190 strcat (pattern, \"}\");
11191 output_asm_insn (pattern, op_list);
11192 return \"\";
11193 }
11194 "
11195 [(set_attr "type" "load4")
11196 (set_attr "conds" "unconditional")
11197 (set_attr "predicable" "no")]
11198)
11199
f7fbdd4a 11200;; Special patterns for dealing with the constant pool
11201
cffb2a26 11202(define_insn "align_4"
e1159bbe 11203 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11204 "TARGET_EITHER"
f7fbdd4a 11205 "*
cffb2a26 11206 assemble_align (32);
f7fbdd4a 11207 return \"\";
cffb2a26 11208 "
11209)
f7fbdd4a 11210
755eb2b4 11211(define_insn "align_8"
11212 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11213 "TARGET_EITHER"
755eb2b4 11214 "*
11215 assemble_align (64);
11216 return \"\";
11217 "
11218)
11219
cffb2a26 11220(define_insn "consttable_end"
e1159bbe 11221 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11222 "TARGET_EITHER"
f7fbdd4a 11223 "*
cffb2a26 11224 making_const_table = FALSE;
f7fbdd4a 11225 return \"\";
cffb2a26 11226 "
11227)
f7fbdd4a 11228
cffb2a26 11229(define_insn "consttable_1"
e1159bbe 11230 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 11231 "TARGET_THUMB1"
f7fbdd4a 11232 "*
cffb2a26 11233 making_const_table = TRUE;
09d688ff 11234 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 11235 assemble_zeros (3);
f7fbdd4a 11236 return \"\";
cffb2a26 11237 "
11238 [(set_attr "length" "4")]
11239)
f7fbdd4a 11240
cffb2a26 11241(define_insn "consttable_2"
e1159bbe 11242 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 11243 "TARGET_THUMB1"
f7fbdd4a 11244 "*
cffb2a26 11245 making_const_table = TRUE;
9b8516be 11246 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 11247 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 11248 assemble_zeros (2);
f7fbdd4a 11249 return \"\";
cffb2a26 11250 "
11251 [(set_attr "length" "4")]
11252)
11253
11254(define_insn "consttable_4"
e1159bbe 11255 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11256 "TARGET_EITHER"
11257 "*
11258 {
9b8516be 11259 rtx x = operands[0];
cffb2a26 11260 making_const_table = TRUE;
9b8516be 11261 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 11262 {
11263 case MODE_FLOAT:
9b8516be 11264 if (GET_MODE (x) == HFmode)
11265 arm_emit_fp16_const (x);
11266 else
11267 {
11268 REAL_VALUE_TYPE r;
11269 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
11270 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
11271 }
11272 break;
cffb2a26 11273 default:
7b04c5d5 11274 /* XXX: Sometimes gcc does something really dumb and ends up with
11275 a HIGH in a constant pool entry, usually because it's trying to
11276 load into a VFP register. We know this will always be used in
11277 combination with a LO_SUM which ignores the high bits, so just
11278 strip off the HIGH. */
11279 if (GET_CODE (x) == HIGH)
11280 x = XEXP (x, 0);
9b8516be 11281 assemble_integer (x, 4, BITS_PER_WORD, 1);
11282 mark_symbol_refs_as_used (x);
cffb2a26 11283 break;
11284 }
11285 return \"\";
11286 }"
11287 [(set_attr "length" "4")]
11288)
11289
11290(define_insn "consttable_8"
e1159bbe 11291 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11292 "TARGET_EITHER"
11293 "*
11294 {
11295 making_const_table = TRUE;
11296 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11297 {
11298 case MODE_FLOAT:
11299 {
badfe841 11300 REAL_VALUE_TYPE r;
11301 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11302 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 11303 break;
11304 }
11305 default:
09d688ff 11306 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11307 break;
11308 }
11309 return \"\";
11310 }"
11311 [(set_attr "length" "8")]
11312)
11313
d98a3884 11314(define_insn "consttable_16"
11315 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11316 "TARGET_EITHER"
11317 "*
11318 {
11319 making_const_table = TRUE;
11320 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11321 {
11322 case MODE_FLOAT:
11323 {
11324 REAL_VALUE_TYPE r;
11325 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11326 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11327 break;
11328 }
11329 default:
11330 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11331 break;
11332 }
11333 return \"\";
11334 }"
11335 [(set_attr "length" "16")]
11336)
11337
cffb2a26 11338;; Miscellaneous Thumb patterns
11339
fd957ef3 11340(define_expand "tablejump"
7db9af5d 11341 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 11342 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 11343 "TARGET_THUMB1"
fd957ef3 11344 "
11345 if (flag_pic)
11346 {
11347 /* Hopefully, CSE will eliminate this copy. */
11348 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11349 rtx reg2 = gen_reg_rtx (SImode);
11350
11351 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11352 operands[0] = reg2;
11353 }
11354 "
11355)
11356
f1039640 11357;; NB never uses BX.
25f905c2 11358(define_insn "*thumb1_tablejump"
cffb2a26 11359 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11360 (use (label_ref (match_operand 1 "" "")))]
25f905c2 11361 "TARGET_THUMB1"
fd957ef3 11362 "mov\\t%|pc, %0"
cffb2a26 11363 [(set_attr "length" "2")]
11364)
0d66636f 11365
331beb1a 11366;; V5 Instructions,
11367
8f4be2be 11368(define_insn "clzsi2"
11369 [(set (match_operand:SI 0 "s_register_operand" "=r")
11370 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11371 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11372 "clz%?\\t%0, %1"
bcaec148 11373 [(set_attr "predicable" "yes")
11374 (set_attr "insn" "clz")])
331beb1a 11375
099ad98b 11376(define_insn "rbitsi2"
11377 [(set (match_operand:SI 0 "s_register_operand" "=r")
11378 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11379 "TARGET_32BIT && arm_arch_thumb2"
11380 "rbit%?\\t%0, %1"
11381 [(set_attr "predicable" "yes")
11382 (set_attr "insn" "clz")])
11383
11384(define_expand "ctzsi2"
11385 [(set (match_operand:SI 0 "s_register_operand" "")
11386 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
11387 "TARGET_32BIT && arm_arch_thumb2"
11388 "
30191172 11389 {
11390 rtx tmp = gen_reg_rtx (SImode);
11391 emit_insn (gen_rbitsi2 (tmp, operands[1]));
11392 emit_insn (gen_clzsi2 (operands[0], tmp));
11393 }
099ad98b 11394 DONE;
11395 "
11396)
11397
e1159bbe 11398;; V5E instructions.
331beb1a 11399
11400(define_insn "prefetch"
f4e79814 11401 [(prefetch (match_operand:SI 0 "address_operand" "p")
11402 (match_operand:SI 1 "" "")
11403 (match_operand:SI 2 "" ""))]
25f905c2 11404 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 11405 "pld\\t%a0")
331beb1a 11406
0d66636f 11407;; General predication pattern
11408
11409(define_cond_exec
11410 [(match_operator 0 "arm_comparison_operator"
11411 [(match_operand 1 "cc_register" "")
11412 (const_int 0)])]
25f905c2 11413 "TARGET_32BIT"
0d66636f 11414 ""
11415)
11416
fb94f18b 11417(define_insn "force_register_use"
11418 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11419 ""
fb94f18b 11420 "%@ %0 needed"
02cfc9c9 11421 [(set_attr "length" "0")]
063a05c7 11422)
7db9af5d 11423
4c44712e 11424
11425;; Patterns for exception handling
11426
11427(define_expand "eh_return"
11428 [(use (match_operand 0 "general_operand" ""))]
11429 "TARGET_EITHER"
11430 "
11431 {
25f905c2 11432 if (TARGET_32BIT)
4c44712e 11433 emit_insn (gen_arm_eh_return (operands[0]));
11434 else
11435 emit_insn (gen_thumb_eh_return (operands[0]));
11436 DONE;
11437 }"
11438)
11439
11440;; We can't expand this before we know where the link register is stored.
11441(define_insn_and_split "arm_eh_return"
11442 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11443 VUNSPEC_EH_RETURN)
11444 (clobber (match_scratch:SI 1 "=&r"))]
11445 "TARGET_ARM"
11446 "#"
11447 "&& reload_completed"
11448 [(const_int 0)]
11449 "
11450 {
11451 arm_set_return_address (operands[0], operands[1]);
11452 DONE;
11453 }"
11454)
11455
11456(define_insn_and_split "thumb_eh_return"
11457 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11458 VUNSPEC_EH_RETURN)
11459 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 11460 "TARGET_THUMB1"
4c44712e 11461 "#"
11462 "&& reload_completed"
11463 [(const_int 0)]
11464 "
11465 {
11466 thumb_set_return_address (operands[0], operands[1]);
11467 DONE;
11468 }"
11469)
11470
f655717d 11471\f
11472;; TLS support
11473
11474(define_insn "load_tp_hard"
11475 [(set (match_operand:SI 0 "register_operand" "=r")
11476 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11477 "TARGET_HARD_TP"
11478 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11479 [(set_attr "predicable" "yes")]
11480)
11481
11482;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11483(define_insn "load_tp_soft"
11484 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11485 (clobber (reg:SI LR_REGNUM))
11486 (clobber (reg:SI IP_REGNUM))
11487 (clobber (reg:CC CC_REGNUM))]
11488 "TARGET_SOFT_TP"
11489 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11490 [(set_attr "conds" "clob")]
11491)
11492
f41e4452 11493;; tls descriptor call
11494(define_insn "tlscall"
11495 [(set (reg:SI R0_REGNUM)
11496 (unspec:SI [(reg:SI R0_REGNUM)
11497 (match_operand:SI 0 "" "X")
11498 (match_operand 1 "" "")] UNSPEC_TLS))
11499 (clobber (reg:SI R1_REGNUM))
11500 (clobber (reg:SI LR_REGNUM))
11501 (clobber (reg:SI CC_REGNUM))]
11502 "TARGET_GNU2_TLS"
11503 {
11504 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11505 INTVAL (operands[1]));
11506 return "bl\\t%c0(tlscall)";
11507 }
11508 [(set_attr "conds" "clob")
11509 (set_attr "length" "4")]
11510)
11511
1fe0edab 11512;; For thread pointer builtin
11513(define_expand "get_thread_pointersi"
11514 [(match_operand:SI 0 "s_register_operand" "=r")]
11515 ""
11516 "
11517 {
11518 arm_load_tp (operands[0]);
11519 DONE;
11520 }")
11521
f41e4452 11522;;
11523
aabe09ac 11524;; We only care about the lower 16 bits of the constant
11525;; being inserted into the upper 16 bits of the register.
eca5c984 11526(define_insn "*arm_movtas_ze"
11527 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11528 (const_int 16)
11529 (const_int 16))
11530 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 11531 "arm_arch_thumb2"
aabe09ac 11532 "movt%?\t%0, %L1"
eca5c984 11533 [(set_attr "predicable" "yes")
11534 (set_attr "length" "4")]
11535)
11536
c0fc3696 11537(define_insn "*arm_rev"
a486b499 11538 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11539 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11540 "arm_arch6"
11541 "@
11542 rev\t%0, %1
11543 rev%?\t%0, %1
11544 rev%?\t%0, %1"
11545 [(set_attr "arch" "t1,t2,32")
11546 (set_attr "length" "2,2,4")]
ff82f757 11547)
11548
11549(define_expand "arm_legacy_rev"
11550 [(set (match_operand:SI 2 "s_register_operand" "")
11551 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11552 (const_int 16))
11553 (match_dup 1)))
11554 (set (match_dup 2)
11555 (lshiftrt:SI (match_dup 2)
11556 (const_int 8)))
11557 (set (match_operand:SI 3 "s_register_operand" "")
11558 (rotatert:SI (match_dup 1)
11559 (const_int 8)))
11560 (set (match_dup 2)
11561 (and:SI (match_dup 2)
11562 (const_int -65281)))
11563 (set (match_operand:SI 0 "s_register_operand" "")
11564 (xor:SI (match_dup 3)
11565 (match_dup 2)))]
11566 "TARGET_32BIT"
11567 ""
11568)
11569
11570;; Reuse temporaries to keep register pressure down.
11571(define_expand "thumb_legacy_rev"
11572 [(set (match_operand:SI 2 "s_register_operand" "")
11573 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11574 (const_int 24)))
11575 (set (match_operand:SI 3 "s_register_operand" "")
11576 (lshiftrt:SI (match_dup 1)
11577 (const_int 24)))
11578 (set (match_dup 3)
11579 (ior:SI (match_dup 3)
11580 (match_dup 2)))
11581 (set (match_operand:SI 4 "s_register_operand" "")
11582 (const_int 16))
11583 (set (match_operand:SI 5 "s_register_operand" "")
11584 (rotatert:SI (match_dup 1)
11585 (match_dup 4)))
11586 (set (match_dup 2)
11587 (ashift:SI (match_dup 5)
11588 (const_int 24)))
11589 (set (match_dup 5)
11590 (lshiftrt:SI (match_dup 5)
11591 (const_int 24)))
11592 (set (match_dup 5)
11593 (ior:SI (match_dup 5)
11594 (match_dup 2)))
11595 (set (match_dup 5)
11596 (rotatert:SI (match_dup 5)
11597 (match_dup 4)))
11598 (set (match_operand:SI 0 "s_register_operand" "")
11599 (ior:SI (match_dup 5)
11600 (match_dup 3)))]
11601 "TARGET_THUMB"
11602 ""
11603)
11604
11605(define_expand "bswapsi2"
11606 [(set (match_operand:SI 0 "s_register_operand" "=r")
11607 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11608"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11609"
8d1af482 11610 if (!arm_arch6)
11611 {
11612 rtx op2 = gen_reg_rtx (SImode);
11613 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11614
8d1af482 11615 if (TARGET_THUMB)
11616 {
11617 rtx op4 = gen_reg_rtx (SImode);
11618 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11619
8d1af482 11620 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11621 op2, op3, op4, op5));
11622 }
11623 else
11624 {
11625 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11626 op2, op3));
11627 }
ff82f757 11628
8d1af482 11629 DONE;
11630 }
ff82f757 11631 "
11632)
11633
a486b499 11634;; bswap16 patterns: use revsh and rev16 instructions for the signed
11635;; and unsigned variants, respectively. For rev16, expose
11636;; byte-swapping in the lower 16 bits only.
11637(define_insn "*arm_revsh"
11638 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11639 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11640 "arm_arch6"
11641 "@
11642 revsh\t%0, %1
11643 revsh%?\t%0, %1
11644 revsh%?\t%0, %1"
11645 [(set_attr "arch" "t1,t2,32")
11646 (set_attr "length" "2,2,4")]
11647)
11648
11649(define_insn "*arm_rev16"
11650 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11651 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11652 "arm_arch6"
11653 "@
11654 rev16\t%0, %1
11655 rev16%?\t%0, %1
11656 rev16%?\t%0, %1"
11657 [(set_attr "arch" "t1,t2,32")
11658 (set_attr "length" "2,2,4")]
11659)
11660
11661(define_expand "bswaphi2"
11662 [(set (match_operand:HI 0 "s_register_operand" "=r")
11663 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11664"arm_arch6"
11665""
11666)
11667
1653cf17 11668;; Patterns for LDRD/STRD in Thumb2 mode
11669
11670(define_insn "*thumb2_ldrd"
11671 [(set (match_operand:SI 0 "s_register_operand" "=r")
11672 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11673 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11674 (set (match_operand:SI 3 "s_register_operand" "=r")
11675 (mem:SI (plus:SI (match_dup 1)
11676 (match_operand:SI 4 "const_int_operand" ""))))]
11677 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11678 && current_tune->prefer_ldrd_strd
11679 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11680 && (operands_ok_ldrd_strd (operands[0], operands[3],
11681 operands[1], INTVAL (operands[2]),
11682 false, true))"
11683 "ldrd%?\t%0, %3, [%1, %2]"
11684 [(set_attr "type" "load2")
11685 (set_attr "predicable" "yes")])
11686
11687(define_insn "*thumb2_ldrd_base"
11688 [(set (match_operand:SI 0 "s_register_operand" "=r")
11689 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11690 (set (match_operand:SI 2 "s_register_operand" "=r")
11691 (mem:SI (plus:SI (match_dup 1)
11692 (const_int 4))))]
11693 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11694 && current_tune->prefer_ldrd_strd
11695 && (operands_ok_ldrd_strd (operands[0], operands[2],
11696 operands[1], 0, false, true))"
11697 "ldrd%?\t%0, %2, [%1]"
11698 [(set_attr "type" "load2")
11699 (set_attr "predicable" "yes")])
11700
11701(define_insn "*thumb2_ldrd_base_neg"
11702 [(set (match_operand:SI 0 "s_register_operand" "=r")
11703 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11704 (const_int -4))))
11705 (set (match_operand:SI 2 "s_register_operand" "=r")
11706 (mem:SI (match_dup 1)))]
11707 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11708 && current_tune->prefer_ldrd_strd
11709 && (operands_ok_ldrd_strd (operands[0], operands[2],
11710 operands[1], -4, false, true))"
11711 "ldrd%?\t%0, %2, [%1, #-4]"
11712 [(set_attr "type" "load2")
11713 (set_attr "predicable" "yes")])
11714
11715(define_insn "*thumb2_strd"
11716 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11717 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11718 (match_operand:SI 2 "s_register_operand" "r"))
11719 (set (mem:SI (plus:SI (match_dup 0)
11720 (match_operand:SI 3 "const_int_operand" "")))
11721 (match_operand:SI 4 "s_register_operand" "r"))]
11722 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11723 && current_tune->prefer_ldrd_strd
11724 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11725 && (operands_ok_ldrd_strd (operands[2], operands[4],
11726 operands[0], INTVAL (operands[1]),
11727 false, false))"
11728 "strd%?\t%2, %4, [%0, %1]"
11729 [(set_attr "type" "store2")
11730 (set_attr "predicable" "yes")])
11731
11732(define_insn "*thumb2_strd_base"
11733 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11734 (match_operand:SI 1 "s_register_operand" "r"))
11735 (set (mem:SI (plus:SI (match_dup 0)
11736 (const_int 4)))
11737 (match_operand:SI 2 "s_register_operand" "r"))]
11738 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11739 && current_tune->prefer_ldrd_strd
11740 && (operands_ok_ldrd_strd (operands[1], operands[2],
11741 operands[0], 0, false, false))"
11742 "strd%?\t%1, %2, [%0]"
11743 [(set_attr "type" "store2")
11744 (set_attr "predicable" "yes")])
11745
11746(define_insn "*thumb2_strd_base_neg"
11747 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11748 (const_int -4)))
11749 (match_operand:SI 1 "s_register_operand" "r"))
11750 (set (mem:SI (match_dup 0))
11751 (match_operand:SI 2 "s_register_operand" "r"))]
11752 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11753 && current_tune->prefer_ldrd_strd
11754 && (operands_ok_ldrd_strd (operands[1], operands[2],
11755 operands[0], -4, false, false))"
11756 "strd%?\t%1, %2, [%0, #-4]"
11757 [(set_attr "type" "store2")
11758 (set_attr "predicable" "yes")])
11759
11760
320ea44d 11761;; Load the load/store multiple patterns
11762(include "ldmstm.md")
426be8c5 11763
11764;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11765;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11766(define_insn "*load_multiple"
11767 [(match_parallel 0 "load_multiple_operation"
11768 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11769 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11770 ])]
11771 "TARGET_32BIT"
11772 "*
11773 {
11774 arm_output_multireg_pop (operands, /*return_pc=*/false,
11775 /*cond=*/const_true_rtx,
11776 /*reverse=*/false,
11777 /*update=*/false);
11778 return \"\";
11779 }
11780 "
11781 [(set_attr "predicable" "yes")]
11782)
11783
d98a3884 11784;; Vector bits common to IWMMXT and Neon
11785(include "vec-common.md")
755eb2b4 11786;; Load the Intel Wireless Multimedia Extension patterns
11787(include "iwmmxt.md")
a2cd141b 11788;; Load the VFP co-processor patterns
11789(include "vfp.md")
25f905c2 11790;; Thumb-2 patterns
11791(include "thumb2.md")
d98a3884 11792;; Neon patterns
11793(include "neon.md")
06df6b17 11794;; Synchronization Primitives
11795(include "sync.md")
bbbe4599 11796;; Fixed-point patterns
11797(include "arm-fixed.md")