]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
In gcc/testsuite/:
[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,
7cf0dbf3 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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
31;; Register numbers
32(define_constants
ccd90aaa 33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
e1159bbe 35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
ccd90aaa 39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
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)
e1159bbe 51
9c08d1fa 52;; UNSPEC Usage:
8a18b90c 53;; Note: sin and cos are no-longer used.
e7d6d136 54;; Unspec enumerators for Neon are defined in neon.md.
e1159bbe 55
e7d6d136 56(define_c_enum "unspec" [
57 UNSPEC_SIN ; `sin' operation (MODE_FLOAT):
58 ; operand 0 is the result,
59 ; operand 1 the parameter.
60 UNPSEC_COS ; `cos' operation (MODE_FLOAT):
61 ; operand 0 is the result,
62 ; operand 1 the parameter.
63 UNSPEC_PUSH_MULT ; `push multiple' operation:
64 ; operand 0 is the first register,
65 ; subsequent registers are in parallel (use ...)
66 ; expressions.
67 UNSPEC_PIC_SYM ; A symbol that has been treated properly for pic
68 ; usage, that is, we will add the pic_register
69 ; value to it before trying to dereference it.
70 UNSPEC_PIC_BASE ; Add PC and all but the last operand together,
71 ; The last operand is the number of a PIC_LABEL
72 ; that points at the containing instruction.
73 UNSPEC_PRLG_STK ; A special barrier that prevents frame accesses
74 ; being scheduled before the stack adjustment insn.
75 UNSPEC_PROLOGUE_USE ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
79 ; register to "use".
80 UNSPEC_CHECK_ARCH ; Set CCs to indicate 26-bit or 32-bit mode.
81 UNSPEC_WSHUFH ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 UNSPEC_WACC ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 UNSPEC_TMOVMSK ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 UNSPEC_WSAD ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 UNSPEC_WSADZ ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 UNSPEC_WMACS ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 UNSPEC_WMACU ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 UNSPEC_WMACSZ ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 UNSPEC_WMACUZ ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 UNSPEC_CLRDI ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 UNSPEC_WMADDS ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 UNSPEC_WMADDU ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 UNSPEC_TLS ; A symbol that has been treated properly for TLS usage.
94 UNSPEC_PIC_LABEL ; A label used for PIC access that does not appear in the
95 ; instruction stream.
96 UNSPEC_STACK_ALIGN ; Doubleword aligned stack pointer. Used to
97 ; generate correct unwind information.
98 UNSPEC_PIC_OFFSET ; A symbolic 12-bit OFFSET that has been treated
99 ; correctly for PIC usage.
851d9296 100 UNSPEC_GOTSYM_OFF ; The offset of the start of the GOT from a
e7d6d136 101 ; a given symbolic address.
102 UNSPEC_THUMB1_CASESI ; A Thumb1 compressed dispatch-table call.
103 UNSPEC_RBIT ; rbit operation.
104 UNSPEC_SYMBOL_OFFSET ; The offset of the start of the symbol from
105 ; another symbolic address.
106 UNSPEC_MEMORY_BARRIER ; Represent a memory barrier.
107])
e1159bbe 108
215b30b3 109;; UNSPEC_VOLATILE Usage:
e1159bbe 110
e7d6d136 111(define_c_enum "unspecv" [
112 VUNSPEC_BLOCKAGE ; `blockage' insn to prevent scheduling across an
113 ; insn in the code.
114 VUNSPEC_EPILOGUE ; `epilogue' insn, used to represent any part of the
115 ; instruction epilogue sequence that isn't expanded
116 ; into normal RTL. Used for both normal and sibcall
117 ; epilogues.
118 VUNSPEC_ALIGN ; `align' insn. Used at the head of a minipool table
119 ; for inlined constants.
120 VUNSPEC_POOL_END ; `end-of-table'. Used to mark the end of a minipool
121 ; table.
122 VUNSPEC_POOL_1 ; `pool-entry(1)'. An entry in the constant pool for
123 ; an 8-bit object.
124 VUNSPEC_POOL_2 ; `pool-entry(2)'. An entry in the constant pool for
125 ; a 16-bit object.
126 VUNSPEC_POOL_4 ; `pool-entry(4)'. An entry in the constant pool for
127 ; a 32-bit object.
128 VUNSPEC_POOL_8 ; `pool-entry(8)'. An entry in the constant pool for
129 ; a 64-bit object.
130 VUNSPEC_POOL_16 ; `pool-entry(16)'. An entry in the constant pool for
131 ; a 128-bit object.
132 VUNSPEC_TMRC ; Used by the iWMMXt TMRC instruction.
133 VUNSPEC_TMCR ; Used by the iWMMXt TMCR instruction.
134 VUNSPEC_ALIGN8 ; 8-byte alignment version of VUNSPEC_ALIGN
135 VUNSPEC_WCMP_EQ ; Used by the iWMMXt WCMPEQ instructions
136 VUNSPEC_WCMP_GTU ; Used by the iWMMXt WCMPGTU instructions
137 VUNSPEC_WCMP_GT ; Used by the iwMMXT WCMPGT instructions
138 VUNSPEC_EH_RETURN ; Use to override the return address for exception
139 ; handling.
140 VUNSPEC_SYNC_COMPARE_AND_SWAP ; Represent an atomic compare swap.
141 VUNSPEC_SYNC_LOCK ; Represent a sync_lock_test_and_set.
142 VUNSPEC_SYNC_OP ; Represent a sync_<op>
143 VUNSPEC_SYNC_NEW_OP ; Represent a sync_new_<op>
144 VUNSPEC_SYNC_OLD_OP ; Represent a sync_old_<op>
145])
b11cae9e 146\f
e1159bbe 147;;---------------------------------------------------------------------------
9c08d1fa 148;; Attributes
149
a651f34d 150;; Processor type. This is created automatically from arm-cores.def.
151(include "arm-tune.md")
152
215b30b3 153; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
154; generating ARM code. This is used to control the length of some insn
155; patterns that share the same RTL in both ARM and Thumb code.
1c494086 156(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 157
ef51b8e1 158; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
159(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
160
747b7458 161; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
162(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
163
331beb1a 164;; Operand number of an input operand that is shifted. Zero if the
165;; given instruction does not shift one of its input operands.
331beb1a 166(define_attr "shift" "" (const_int 0))
167
3d91c5d6 168; Floating Point Unit. If we only have floating point emulation, then there
169; is no point in scheduling the floating point insns. (Well, for best
170; performance we should try and group them together).
4fea7d65 171(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 172 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 173
06df6b17 174(define_attr "sync_result" "none,0,1,2,3,4,5" (const_string "none"))
175(define_attr "sync_memory" "none,0,1,2,3,4,5" (const_string "none"))
176(define_attr "sync_required_value" "none,0,1,2,3,4,5" (const_string "none"))
177(define_attr "sync_new_value" "none,0,1,2,3,4,5" (const_string "none"))
178(define_attr "sync_t1" "none,0,1,2,3,4,5" (const_string "none"))
179(define_attr "sync_t2" "none,0,1,2,3,4,5" (const_string "none"))
180(define_attr "sync_release_barrier" "yes,no" (const_string "yes"))
181(define_attr "sync_op" "none,add,sub,ior,xor,and,nand"
182 (const_string "none"))
183
094e994f 184; LENGTH of an instruction (in bytes)
06df6b17 185(define_attr "length" ""
186 (cond [(not (eq_attr "sync_memory" "none"))
187 (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
188 ] (const_int 4)))
9c08d1fa 189
d5d4dc8d 190; The architecture which supports the instruction (or alternative).
191; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
192; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
193; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
194; arm_arch6. This attribute is used to compute attribute "enabled",
195; use type "any" to enable an alternative in all cases.
a651f34d 196(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,nota8"
d5d4dc8d 197 (const_string "any"))
198
199(define_attr "arch_enabled" "no,yes"
200 (cond [(eq_attr "arch" "any")
201 (const_string "yes")
202
203 (and (eq_attr "arch" "a")
204 (ne (symbol_ref "TARGET_ARM") (const_int 0)))
205 (const_string "yes")
206
207 (and (eq_attr "arch" "t")
208 (ne (symbol_ref "TARGET_THUMB") (const_int 0)))
209 (const_string "yes")
210
211 (and (eq_attr "arch" "t1")
212 (ne (symbol_ref "TARGET_THUMB1") (const_int 0)))
213 (const_string "yes")
214
215 (and (eq_attr "arch" "t2")
216 (ne (symbol_ref "TARGET_THUMB2") (const_int 0)))
217 (const_string "yes")
218
219 (and (eq_attr "arch" "32")
220 (ne (symbol_ref "TARGET_32BIT") (const_int 0)))
221 (const_string "yes")
222
223 (and (eq_attr "arch" "v6")
224 (ne (symbol_ref "(TARGET_32BIT && arm_arch6)") (const_int 0)))
225 (const_string "yes")
226
227 (and (eq_attr "arch" "nov6")
228 (ne (symbol_ref "(TARGET_32BIT && !arm_arch6)") (const_int 0)))
a651f34d 229 (const_string "yes")
230
231 (and (eq_attr "arch" "onlya8")
232 (eq_attr "tune" "cortexa8"))
233 (const_string "yes")
234
235 (and (eq_attr "arch" "nota8")
236 (not (eq_attr "tune" "cortexa8")))
d5d4dc8d 237 (const_string "yes")]
238 (const_string "no")))
239
240; Allows an insn to disable certain alternatives for reasons other than
241; arch support.
242(define_attr "insn_enabled" "no,yes"
243 (const_string "yes"))
244
245; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 246 (define_attr "enabled" "no,yes"
247 (if_then_else (eq_attr "insn_enabled" "yes")
248 (if_then_else (eq_attr "arch_enabled" "yes")
249 (const_string "yes")
250 (const_string "no"))
251 (const_string "no")))
d5d4dc8d 252
56d27660 253; POOL_RANGE is how far away from a constant pool entry that this insn
254; can be placed. If the distance is zero, then this insn will never
255; reference the pool.
cffb2a26 256; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
257; before its address.
cde1623a 258(define_attr "arm_pool_range" "" (const_int 0))
259(define_attr "thumb2_pool_range" "" (const_int 0))
260(define_attr "arm_neg_pool_range" "" (const_int 0))
261(define_attr "thumb2_neg_pool_range" "" (const_int 0))
262
263(define_attr "pool_range" ""
264 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
265 (attr "arm_pool_range")))
266(define_attr "neg_pool_range" ""
267 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
268 (attr "arm_neg_pool_range")))
56d27660 269
215b30b3 270; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 271; If such an insn references the pool, then we have no way of knowing how,
272; so use the most conservative value for pool_range.
9c08d1fa 273(define_asm_attributes
4d7a8451 274 [(set_attr "conds" "clob")
275 (set_attr "length" "4")
276 (set_attr "pool_range" "250")])
9c08d1fa 277
a2cd141b 278;; The instruction used to implement a particular pattern. This
279;; information is used by pipeline descriptions to provide accurate
280;; scheduling information.
281
282(define_attr "insn"
934a1e72 283 "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,other"
a2cd141b 284 (const_string "other"))
285
9c08d1fa 286; TYPE attribute is used to detect floating point instructions which, if
287; running on a co-processor can run in parallel with other, basic instructions
288; If write-buffer scheduling is enabled then it can also be used in the
289; scheduling of writes.
290
291; Classification of each insn
607978a1 292; Note: vfp.md has different meanings for some of these, and some further
293; types as well. See that file for details.
a2cd141b 294; alu any alu instruction that doesn't hit memory or fp
295; regs or have a shifted source operand
296; alu_shift any data instruction that doesn't hit memory or fp
297; regs, but has a source operand shifted by a constant
298; alu_shift_reg any data instruction that doesn't hit memory or fp
299; regs, but has a source operand shifted by a register value
f7fbdd4a 300; mult a multiply instruction
9c08d1fa 301; block blockage insn, this blocks all functional units
302; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 303; fdivd DFmode floating point division
304; fdivs SFmode floating point division
305; fmul Floating point multiply
306; ffmul Fast floating point multiply
307; farith Floating point arithmetic (4 cycle)
308; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 309; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 310; even on a machine with an fpa.
013b9671 311; f_fpa_load a floating point load from memory. Only for the FPA.
312; f_fpa_store a floating point store to memory. Only for the FPA.
313; f_load[sd] A single/double load from memory. Used for VFP unit.
314; f_store[sd] A single/double store to memory. Used for VFP unit.
c0e1af52 315; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 316; f_mem_r a transfer of a floating point register to a real reg via mem
317; r_mem_f the reverse of f_mem_r
318; f_2_r fast transfer float to arm (no memory needed)
319; r_2_f fast transfer arm to float
c0e1af52 320; f_cvt convert floating<->integral
a2cd141b 321; branch a branch
9c08d1fa 322; call a subroutine call
a2cd141b 323; load_byte load byte(s) from memory to arm registers
324; load1 load 1 word from memory to arm registers
325; load2 load 2 words from memory to arm registers
326; load3 load 3 words from memory to arm registers
327; load4 load 4 words from memory to arm registers
328; store store 1 word to memory from arm registers
9c08d1fa 329; store2 store 2 words
330; store3 store 3 words
a2cd141b 331; store4 store 4 (or more) words
2c6c7d8b 332; Additions for Cirrus Maverick co-processor:
333; mav_farith Floating point arithmetic (4 cycle)
334; mav_dmult Double multiplies (7 cycle)
9c08d1fa 335;
bcaec148 336
9c08d1fa 337(define_attr "type"
013b9671 338 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_fpa_load,f_fpa_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
a2cd141b 339 (if_then_else
340 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
341 (const_string "mult")
342 (const_string "alu")))
9c08d1fa 343
9888ad6d 344; Load scheduling, set from the arm_ld_sched variable
4c834714 345; initialized by arm_option_override()
9888ad6d 346(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 347
c52acdd2 348;; Classification of NEON instructions for scheduling purposes.
349;; Do not set this attribute and the "type" attribute together in
350;; any one instruction pattern.
351(define_attr "neon_type"
352 "neon_int_1,\
353 neon_int_2,\
354 neon_int_3,\
355 neon_int_4,\
356 neon_int_5,\
357 neon_vqneg_vqabs,\
358 neon_vmov,\
359 neon_vaba,\
360 neon_vsma,\
361 neon_vaba_qqq,\
362 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
363 neon_mul_qqq_8_16_32_ddd_32,\
364 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
365 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
366 neon_mla_qqq_8_16,\
367 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
368 neon_mla_qqq_32_qqd_32_scalar,\
369 neon_mul_ddd_16_scalar_32_16_long_scalar,\
370 neon_mul_qqd_32_scalar,\
371 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
372 neon_shift_1,\
373 neon_shift_2,\
374 neon_shift_3,\
375 neon_vshl_ddd,\
376 neon_vqshl_vrshl_vqrshl_qqq,\
377 neon_vsra_vrsra,\
378 neon_fp_vadd_ddd_vabs_dd,\
379 neon_fp_vadd_qqq_vabs_qq,\
380 neon_fp_vsum,\
381 neon_fp_vmul_ddd,\
382 neon_fp_vmul_qqd,\
383 neon_fp_vmla_ddd,\
384 neon_fp_vmla_qqq,\
385 neon_fp_vmla_ddd_scalar,\
386 neon_fp_vmla_qqq_scalar,\
387 neon_fp_vrecps_vrsqrts_ddd,\
388 neon_fp_vrecps_vrsqrts_qqq,\
389 neon_bp_simple,\
390 neon_bp_2cycle,\
391 neon_bp_3cycle,\
392 neon_ldr,\
393 neon_str,\
394 neon_vld1_1_2_regs,\
395 neon_vld1_3_4_regs,\
396 neon_vld2_2_regs_vld1_vld2_all_lanes,\
397 neon_vld2_4_regs,\
398 neon_vld3_vld4,\
399 neon_vst1_1_2_regs_vst2_2_regs,\
400 neon_vst1_3_4_regs,\
401 neon_vst2_4_regs_vst3_vst4,\
402 neon_vst3_vst4,\
403 neon_vld1_vld2_lane,\
404 neon_vld3_vld4_lane,\
405 neon_vst1_vst2_lane,\
406 neon_vst3_vst4_lane,\
407 neon_vld3_vld4_all_lanes,\
408 neon_mcr,\
409 neon_mcr_2_mcrr,\
410 neon_mrc,\
411 neon_mrrc,\
412 neon_ldm_2,\
413 neon_stm_2,\
414 none"
415 (const_string "none"))
416
f7fbdd4a 417; condition codes: this one is used by final_prescan_insn to speed up
418; conditionalizing instructions. It saves having to scan the rtl to see if
419; it uses or alters the condition codes.
215b30b3 420;
f7fbdd4a 421; USE means that the condition codes are used by the insn in the process of
215b30b3 422; outputting code, this means (at present) that we can't use the insn in
423; inlined branches
424;
f7fbdd4a 425; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 426; well defined manner.
427;
f7fbdd4a 428; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 429; they are altered at all
430;
ad6d3e2a 431; UNCONDITIONAL means the instruction can not be conditionally executed and
432; that the instruction does not use or alter the condition codes.
c52acdd2 433;
ad6d3e2a 434; NOCOND means that the instruction does not use or alter the condition
435; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 436
b0694be0 437(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 438 (if_then_else
439 (ior (eq_attr "is_thumb1" "yes")
440 (eq_attr "type" "call"))
c1a66faf 441 (const_string "clob")
c52acdd2 442 (if_then_else (eq_attr "neon_type" "none")
443 (const_string "nocond")
444 (const_string "unconditional"))))
f7fbdd4a 445
215b30b3 446; Predicable means that the insn can be conditionally executed based on
447; an automatically added predicate (additional patterns are generated by
448; gen...). We default to 'no' because no Thumb patterns match this rule
449; and not all ARM patterns do.
0d66636f 450(define_attr "predicable" "no,yes" (const_string "no"))
451
129a2fe4 452; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
453; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 454; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 455; affect the schedule).
74a71f7d 456(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 457
215b30b3 458; WRITE_CONFLICT implies that a read following an unrelated write is likely
459; to stall the processor. Used with model_wbuf above.
9c08d1fa 460(define_attr "write_conflict" "no,yes"
461 (if_then_else (eq_attr "type"
013b9671 462 "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 463 (const_string "yes")
464 (const_string "no")))
465
215b30b3 466; Classify the insns into those that take one cycle and those that take more
467; than one on the main cpu execution unit.
f7fbdd4a 468(define_attr "core_cycles" "single,multi"
469 (if_then_else (eq_attr "type"
a2cd141b 470 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 471 (const_string "single")
472 (const_string "multi")))
473
cffb2a26 474;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 475;; distant label. Only applicable to Thumb code.
cffb2a26 476(define_attr "far_jump" "yes,no" (const_string "no"))
477
d51f92df 478
25f905c2 479;; The number of machine instructions this pattern expands to.
480;; Used for Thumb-2 conditional execution.
481(define_attr "ce_count" "" (const_int 1))
482
d51f92df 483;;---------------------------------------------------------------------------
fd781bb2 484;; Mode iterators
d51f92df 485
3de0dec6 486(include "iterators.md")
03770691 487
d51f92df 488;;---------------------------------------------------------------------------
489;; Predicates
490
9c9db025 491(include "predicates.md")
234f6557 492(include "constraints.md")
9c9db025 493
a2cd141b 494;;---------------------------------------------------------------------------
495;; Pipeline descriptions
215b30b3 496
e3879fd0 497(define_attr "tune_cortexr4" "yes,no"
498 (const (if_then_else
7d3cda8c 499 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 500 (const_string "yes")
501 (const_string "no"))))
502
a2cd141b 503;; True if the generic scheduling description should be used.
504
505(define_attr "generic_sched" "yes,no"
2546d93a 506 (const (if_then_else
0e266d06 507 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexm4")
2546d93a 508 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 509 (const_string "no")
510 (const_string "yes"))))
511
c0e1af52 512(define_attr "generic_vfp" "yes,no"
513 (const (if_then_else
514 (and (eq_attr "fpu" "vfp")
2546d93a 515 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 516 (eq_attr "tune_cortexr4" "no"))
c0e1af52 517 (const_string "yes")
518 (const_string "no"))))
519
a2cd141b 520(include "arm-generic.md")
521(include "arm926ejs.md")
c0e1af52 522(include "arm1020e.md")
a2cd141b 523(include "arm1026ejs.md")
524(include "arm1136jfs.md")
0e266d06 525(include "fa526.md")
526(include "fa606te.md")
527(include "fa626te.md")
528(include "fmp626.md")
529(include "fa726te.md")
3f1e069f 530(include "cortex-a5.md")
bcaec148 531(include "cortex-a8.md")
036068af 532(include "cortex-a9.md")
934a1e72 533(include "cortex-r4.md")
e3879fd0 534(include "cortex-r4f.md")
2546d93a 535(include "cortex-m4.md")
536(include "cortex-m4-fpu.md")
55e3ada8 537(include "vfp11.md")
3586df96 538
9c08d1fa 539\f
215b30b3 540;;---------------------------------------------------------------------------
e1159bbe 541;; Insn patterns
542;;
a0f94409 543;; Addition insns.
215b30b3 544
9c08d1fa 545;; Note: For DImode insns, there is normally no reason why operands should
546;; not be in the same register, what we don't want is for something being
547;; written to partially overlap something that is an input.
7d57ec45 548;; Cirrus 64bit additions should not be split because we have a native
549;; 64bit addition instructions.
9c08d1fa 550
cffb2a26 551(define_expand "adddi3"
552 [(parallel
215b30b3 553 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 554 (plus:DI (match_operand:DI 1 "s_register_operand" "")
555 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 556 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 557 "TARGET_EITHER"
558 "
a2cd141b 559 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 560 {
561 if (!cirrus_fp_register (operands[0], DImode))
562 operands[0] = force_reg (DImode, operands[0]);
563 if (!cirrus_fp_register (operands[1], DImode))
564 operands[1] = force_reg (DImode, operands[1]);
565 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
566 DONE;
567 }
568
25f905c2 569 if (TARGET_THUMB1)
cffb2a26 570 {
571 if (GET_CODE (operands[1]) != REG)
bc5a93af 572 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 573 if (GET_CODE (operands[2]) != REG)
bc5a93af 574 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 575 }
576 "
577)
578
25f905c2 579(define_insn "*thumb1_adddi3"
cffb2a26 580 [(set (match_operand:DI 0 "register_operand" "=l")
581 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 582 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 583 (clobber (reg:CC CC_REGNUM))
cffb2a26 584 ]
25f905c2 585 "TARGET_THUMB1"
cffb2a26 586 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
587 [(set_attr "length" "4")]
588)
589
a0f94409 590(define_insn_and_split "*arm_adddi3"
cffb2a26 591 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 592 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
593 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 594 (clobber (reg:CC CC_REGNUM))]
94829feb 595 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 596 "#"
94829feb 597 "TARGET_32BIT && reload_completed
598 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 599 [(parallel [(set (reg:CC_C CC_REGNUM)
600 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
601 (match_dup 1)))
602 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 603 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
604 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 605 "
606 {
607 operands[3] = gen_highpart (SImode, operands[0]);
608 operands[0] = gen_lowpart (SImode, operands[0]);
609 operands[4] = gen_highpart (SImode, operands[1]);
610 operands[1] = gen_lowpart (SImode, operands[1]);
611 operands[5] = gen_highpart (SImode, operands[2]);
612 operands[2] = gen_lowpart (SImode, operands[2]);
613 }"
cffb2a26 614 [(set_attr "conds" "clob")
615 (set_attr "length" "8")]
616)
9c08d1fa 617
a0f94409 618(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 619 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
620 (plus:DI (sign_extend:DI
97499065 621 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 622 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 623 (clobber (reg:CC CC_REGNUM))]
25f905c2 624 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 625 "#"
25f905c2 626 "TARGET_32BIT && reload_completed"
a0f94409 627 [(parallel [(set (reg:CC_C CC_REGNUM)
628 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
629 (match_dup 1)))
630 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 631 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 632 (const_int 31))
080c0b9a 633 (match_dup 4))
634 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 635 "
636 {
637 operands[3] = gen_highpart (SImode, operands[0]);
638 operands[0] = gen_lowpart (SImode, operands[0]);
639 operands[4] = gen_highpart (SImode, operands[1]);
640 operands[1] = gen_lowpart (SImode, operands[1]);
641 operands[2] = gen_lowpart (SImode, operands[2]);
642 }"
215b30b3 643 [(set_attr "conds" "clob")
644 (set_attr "length" "8")]
645)
9c08d1fa 646
a0f94409 647(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 648 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
649 (plus:DI (zero_extend:DI
97499065 650 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 651 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 652 (clobber (reg:CC CC_REGNUM))]
25f905c2 653 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 654 "#"
25f905c2 655 "TARGET_32BIT && reload_completed"
a0f94409 656 [(parallel [(set (reg:CC_C CC_REGNUM)
657 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
658 (match_dup 1)))
659 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 660 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
661 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 662 "
663 {
664 operands[3] = gen_highpart (SImode, operands[0]);
665 operands[0] = gen_lowpart (SImode, operands[0]);
666 operands[4] = gen_highpart (SImode, operands[1]);
667 operands[1] = gen_lowpart (SImode, operands[1]);
668 operands[2] = gen_lowpart (SImode, operands[2]);
669 }"
cffb2a26 670 [(set_attr "conds" "clob")
671 (set_attr "length" "8")]
672)
b11cae9e 673
87b22bf7 674(define_expand "addsi3"
cffb2a26 675 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 676 (plus:SI (match_operand:SI 1 "s_register_operand" "")
677 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 678 "TARGET_EITHER"
87b22bf7 679 "
25f905c2 680 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 681 {
96f57e36 682 arm_split_constant (PLUS, SImode, NULL_RTX,
683 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 684 optimize && can_create_pseudo_p ());
87b22bf7 685 DONE;
686 }
cffb2a26 687 "
688)
87b22bf7 689
5bd751ff 690; If there is a scratch available, this will be faster than synthesizing the
a0f94409 691; addition.
692(define_peephole2
693 [(match_scratch:SI 3 "r")
372575c7 694 (set (match_operand:SI 0 "arm_general_register_operand" "")
695 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 696 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 697 "TARGET_32BIT &&
a0f94409 698 !(const_ok_for_arm (INTVAL (operands[2]))
699 || const_ok_for_arm (-INTVAL (operands[2])))
700 && const_ok_for_arm (~INTVAL (operands[2]))"
701 [(set (match_dup 3) (match_dup 2))
702 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
703 ""
704)
87b22bf7 705
2f02c19f 706;; The r/r/k alternative is required when reloading the address
707;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
708;; put the duplicated register first, and not try the commutative version.
a0f94409 709(define_insn_and_split "*arm_addsi3"
bccb5444 710 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k,r")
711 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
712 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
25f905c2 713 "TARGET_32BIT"
5565501b 714 "@
715 add%?\\t%0, %1, %2
aaa37ad6 716 add%?\\t%0, %1, %2
2f02c19f 717 add%?\\t%0, %2, %1
aaa37ad6 718 sub%?\\t%0, %1, #%n2
87b22bf7 719 sub%?\\t%0, %1, #%n2
720 #"
a3ffc315 721 "TARGET_32BIT
722 && GET_CODE (operands[2]) == CONST_INT
a0f94409 723 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 724 || const_ok_for_arm (-INTVAL (operands[2])))
725 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 726 [(clobber (const_int 0))]
727 "
96f57e36 728 arm_split_constant (PLUS, SImode, curr_insn,
729 INTVAL (operands[2]), operands[0],
a0f94409 730 operands[1], 0);
731 DONE;
732 "
2f02c19f 733 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 734 (set_attr "predicable" "yes")]
cffb2a26 735)
736
0bdb6455 737(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 738 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
739 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
740 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 741 "TARGET_THUMB1"
cffb2a26 742 "*
0d66636f 743 static const char * const asms[] =
cffb2a26 744 {
745 \"add\\t%0, %0, %2\",
746 \"sub\\t%0, %0, #%n2\",
747 \"add\\t%0, %1, %2\",
748 \"add\\t%0, %0, %2\",
749 \"add\\t%0, %0, %2\",
750 \"add\\t%0, %1, %2\",
0bdb6455 751 \"add\\t%0, %1, %2\",
752 \"#\",
bf7bc2f6 753 \"#\",
0bdb6455 754 \"#\"
cffb2a26 755 };
756 if ((which_alternative == 2 || which_alternative == 6)
757 && GET_CODE (operands[2]) == CONST_INT
758 && INTVAL (operands[2]) < 0)
759 return \"sub\\t%0, %1, #%n2\";
760 return asms[which_alternative];
761 "
0bdb6455 762 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 763 && ((operands[1] != stack_pointer_rtx
764 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
765 || (operands[1] == stack_pointer_rtx
766 && INTVAL (operands[2]) > 1020))"
0bdb6455 767 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
768 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
769 {
770 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 771 if (operands[1] == stack_pointer_rtx)
772 offset -= 1020;
773 else
774 {
775 if (offset > 255)
776 offset = 255;
777 else if (offset < -255)
778 offset = -255;
779 }
0bdb6455 780 operands[3] = GEN_INT (offset);
781 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
782 }
bf7bc2f6 783 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 784)
785
786;; Reloading and elimination of the frame pointer can
787;; sometimes cause this optimization to be missed.
a0f94409 788(define_peephole2
372575c7 789 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 790 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 791 (set (match_dup 0)
372575c7 792 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 793 "TARGET_THUMB1
cffb2a26 794 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
795 && (INTVAL (operands[1]) & 3) == 0"
372575c7 796 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 797 ""
cffb2a26 798)
b11cae9e 799
90c2bcf0 800(define_insn "addsi3_compare0"
bd5b4116 801 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 802 (compare:CC_NOOV
215b30b3 803 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
804 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 805 (const_int 0)))
806 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 807 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 808 "TARGET_ARM"
5565501b 809 "@
25f905c2 810 add%.\\t%0, %1, %2
811 sub%.\\t%0, %1, #%n2"
cffb2a26 812 [(set_attr "conds" "set")]
813)
9c08d1fa 814
aea4c774 815(define_insn "*addsi3_compare0_scratch"
bd5b4116 816 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 817 (compare:CC_NOOV
215b30b3 818 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
819 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 820 (const_int 0)))]
ec792a7b 821 "TARGET_ARM"
cffb2a26 822 "@
823 cmn%?\\t%0, %1
824 cmp%?\\t%0, #%n1"
0d66636f 825 [(set_attr "conds" "set")]
826)
cffb2a26 827
aed179ae 828(define_insn "*compare_negsi_si"
829 [(set (reg:CC_Z CC_REGNUM)
830 (compare:CC_Z
831 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
832 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 833 "TARGET_32BIT"
aed179ae 834 "cmn%?\\t%1, %0"
0d66636f 835 [(set_attr "conds" "set")]
836)
aea4c774 837
203c488f 838;; This is the canonicalization of addsi3_compare0_for_combiner when the
839;; addend is a constant.
840(define_insn "*cmpsi2_addneg"
841 [(set (reg:CC CC_REGNUM)
842 (compare:CC
843 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 844 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 845 (set (match_operand:SI 0 "s_register_operand" "=r,r")
846 (plus:SI (match_dup 1)
2a977b78 847 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 848 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 849 "@
2a977b78 850 add%.\\t%0, %1, %3
851 sub%.\\t%0, %1, #%n3"
203c488f 852 [(set_attr "conds" "set")]
853)
854
855;; Convert the sequence
856;; sub rd, rn, #1
857;; cmn rd, #1 (equivalent to cmp rd, #-1)
858;; bne dest
859;; into
860;; subs rd, rn, #1
861;; bcs dest ((unsigned)rn >= 1)
862;; similarly for the beq variant using bcc.
863;; This is a common looping idiom (while (n--))
864(define_peephole2
372575c7 865 [(set (match_operand:SI 0 "arm_general_register_operand" "")
866 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 867 (const_int -1)))
868 (set (match_operand 2 "cc_register" "")
869 (compare (match_dup 0) (const_int -1)))
870 (set (pc)
871 (if_then_else (match_operator 3 "equality_operator"
872 [(match_dup 2) (const_int 0)])
873 (match_operand 4 "" "")
874 (match_operand 5 "" "")))]
25f905c2 875 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 876 [(parallel[
877 (set (match_dup 2)
878 (compare:CC
879 (match_dup 1) (const_int 1)))
880 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
881 (set (pc)
882 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
883 (match_dup 4)
884 (match_dup 5)))]
885 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
886 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
887 ? GEU : LTU),
888 VOIDmode,
889 operands[2], const0_rtx);"
890)
891
ebcc79bc 892;; The next four insns work because they compare the result with one of
893;; the operands, and we know that the use of the condition code is
894;; either GEU or LTU, so we can use the carry flag from the addition
895;; instead of doing the compare a second time.
896(define_insn "*addsi3_compare_op1"
bd5b4116 897 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 898 (compare:CC_C
899 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
900 (match_operand:SI 2 "arm_add_operand" "rI,L"))
901 (match_dup 1)))
902 (set (match_operand:SI 0 "s_register_operand" "=r,r")
903 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 904 "TARGET_32BIT"
ebcc79bc 905 "@
25f905c2 906 add%.\\t%0, %1, %2
907 sub%.\\t%0, %1, #%n2"
0d66636f 908 [(set_attr "conds" "set")]
909)
ebcc79bc 910
911(define_insn "*addsi3_compare_op2"
bd5b4116 912 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 913 (compare:CC_C
914 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
915 (match_operand:SI 2 "arm_add_operand" "rI,L"))
916 (match_dup 2)))
5565501b 917 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 918 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 919 "TARGET_32BIT"
5565501b 920 "@
25f905c2 921 add%.\\t%0, %1, %2
922 sub%.\\t%0, %1, #%n2"
0d66636f 923 [(set_attr "conds" "set")]
924)
9c08d1fa 925
ebcc79bc 926(define_insn "*compare_addsi2_op0"
bd5b4116 927 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 928 (compare:CC_C
929 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
930 (match_operand:SI 1 "arm_add_operand" "rI,L"))
931 (match_dup 0)))]
25f905c2 932 "TARGET_32BIT"
ebcc79bc 933 "@
934 cmn%?\\t%0, %1
935 cmp%?\\t%0, #%n1"
0d66636f 936 [(set_attr "conds" "set")]
937)
ebcc79bc 938
939(define_insn "*compare_addsi2_op1"
bd5b4116 940 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 941 (compare:CC_C
942 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
943 (match_operand:SI 1 "arm_add_operand" "rI,L"))
944 (match_dup 1)))]
25f905c2 945 "TARGET_32BIT"
ebcc79bc 946 "@
947 cmn%?\\t%0, %1
948 cmp%?\\t%0, #%n1"
0d66636f 949 [(set_attr "conds" "set")]
950)
ebcc79bc 951
080c0b9a 952(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 953 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 954 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 955 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 956 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 957 "TARGET_32BIT"
ebcc79bc 958 "adc%?\\t%0, %1, %2"
cffb2a26 959 [(set_attr "conds" "use")]
960)
ebcc79bc 961
080c0b9a 962(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 963 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 964 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
965 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 966 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 967 "TARGET_32BIT"
ebcc79bc 968 "adc%?\\t%0, %1, %2"
0d66636f 969 [(set_attr "conds" "use")]
970)
ebcc79bc 971
080c0b9a 972(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 973 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 974 (plus:SI (plus:SI
975 (match_operator:SI 2 "shift_operator"
976 [(match_operand:SI 3 "s_register_operand" "r")
977 (match_operand:SI 4 "reg_or_int_operand" "rM")])
978 (match_operand:SI 1 "s_register_operand" "r"))
979 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 980 "TARGET_32BIT"
080c0b9a 981 "adc%?\\t%0, %1, %3%S2"
982 [(set_attr "conds" "use")
983 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
984 (const_string "alu_shift")
985 (const_string "alu_shift_reg")))]
cffb2a26 986)
ebcc79bc 987
25f905c2 988(define_expand "incscc"
989 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
990 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
991 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
992 (match_operand:SI 1 "s_register_operand" "0,?r")))]
993 "TARGET_32BIT"
994 ""
995)
996
997(define_insn "*arm_incscc"
9c08d1fa 998 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 999 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1000 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 1001 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 1002 "TARGET_ARM"
5565501b 1003 "@
1004 add%d2\\t%0, %1, #1
1005 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 1006 [(set_attr "conds" "use")
215b30b3 1007 (set_attr "length" "4,8")]
1008)
9c08d1fa 1009
d795fb69 1010; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1011(define_split
1012 [(set (match_operand:SI 0 "s_register_operand" "")
1013 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1014 (match_operand:SI 2 "s_register_operand" ""))
1015 (const_int -1)))
1016 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1017 "TARGET_32BIT"
d795fb69 1018 [(set (match_dup 3) (match_dup 1))
1019 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1020 "
1021 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1022")
1023
604f3a0a 1024(define_expand "addsf3"
1025 [(set (match_operand:SF 0 "s_register_operand" "")
1026 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1027 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 1028 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1029 "
a2cd141b 1030 if (TARGET_MAVERICK
604f3a0a 1031 && !cirrus_fp_register (operands[2], SFmode))
1032 operands[2] = force_reg (SFmode, operands[2]);
1033")
1034
604f3a0a 1035(define_expand "adddf3"
1036 [(set (match_operand:DF 0 "s_register_operand" "")
1037 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1038 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1039 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1040 "
a2cd141b 1041 if (TARGET_MAVERICK
604f3a0a 1042 && !cirrus_fp_register (operands[2], DFmode))
1043 operands[2] = force_reg (DFmode, operands[2]);
1044")
1045
cffb2a26 1046(define_expand "subdi3"
1047 [(parallel
1048 [(set (match_operand:DI 0 "s_register_operand" "")
1049 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1050 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1051 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1052 "TARGET_EITHER"
1053 "
a2cd141b 1054 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1055 && TARGET_32BIT
7d57ec45 1056 && cirrus_fp_register (operands[0], DImode)
1057 && cirrus_fp_register (operands[1], DImode))
1058 {
1059 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1060 DONE;
1061 }
1062
25f905c2 1063 if (TARGET_THUMB1)
cffb2a26 1064 {
1065 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1066 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1067 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1068 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1069 }
1070 "
1071)
1072
1073(define_insn "*arm_subdi3"
1074 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1075 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1076 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1077 (clobber (reg:CC CC_REGNUM))]
94829feb 1078 "TARGET_32BIT && !TARGET_NEON"
97499065 1079 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1080 [(set_attr "conds" "clob")
1081 (set_attr "length" "8")]
1082)
1083
1084(define_insn "*thumb_subdi3"
1085 [(set (match_operand:DI 0 "register_operand" "=l")
1086 (minus:DI (match_operand:DI 1 "register_operand" "0")
1087 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1088 (clobber (reg:CC CC_REGNUM))]
25f905c2 1089 "TARGET_THUMB1"
cffb2a26 1090 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1091 [(set_attr "length" "4")]
1092)
9c08d1fa 1093
f7fbdd4a 1094(define_insn "*subdi_di_zesidi"
cffb2a26 1095 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1096 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1097 (zero_extend:DI
cffb2a26 1098 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1099 (clobber (reg:CC CC_REGNUM))]
25f905c2 1100 "TARGET_32BIT"
97499065 1101 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1102 [(set_attr "conds" "clob")
1103 (set_attr "length" "8")]
1104)
9c08d1fa 1105
f7fbdd4a 1106(define_insn "*subdi_di_sesidi"
cffb2a26 1107 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1108 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1109 (sign_extend:DI
cffb2a26 1110 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1111 (clobber (reg:CC CC_REGNUM))]
25f905c2 1112 "TARGET_32BIT"
97499065 1113 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1114 [(set_attr "conds" "clob")
1115 (set_attr "length" "8")]
1116)
9c08d1fa 1117
f7fbdd4a 1118(define_insn "*subdi_zesidi_di"
cffb2a26 1119 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1120 (minus:DI (zero_extend:DI
cffb2a26 1121 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1122 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1123 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1124 "TARGET_ARM"
97499065 1125 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1126 [(set_attr "conds" "clob")
1127 (set_attr "length" "8")]
1128)
9c08d1fa 1129
f7fbdd4a 1130(define_insn "*subdi_sesidi_di"
cffb2a26 1131 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1132 (minus:DI (sign_extend:DI
cffb2a26 1133 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1134 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1135 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1136 "TARGET_ARM"
97499065 1137 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1138 [(set_attr "conds" "clob")
1139 (set_attr "length" "8")]
1140)
9c08d1fa 1141
f7fbdd4a 1142(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1143 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1144 (minus:DI (zero_extend:DI
cffb2a26 1145 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1146 (zero_extend:DI
cffb2a26 1147 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1148 (clobber (reg:CC CC_REGNUM))]
25f905c2 1149 "TARGET_32BIT"
1150 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1151 [(set_attr "conds" "clob")
1152 (set_attr "length" "8")]
1153)
b11cae9e 1154
87b22bf7 1155(define_expand "subsi3"
cffb2a26 1156 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1157 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1158 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1159 "TARGET_EITHER"
87b22bf7 1160 "
1161 if (GET_CODE (operands[1]) == CONST_INT)
1162 {
25f905c2 1163 if (TARGET_32BIT)
cffb2a26 1164 {
96f57e36 1165 arm_split_constant (MINUS, SImode, NULL_RTX,
1166 INTVAL (operands[1]), operands[0],
e1ba4a27 1167 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1168 DONE;
1169 }
25f905c2 1170 else /* TARGET_THUMB1 */
cffb2a26 1171 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1172 }
cffb2a26 1173 "
1174)
87b22bf7 1175
747b7458 1176(define_insn "thumb1_subsi3_insn"
cffb2a26 1177 [(set (match_operand:SI 0 "register_operand" "=l")
1178 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1179 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1180 "TARGET_THUMB1"
cffb2a26 1181 "sub\\t%0, %1, %2"
747b7458 1182 [(set_attr "length" "2")
1183 (set_attr "conds" "set")])
cffb2a26 1184
25f905c2 1185; ??? Check Thumb-2 split length
a0f94409 1186(define_insn_and_split "*arm_subsi3_insn"
080c0b9a 1187 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
bccb5444 1188 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1189 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
25f905c2 1190 "TARGET_32BIT"
e2348bcb 1191 "@
87b22bf7 1192 rsb%?\\t%0, %2, %1
aaa37ad6 1193 sub%?\\t%0, %1, %2
080c0b9a 1194 sub%?\\t%0, %1, %2
1195 #
87b22bf7 1196 #"
080c0b9a 1197 "&& ((GET_CODE (operands[1]) == CONST_INT
1198 && !const_ok_for_arm (INTVAL (operands[1])))
1199 || (GET_CODE (operands[2]) == CONST_INT
1200 && !const_ok_for_arm (INTVAL (operands[2]))))"
87b22bf7 1201 [(clobber (const_int 0))]
1202 "
96f57e36 1203 arm_split_constant (MINUS, SImode, curr_insn,
1204 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1205 DONE;
cffb2a26 1206 "
080c0b9a 1207 [(set_attr "length" "4,4,4,16,16")
a0f94409 1208 (set_attr "predicable" "yes")]
1209)
1210
1211(define_peephole2
1212 [(match_scratch:SI 3 "r")
372575c7 1213 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1214 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1215 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1216 "TARGET_32BIT
a0f94409 1217 && !const_ok_for_arm (INTVAL (operands[1]))
1218 && const_ok_for_arm (~INTVAL (operands[1]))"
1219 [(set (match_dup 3) (match_dup 1))
1220 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1221 ""
cffb2a26 1222)
b11cae9e 1223
f7fbdd4a 1224(define_insn "*subsi3_compare0"
bd5b4116 1225 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1226 (compare:CC_NOOV
1227 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1228 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1229 (const_int 0)))
9c08d1fa 1230 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1231 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1232 "TARGET_32BIT"
e2348bcb 1233 "@
25f905c2 1234 sub%.\\t%0, %1, %2
1235 rsb%.\\t%0, %2, %1"
cffb2a26 1236 [(set_attr "conds" "set")]
1237)
9c08d1fa 1238
080c0b9a 1239(define_insn "*subsi3_compare"
1240 [(set (reg:CC CC_REGNUM)
1241 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1242 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1243 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1244 (minus:SI (match_dup 1) (match_dup 2)))]
1245 "TARGET_32BIT"
1246 "@
1247 sub%.\\t%0, %1, %2
1248 rsb%.\\t%0, %2, %1"
1249 [(set_attr "conds" "set")]
1250)
1251
25f905c2 1252(define_expand "decscc"
1253 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1254 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1255 (match_operator:SI 2 "arm_comparison_operator"
1256 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1257 "TARGET_32BIT"
1258 ""
1259)
1260
1261(define_insn "*arm_decscc"
cffb2a26 1262 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1263 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1264 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1265 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1266 "TARGET_ARM"
e2348bcb 1267 "@
215b30b3 1268 sub%d2\\t%0, %1, #1
1269 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1270 [(set_attr "conds" "use")
1271 (set_attr "length" "*,8")]
1272)
9c08d1fa 1273
604f3a0a 1274(define_expand "subsf3"
1275 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1276 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1277 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1278 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1279 "
a2cd141b 1280 if (TARGET_MAVERICK)
604f3a0a 1281 {
1282 if (!cirrus_fp_register (operands[1], SFmode))
1283 operands[1] = force_reg (SFmode, operands[1]);
1284 if (!cirrus_fp_register (operands[2], SFmode))
1285 operands[2] = force_reg (SFmode, operands[2]);
1286 }
1287")
1288
604f3a0a 1289(define_expand "subdf3"
1290 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1291 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1292 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1293 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1294 "
a2cd141b 1295 if (TARGET_MAVERICK)
604f3a0a 1296 {
1297 if (!cirrus_fp_register (operands[1], DFmode))
1298 operands[1] = force_reg (DFmode, operands[1]);
1299 if (!cirrus_fp_register (operands[2], DFmode))
1300 operands[2] = force_reg (DFmode, operands[2]);
1301 }
1302")
1303
b11cae9e 1304\f
1305;; Multiplication insns
1306
cffb2a26 1307(define_expand "mulsi3"
1308 [(set (match_operand:SI 0 "s_register_operand" "")
1309 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1310 (match_operand:SI 1 "s_register_operand" "")))]
1311 "TARGET_EITHER"
1312 ""
1313)
1314
9c08d1fa 1315;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1316(define_insn "*arm_mulsi3"
1317 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1318 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1319 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1320 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1321 "mul%?\\t%0, %2, %1"
a2cd141b 1322 [(set_attr "insn" "mul")
0d66636f 1323 (set_attr "predicable" "yes")]
cffb2a26 1324)
1325
58d7d654 1326(define_insn "*arm_mulsi3_v6"
1327 [(set (match_operand:SI 0 "s_register_operand" "=r")
1328 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1329 (match_operand:SI 2 "s_register_operand" "r")))]
1330 "TARGET_32BIT && arm_arch6"
1331 "mul%?\\t%0, %1, %2"
1332 [(set_attr "insn" "mul")
1333 (set_attr "predicable" "yes")]
1334)
1335
215b30b3 1336; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1337; 1 and 2; are the same, because reload will make operand 0 match
1338; operand 1 without realizing that this conflicts with operand 2. We fix
1339; this by adding another alternative to match this case, and then `reload'
1340; it ourselves. This alternative must come first.
cffb2a26 1341(define_insn "*thumb_mulsi3"
1342 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1343 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1344 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1345 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1346 "*
1347 if (which_alternative < 2)
20c4e896 1348 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1349 else
20c4e896 1350 return \"mul\\t%0, %2\";
cffb2a26 1351 "
1352 [(set_attr "length" "4,4,2")
a2cd141b 1353 (set_attr "insn" "mul")]
cffb2a26 1354)
b11cae9e 1355
58d7d654 1356(define_insn "*thumb_mulsi3_v6"
1357 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1358 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1359 (match_operand:SI 2 "register_operand" "l,0,0")))]
1360 "TARGET_THUMB1 && arm_arch6"
1361 "@
1490694c 1362 mul\\t%0, %2
1363 mul\\t%0, %1
58d7d654 1364 mul\\t%0, %1"
1365 [(set_attr "length" "2")
1366 (set_attr "insn" "mul")]
1367)
1368
f7fbdd4a 1369(define_insn "*mulsi3_compare0"
bd5b4116 1370 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1371 (compare:CC_NOOV (mult:SI
1372 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1373 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1374 (const_int 0)))
1375 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1376 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1377 "TARGET_ARM && !arm_arch6"
1378 "mul%.\\t%0, %2, %1"
1379 [(set_attr "conds" "set")
1380 (set_attr "insn" "muls")]
1381)
1382
1383(define_insn "*mulsi3_compare0_v6"
1384 [(set (reg:CC_NOOV CC_REGNUM)
1385 (compare:CC_NOOV (mult:SI
1386 (match_operand:SI 2 "s_register_operand" "r")
1387 (match_operand:SI 1 "s_register_operand" "r"))
1388 (const_int 0)))
1389 (set (match_operand:SI 0 "s_register_operand" "=r")
1390 (mult:SI (match_dup 2) (match_dup 1)))]
1391 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1392 "mul%.\\t%0, %2, %1"
cffb2a26 1393 [(set_attr "conds" "set")
a2cd141b 1394 (set_attr "insn" "muls")]
cffb2a26 1395)
9c08d1fa 1396
f7fbdd4a 1397(define_insn "*mulsi_compare0_scratch"
bd5b4116 1398 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1399 (compare:CC_NOOV (mult:SI
1400 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1401 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1402 (const_int 0)))
1403 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1404 "TARGET_ARM && !arm_arch6"
1405 "mul%.\\t%0, %2, %1"
1406 [(set_attr "conds" "set")
1407 (set_attr "insn" "muls")]
1408)
1409
1410(define_insn "*mulsi_compare0_scratch_v6"
1411 [(set (reg:CC_NOOV CC_REGNUM)
1412 (compare:CC_NOOV (mult:SI
1413 (match_operand:SI 2 "s_register_operand" "r")
1414 (match_operand:SI 1 "s_register_operand" "r"))
1415 (const_int 0)))
1416 (clobber (match_scratch:SI 0 "=r"))]
1417 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1418 "mul%.\\t%0, %2, %1"
cffb2a26 1419 [(set_attr "conds" "set")
a2cd141b 1420 (set_attr "insn" "muls")]
cffb2a26 1421)
9c08d1fa 1422
b11cae9e 1423;; Unnamed templates to match MLA instruction.
1424
f7fbdd4a 1425(define_insn "*mulsi3addsi"
9c08d1fa 1426 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1427 (plus:SI
9c08d1fa 1428 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1429 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1430 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1431 "TARGET_32BIT && !arm_arch6"
1432 "mla%?\\t%0, %2, %1, %3"
1433 [(set_attr "insn" "mla")
1434 (set_attr "predicable" "yes")]
1435)
1436
1437(define_insn "*mulsi3addsi_v6"
1438 [(set (match_operand:SI 0 "s_register_operand" "=r")
1439 (plus:SI
1440 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1441 (match_operand:SI 1 "s_register_operand" "r"))
1442 (match_operand:SI 3 "s_register_operand" "r")))]
1443 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1444 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1445 [(set_attr "insn" "mla")
0d66636f 1446 (set_attr "predicable" "yes")]
1447)
b11cae9e 1448
f7fbdd4a 1449(define_insn "*mulsi3addsi_compare0"
bd5b4116 1450 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1451 (compare:CC_NOOV
1452 (plus:SI (mult:SI
1453 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1454 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1455 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1456 (const_int 0)))
9c08d1fa 1457 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1458 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1459 (match_dup 3)))]
58d7d654 1460 "TARGET_ARM && arm_arch6"
1461 "mla%.\\t%0, %2, %1, %3"
1462 [(set_attr "conds" "set")
1463 (set_attr "insn" "mlas")]
1464)
1465
1466(define_insn "*mulsi3addsi_compare0_v6"
1467 [(set (reg:CC_NOOV CC_REGNUM)
1468 (compare:CC_NOOV
1469 (plus:SI (mult:SI
1470 (match_operand:SI 2 "s_register_operand" "r")
1471 (match_operand:SI 1 "s_register_operand" "r"))
1472 (match_operand:SI 3 "s_register_operand" "r"))
1473 (const_int 0)))
1474 (set (match_operand:SI 0 "s_register_operand" "=r")
1475 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1476 (match_dup 3)))]
1477 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1478 "mla%.\\t%0, %2, %1, %3"
0d66636f 1479 [(set_attr "conds" "set")
a2cd141b 1480 (set_attr "insn" "mlas")]
0d66636f 1481)
9c08d1fa 1482
f7fbdd4a 1483(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1484 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1485 (compare:CC_NOOV
1486 (plus:SI (mult:SI
1487 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1488 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1489 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1490 (const_int 0)))
9c08d1fa 1491 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1492 "TARGET_ARM && !arm_arch6"
1493 "mla%.\\t%0, %2, %1, %3"
1494 [(set_attr "conds" "set")
1495 (set_attr "insn" "mlas")]
1496)
1497
1498(define_insn "*mulsi3addsi_compare0_scratch_v6"
1499 [(set (reg:CC_NOOV CC_REGNUM)
1500 (compare:CC_NOOV
1501 (plus:SI (mult:SI
1502 (match_operand:SI 2 "s_register_operand" "r")
1503 (match_operand:SI 1 "s_register_operand" "r"))
1504 (match_operand:SI 3 "s_register_operand" "r"))
1505 (const_int 0)))
1506 (clobber (match_scratch:SI 0 "=r"))]
1507 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1508 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1509 [(set_attr "conds" "set")
a2cd141b 1510 (set_attr "insn" "mlas")]
cffb2a26 1511)
f7fbdd4a 1512
89545238 1513(define_insn "*mulsi3subsi"
1514 [(set (match_operand:SI 0 "s_register_operand" "=r")
1515 (minus:SI
1516 (match_operand:SI 3 "s_register_operand" "r")
1517 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1518 (match_operand:SI 1 "s_register_operand" "r"))))]
1519 "TARGET_32BIT && arm_arch_thumb2"
1520 "mls%?\\t%0, %2, %1, %3"
1521 [(set_attr "insn" "mla")
1522 (set_attr "predicable" "yes")]
1523)
1524
5cdca009 1525(define_expand "maddsidi4"
1526 [(set (match_operand:DI 0 "s_register_operand" "")
1527 (plus:DI
1528 (mult:DI
1529 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1530 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1531 (match_operand:DI 3 "s_register_operand" "")))]
1532 "TARGET_32BIT && arm_arch3m"
1533 "")
82b85d08 1534
1535(define_insn "*mulsidi3adddi"
fe8dbf85 1536 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1537 (plus:DI
215b30b3 1538 (mult:DI
fe8dbf85 1539 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1540 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1541 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1542 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1543 "smlal%?\\t%Q0, %R0, %3, %2"
1544 [(set_attr "insn" "smlal")
1545 (set_attr "predicable" "yes")]
1546)
1547
1548(define_insn "*mulsidi3adddi_v6"
1549 [(set (match_operand:DI 0 "s_register_operand" "=r")
1550 (plus:DI
1551 (mult:DI
1552 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1553 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1554 (match_operand:DI 1 "s_register_operand" "0")))]
1555 "TARGET_32BIT && arm_arch6"
fe8dbf85 1556 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1557 [(set_attr "insn" "smlal")
0d66636f 1558 (set_attr "predicable" "yes")]
1559)
82b85d08 1560
957788b0 1561;; 32x32->64 widening multiply.
1562;; As with mulsi3, the only difference between the v3-5 and v6+
1563;; versions of these patterns is the requirement that the output not
1564;; overlap the inputs, but that still means we have to have a named
1565;; expander and two different starred insns.
1566
1567(define_expand "mulsidi3"
1568 [(set (match_operand:DI 0 "s_register_operand" "")
1569 (mult:DI
1570 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1571 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1572 "TARGET_32BIT && arm_arch3m"
1573 ""
1574)
1575
1576(define_insn "*mulsidi3_nov6"
f7fbdd4a 1577 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1578 (mult:DI
1579 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1580 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1581 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1582 "smull%?\\t%Q0, %R0, %1, %2"
1583 [(set_attr "insn" "smull")
1584 (set_attr "predicable" "yes")]
1585)
1586
957788b0 1587(define_insn "*mulsidi3_v6"
58d7d654 1588 [(set (match_operand:DI 0 "s_register_operand" "=r")
1589 (mult:DI
1590 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1591 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1592 "TARGET_32BIT && arm_arch6"
97499065 1593 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1594 [(set_attr "insn" "smull")
0d66636f 1595 (set_attr "predicable" "yes")]
1596)
f7fbdd4a 1597
957788b0 1598(define_expand "umulsidi3"
1599 [(set (match_operand:DI 0 "s_register_operand" "")
1600 (mult:DI
1601 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1602 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1603 "TARGET_32BIT && arm_arch3m"
1604 ""
1605)
1606
1607(define_insn "*umulsidi3_nov6"
f7fbdd4a 1608 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1609 (mult:DI
1610 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1611 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1612 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1613 "umull%?\\t%Q0, %R0, %1, %2"
1614 [(set_attr "insn" "umull")
1615 (set_attr "predicable" "yes")]
1616)
1617
957788b0 1618(define_insn "*umulsidi3_v6"
58d7d654 1619 [(set (match_operand:DI 0 "s_register_operand" "=r")
1620 (mult:DI
1621 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1622 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1623 "TARGET_32BIT && arm_arch6"
97499065 1624 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1625 [(set_attr "insn" "umull")
0d66636f 1626 (set_attr "predicable" "yes")]
1627)
b11cae9e 1628
5cdca009 1629(define_expand "umaddsidi4"
1630 [(set (match_operand:DI 0 "s_register_operand" "")
1631 (plus:DI
1632 (mult:DI
1633 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1634 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1635 (match_operand:DI 3 "s_register_operand" "")))]
1636 "TARGET_32BIT && arm_arch3m"
1637 "")
82b85d08 1638
1639(define_insn "*umulsidi3adddi"
8ead09f9 1640 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1641 (plus:DI
215b30b3 1642 (mult:DI
fe8dbf85 1643 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1644 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1645 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1646 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1647 "umlal%?\\t%Q0, %R0, %3, %2"
1648 [(set_attr "insn" "umlal")
1649 (set_attr "predicable" "yes")]
1650)
1651
1652(define_insn "*umulsidi3adddi_v6"
1653 [(set (match_operand:DI 0 "s_register_operand" "=r")
1654 (plus:DI
1655 (mult:DI
1656 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1657 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1658 (match_operand:DI 1 "s_register_operand" "0")))]
1659 "TARGET_32BIT && arm_arch6"
fe8dbf85 1660 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1661 [(set_attr "insn" "umlal")
0d66636f 1662 (set_attr "predicable" "yes")]
1663)
82b85d08 1664
957788b0 1665(define_expand "smulsi3_highpart"
1666 [(parallel
1667 [(set (match_operand:SI 0 "s_register_operand" "")
1668 (truncate:SI
1669 (lshiftrt:DI
1670 (mult:DI
1671 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1672 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1673 (const_int 32))))
1674 (clobber (match_scratch:SI 3 ""))])]
1675 "TARGET_32BIT && arm_arch3m"
1676 ""
1677)
1678
1679(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1680 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1681 (truncate:SI
1682 (lshiftrt:DI
215b30b3 1683 (mult:DI
e5fea38e 1684 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1685 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1686 (const_int 32))))
1687 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1688 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1689 "smull%?\\t%3, %0, %2, %1"
1690 [(set_attr "insn" "smull")
1691 (set_attr "predicable" "yes")]
1692)
1693
957788b0 1694(define_insn "*smulsi3_highpart_v6"
58d7d654 1695 [(set (match_operand:SI 0 "s_register_operand" "=r")
1696 (truncate:SI
1697 (lshiftrt:DI
1698 (mult:DI
1699 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1700 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1701 (const_int 32))))
1702 (clobber (match_scratch:SI 3 "=r"))]
1703 "TARGET_32BIT && arm_arch6"
f082f1c4 1704 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1705 [(set_attr "insn" "smull")
0d66636f 1706 (set_attr "predicable" "yes")]
cffb2a26 1707)
f082f1c4 1708
957788b0 1709(define_expand "umulsi3_highpart"
1710 [(parallel
1711 [(set (match_operand:SI 0 "s_register_operand" "")
1712 (truncate:SI
1713 (lshiftrt:DI
1714 (mult:DI
1715 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1716 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1717 (const_int 32))))
1718 (clobber (match_scratch:SI 3 ""))])]
1719 "TARGET_32BIT && arm_arch3m"
1720 ""
1721)
1722
1723(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1724 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1725 (truncate:SI
1726 (lshiftrt:DI
215b30b3 1727 (mult:DI
e5fea38e 1728 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1729 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1730 (const_int 32))))
1731 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1732 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1733 "umull%?\\t%3, %0, %2, %1"
1734 [(set_attr "insn" "umull")
1735 (set_attr "predicable" "yes")]
1736)
1737
957788b0 1738(define_insn "*umulsi3_highpart_v6"
58d7d654 1739 [(set (match_operand:SI 0 "s_register_operand" "=r")
1740 (truncate:SI
1741 (lshiftrt:DI
1742 (mult:DI
1743 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1744 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1745 (const_int 32))))
1746 (clobber (match_scratch:SI 3 "=r"))]
1747 "TARGET_32BIT && arm_arch6"
f082f1c4 1748 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1749 [(set_attr "insn" "umull")
0d66636f 1750 (set_attr "predicable" "yes")]
cffb2a26 1751)
f082f1c4 1752
331beb1a 1753(define_insn "mulhisi3"
1754 [(set (match_operand:SI 0 "s_register_operand" "=r")
1755 (mult:SI (sign_extend:SI
1756 (match_operand:HI 1 "s_register_operand" "%r"))
1757 (sign_extend:SI
1758 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1759 "TARGET_DSP_MULTIPLY"
61a2d04c 1760 "smulbb%?\\t%0, %1, %2"
a2cd141b 1761 [(set_attr "insn" "smulxy")
fec538d9 1762 (set_attr "predicable" "yes")]
1763)
1764
1765(define_insn "*mulhisi3tb"
1766 [(set (match_operand:SI 0 "s_register_operand" "=r")
1767 (mult:SI (ashiftrt:SI
1768 (match_operand:SI 1 "s_register_operand" "r")
1769 (const_int 16))
1770 (sign_extend:SI
1771 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1772 "TARGET_DSP_MULTIPLY"
fec538d9 1773 "smultb%?\\t%0, %1, %2"
a2cd141b 1774 [(set_attr "insn" "smulxy")
fec538d9 1775 (set_attr "predicable" "yes")]
1776)
1777
1778(define_insn "*mulhisi3bt"
1779 [(set (match_operand:SI 0 "s_register_operand" "=r")
1780 (mult:SI (sign_extend:SI
1781 (match_operand:HI 1 "s_register_operand" "r"))
1782 (ashiftrt:SI
1783 (match_operand:SI 2 "s_register_operand" "r")
1784 (const_int 16))))]
25f905c2 1785 "TARGET_DSP_MULTIPLY"
fec538d9 1786 "smulbt%?\\t%0, %1, %2"
a2cd141b 1787 [(set_attr "insn" "smulxy")
fec538d9 1788 (set_attr "predicable" "yes")]
1789)
1790
1791(define_insn "*mulhisi3tt"
1792 [(set (match_operand:SI 0 "s_register_operand" "=r")
1793 (mult:SI (ashiftrt:SI
1794 (match_operand:SI 1 "s_register_operand" "r")
1795 (const_int 16))
1796 (ashiftrt:SI
1797 (match_operand:SI 2 "s_register_operand" "r")
1798 (const_int 16))))]
25f905c2 1799 "TARGET_DSP_MULTIPLY"
fec538d9 1800 "smultt%?\\t%0, %1, %2"
a2cd141b 1801 [(set_attr "insn" "smulxy")
fec538d9 1802 (set_attr "predicable" "yes")]
331beb1a 1803)
1804
5cdca009 1805(define_insn "maddhisi4"
331beb1a 1806 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1807 (plus:SI (mult:SI (sign_extend:SI
1808 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1809 (sign_extend:SI
cfa6c608 1810 (match_operand:HI 2 "s_register_operand" "r")))
1811 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1812 "TARGET_DSP_MULTIPLY"
5cdca009 1813 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1814 [(set_attr "insn" "smlaxy")
fec538d9 1815 (set_attr "predicable" "yes")]
331beb1a 1816)
1817
9a92f368 1818;; Note: there is no maddhisi4ibt because this one is canonical form
1819(define_insn "*maddhisi4tb"
1820 [(set (match_operand:SI 0 "s_register_operand" "=r")
1821 (plus:SI (mult:SI (ashiftrt:SI
1822 (match_operand:SI 1 "s_register_operand" "r")
1823 (const_int 16))
1824 (sign_extend:SI
1825 (match_operand:HI 2 "s_register_operand" "r")))
1826 (match_operand:SI 3 "s_register_operand" "r")))]
1827 "TARGET_DSP_MULTIPLY"
1828 "smlatb%?\\t%0, %1, %2, %3"
1829 [(set_attr "insn" "smlaxy")
1830 (set_attr "predicable" "yes")]
1831)
1832
1833(define_insn "*maddhisi4tt"
1834 [(set (match_operand:SI 0 "s_register_operand" "=r")
1835 (plus:SI (mult:SI (ashiftrt:SI
1836 (match_operand:SI 1 "s_register_operand" "r")
1837 (const_int 16))
1838 (ashiftrt:SI
1839 (match_operand:SI 2 "s_register_operand" "r")
1840 (const_int 16)))
1841 (match_operand:SI 3 "s_register_operand" "r")))]
1842 "TARGET_DSP_MULTIPLY"
1843 "smlatt%?\\t%0, %1, %2, %3"
1844 [(set_attr "insn" "smlaxy")
1845 (set_attr "predicable" "yes")]
1846)
1847
5cdca009 1848(define_insn "*maddhidi4"
331beb1a 1849 [(set (match_operand:DI 0 "s_register_operand" "=r")
1850 (plus:DI
331beb1a 1851 (mult:DI (sign_extend:DI
cfa6c608 1852 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1853 (sign_extend:DI
cfa6c608 1854 (match_operand:HI 2 "s_register_operand" "r")))
1855 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1856 "TARGET_DSP_MULTIPLY"
5cdca009 1857 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1858 [(set_attr "insn" "smlalxy")
fec538d9 1859 (set_attr "predicable" "yes")])
331beb1a 1860
9a92f368 1861;; Note: there is no maddhidi4ibt because this one is canonical form
1862(define_insn "*maddhidi4tb"
1863 [(set (match_operand:DI 0 "s_register_operand" "=r")
1864 (plus:DI
1865 (mult:DI (sign_extend:DI
1866 (ashiftrt:SI
1867 (match_operand:SI 1 "s_register_operand" "r")
1868 (const_int 16)))
1869 (sign_extend:DI
1870 (match_operand:HI 2 "s_register_operand" "r")))
1871 (match_operand:DI 3 "s_register_operand" "0")))]
1872 "TARGET_DSP_MULTIPLY"
1873 "smlaltb%?\\t%Q0, %R0, %1, %2"
1874 [(set_attr "insn" "smlalxy")
1875 (set_attr "predicable" "yes")])
1876
1877(define_insn "*maddhidi4tt"
1878 [(set (match_operand:DI 0 "s_register_operand" "=r")
1879 (plus:DI
1880 (mult:DI (sign_extend:DI
1881 (ashiftrt:SI
1882 (match_operand:SI 1 "s_register_operand" "r")
1883 (const_int 16)))
1884 (sign_extend:DI
1885 (ashiftrt:SI
1886 (match_operand:SI 2 "s_register_operand" "r")
1887 (const_int 16))))
1888 (match_operand:DI 3 "s_register_operand" "0")))]
1889 "TARGET_DSP_MULTIPLY"
1890 "smlaltt%?\\t%Q0, %R0, %1, %2"
1891 [(set_attr "insn" "smlalxy")
1892 (set_attr "predicable" "yes")])
1893
604f3a0a 1894(define_expand "mulsf3"
1895 [(set (match_operand:SF 0 "s_register_operand" "")
1896 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1897 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1898 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1899 "
a2cd141b 1900 if (TARGET_MAVERICK
604f3a0a 1901 && !cirrus_fp_register (operands[2], SFmode))
1902 operands[2] = force_reg (SFmode, operands[2]);
1903")
1904
604f3a0a 1905(define_expand "muldf3"
1906 [(set (match_operand:DF 0 "s_register_operand" "")
1907 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1908 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1909 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1910 "
a2cd141b 1911 if (TARGET_MAVERICK
604f3a0a 1912 && !cirrus_fp_register (operands[2], DFmode))
1913 operands[2] = force_reg (DFmode, operands[2]);
1914")
b11cae9e 1915\f
1916;; Division insns
1917
7db9af5d 1918(define_expand "divsf3"
1919 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1920 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1921 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1922 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1923 "")
9c08d1fa 1924
7db9af5d 1925(define_expand "divdf3"
1926 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1927 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1928 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1929 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1930 "")
b11cae9e 1931\f
1932;; Modulo insns
1933
7db9af5d 1934(define_expand "modsf3"
1935 [(set (match_operand:SF 0 "s_register_operand" "")
1936 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1937 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1938 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1939 "")
9c08d1fa 1940
7db9af5d 1941(define_expand "moddf3"
1942 [(set (match_operand:DF 0 "s_register_operand" "")
1943 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1944 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1945 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1946 "")
b11cae9e 1947\f
1948;; Boolean and,ior,xor insns
1949
f6ebffac 1950;; Split up double word logical operations
1951
1952;; Split up simple DImode logical operations. Simply perform the logical
1953;; operation on the upper and lower halves of the registers.
1954(define_split
1955 [(set (match_operand:DI 0 "s_register_operand" "")
1956 (match_operator:DI 6 "logical_binary_operator"
1957 [(match_operand:DI 1 "s_register_operand" "")
1958 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1959 "TARGET_32BIT && reload_completed
e2669ea7 1960 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1961 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1962 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1963 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1964 "
215b30b3 1965 {
1966 operands[3] = gen_highpart (SImode, operands[0]);
1967 operands[0] = gen_lowpart (SImode, operands[0]);
1968 operands[4] = gen_highpart (SImode, operands[1]);
1969 operands[1] = gen_lowpart (SImode, operands[1]);
1970 operands[5] = gen_highpart (SImode, operands[2]);
1971 operands[2] = gen_lowpart (SImode, operands[2]);
1972 }"
1973)
f6ebffac 1974
f6ebffac 1975(define_split
1976 [(set (match_operand:DI 0 "s_register_operand" "")
1977 (match_operator:DI 6 "logical_binary_operator"
1978 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1979 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1980 "TARGET_32BIT && reload_completed"
f6ebffac 1981 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1982 (set (match_dup 3) (match_op_dup:SI 6
1983 [(ashiftrt:SI (match_dup 2) (const_int 31))
1984 (match_dup 4)]))]
1985 "
215b30b3 1986 {
1987 operands[3] = gen_highpart (SImode, operands[0]);
1988 operands[0] = gen_lowpart (SImode, operands[0]);
1989 operands[4] = gen_highpart (SImode, operands[1]);
1990 operands[1] = gen_lowpart (SImode, operands[1]);
1991 operands[5] = gen_highpart (SImode, operands[2]);
1992 operands[2] = gen_lowpart (SImode, operands[2]);
1993 }"
1994)
f6ebffac 1995
f6ebffac 1996;; The zero extend of operand 2 means we can just copy the high part of
1997;; operand1 into operand0.
1998(define_split
1999 [(set (match_operand:DI 0 "s_register_operand" "")
2000 (ior:DI
2001 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2002 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2003 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2004 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2005 (set (match_dup 3) (match_dup 4))]
2006 "
215b30b3 2007 {
2008 operands[4] = gen_highpart (SImode, operands[1]);
2009 operands[3] = gen_highpart (SImode, operands[0]);
2010 operands[0] = gen_lowpart (SImode, operands[0]);
2011 operands[1] = gen_lowpart (SImode, operands[1]);
2012 }"
2013)
f6ebffac 2014
2015;; The zero extend of operand 2 means we can just copy the high part of
2016;; operand1 into operand0.
2017(define_split
2018 [(set (match_operand:DI 0 "s_register_operand" "")
2019 (xor:DI
2020 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2021 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2022 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2023 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2024 (set (match_dup 3) (match_dup 4))]
2025 "
215b30b3 2026 {
2027 operands[4] = gen_highpart (SImode, operands[1]);
2028 operands[3] = gen_highpart (SImode, operands[0]);
2029 operands[0] = gen_lowpart (SImode, operands[0]);
2030 operands[1] = gen_lowpart (SImode, operands[1]);
2031 }"
2032)
f6ebffac 2033
e2669ea7 2034(define_expand "anddi3"
2035 [(set (match_operand:DI 0 "s_register_operand" "")
2036 (and:DI (match_operand:DI 1 "s_register_operand" "")
2037 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2038 "TARGET_32BIT"
2039 ""
2040)
2041
2042(define_insn "*anddi3_insn"
cffb2a26 2043 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2044 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2045 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2046 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2047 "#"
215b30b3 2048 [(set_attr "length" "8")]
2049)
b11cae9e 2050
a0f94409 2051(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2052 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2053 (and:DI (zero_extend:DI
2054 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2055 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2056 "TARGET_32BIT"
f6ebffac 2057 "#"
25f905c2 2058 "TARGET_32BIT && reload_completed"
a0f94409 2059 ; The zero extend of operand 2 clears the high word of the output
2060 ; operand.
2061 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2062 (set (match_dup 3) (const_int 0))]
2063 "
2064 {
2065 operands[3] = gen_highpart (SImode, operands[0]);
2066 operands[0] = gen_lowpart (SImode, operands[0]);
2067 operands[1] = gen_lowpart (SImode, operands[1]);
2068 }"
215b30b3 2069 [(set_attr "length" "8")]
2070)
b11cae9e 2071
f7fbdd4a 2072(define_insn "*anddi_sesdi_di"
cffb2a26 2073 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2074 (and:DI (sign_extend:DI
2075 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2076 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2077 "TARGET_32BIT"
f6ebffac 2078 "#"
cffb2a26 2079 [(set_attr "length" "8")]
2080)
b11cae9e 2081
87b22bf7 2082(define_expand "andsi3"
cffb2a26 2083 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2084 (and:SI (match_operand:SI 1 "s_register_operand" "")
2085 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2086 "TARGET_EITHER"
87b22bf7 2087 "
25f905c2 2088 if (TARGET_32BIT)
87b22bf7 2089 {
cffb2a26 2090 if (GET_CODE (operands[2]) == CONST_INT)
2091 {
47b5b27b 2092 if (INTVAL (operands[2]) == 255 && arm_arch6)
2093 {
2094 operands[1] = convert_to_mode (QImode, operands[1], 1);
2095 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2096 operands[1]));
2097 }
2098 else
2099 arm_split_constant (AND, SImode, NULL_RTX,
2100 INTVAL (operands[2]), operands[0],
2101 operands[1],
2102 optimize && can_create_pseudo_p ());
615caa51 2103
cffb2a26 2104 DONE;
2105 }
87b22bf7 2106 }
25f905c2 2107 else /* TARGET_THUMB1 */
cffb2a26 2108 {
2109 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2110 {
2111 rtx tmp = force_reg (SImode, operands[2]);
2112 if (rtx_equal_p (operands[0], operands[1]))
2113 operands[2] = tmp;
2114 else
2115 {
2116 operands[2] = operands[1];
2117 operands[1] = tmp;
2118 }
2119 }
cffb2a26 2120 else
2121 {
2122 int i;
2123
215b30b3 2124 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2125 {
215b30b3 2126 operands[2] = force_reg (SImode,
2127 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2128
747b7458 2129 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2130
2131 DONE;
2132 }
87b22bf7 2133
cffb2a26 2134 for (i = 9; i <= 31; i++)
2135 {
2136 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2137 {
2138 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2139 const0_rtx));
2140 DONE;
2141 }
215b30b3 2142 else if ((((HOST_WIDE_INT) 1) << i) - 1
2143 == ~INTVAL (operands[2]))
cffb2a26 2144 {
2145 rtx shift = GEN_INT (i);
2146 rtx reg = gen_reg_rtx (SImode);
2147
2148 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2149 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2150
2151 DONE;
2152 }
2153 }
2154
2155 operands[2] = force_reg (SImode, operands[2]);
2156 }
215b30b3 2157 }
2158 "
cffb2a26 2159)
2160
25f905c2 2161; ??? Check split length for Thumb-2
a0f94409 2162(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2163 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2164 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2165 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2166 "TARGET_32BIT"
5565501b 2167 "@
2168 and%?\\t%0, %1, %2
87b22bf7 2169 bic%?\\t%0, %1, #%B2
2170 #"
25f905c2 2171 "TARGET_32BIT
a0f94409 2172 && GET_CODE (operands[2]) == CONST_INT
2173 && !(const_ok_for_arm (INTVAL (operands[2]))
2174 || const_ok_for_arm (~INTVAL (operands[2])))"
2175 [(clobber (const_int 0))]
2176 "
96f57e36 2177 arm_split_constant (AND, SImode, curr_insn,
2178 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2179 DONE;
2180 "
0d66636f 2181 [(set_attr "length" "4,4,16")
2182 (set_attr "predicable" "yes")]
cffb2a26 2183)
2184
25f905c2 2185(define_insn "*thumb1_andsi3_insn"
cffb2a26 2186 [(set (match_operand:SI 0 "register_operand" "=l")
2187 (and:SI (match_operand:SI 1 "register_operand" "%0")
2188 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2189 "TARGET_THUMB1"
747b7458 2190 "and\\t%0, %2"
2191 [(set_attr "length" "2")
2192 (set_attr "conds" "set")])
87b22bf7 2193
f7fbdd4a 2194(define_insn "*andsi3_compare0"
bd5b4116 2195 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2196 (compare:CC_NOOV
2197 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2198 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2199 (const_int 0)))
cffb2a26 2200 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2201 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2202 "TARGET_32BIT"
5565501b 2203 "@
25f905c2 2204 and%.\\t%0, %1, %2
2205 bic%.\\t%0, %1, #%B2"
cffb2a26 2206 [(set_attr "conds" "set")]
2207)
9c08d1fa 2208
f7fbdd4a 2209(define_insn "*andsi3_compare0_scratch"
bd5b4116 2210 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2211 (compare:CC_NOOV
2212 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2213 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2214 (const_int 0)))
dd193d7c 2215 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2216 "TARGET_32BIT"
5565501b 2217 "@
2218 tst%?\\t%0, %1
25f905c2 2219 bic%.\\t%2, %0, #%B1"
0d66636f 2220 [(set_attr "conds" "set")]
2221)
9c08d1fa 2222
f7fbdd4a 2223(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2224 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2225 (compare:CC_NOOV (zero_extract:SI
2226 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2227 (match_operand 1 "const_int_operand" "n")
2228 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2229 (const_int 0)))]
25f905c2 2230 "TARGET_32BIT
cffb2a26 2231 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2232 && INTVAL (operands[1]) > 0
2233 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2234 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2235 "*
5c49a439 2236 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2237 << INTVAL (operands[2]));
40dbec34 2238 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2239 return \"\";
0d66636f 2240 "
2241 [(set_attr "conds" "set")]
2242)
9c08d1fa 2243
f4462328 2244(define_insn_and_split "*ne_zeroextractsi"
c4034607 2245 [(set (match_operand:SI 0 "s_register_operand" "=r")
2246 (ne:SI (zero_extract:SI
2247 (match_operand:SI 1 "s_register_operand" "r")
2248 (match_operand:SI 2 "const_int_operand" "n")
2249 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2250 (const_int 0)))
2251 (clobber (reg:CC CC_REGNUM))]
25f905c2 2252 "TARGET_32BIT
cffb2a26 2253 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2254 && INTVAL (operands[2]) > 0
2255 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2256 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2257 "#"
25f905c2 2258 "TARGET_32BIT
f4462328 2259 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2260 && INTVAL (operands[2]) > 0
2261 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2262 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2263 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2264 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2265 (const_int 0)))
2266 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2267 (set (match_dup 0)
2268 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2269 (match_dup 0) (const_int 1)))]
2270 "
2271 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2272 << INTVAL (operands[3]));
2273 "
2274 [(set_attr "conds" "clob")
25f905c2 2275 (set (attr "length")
2276 (if_then_else (eq_attr "is_thumb" "yes")
2277 (const_int 12)
2278 (const_int 8)))]
f4462328 2279)
2280
2281(define_insn_and_split "*ne_zeroextractsi_shifted"
2282 [(set (match_operand:SI 0 "s_register_operand" "=r")
2283 (ne:SI (zero_extract:SI
2284 (match_operand:SI 1 "s_register_operand" "r")
2285 (match_operand:SI 2 "const_int_operand" "n")
2286 (const_int 0))
2287 (const_int 0)))
2288 (clobber (reg:CC CC_REGNUM))]
2289 "TARGET_ARM"
2290 "#"
2291 "TARGET_ARM"
2292 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2293 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2294 (const_int 0)))
2295 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2296 (set (match_dup 0)
2297 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2298 (match_dup 0) (const_int 1)))]
2299 "
2300 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2301 "
2302 [(set_attr "conds" "clob")
2303 (set_attr "length" "8")]
2304)
2305
2306(define_insn_and_split "*ite_ne_zeroextractsi"
2307 [(set (match_operand:SI 0 "s_register_operand" "=r")
2308 (if_then_else:SI (ne (zero_extract:SI
2309 (match_operand:SI 1 "s_register_operand" "r")
2310 (match_operand:SI 2 "const_int_operand" "n")
2311 (match_operand:SI 3 "const_int_operand" "n"))
2312 (const_int 0))
2313 (match_operand:SI 4 "arm_not_operand" "rIK")
2314 (const_int 0)))
2315 (clobber (reg:CC CC_REGNUM))]
2316 "TARGET_ARM
2317 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2318 && INTVAL (operands[2]) > 0
2319 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2320 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2321 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2322 "#"
2323 "TARGET_ARM
2324 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2325 && INTVAL (operands[2]) > 0
2326 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2327 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2328 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2329 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2330 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2331 (const_int 0)))
2332 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2333 (set (match_dup 0)
2334 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2335 (match_dup 0) (match_dup 4)))]
2336 "
c4034607 2337 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2338 << INTVAL (operands[3]));
2339 "
2340 [(set_attr "conds" "clob")
2341 (set_attr "length" "8")]
2342)
2343
2344(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2345 [(set (match_operand:SI 0 "s_register_operand" "=r")
2346 (if_then_else:SI (ne (zero_extract:SI
2347 (match_operand:SI 1 "s_register_operand" "r")
2348 (match_operand:SI 2 "const_int_operand" "n")
2349 (const_int 0))
2350 (const_int 0))
2351 (match_operand:SI 3 "arm_not_operand" "rIK")
2352 (const_int 0)))
2353 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2354 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2355 "#"
f8d7bf2f 2356 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2357 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2358 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2359 (const_int 0)))
2360 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2361 (set (match_dup 0)
2362 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2363 (match_dup 0) (match_dup 3)))]
2364 "
2365 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2366 "
2367 [(set_attr "conds" "clob")
215b30b3 2368 (set_attr "length" "8")]
2369)
9c08d1fa 2370
58d6528b 2371(define_split
2372 [(set (match_operand:SI 0 "s_register_operand" "")
2373 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2374 (match_operand:SI 2 "const_int_operand" "")
2375 (match_operand:SI 3 "const_int_operand" "")))
2376 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2377 "TARGET_THUMB1"
58d6528b 2378 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2379 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2380 "{
2381 HOST_WIDE_INT temp = INTVAL (operands[2]);
2382
2383 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2384 operands[3] = GEN_INT (32 - temp);
2385 }"
2386)
2387
25f905c2 2388;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2389(define_split
2390 [(set (match_operand:SI 0 "s_register_operand" "")
2391 (match_operator:SI 1 "shiftable_operator"
2392 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2393 (match_operand:SI 3 "const_int_operand" "")
2394 (match_operand:SI 4 "const_int_operand" ""))
2395 (match_operand:SI 5 "s_register_operand" "")]))
2396 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2397 "TARGET_ARM"
2398 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2399 (set (match_dup 0)
2400 (match_op_dup 1
2401 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2402 (match_dup 5)]))]
2403 "{
2404 HOST_WIDE_INT temp = INTVAL (operands[3]);
2405
2406 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2407 operands[4] = GEN_INT (32 - temp);
2408 }"
2409)
2410
58d6528b 2411(define_split
2412 [(set (match_operand:SI 0 "s_register_operand" "")
2413 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2414 (match_operand:SI 2 "const_int_operand" "")
2415 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2416 "TARGET_THUMB1"
58d6528b 2417 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2418 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2419 "{
2420 HOST_WIDE_INT temp = INTVAL (operands[2]);
2421
2422 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2423 operands[3] = GEN_INT (32 - temp);
2424 }"
2425)
2426
d7863cfe 2427(define_split
2428 [(set (match_operand:SI 0 "s_register_operand" "")
2429 (match_operator:SI 1 "shiftable_operator"
2430 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2431 (match_operand:SI 3 "const_int_operand" "")
2432 (match_operand:SI 4 "const_int_operand" ""))
2433 (match_operand:SI 5 "s_register_operand" "")]))
2434 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2435 "TARGET_ARM"
2436 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2437 (set (match_dup 0)
2438 (match_op_dup 1
2439 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2440 (match_dup 5)]))]
2441 "{
2442 HOST_WIDE_INT temp = INTVAL (operands[3]);
2443
2444 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2445 operands[4] = GEN_INT (32 - temp);
2446 }"
2447)
2448
a42059fd 2449;;; ??? This pattern is bogus. If operand3 has bits outside the range
2450;;; represented by the bitfield, then this will produce incorrect results.
2451;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2452;;; which have a real bit-field insert instruction, the truncation happens
2453;;; in the bit-field insert instruction itself. Since arm does not have a
2454;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2455;;; the value before we insert. This loses some of the advantage of having
2456;;; this insv pattern, so this pattern needs to be reevalutated.
2457
8a18b90c 2458(define_expand "insv"
2459 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2460 (match_operand:SI 1 "general_operand" "")
2461 (match_operand:SI 2 "general_operand" ""))
19335226 2462 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2463 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2464 "
215b30b3 2465 {
2466 int start_bit = INTVAL (operands[2]);
2467 int width = INTVAL (operands[1]);
2468 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2469 rtx target, subtarget;
2470
8b054d5a 2471 if (arm_arch_thumb2)
2472 {
2473 bool use_bfi = TRUE;
2474
2475 if (GET_CODE (operands[3]) == CONST_INT)
2476 {
2477 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2478
2479 if (val == 0)
2480 {
2481 emit_insn (gen_insv_zero (operands[0], operands[1],
2482 operands[2]));
2483 DONE;
2484 }
2485
2486 /* See if the set can be done with a single orr instruction. */
2487 if (val == mask && const_ok_for_arm (val << start_bit))
2488 use_bfi = FALSE;
2489 }
2490
2491 if (use_bfi)
2492 {
2493 if (GET_CODE (operands[3]) != REG)
2494 operands[3] = force_reg (SImode, operands[3]);
2495
2496 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2497 operands[3]));
2498 DONE;
2499 }
2500 }
2501
3f8fde42 2502 target = copy_rtx (operands[0]);
215b30b3 2503 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2504 subreg as the final target. */
2505 if (GET_CODE (target) == SUBREG)
2506 {
2507 subtarget = gen_reg_rtx (SImode);
2508 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2509 < GET_MODE_SIZE (SImode))
2510 target = SUBREG_REG (target);
2511 }
2512 else
2513 subtarget = target;
8a18b90c 2514
215b30b3 2515 if (GET_CODE (operands[3]) == CONST_INT)
2516 {
2517 /* Since we are inserting a known constant, we may be able to
2518 reduce the number of bits that we have to clear so that
2519 the mask becomes simple. */
2520 /* ??? This code does not check to see if the new mask is actually
2521 simpler. It may not be. */
2522 rtx op1 = gen_reg_rtx (SImode);
2523 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2524 start of this pattern. */
2525 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2526 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2527
c5b3a71b 2528 emit_insn (gen_andsi3 (op1, operands[0],
2529 gen_int_mode (~mask2, SImode)));
215b30b3 2530 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2531 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2532 }
2533 else if (start_bit == 0
2534 && !(const_ok_for_arm (mask)
2535 || const_ok_for_arm (~mask)))
2536 {
2537 /* A Trick, since we are setting the bottom bits in the word,
2538 we can shift operand[3] up, operand[0] down, OR them together
2539 and rotate the result back again. This takes 3 insns, and
5910bb95 2540 the third might be mergeable into another op. */
215b30b3 2541 /* The shift up copes with the possibility that operand[3] is
2542 wider than the bitfield. */
2543 rtx op0 = gen_reg_rtx (SImode);
2544 rtx op1 = gen_reg_rtx (SImode);
2545
2546 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2547 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2548 emit_insn (gen_iorsi3 (op1, op1, op0));
2549 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2550 }
2551 else if ((width + start_bit == 32)
2552 && !(const_ok_for_arm (mask)
2553 || const_ok_for_arm (~mask)))
2554 {
2555 /* Similar trick, but slightly less efficient. */
8a18b90c 2556
215b30b3 2557 rtx op0 = gen_reg_rtx (SImode);
2558 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2559
215b30b3 2560 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2561 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2562 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2563 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2564 }
2565 else
2566 {
c5b3a71b 2567 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2568 rtx op1 = gen_reg_rtx (SImode);
2569 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2570
215b30b3 2571 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2572 {
2573 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2574
215b30b3 2575 emit_insn (gen_movsi (tmp, op0));
2576 op0 = tmp;
2577 }
8a18b90c 2578
215b30b3 2579 /* Mask out any bits in operand[3] that are not needed. */
2580 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2581
215b30b3 2582 if (GET_CODE (op0) == CONST_INT
2583 && (const_ok_for_arm (mask << start_bit)
2584 || const_ok_for_arm (~(mask << start_bit))))
2585 {
c5b3a71b 2586 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2587 emit_insn (gen_andsi3 (op2, operands[0], op0));
2588 }
2589 else
2590 {
2591 if (GET_CODE (op0) == CONST_INT)
2592 {
2593 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2594
215b30b3 2595 emit_insn (gen_movsi (tmp, op0));
2596 op0 = tmp;
2597 }
2598
2599 if (start_bit != 0)
2600 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2601
215b30b3 2602 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2603 }
8a18b90c 2604
215b30b3 2605 if (start_bit != 0)
2606 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2607
215b30b3 2608 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2609 }
f082f1c4 2610
215b30b3 2611 if (subtarget != target)
2612 {
2613 /* If TARGET is still a SUBREG, then it must be wider than a word,
2614 so we must be careful only to set the subword we were asked to. */
2615 if (GET_CODE (target) == SUBREG)
2616 emit_move_insn (target, subtarget);
2617 else
2618 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2619 }
8a18b90c 2620
215b30b3 2621 DONE;
2622 }"
2623)
8a18b90c 2624
8b054d5a 2625(define_insn "insv_zero"
2626 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2627 (match_operand:SI 1 "const_int_operand" "M")
2628 (match_operand:SI 2 "const_int_operand" "M"))
2629 (const_int 0))]
2630 "arm_arch_thumb2"
2631 "bfc%?\t%0, %2, %1"
2632 [(set_attr "length" "4")
2633 (set_attr "predicable" "yes")]
2634)
2635
2636(define_insn "insv_t2"
2637 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2638 (match_operand:SI 1 "const_int_operand" "M")
2639 (match_operand:SI 2 "const_int_operand" "M"))
2640 (match_operand:SI 3 "s_register_operand" "r"))]
2641 "arm_arch_thumb2"
2642 "bfi%?\t%0, %3, %2, %1"
2643 [(set_attr "length" "4")
2644 (set_attr "predicable" "yes")]
2645)
2646
215b30b3 2647; constants for op 2 will never be given to these patterns.
a0f94409 2648(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2649 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2650 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2651 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2652 "TARGET_32BIT"
f6ebffac 2653 "#"
e2669ea7 2654 "TARGET_32BIT && reload_completed
2655 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2656 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2657 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2658 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2659 "
2660 {
2661 operands[3] = gen_highpart (SImode, operands[0]);
2662 operands[0] = gen_lowpart (SImode, operands[0]);
2663 operands[4] = gen_highpart (SImode, operands[1]);
2664 operands[1] = gen_lowpart (SImode, operands[1]);
2665 operands[5] = gen_highpart (SImode, operands[2]);
2666 operands[2] = gen_lowpart (SImode, operands[2]);
2667 }"
0d66636f 2668 [(set_attr "length" "8")
2669 (set_attr "predicable" "yes")]
2670)
9c08d1fa 2671
a0f94409 2672(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2673 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2674 (and:DI (not:DI (zero_extend:DI
2675 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2676 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2677 "TARGET_32BIT"
e2348bcb 2678 "@
97499065 2679 bic%?\\t%Q0, %Q1, %2
f6ebffac 2680 #"
a0f94409 2681 ; (not (zero_extend ...)) allows us to just copy the high word from
2682 ; operand1 to operand0.
25f905c2 2683 "TARGET_32BIT
a0f94409 2684 && reload_completed
2685 && operands[0] != operands[1]"
5a097f7d 2686 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2687 (set (match_dup 3) (match_dup 4))]
2688 "
2689 {
2690 operands[3] = gen_highpart (SImode, operands[0]);
2691 operands[0] = gen_lowpart (SImode, operands[0]);
2692 operands[4] = gen_highpart (SImode, operands[1]);
2693 operands[1] = gen_lowpart (SImode, operands[1]);
2694 }"
0d66636f 2695 [(set_attr "length" "4,8")
2696 (set_attr "predicable" "yes")]
2697)
9c08d1fa 2698
a0f94409 2699(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2700 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2701 (and:DI (not:DI (sign_extend:DI
2702 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2703 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2704 "TARGET_32BIT"
f6ebffac 2705 "#"
25f905c2 2706 "TARGET_32BIT && reload_completed"
5a097f7d 2707 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2708 (set (match_dup 3) (and:SI (not:SI
2709 (ashiftrt:SI (match_dup 2) (const_int 31)))
2710 (match_dup 4)))]
2711 "
2712 {
2713 operands[3] = gen_highpart (SImode, operands[0]);
2714 operands[0] = gen_lowpart (SImode, operands[0]);
2715 operands[4] = gen_highpart (SImode, operands[1]);
2716 operands[1] = gen_lowpart (SImode, operands[1]);
2717 }"
0d66636f 2718 [(set_attr "length" "8")
2719 (set_attr "predicable" "yes")]
2720)
9c08d1fa 2721
8a18b90c 2722(define_insn "andsi_notsi_si"
9c08d1fa 2723 [(set (match_operand:SI 0 "s_register_operand" "=r")
2724 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2725 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2726 "TARGET_32BIT"
0d66636f 2727 "bic%?\\t%0, %1, %2"
2728 [(set_attr "predicable" "yes")]
2729)
b11cae9e 2730
747b7458 2731(define_insn "thumb1_bicsi3"
cffb2a26 2732 [(set (match_operand:SI 0 "register_operand" "=l")
2733 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2734 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2735 "TARGET_THUMB1"
747b7458 2736 "bic\\t%0, %1"
2737 [(set_attr "length" "2")
2738 (set_attr "conds" "set")])
cffb2a26 2739
8a18b90c 2740(define_insn "andsi_not_shiftsi_si"
a2cd141b 2741 [(set (match_operand:SI 0 "s_register_operand" "=r")
2742 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2743 [(match_operand:SI 2 "s_register_operand" "r")
2744 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2745 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2746 "TARGET_ARM"
6c4c2133 2747 "bic%?\\t%0, %1, %2%S4"
344495ea 2748 [(set_attr "predicable" "yes")
331beb1a 2749 (set_attr "shift" "2")
a2cd141b 2750 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2751 (const_string "alu_shift")
2752 (const_string "alu_shift_reg")))]
6c4c2133 2753)
8a18b90c 2754
f7fbdd4a 2755(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2756 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2757 (compare:CC_NOOV
2758 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2759 (match_operand:SI 1 "s_register_operand" "r"))
2760 (const_int 0)))
9c08d1fa 2761 (set (match_operand:SI 0 "s_register_operand" "=r")
2762 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2763 "TARGET_32BIT"
2764 "bic%.\\t%0, %1, %2"
0d66636f 2765 [(set_attr "conds" "set")]
2766)
9c08d1fa 2767
f7fbdd4a 2768(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2769 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2770 (compare:CC_NOOV
2771 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2772 (match_operand:SI 1 "s_register_operand" "r"))
2773 (const_int 0)))
9c08d1fa 2774 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2775 "TARGET_32BIT"
2776 "bic%.\\t%0, %1, %2"
0d66636f 2777 [(set_attr "conds" "set")]
2778)
9c08d1fa 2779
e2669ea7 2780(define_expand "iordi3"
2781 [(set (match_operand:DI 0 "s_register_operand" "")
2782 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2783 (match_operand:DI 2 "neon_logic_op2" "")))]
2784 "TARGET_32BIT"
2785 ""
2786)
2787
2788(define_insn "*iordi3_insn"
cffb2a26 2789 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2790 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2791 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2792 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2793 "#"
0d66636f 2794 [(set_attr "length" "8")
2795 (set_attr "predicable" "yes")]
cffb2a26 2796)
9c08d1fa 2797
f7fbdd4a 2798(define_insn "*iordi_zesidi_di"
9c08d1fa 2799 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2800 (ior:DI (zero_extend:DI
2801 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2802 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2803 "TARGET_32BIT"
e2348bcb 2804 "@
97499065 2805 orr%?\\t%Q0, %Q1, %2
f6ebffac 2806 #"
0d66636f 2807 [(set_attr "length" "4,8")
2808 (set_attr "predicable" "yes")]
cffb2a26 2809)
9c08d1fa 2810
f7fbdd4a 2811(define_insn "*iordi_sesidi_di"
9c08d1fa 2812 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2813 (ior:DI (sign_extend:DI
2814 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2815 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2816 "TARGET_32BIT"
f6ebffac 2817 "#"
0d66636f 2818 [(set_attr "length" "8")
2819 (set_attr "predicable" "yes")]
cffb2a26 2820)
9c08d1fa 2821
87b22bf7 2822(define_expand "iorsi3"
cffb2a26 2823 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2824 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2825 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2826 "TARGET_EITHER"
87b22bf7 2827 "
2828 if (GET_CODE (operands[2]) == CONST_INT)
2829 {
25f905c2 2830 if (TARGET_32BIT)
cffb2a26 2831 {
96f57e36 2832 arm_split_constant (IOR, SImode, NULL_RTX,
2833 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2834 optimize && can_create_pseudo_p ());
cffb2a26 2835 DONE;
2836 }
25f905c2 2837 else /* TARGET_THUMB1 */
923ffadb 2838 {
2839 rtx tmp = force_reg (SImode, operands[2]);
2840 if (rtx_equal_p (operands[0], operands[1]))
2841 operands[2] = tmp;
2842 else
2843 {
2844 operands[2] = operands[1];
2845 operands[1] = tmp;
2846 }
2847 }
87b22bf7 2848 }
cffb2a26 2849 "
2850)
87b22bf7 2851
d5d4dc8d 2852(define_insn_and_split "*iorsi3_insn"
2853 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2854 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2855 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2856 "TARGET_32BIT"
87b22bf7 2857 "@
2858 orr%?\\t%0, %1, %2
d5d4dc8d 2859 orn%?\\t%0, %1, #%B2
87b22bf7 2860 #"
d5d4dc8d 2861 "TARGET_32BIT
a0f94409 2862 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2863 && !(const_ok_for_arm (INTVAL (operands[2]))
2864 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2865 [(clobber (const_int 0))]
d5d4dc8d 2866{
96f57e36 2867 arm_split_constant (IOR, SImode, curr_insn,
2868 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2869 DONE;
d5d4dc8d 2870}
2871 [(set_attr "length" "4,4,16")
2872 (set_attr "arch" "32,t2,32")
2873 (set_attr "predicable" "yes")])
cffb2a26 2874
747b7458 2875(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2876 [(set (match_operand:SI 0 "register_operand" "=l")
2877 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2878 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2879 "TARGET_THUMB1"
747b7458 2880 "orr\\t%0, %2"
2881 [(set_attr "length" "2")
2882 (set_attr "conds" "set")])
9c08d1fa 2883
a0f94409 2884(define_peephole2
2885 [(match_scratch:SI 3 "r")
372575c7 2886 (set (match_operand:SI 0 "arm_general_register_operand" "")
2887 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2888 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2889 "TARGET_ARM
a0f94409 2890 && !const_ok_for_arm (INTVAL (operands[2]))
2891 && const_ok_for_arm (~INTVAL (operands[2]))"
2892 [(set (match_dup 3) (match_dup 2))
2893 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2894 ""
215b30b3 2895)
a0f94409 2896
f7fbdd4a 2897(define_insn "*iorsi3_compare0"
bd5b4116 2898 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2899 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2900 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2901 (const_int 0)))
2902 (set (match_operand:SI 0 "s_register_operand" "=r")
2903 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2904 "TARGET_32BIT"
2905 "orr%.\\t%0, %1, %2"
cffb2a26 2906 [(set_attr "conds" "set")]
2907)
9c08d1fa 2908
f7fbdd4a 2909(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2910 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2911 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2912 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2913 (const_int 0)))
2914 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2915 "TARGET_32BIT"
2916 "orr%.\\t%0, %1, %2"
0d66636f 2917 [(set_attr "conds" "set")]
2918)
9c08d1fa 2919
e2669ea7 2920(define_expand "xordi3"
2921 [(set (match_operand:DI 0 "s_register_operand" "")
2922 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2923 (match_operand:DI 2 "s_register_operand" "")))]
2924 "TARGET_32BIT"
2925 ""
2926)
2927
2928(define_insn "*xordi3_insn"
cffb2a26 2929 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2930 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2931 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2932 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2933 "#"
0d66636f 2934 [(set_attr "length" "8")
2935 (set_attr "predicable" "yes")]
cffb2a26 2936)
9c08d1fa 2937
f7fbdd4a 2938(define_insn "*xordi_zesidi_di"
9c08d1fa 2939 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2940 (xor:DI (zero_extend:DI
2941 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2942 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2943 "TARGET_32BIT"
e2348bcb 2944 "@
97499065 2945 eor%?\\t%Q0, %Q1, %2
f6ebffac 2946 #"
0d66636f 2947 [(set_attr "length" "4,8")
2948 (set_attr "predicable" "yes")]
cffb2a26 2949)
9c08d1fa 2950
f7fbdd4a 2951(define_insn "*xordi_sesidi_di"
9c08d1fa 2952 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2953 (xor:DI (sign_extend:DI
2954 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2955 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2956 "TARGET_32BIT"
f6ebffac 2957 "#"
0d66636f 2958 [(set_attr "length" "8")
2959 (set_attr "predicable" "yes")]
cffb2a26 2960)
9c08d1fa 2961
cffb2a26 2962(define_expand "xorsi3"
2963 [(set (match_operand:SI 0 "s_register_operand" "")
2964 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2965 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2966 "TARGET_EITHER"
923ffadb 2967 "if (GET_CODE (operands[2]) == CONST_INT)
2968 {
2969 if (TARGET_32BIT)
2970 {
2971 arm_split_constant (XOR, SImode, NULL_RTX,
2972 INTVAL (operands[2]), operands[0], operands[1],
2973 optimize && can_create_pseudo_p ());
2974 DONE;
2975 }
2976 else /* TARGET_THUMB1 */
2977 {
2978 rtx tmp = force_reg (SImode, operands[2]);
2979 if (rtx_equal_p (operands[0], operands[1]))
2980 operands[2] = tmp;
2981 else
2982 {
2983 operands[2] = operands[1];
2984 operands[1] = tmp;
2985 }
2986 }
2987 }"
cffb2a26 2988)
2989
2990(define_insn "*arm_xorsi3"
2991 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2992 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2993 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2994 "TARGET_32BIT"
cffb2a26 2995 "eor%?\\t%0, %1, %2"
0d66636f 2996 [(set_attr "predicable" "yes")]
cffb2a26 2997)
2998
747b7458 2999(define_insn "*thumb1_xorsi3_insn"
cffb2a26 3000 [(set (match_operand:SI 0 "register_operand" "=l")
3001 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3002 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3003 "TARGET_THUMB1"
747b7458 3004 "eor\\t%0, %2"
3005 [(set_attr "length" "2")
3006 (set_attr "conds" "set")])
9c08d1fa 3007
f7fbdd4a 3008(define_insn "*xorsi3_compare0"
bd5b4116 3009 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3010 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3011 (match_operand:SI 2 "arm_rhs_operand" "rI"))
3012 (const_int 0)))
3013 (set (match_operand:SI 0 "s_register_operand" "=r")
3014 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3015 "TARGET_32BIT"
3016 "eor%.\\t%0, %1, %2"
0d66636f 3017 [(set_attr "conds" "set")]
3018)
9c08d1fa 3019
f7fbdd4a 3020(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3021 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3022 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
3023 (match_operand:SI 1 "arm_rhs_operand" "rI"))
3024 (const_int 0)))]
25f905c2 3025 "TARGET_32BIT"
40dbec34 3026 "teq%?\\t%0, %1"
cffb2a26 3027 [(set_attr "conds" "set")]
3028)
9c08d1fa 3029
215b30b3 3030; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3031; (NOT D) we can sometimes merge the final NOT into one of the following
3032; insns.
9c08d1fa 3033
3034(define_split
a058e94a 3035 [(set (match_operand:SI 0 "s_register_operand" "")
3036 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3037 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3038 (match_operand:SI 3 "arm_rhs_operand" "")))
3039 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3040 "TARGET_32BIT"
9c08d1fa 3041 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3042 (not:SI (match_dup 3))))
3043 (set (match_dup 0) (not:SI (match_dup 4)))]
3044 ""
3045)
3046
f7fbdd4a 3047(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 3048 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3049 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3050 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3051 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3052 "TARGET_32BIT"
40dbec34 3053 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 3054 [(set_attr "length" "8")
25f905c2 3055 (set_attr "ce_count" "2")
0d66636f 3056 (set_attr "predicable" "yes")]
cffb2a26 3057)
9c08d1fa 3058
25f905c2 3059; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3060; insns are available?
d7863cfe 3061(define_split
3062 [(set (match_operand:SI 0 "s_register_operand" "")
3063 (match_operator:SI 1 "logical_binary_operator"
3064 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3065 (match_operand:SI 3 "const_int_operand" "")
3066 (match_operand:SI 4 "const_int_operand" ""))
3067 (match_operator:SI 9 "logical_binary_operator"
3068 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3069 (match_operand:SI 6 "const_int_operand" ""))
3070 (match_operand:SI 7 "s_register_operand" "")])]))
3071 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3072 "TARGET_32BIT
d7863cfe 3073 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3074 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3075 [(set (match_dup 8)
3076 (match_op_dup 1
3077 [(ashift:SI (match_dup 2) (match_dup 4))
3078 (match_dup 5)]))
3079 (set (match_dup 0)
3080 (match_op_dup 1
3081 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3082 (match_dup 7)]))]
3083 "
3084 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3085")
3086
3087(define_split
3088 [(set (match_operand:SI 0 "s_register_operand" "")
3089 (match_operator:SI 1 "logical_binary_operator"
3090 [(match_operator:SI 9 "logical_binary_operator"
3091 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3092 (match_operand:SI 6 "const_int_operand" ""))
3093 (match_operand:SI 7 "s_register_operand" "")])
3094 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3095 (match_operand:SI 3 "const_int_operand" "")
3096 (match_operand:SI 4 "const_int_operand" ""))]))
3097 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3098 "TARGET_32BIT
d7863cfe 3099 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3100 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3101 [(set (match_dup 8)
3102 (match_op_dup 1
3103 [(ashift:SI (match_dup 2) (match_dup 4))
3104 (match_dup 5)]))
3105 (set (match_dup 0)
3106 (match_op_dup 1
3107 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3108 (match_dup 7)]))]
3109 "
3110 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3111")
3112
3113(define_split
3114 [(set (match_operand:SI 0 "s_register_operand" "")
3115 (match_operator:SI 1 "logical_binary_operator"
3116 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3117 (match_operand:SI 3 "const_int_operand" "")
3118 (match_operand:SI 4 "const_int_operand" ""))
3119 (match_operator:SI 9 "logical_binary_operator"
3120 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3121 (match_operand:SI 6 "const_int_operand" ""))
3122 (match_operand:SI 7 "s_register_operand" "")])]))
3123 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3124 "TARGET_32BIT
d7863cfe 3125 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3126 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3127 [(set (match_dup 8)
3128 (match_op_dup 1
3129 [(ashift:SI (match_dup 2) (match_dup 4))
3130 (match_dup 5)]))
3131 (set (match_dup 0)
3132 (match_op_dup 1
3133 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3134 (match_dup 7)]))]
3135 "
3136 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3137")
3138
3139(define_split
3140 [(set (match_operand:SI 0 "s_register_operand" "")
3141 (match_operator:SI 1 "logical_binary_operator"
3142 [(match_operator:SI 9 "logical_binary_operator"
3143 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3144 (match_operand:SI 6 "const_int_operand" ""))
3145 (match_operand:SI 7 "s_register_operand" "")])
3146 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3147 (match_operand:SI 3 "const_int_operand" "")
3148 (match_operand:SI 4 "const_int_operand" ""))]))
3149 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3150 "TARGET_32BIT
d7863cfe 3151 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3152 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3153 [(set (match_dup 8)
3154 (match_op_dup 1
3155 [(ashift:SI (match_dup 2) (match_dup 4))
3156 (match_dup 5)]))
3157 (set (match_dup 0)
3158 (match_op_dup 1
3159 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3160 (match_dup 7)]))]
3161 "
3162 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3163")
9c08d1fa 3164\f
3165
3166;; Minimum and maximum insns
3167
8b9dc177 3168(define_expand "smaxsi3"
3169 [(parallel [
3170 (set (match_operand:SI 0 "s_register_operand" "")
3171 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3172 (match_operand:SI 2 "arm_rhs_operand" "")))
3173 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3174 "TARGET_32BIT"
8b9dc177 3175 "
8774928b 3176 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3177 {
3178 /* No need for a clobber of the condition code register here. */
3179 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3180 gen_rtx_SMAX (SImode, operands[1],
3181 operands[2])));
3182 DONE;
3183 }
3184")
3185
3186(define_insn "*smax_0"
3187 [(set (match_operand:SI 0 "s_register_operand" "=r")
3188 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3189 (const_int 0)))]
25f905c2 3190 "TARGET_32BIT"
8b9dc177 3191 "bic%?\\t%0, %1, %1, asr #31"
3192 [(set_attr "predicable" "yes")]
3193)
3194
8774928b 3195(define_insn "*smax_m1"
3196 [(set (match_operand:SI 0 "s_register_operand" "=r")
3197 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3198 (const_int -1)))]
25f905c2 3199 "TARGET_32BIT"
8774928b 3200 "orr%?\\t%0, %1, %1, asr #31"
3201 [(set_attr "predicable" "yes")]
3202)
3203
25f905c2 3204(define_insn "*arm_smax_insn"
8b9dc177 3205 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3206 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3207 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3208 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3209 "TARGET_ARM"
e2348bcb 3210 "@
3211 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3212 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3213 [(set_attr "conds" "clob")
8b9dc177 3214 (set_attr "length" "8,12")]
cffb2a26 3215)
9c08d1fa 3216
8b9dc177 3217(define_expand "sminsi3"
3218 [(parallel [
3219 (set (match_operand:SI 0 "s_register_operand" "")
3220 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3221 (match_operand:SI 2 "arm_rhs_operand" "")))
3222 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3223 "TARGET_32BIT"
8b9dc177 3224 "
3225 if (operands[2] == const0_rtx)
3226 {
3227 /* No need for a clobber of the condition code register here. */
3228 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3229 gen_rtx_SMIN (SImode, operands[1],
3230 operands[2])));
3231 DONE;
3232 }
3233")
3234
3235(define_insn "*smin_0"
3236 [(set (match_operand:SI 0 "s_register_operand" "=r")
3237 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3238 (const_int 0)))]
25f905c2 3239 "TARGET_32BIT"
8b9dc177 3240 "and%?\\t%0, %1, %1, asr #31"
3241 [(set_attr "predicable" "yes")]
3242)
3243
25f905c2 3244(define_insn "*arm_smin_insn"
8b9dc177 3245 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3246 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3247 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3248 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3249 "TARGET_ARM"
e2348bcb 3250 "@
3251 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3252 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3253 [(set_attr "conds" "clob")
8b9dc177 3254 (set_attr "length" "8,12")]
0d66636f 3255)
9c08d1fa 3256
25f905c2 3257(define_expand "umaxsi3"
3258 [(parallel [
3259 (set (match_operand:SI 0 "s_register_operand" "")
3260 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3261 (match_operand:SI 2 "arm_rhs_operand" "")))
3262 (clobber (reg:CC CC_REGNUM))])]
3263 "TARGET_32BIT"
3264 ""
3265)
3266
3267(define_insn "*arm_umaxsi3"
9c08d1fa 3268 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3269 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3270 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3271 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3272 "TARGET_ARM"
e2348bcb 3273 "@
3274 cmp\\t%1, %2\;movcc\\t%0, %2
3275 cmp\\t%1, %2\;movcs\\t%0, %1
3276 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3277 [(set_attr "conds" "clob")
3278 (set_attr "length" "8,8,12")]
3279)
9c08d1fa 3280
25f905c2 3281(define_expand "uminsi3"
3282 [(parallel [
3283 (set (match_operand:SI 0 "s_register_operand" "")
3284 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3285 (match_operand:SI 2 "arm_rhs_operand" "")))
3286 (clobber (reg:CC CC_REGNUM))])]
3287 "TARGET_32BIT"
3288 ""
3289)
3290
3291(define_insn "*arm_uminsi3"
9c08d1fa 3292 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3293 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3294 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3295 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3296 "TARGET_ARM"
e2348bcb 3297 "@
3298 cmp\\t%1, %2\;movcs\\t%0, %2
3299 cmp\\t%1, %2\;movcc\\t%0, %1
3300 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3301 [(set_attr "conds" "clob")
3302 (set_attr "length" "8,8,12")]
3303)
9c08d1fa 3304
8a18b90c 3305(define_insn "*store_minmaxsi"
9c08d1fa 3306 [(set (match_operand:SI 0 "memory_operand" "=m")
3307 (match_operator:SI 3 "minmax_operator"
3308 [(match_operand:SI 1 "s_register_operand" "r")
3309 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3310 (clobber (reg:CC CC_REGNUM))]
25f905c2 3311 "TARGET_32BIT"
9c08d1fa 3312 "*
dc55b8a9 3313 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3314 operands[1], operands[2]);
e2348bcb 3315 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3316 if (TARGET_THUMB2)
3317 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3318 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3319 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3320 return \"\";
0d66636f 3321 "
3322 [(set_attr "conds" "clob")
25f905c2 3323 (set (attr "length")
3324 (if_then_else (eq_attr "is_thumb" "yes")
3325 (const_int 14)
3326 (const_int 12)))
0d66636f 3327 (set_attr "type" "store1")]
3328)
9c08d1fa 3329
8a18b90c 3330; Reject the frame pointer in operand[1], since reloading this after
3331; it has been eliminated can cause carnage.
f7fbdd4a 3332(define_insn "*minmax_arithsi"
9c08d1fa 3333 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3334 (match_operator:SI 4 "shiftable_operator"
3335 [(match_operator:SI 5 "minmax_operator"
3336 [(match_operand:SI 2 "s_register_operand" "r,r")
3337 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3338 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3339 (clobber (reg:CC CC_REGNUM))]
25f905c2 3340 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3341 "*
0d66636f 3342 {
3343 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3344 bool need_else;
3345
3346 if (which_alternative != 0 || operands[3] != const0_rtx
3347 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3348 need_else = true;
3349 else
3350 need_else = false;
0d66636f 3351
dc55b8a9 3352 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3353 operands[2], operands[3]);
0d66636f 3354 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3355 if (TARGET_THUMB2)
3356 {
3357 if (need_else)
3358 output_asm_insn (\"ite\\t%d5\", operands);
3359 else
3360 output_asm_insn (\"it\\t%d5\", operands);
3361 }
0d66636f 3362 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3363 if (need_else)
0d66636f 3364 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3365 return \"\";
215b30b3 3366 }"
0d66636f 3367 [(set_attr "conds" "clob")
25f905c2 3368 (set (attr "length")
3369 (if_then_else (eq_attr "is_thumb" "yes")
3370 (const_int 14)
3371 (const_int 12)))]
0d66636f 3372)
9c08d1fa 3373
b11cae9e 3374\f
3375;; Shift and rotation insns
3376
a2cd141b 3377(define_expand "ashldi3"
3378 [(set (match_operand:DI 0 "s_register_operand" "")
3379 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3380 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3381 "TARGET_32BIT"
a2cd141b 3382 "
3383 if (GET_CODE (operands[2]) == CONST_INT)
3384 {
3385 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3386 {
3387 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3388 DONE;
3389 }
3390 /* Ideally we shouldn't fail here if we could know that operands[1]
3391 ends up already living in an iwmmxt register. Otherwise it's
3392 cheaper to have the alternate code being generated than moving
1d60d981 3393 values to iwmmxt regs and back. */
a2cd141b 3394 FAIL;
3395 }
3396 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3397 FAIL;
3398 "
3399)
3400
3401(define_insn "arm_ashldi3_1bit"
50ad1bf9 3402 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3403 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3404 (const_int 1)))
3405 (clobber (reg:CC CC_REGNUM))]
25f905c2 3406 "TARGET_32BIT"
a2cd141b 3407 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3408 [(set_attr "conds" "clob")
3409 (set_attr "length" "8")]
3410)
3411
87b22bf7 3412(define_expand "ashlsi3"
cffb2a26 3413 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3414 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3415 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3416 "TARGET_EITHER"
87b22bf7 3417 "
3418 if (GET_CODE (operands[2]) == CONST_INT
3419 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3420 {
3421 emit_insn (gen_movsi (operands[0], const0_rtx));
3422 DONE;
3423 }
cffb2a26 3424 "
3425)
3426
25f905c2 3427(define_insn "*thumb1_ashlsi3"
cffb2a26 3428 [(set (match_operand:SI 0 "register_operand" "=l,l")
3429 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3430 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3431 "TARGET_THUMB1"
cffb2a26 3432 "lsl\\t%0, %1, %2"
747b7458 3433 [(set_attr "length" "2")
3434 (set_attr "conds" "set")])
b11cae9e 3435
a2cd141b 3436(define_expand "ashrdi3"
3437 [(set (match_operand:DI 0 "s_register_operand" "")
3438 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3439 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3440 "TARGET_32BIT"
a2cd141b 3441 "
3442 if (GET_CODE (operands[2]) == CONST_INT)
3443 {
3444 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3445 {
3446 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3447 DONE;
3448 }
3449 /* Ideally we shouldn't fail here if we could know that operands[1]
3450 ends up already living in an iwmmxt register. Otherwise it's
3451 cheaper to have the alternate code being generated than moving
1d60d981 3452 values to iwmmxt regs and back. */
a2cd141b 3453 FAIL;
3454 }
3455 else if (!TARGET_REALLY_IWMMXT)
3456 FAIL;
3457 "
3458)
3459
3460(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3461 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3462 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3463 (const_int 1)))
3464 (clobber (reg:CC CC_REGNUM))]
25f905c2 3465 "TARGET_32BIT"
a2cd141b 3466 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3467 [(set_attr "conds" "clob")
d2a518d1 3468 (set_attr "insn" "mov")
a2cd141b 3469 (set_attr "length" "8")]
3470)
3471
87b22bf7 3472(define_expand "ashrsi3"
cffb2a26 3473 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3474 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3475 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3476 "TARGET_EITHER"
87b22bf7 3477 "
3478 if (GET_CODE (operands[2]) == CONST_INT
3479 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3480 operands[2] = GEN_INT (31);
cffb2a26 3481 "
3482)
3483
25f905c2 3484(define_insn "*thumb1_ashrsi3"
cffb2a26 3485 [(set (match_operand:SI 0 "register_operand" "=l,l")
3486 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3487 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3488 "TARGET_THUMB1"
cffb2a26 3489 "asr\\t%0, %1, %2"
747b7458 3490 [(set_attr "length" "2")
3491 (set_attr "conds" "set")])
b11cae9e 3492
a2cd141b 3493(define_expand "lshrdi3"
3494 [(set (match_operand:DI 0 "s_register_operand" "")
3495 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3496 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3497 "TARGET_32BIT"
a2cd141b 3498 "
3499 if (GET_CODE (operands[2]) == CONST_INT)
3500 {
3501 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3502 {
3503 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3504 DONE;
3505 }
3506 /* Ideally we shouldn't fail here if we could know that operands[1]
3507 ends up already living in an iwmmxt register. Otherwise it's
3508 cheaper to have the alternate code being generated than moving
1d60d981 3509 values to iwmmxt regs and back. */
a2cd141b 3510 FAIL;
3511 }
3512 else if (!TARGET_REALLY_IWMMXT)
3513 FAIL;
3514 "
3515)
3516
3517(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3518 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3519 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3520 (const_int 1)))
3521 (clobber (reg:CC CC_REGNUM))]
25f905c2 3522 "TARGET_32BIT"
a2cd141b 3523 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3524 [(set_attr "conds" "clob")
d2a518d1 3525 (set_attr "insn" "mov")
a2cd141b 3526 (set_attr "length" "8")]
3527)
3528
87b22bf7 3529(define_expand "lshrsi3"
cffb2a26 3530 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3531 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3532 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3533 "TARGET_EITHER"
87b22bf7 3534 "
3535 if (GET_CODE (operands[2]) == CONST_INT
3536 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3537 {
3538 emit_insn (gen_movsi (operands[0], const0_rtx));
3539 DONE;
3540 }
cffb2a26 3541 "
3542)
3543
25f905c2 3544(define_insn "*thumb1_lshrsi3"
cffb2a26 3545 [(set (match_operand:SI 0 "register_operand" "=l,l")
3546 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3547 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3548 "TARGET_THUMB1"
cffb2a26 3549 "lsr\\t%0, %1, %2"
747b7458 3550 [(set_attr "length" "2")
3551 (set_attr "conds" "set")])
b11cae9e 3552
87b22bf7 3553(define_expand "rotlsi3"
cffb2a26 3554 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3555 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3556 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3557 "TARGET_32BIT"
87b22bf7 3558 "
3559 if (GET_CODE (operands[2]) == CONST_INT)
3560 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3561 else
b11cae9e 3562 {
87b22bf7 3563 rtx reg = gen_reg_rtx (SImode);
3564 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3565 operands[2] = reg;
b11cae9e 3566 }
cffb2a26 3567 "
3568)
9c08d1fa 3569
87b22bf7 3570(define_expand "rotrsi3"
cffb2a26 3571 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3572 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3573 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3574 "TARGET_EITHER"
87b22bf7 3575 "
25f905c2 3576 if (TARGET_32BIT)
cffb2a26 3577 {
3578 if (GET_CODE (operands[2]) == CONST_INT
3579 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3580 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3581 }
25f905c2 3582 else /* TARGET_THUMB1 */
cffb2a26 3583 {
3584 if (GET_CODE (operands [2]) == CONST_INT)
3585 operands [2] = force_reg (SImode, operands[2]);
3586 }
3587 "
3588)
87b22bf7 3589
25f905c2 3590(define_insn "*thumb1_rotrsi3"
cffb2a26 3591 [(set (match_operand:SI 0 "register_operand" "=l")
3592 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3593 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3594 "TARGET_THUMB1"
cffb2a26 3595 "ror\\t%0, %0, %2"
3596 [(set_attr "length" "2")]
3597)
3598
3599(define_insn "*arm_shiftsi3"
3600 [(set (match_operand:SI 0 "s_register_operand" "=r")
3601 (match_operator:SI 3 "shift_operator"
3602 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3603 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3604 "TARGET_32BIT"
3605 "* return arm_output_shift(operands, 0);"
344495ea 3606 [(set_attr "predicable" "yes")
331beb1a 3607 (set_attr "shift" "1")
a2cd141b 3608 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3609 (const_string "alu_shift")
3610 (const_string "alu_shift_reg")))]
6c4c2133 3611)
87b22bf7 3612
f7fbdd4a 3613(define_insn "*shiftsi3_compare0"
bd5b4116 3614 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3615 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3616 [(match_operand:SI 1 "s_register_operand" "r")
3617 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3618 (const_int 0)))
3619 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3620 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3621 "TARGET_32BIT"
3622 "* return arm_output_shift(operands, 1);"
344495ea 3623 [(set_attr "conds" "set")
331beb1a 3624 (set_attr "shift" "1")
a2cd141b 3625 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3626 (const_string "alu_shift")
3627 (const_string "alu_shift_reg")))]
0d66636f 3628)
9c08d1fa 3629
f7fbdd4a 3630(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3631 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3632 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3633 [(match_operand:SI 1 "s_register_operand" "r")
3634 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3635 (const_int 0)))
3636 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3637 "TARGET_32BIT"
3638 "* return arm_output_shift(operands, 1);"
344495ea 3639 [(set_attr "conds" "set")
a2cd141b 3640 (set_attr "shift" "1")]
0d66636f 3641)
9c08d1fa 3642
d5d4dc8d 3643(define_insn "*not_shiftsi"
3644 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3645 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3646 [(match_operand:SI 1 "s_register_operand" "r,r")
3647 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3648 "TARGET_32BIT"
6c4c2133 3649 "mvn%?\\t%0, %1%S3"
344495ea 3650 [(set_attr "predicable" "yes")
331beb1a 3651 (set_attr "shift" "1")
d2a518d1 3652 (set_attr "insn" "mvn")
d5d4dc8d 3653 (set_attr "arch" "32,a")
3654 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3655
d5d4dc8d 3656(define_insn "*not_shiftsi_compare0"
bd5b4116 3657 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3658 (compare:CC_NOOV
3659 (not:SI (match_operator:SI 3 "shift_operator"
3660 [(match_operand:SI 1 "s_register_operand" "r,r")
3661 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3662 (const_int 0)))
3663 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3664 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3665 "TARGET_32BIT"
25f905c2 3666 "mvn%.\\t%0, %1%S3"
344495ea 3667 [(set_attr "conds" "set")
331beb1a 3668 (set_attr "shift" "1")
d2a518d1 3669 (set_attr "insn" "mvn")
d5d4dc8d 3670 (set_attr "arch" "32,a")
3671 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3672
d5d4dc8d 3673(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3674 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3675 (compare:CC_NOOV
3676 (not:SI (match_operator:SI 3 "shift_operator"
3677 [(match_operand:SI 1 "s_register_operand" "r,r")
3678 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3679 (const_int 0)))
3680 (clobber (match_scratch:SI 0 "=r,r"))]
3681 "TARGET_32BIT"
25f905c2 3682 "mvn%.\\t%0, %1%S3"
344495ea 3683 [(set_attr "conds" "set")
331beb1a 3684 (set_attr "shift" "1")
d2a518d1 3685 (set_attr "insn" "mvn")
d5d4dc8d 3686 (set_attr "arch" "32,a")
3687 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3688
cffb2a26 3689;; We don't really have extzv, but defining this using shifts helps
3690;; to reduce register pressure later on.
3691
3692(define_expand "extzv"
3693 [(set (match_dup 4)
3694 (ashift:SI (match_operand:SI 1 "register_operand" "")
3695 (match_operand:SI 2 "const_int_operand" "")))
3696 (set (match_operand:SI 0 "register_operand" "")
3697 (lshiftrt:SI (match_dup 4)
215b30b3 3698 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3699 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3700 "
3701 {
3702 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3703 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3704
8b054d5a 3705 if (arm_arch_thumb2)
3706 {
3707 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3708 operands[3]));
3709 DONE;
3710 }
3711
cffb2a26 3712 operands[3] = GEN_INT (rshift);
3713
3714 if (lshift == 0)
3715 {
3716 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3717 DONE;
3718 }
3719
3720 operands[2] = GEN_INT (lshift);
3721 operands[4] = gen_reg_rtx (SImode);
215b30b3 3722 }"
cffb2a26 3723)
3724
8b054d5a 3725(define_insn "extv"
3726 [(set (match_operand:SI 0 "s_register_operand" "=r")
3727 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3728 (match_operand:SI 2 "const_int_operand" "M")
3729 (match_operand:SI 3 "const_int_operand" "M")))]
3730 "arm_arch_thumb2"
3731 "sbfx%?\t%0, %1, %3, %2"
3732 [(set_attr "length" "4")
3733 (set_attr "predicable" "yes")]
3734)
3735
3736(define_insn "extzv_t2"
3737 [(set (match_operand:SI 0 "s_register_operand" "=r")
3738 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3739 (match_operand:SI 2 "const_int_operand" "M")
3740 (match_operand:SI 3 "const_int_operand" "M")))]
3741 "arm_arch_thumb2"
3742 "ubfx%?\t%0, %1, %3, %2"
3743 [(set_attr "length" "4")
3744 (set_attr "predicable" "yes")]
3745)
3746
7d3cda8c 3747
3748;; Division instructions
3749(define_insn "divsi3"
3750 [(set (match_operand:SI 0 "s_register_operand" "=r")
3751 (div:SI (match_operand:SI 1 "s_register_operand" "r")
3752 (match_operand:SI 2 "s_register_operand" "r")))]
3753 "TARGET_IDIV"
3754 "sdiv%?\t%0, %1, %2"
3755 [(set_attr "predicable" "yes")
3756 (set_attr "insn" "sdiv")]
3757)
3758
3759(define_insn "udivsi3"
3760 [(set (match_operand:SI 0 "s_register_operand" "=r")
3761 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
3762 (match_operand:SI 2 "s_register_operand" "r")))]
3763 "TARGET_IDIV"
3764 "udiv%?\t%0, %1, %2"
3765 [(set_attr "predicable" "yes")
3766 (set_attr "insn" "udiv")]
3767)
3768
b11cae9e 3769\f
3770;; Unary arithmetic insns
3771
cffb2a26 3772(define_expand "negdi2"
3773 [(parallel
8135a42b 3774 [(set (match_operand:DI 0 "s_register_operand" "")
3775 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3776 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3777 "TARGET_EITHER"
8135a42b 3778 ""
cffb2a26 3779)
3780
3781;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 3782;; The first alternative allows the common case of a *full* overlap.
cffb2a26 3783(define_insn "*arm_negdi2"
458a8706 3784 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3785 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 3786 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3787 "TARGET_ARM"
97499065 3788 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3789 [(set_attr "conds" "clob")
3790 (set_attr "length" "8")]
3791)
b11cae9e 3792
25f905c2 3793(define_insn "*thumb1_negdi2"
8135a42b 3794 [(set (match_operand:DI 0 "register_operand" "=&l")
3795 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3796 (clobber (reg:CC CC_REGNUM))]
25f905c2 3797 "TARGET_THUMB1"
cffb2a26 3798 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3799 [(set_attr "length" "6")]
3800)
3801
3802(define_expand "negsi2"
3803 [(set (match_operand:SI 0 "s_register_operand" "")
3804 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3805 "TARGET_EITHER"
b11cae9e 3806 ""
cffb2a26 3807)
3808
3809(define_insn "*arm_negsi2"
3810 [(set (match_operand:SI 0 "s_register_operand" "=r")
3811 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3812 "TARGET_32BIT"
cffb2a26 3813 "rsb%?\\t%0, %1, #0"
0d66636f 3814 [(set_attr "predicable" "yes")]
cffb2a26 3815)
3816
25f905c2 3817(define_insn "*thumb1_negsi2"
cffb2a26 3818 [(set (match_operand:SI 0 "register_operand" "=l")
3819 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3820 "TARGET_THUMB1"
cffb2a26 3821 "neg\\t%0, %1"
3822 [(set_attr "length" "2")]
3823)
b11cae9e 3824
604f3a0a 3825(define_expand "negsf2"
3826 [(set (match_operand:SF 0 "s_register_operand" "")
3827 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3828 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3829 ""
3830)
3831
3832(define_expand "negdf2"
3833 [(set (match_operand:DF 0 "s_register_operand" "")
3834 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3835 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3836 "")
3837
9c08d1fa 3838;; abssi2 doesn't really clobber the condition codes if a different register
3839;; is being set. To keep things simple, assume during rtl manipulations that
3840;; it does, but tell the final scan operator the truth. Similarly for
3841;; (neg (abs...))
3842
604f3a0a 3843(define_expand "abssi2"
3844 [(parallel
3845 [(set (match_operand:SI 0 "s_register_operand" "")
3846 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3847 (clobber (match_dup 2))])]
3848 "TARGET_EITHER"
3849 "
25f905c2 3850 if (TARGET_THUMB1)
ba156559 3851 operands[2] = gen_rtx_SCRATCH (SImode);
3852 else
3853 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3854")
604f3a0a 3855
7d57ec45 3856(define_insn "*arm_abssi2"
ba156559 3857 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3858 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3859 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3860 "TARGET_ARM"
e2348bcb 3861 "@
3862 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3863 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3864 [(set_attr "conds" "clob,*")
331beb1a 3865 (set_attr "shift" "1")
0d66636f 3866 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3867 (set_attr "length" "8")]
3868)
9c08d1fa 3869
25f905c2 3870(define_insn_and_split "*thumb1_abssi2"
ba156559 3871 [(set (match_operand:SI 0 "s_register_operand" "=l")
3872 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3873 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3874 "TARGET_THUMB1"
ba156559 3875 "#"
25f905c2 3876 "TARGET_THUMB1 && reload_completed"
ba156559 3877 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3878 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3879 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3880 ""
3881 [(set_attr "length" "6")]
3882)
3883
3884(define_insn "*arm_neg_abssi2"
9c08d1fa 3885 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3886 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3887 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3888 "TARGET_ARM"
e2348bcb 3889 "@
3890 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3891 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3892 [(set_attr "conds" "clob,*")
331beb1a 3893 (set_attr "shift" "1")
0d66636f 3894 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3895 (set_attr "length" "8")]
3896)
b11cae9e 3897
25f905c2 3898(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3899 [(set (match_operand:SI 0 "s_register_operand" "=l")
3900 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3901 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3902 "TARGET_THUMB1"
ba156559 3903 "#"
25f905c2 3904 "TARGET_THUMB1 && reload_completed"
ba156559 3905 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3906 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3907 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3908 ""
3909 [(set_attr "length" "6")]
3910)
3911
604f3a0a 3912(define_expand "abssf2"
3913 [(set (match_operand:SF 0 "s_register_operand" "")
3914 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3915 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3916 "")
3917
604f3a0a 3918(define_expand "absdf2"
3919 [(set (match_operand:DF 0 "s_register_operand" "")
3920 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3921 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3922 "")
3923
7db9af5d 3924(define_expand "sqrtsf2"
3925 [(set (match_operand:SF 0 "s_register_operand" "")
3926 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3927 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3928 "")
9c08d1fa 3929
7db9af5d 3930(define_expand "sqrtdf2"
3931 [(set (match_operand:DF 0 "s_register_operand" "")
3932 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3933 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3934 "")
9c08d1fa 3935
a0f94409 3936(define_insn_and_split "one_cmpldi2"
9c08d1fa 3937 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3938 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3939 "TARGET_32BIT"
f6ebffac 3940 "#"
25f905c2 3941 "TARGET_32BIT && reload_completed"
a0f94409 3942 [(set (match_dup 0) (not:SI (match_dup 1)))
3943 (set (match_dup 2) (not:SI (match_dup 3)))]
3944 "
3945 {
3946 operands[2] = gen_highpart (SImode, operands[0]);
3947 operands[0] = gen_lowpart (SImode, operands[0]);
3948 operands[3] = gen_highpart (SImode, operands[1]);
3949 operands[1] = gen_lowpart (SImode, operands[1]);
3950 }"
0d66636f 3951 [(set_attr "length" "8")
3952 (set_attr "predicable" "yes")]
cffb2a26 3953)
b11cae9e 3954
cffb2a26 3955(define_expand "one_cmplsi2"
3956 [(set (match_operand:SI 0 "s_register_operand" "")
3957 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3958 "TARGET_EITHER"
b11cae9e 3959 ""
cffb2a26 3960)
3961
3962(define_insn "*arm_one_cmplsi2"
3963 [(set (match_operand:SI 0 "s_register_operand" "=r")
3964 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3965 "TARGET_32BIT"
cffb2a26 3966 "mvn%?\\t%0, %1"
d2a518d1 3967 [(set_attr "predicable" "yes")
3968 (set_attr "insn" "mvn")]
cffb2a26 3969)
3970
25f905c2 3971(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3972 [(set (match_operand:SI 0 "register_operand" "=l")
3973 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3974 "TARGET_THUMB1"
cffb2a26 3975 "mvn\\t%0, %1"
d2a518d1 3976 [(set_attr "length" "2")
3977 (set_attr "insn" "mvn")]
cffb2a26 3978)
9c08d1fa 3979
f7fbdd4a 3980(define_insn "*notsi_compare0"
bd5b4116 3981 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3982 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3983 (const_int 0)))
3984 (set (match_operand:SI 0 "s_register_operand" "=r")
3985 (not:SI (match_dup 1)))]
25f905c2 3986 "TARGET_32BIT"
3987 "mvn%.\\t%0, %1"
d2a518d1 3988 [(set_attr "conds" "set")
3989 (set_attr "insn" "mvn")]
cffb2a26 3990)
9c08d1fa 3991
f7fbdd4a 3992(define_insn "*notsi_compare0_scratch"
bd5b4116 3993 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3994 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3995 (const_int 0)))
3996 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3997 "TARGET_32BIT"
3998 "mvn%.\\t%0, %1"
d2a518d1 3999 [(set_attr "conds" "set")
4000 (set_attr "insn" "mvn")]
cffb2a26 4001)
b11cae9e 4002\f
4003;; Fixed <--> Floating conversion insns
4004
9b8516be 4005(define_expand "floatsihf2"
4006 [(set (match_operand:HF 0 "general_operand" "")
4007 (float:HF (match_operand:SI 1 "general_operand" "")))]
4008 "TARGET_EITHER"
4009 "
4010 {
4011 rtx op1 = gen_reg_rtx (SFmode);
4012 expand_float (op1, operands[1], 0);
4013 op1 = convert_to_mode (HFmode, op1, 0);
4014 emit_move_insn (operands[0], op1);
4015 DONE;
4016 }"
4017)
4018
4019(define_expand "floatdihf2"
4020 [(set (match_operand:HF 0 "general_operand" "")
4021 (float:HF (match_operand:DI 1 "general_operand" "")))]
4022 "TARGET_EITHER"
4023 "
4024 {
4025 rtx op1 = gen_reg_rtx (SFmode);
4026 expand_float (op1, operands[1], 0);
4027 op1 = convert_to_mode (HFmode, op1, 0);
4028 emit_move_insn (operands[0], op1);
4029 DONE;
4030 }"
4031)
4032
604f3a0a 4033(define_expand "floatsisf2"
4034 [(set (match_operand:SF 0 "s_register_operand" "")
4035 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4036 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4037 "
a2cd141b 4038 if (TARGET_MAVERICK)
604f3a0a 4039 {
4040 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
4041 DONE;
4042 }
4043")
4044
604f3a0a 4045(define_expand "floatsidf2"
4046 [(set (match_operand:DF 0 "s_register_operand" "")
4047 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4048 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4049 "
a2cd141b 4050 if (TARGET_MAVERICK)
604f3a0a 4051 {
4052 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
4053 DONE;
4054 }
4055")
4056
9b8516be 4057(define_expand "fix_trunchfsi2"
4058 [(set (match_operand:SI 0 "general_operand" "")
4059 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4060 "TARGET_EITHER"
4061 "
4062 {
4063 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4064 expand_fix (operands[0], op1, 0);
4065 DONE;
4066 }"
4067)
4068
4069(define_expand "fix_trunchfdi2"
4070 [(set (match_operand:DI 0 "general_operand" "")
4071 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4072 "TARGET_EITHER"
4073 "
4074 {
4075 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4076 expand_fix (operands[0], op1, 0);
4077 DONE;
4078 }"
4079)
4080
604f3a0a 4081(define_expand "fix_truncsfsi2"
4082 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4083 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4084 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4085 "
a2cd141b 4086 if (TARGET_MAVERICK)
604f3a0a 4087 {
4088 if (!cirrus_fp_register (operands[0], SImode))
4089 operands[0] = force_reg (SImode, operands[0]);
4090 if (!cirrus_fp_register (operands[1], SFmode))
4091 operands[1] = force_reg (SFmode, operands[0]);
4092 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4093 DONE;
4094 }
4095")
4096
604f3a0a 4097(define_expand "fix_truncdfsi2"
4098 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4099 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4100 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4101 "
a2cd141b 4102 if (TARGET_MAVERICK)
604f3a0a 4103 {
4104 if (!cirrus_fp_register (operands[1], DFmode))
4105 operands[1] = force_reg (DFmode, operands[0]);
4106 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4107 DONE;
4108 }
4109")
4110
f544c6d2 4111;; Truncation insns
b11cae9e 4112
604f3a0a 4113(define_expand "truncdfsf2"
4114 [(set (match_operand:SF 0 "s_register_operand" "")
4115 (float_truncate:SF
4116 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4117 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4118 ""
4119)
9b8516be 4120
4121/* DFmode -> HFmode conversions have to go through SFmode. */
4122(define_expand "truncdfhf2"
4123 [(set (match_operand:HF 0 "general_operand" "")
4124 (float_truncate:HF
4125 (match_operand:DF 1 "general_operand" "")))]
4126 "TARGET_EITHER"
4127 "
4128 {
4129 rtx op1;
4130 op1 = convert_to_mode (SFmode, operands[1], 0);
4131 op1 = convert_to_mode (HFmode, op1, 0);
4132 emit_move_insn (operands[0], op1);
4133 DONE;
4134 }"
4135)
b11cae9e 4136\f
9c08d1fa 4137;; Zero and sign extension instructions.
b11cae9e 4138
848e66ac 4139(define_insn "zero_extend<mode>di2"
4140 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4141 (zero_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4142 "<qhs_extenddi_cstr>")))]
848e66ac 4143 "TARGET_32BIT <qhs_zextenddi_cond>"
4144 "#"
4145 [(set_attr "length" "8")
4146 (set_attr "ce_count" "2")
4147 (set_attr "predicable" "yes")]
25f905c2 4148)
4149
848e66ac 4150(define_insn "extend<mode>di2"
9c08d1fa 4151 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4152 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4153 "<qhs_extenddi_cstr>")))]
848e66ac 4154 "TARGET_32BIT <qhs_sextenddi_cond>"
4155 "#"
0d66636f 4156 [(set_attr "length" "8")
848e66ac 4157 (set_attr "ce_count" "2")
4158 (set_attr "shift" "1")
0d66636f 4159 (set_attr "predicable" "yes")]
4160)
9c08d1fa 4161
848e66ac 4162;; Splits for all extensions to DImode
4163(define_split
4164 [(set (match_operand:DI 0 "s_register_operand" "")
4165 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4166 "TARGET_32BIT"
848e66ac 4167 [(set (match_dup 0) (match_dup 1))]
4168{
848e66ac 4169 rtx lo_part = gen_lowpart (SImode, operands[0]);
4170 enum machine_mode src_mode = GET_MODE (operands[1]);
4171
4172 if (REG_P (operands[0])
4173 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4174 emit_clobber (operands[0]);
4175 if (!REG_P (lo_part) || src_mode != SImode
4176 || !rtx_equal_p (lo_part, operands[1]))
4177 {
4178 if (src_mode == SImode)
4179 emit_move_insn (lo_part, operands[1]);
4180 else
4181 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4182 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4183 operands[1] = lo_part;
4184 }
4185 operands[0] = gen_highpart (SImode, operands[0]);
4186 operands[1] = const0_rtx;
4187})
9c08d1fa 4188
848e66ac 4189(define_split
25f905c2 4190 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4191 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4192 "TARGET_32BIT"
848e66ac 4193 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4194{
4195 rtx lo_part = gen_lowpart (SImode, operands[0]);
4196 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4197
848e66ac 4198 if (REG_P (operands[0])
4199 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4200 emit_clobber (operands[0]);
4201
4202 if (!REG_P (lo_part) || src_mode != SImode
4203 || !rtx_equal_p (lo_part, operands[1]))
4204 {
4205 if (src_mode == SImode)
4206 emit_move_insn (lo_part, operands[1]);
4207 else
4208 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4209 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4210 operands[1] = lo_part;
4211 }
4212 operands[0] = gen_highpart (SImode, operands[0]);
4213})
9c08d1fa 4214
4215(define_expand "zero_extendhisi2"
ef51b8e1 4216 [(set (match_operand:SI 0 "s_register_operand" "")
4217 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4218 "TARGET_EITHER"
ef51b8e1 4219{
4220 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4221 {
ef51b8e1 4222 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4223 DONE;
25f7a26e 4224 }
ef51b8e1 4225 if (!arm_arch6 && !MEM_P (operands[1]))
4226 {
4227 rtx t = gen_lowpart (SImode, operands[1]);
4228 rtx tmp = gen_reg_rtx (SImode);
4229 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4230 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4231 DONE;
4232 }
4233})
9c08d1fa 4234
ef51b8e1 4235(define_split
b146458f 4236 [(set (match_operand:SI 0 "s_register_operand" "")
4237 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4238 "!TARGET_THUMB2 && !arm_arch6"
4239 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4240 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4241{
4242 operands[2] = gen_lowpart (SImode, operands[1]);
4243})
4244
4245(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4246 [(set (match_operand:SI 0 "register_operand" "=l,l")
4247 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4248 "TARGET_THUMB1"
848e66ac 4249{
a2cd141b 4250 rtx mem;
4251
ef51b8e1 4252 if (which_alternative == 0 && arm_arch6)
848e66ac 4253 return "uxth\t%0, %1";
ef51b8e1 4254 if (which_alternative == 0)
848e66ac 4255 return "#";
a2cd141b 4256
4257 mem = XEXP (operands[1], 0);
4258
4259 if (GET_CODE (mem) == CONST)
4260 mem = XEXP (mem, 0);
4261
a2cd141b 4262 if (GET_CODE (mem) == PLUS)
4263 {
4264 rtx a = XEXP (mem, 0);
a2cd141b 4265
4266 /* This can happen due to bugs in reload. */
4267 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4268 {
4269 rtx ops[2];
4270 ops[0] = operands[0];
4271 ops[1] = a;
4272
848e66ac 4273 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4274
4275 XEXP (mem, 0) = operands[0];
4276 }
a2cd141b 4277 }
4278
848e66ac 4279 return "ldrh\t%0, %1";
4280}
ef51b8e1 4281 [(set_attr_alternative "length"
4282 [(if_then_else (eq_attr "is_arch6" "yes")
4283 (const_int 2) (const_int 4))
4284 (const_int 4)])
848e66ac 4285 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4286)
4287
cffb2a26 4288(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4289 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4290 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4291 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4292 "@
4293 #
4294 ldr%(h%)\\t%0, %1"
4295 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4296 (set_attr "predicable" "yes")]
cffb2a26 4297)
f7fbdd4a 4298
a2cd141b 4299(define_insn "*arm_zero_extendhisi2_v6"
4300 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4301 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4302 "TARGET_ARM && arm_arch6"
4303 "@
4304 uxth%?\\t%0, %1
25f905c2 4305 ldr%(h%)\\t%0, %1"
a2cd141b 4306 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4307 (set_attr "predicable" "yes")]
a2cd141b 4308)
4309
4310(define_insn "*arm_zero_extendhisi2addsi"
4311 [(set (match_operand:SI 0 "s_register_operand" "=r")
4312 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4313 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4314 "TARGET_INT_SIMD"
a2cd141b 4315 "uxtah%?\\t%0, %2, %1"
4316 [(set_attr "type" "alu_shift")
4317 (set_attr "predicable" "yes")]
4318)
4319
87b22bf7 4320(define_expand "zero_extendqisi2"
cffb2a26 4321 [(set (match_operand:SI 0 "s_register_operand" "")
4322 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4323 "TARGET_EITHER"
ef51b8e1 4324{
4325 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4326 {
ef51b8e1 4327 emit_insn (gen_andsi3 (operands[0],
4328 gen_lowpart (SImode, operands[1]),
4329 GEN_INT (255)));
4330 DONE;
4331 }
4332 if (!arm_arch6 && !MEM_P (operands[1]))
4333 {
4334 rtx t = gen_lowpart (SImode, operands[1]);
4335 rtx tmp = gen_reg_rtx (SImode);
4336 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4337 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4338 DONE;
4339 }
4340})
cffb2a26 4341
ef51b8e1 4342(define_split
b146458f 4343 [(set (match_operand:SI 0 "s_register_operand" "")
4344 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4345 "!arm_arch6"
4346 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4347 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4348{
4349 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4350 if (TARGET_ARM)
4351 {
4352 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4353 DONE;
4354 }
ef51b8e1 4355})
9c08d1fa 4356
25f905c2 4357(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4358 [(set (match_operand:SI 0 "register_operand" "=l,l")
4359 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4360 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4361 "@
4362 #
4363 ldrb\\t%0, %1"
4364 [(set_attr "length" "4,2")
4365 (set_attr "type" "alu_shift,load_byte")
4366 (set_attr "pool_range" "*,32")]
cffb2a26 4367)
4368
25f905c2 4369(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4370 [(set (match_operand:SI 0 "register_operand" "=l,l")
4371 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4372 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4373 "@
4374 uxtb\\t%0, %1
4375 ldrb\\t%0, %1"
848e66ac 4376 [(set_attr "length" "2")
4377 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4378)
4379
cffb2a26 4380(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4381 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4382 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4383 "TARGET_ARM && !arm_arch6"
ef51b8e1 4384 "@
4385 #
4386 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4387 [(set_attr "length" "8,4")
4388 (set_attr "type" "alu_shift,load_byte")
848e66ac 4389 (set_attr "predicable" "yes")]
cffb2a26 4390)
87b22bf7 4391
a2cd141b 4392(define_insn "*arm_zero_extendqisi2_v6"
4393 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4394 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4395 "TARGET_ARM && arm_arch6"
4396 "@
25f905c2 4397 uxtb%(%)\\t%0, %1
4398 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4399 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4400 (set_attr "predicable" "yes")]
a2cd141b 4401)
4402
4403(define_insn "*arm_zero_extendqisi2addsi"
4404 [(set (match_operand:SI 0 "s_register_operand" "=r")
4405 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4406 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4407 "TARGET_INT_SIMD"
a2cd141b 4408 "uxtab%?\\t%0, %2, %1"
4409 [(set_attr "predicable" "yes")
bcaec148 4410 (set_attr "insn" "xtab")
a2cd141b 4411 (set_attr "type" "alu_shift")]
4412)
4413
87b22bf7 4414(define_split
4415 [(set (match_operand:SI 0 "s_register_operand" "")
4416 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4417 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4418 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4419 [(set (match_dup 2) (match_dup 1))
4420 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4421 ""
4422)
9c08d1fa 4423
8a4d25d6 4424(define_split
4425 [(set (match_operand:SI 0 "s_register_operand" "")
4426 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4427 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4428 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4429 [(set (match_dup 2) (match_dup 1))
4430 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4431 ""
4432)
4433
1c274529 4434
4435(define_split
4436 [(set (match_operand:SI 0 "s_register_operand" "")
4437 (ior_xor:SI (and:SI (ashift:SI
4438 (match_operand:SI 1 "s_register_operand" "")
4439 (match_operand:SI 2 "const_int_operand" ""))
4440 (match_operand:SI 3 "const_int_operand" ""))
4441 (zero_extend:SI
4442 (match_operator 5 "subreg_lowpart_operator"
4443 [(match_operand:SI 4 "s_register_operand" "")]))))]
4444 "TARGET_32BIT
63787642 4445 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4446 == (GET_MODE_MASK (GET_MODE (operands[5]))
4447 & (GET_MODE_MASK (GET_MODE (operands[5]))
4448 << (INTVAL (operands[2])))))"
4449 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4450 (match_dup 4)))
4451 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4452 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4453)
4454
f7fbdd4a 4455(define_insn "*compareqi_eq0"
bd5b4116 4456 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4457 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4458 (const_int 0)))]
25f905c2 4459 "TARGET_32BIT"
87b22bf7 4460 "tst\\t%0, #255"
cffb2a26 4461 [(set_attr "conds" "set")]
4462)
b11cae9e 4463
b11cae9e 4464(define_expand "extendhisi2"
ef51b8e1 4465 [(set (match_operand:SI 0 "s_register_operand" "")
4466 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4467 "TARGET_EITHER"
ef51b8e1 4468{
4469 if (TARGET_THUMB1)
4470 {
4471 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4472 DONE;
4473 }
4474 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4475 {
4476 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4477 DONE;
4478 }
ed29c566 4479
ef51b8e1 4480 if (!arm_arch6 && !MEM_P (operands[1]))
4481 {
4482 rtx t = gen_lowpart (SImode, operands[1]);
4483 rtx tmp = gen_reg_rtx (SImode);
4484 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4485 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4486 DONE;
4487 }
4488})
cffb2a26 4489
ef51b8e1 4490(define_split
4491 [(parallel
4492 [(set (match_operand:SI 0 "register_operand" "")
4493 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4494 (clobber (match_scratch:SI 2 ""))])]
4495 "!arm_arch6"
4496 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4497 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4498{
4499 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4500})
25f7a26e 4501
a2cd141b 4502;; We used to have an early-clobber on the scratch register here.
4503;; However, there's a bug somewhere in reload which means that this
4504;; can be partially ignored during spill allocation if the memory
ed29c566 4505;; address also needs reloading; this causes us to die later on when
a2cd141b 4506;; we try to verify the operands. Fortunately, we don't really need
4507;; the early-clobber: we can always use operand 0 if operand 2
4508;; overlaps the address.
ef51b8e1 4509(define_insn "thumb1_extendhisi2"
a2cd141b 4510 [(set (match_operand:SI 0 "register_operand" "=l,l")
4511 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4512 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4513 "TARGET_THUMB1"
a2cd141b 4514 "*
4515 {
4516 rtx ops[4];
4517 rtx mem;
4518
ef51b8e1 4519 if (which_alternative == 0 && !arm_arch6)
4520 return \"#\";
a2cd141b 4521 if (which_alternative == 0)
4522 return \"sxth\\t%0, %1\";
4523
4524 mem = XEXP (operands[1], 0);
4525
4526 /* This code used to try to use 'V', and fix the address only if it was
4527 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4528 range of QImode offsets, and offsettable_address_p does a QImode
4529 address check. */
4530
4531 if (GET_CODE (mem) == CONST)
4532 mem = XEXP (mem, 0);
4533
4534 if (GET_CODE (mem) == LABEL_REF)
4535 return \"ldr\\t%0, %1\";
4536
4537 if (GET_CODE (mem) == PLUS)
4538 {
4539 rtx a = XEXP (mem, 0);
4540 rtx b = XEXP (mem, 1);
4541
4542 if (GET_CODE (a) == LABEL_REF
4543 && GET_CODE (b) == CONST_INT)
4544 return \"ldr\\t%0, %1\";
4545
4546 if (GET_CODE (b) == REG)
4547 return \"ldrsh\\t%0, %1\";
4548
4549 ops[1] = a;
4550 ops[2] = b;
4551 }
4552 else
4553 {
4554 ops[1] = mem;
4555 ops[2] = const0_rtx;
4556 }
4557
ed29c566 4558 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4559
4560 ops[0] = operands[0];
4561 if (reg_mentioned_p (operands[2], ops[1]))
4562 ops[3] = ops[0];
4563 else
4564 ops[3] = operands[2];
4565 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4566 return \"\";
4567 }"
ef51b8e1 4568 [(set_attr_alternative "length"
4569 [(if_then_else (eq_attr "is_arch6" "yes")
4570 (const_int 2) (const_int 4))
4571 (const_int 4)])
a2cd141b 4572 (set_attr "type" "alu_shift,load_byte")
4573 (set_attr "pool_range" "*,1020")]
4574)
4575
25f905c2 4576;; This pattern will only be used when ldsh is not available
25f7a26e 4577(define_expand "extendhisi2_mem"
eab14235 4578 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4579 (set (match_dup 3)
eab14235 4580 (zero_extend:SI (match_dup 7)))
25f7a26e 4581 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4582 (set (match_operand:SI 0 "" "")
4583 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4584 "TARGET_ARM"
25f7a26e 4585 "
215b30b3 4586 {
4587 rtx mem1, mem2;
4588 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4589
788fcce0 4590 mem1 = change_address (operands[1], QImode, addr);
4591 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4592 operands[0] = gen_lowpart (SImode, operands[0]);
4593 operands[1] = mem1;
4594 operands[2] = gen_reg_rtx (SImode);
4595 operands[3] = gen_reg_rtx (SImode);
4596 operands[6] = gen_reg_rtx (SImode);
4597 operands[7] = mem2;
25f7a26e 4598
215b30b3 4599 if (BYTES_BIG_ENDIAN)
4600 {
4601 operands[4] = operands[2];
4602 operands[5] = operands[3];
4603 }
4604 else
4605 {
4606 operands[4] = operands[3];
4607 operands[5] = operands[2];
4608 }
4609 }"
4610)
b11cae9e 4611
ef51b8e1 4612(define_split
4613 [(set (match_operand:SI 0 "register_operand" "")
4614 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4615 "!arm_arch6"
4616 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4617 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4618{
4619 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4620})
4621
a2cd141b 4622(define_insn "*arm_extendhisi2"
ef51b8e1 4623 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4624 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4625 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4626 "@
4627 #
4628 ldr%(sh%)\\t%0, %1"
4629 [(set_attr "length" "8,4")
4630 (set_attr "type" "alu_shift,load_byte")
0d66636f 4631 (set_attr "predicable" "yes")
ef51b8e1 4632 (set_attr "pool_range" "*,256")
4633 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4634)
f7fbdd4a 4635
25f905c2 4636;; ??? Check Thumb-2 pool range
a2cd141b 4637(define_insn "*arm_extendhisi2_v6"
4638 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4639 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4640 "TARGET_32BIT && arm_arch6"
a2cd141b 4641 "@
4642 sxth%?\\t%0, %1
25f905c2 4643 ldr%(sh%)\\t%0, %1"
a2cd141b 4644 [(set_attr "type" "alu_shift,load_byte")
4645 (set_attr "predicable" "yes")
4646 (set_attr "pool_range" "*,256")
4647 (set_attr "neg_pool_range" "*,244")]
4648)
4649
4650(define_insn "*arm_extendhisi2addsi"
4651 [(set (match_operand:SI 0 "s_register_operand" "=r")
4652 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4653 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4654 "TARGET_INT_SIMD"
a2cd141b 4655 "sxtah%?\\t%0, %2, %1"
4656)
4657
c8f69309 4658(define_expand "extendqihi2"
4659 [(set (match_dup 2)
bed7d9a5 4660 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4661 (const_int 24)))
9c08d1fa 4662 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4663 (ashiftrt:SI (match_dup 2)
4664 (const_int 24)))]
cffb2a26 4665 "TARGET_ARM"
c8f69309 4666 "
215b30b3 4667 {
4668 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4669 {
4670 emit_insn (gen_rtx_SET (VOIDmode,
4671 operands[0],
4672 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4673 DONE;
4674 }
4675 if (!s_register_operand (operands[1], QImode))
4676 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4677 operands[0] = gen_lowpart (SImode, operands[0]);
4678 operands[1] = gen_lowpart (SImode, operands[1]);
4679 operands[2] = gen_reg_rtx (SImode);
4680 }"
4681)
f7fbdd4a 4682
25f905c2 4683(define_insn "*arm_extendqihi_insn"
b4e8a300 4684 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4685 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4686 "TARGET_ARM && arm_arch4"
25f905c2 4687 "ldr%(sb%)\\t%0, %1"
a2cd141b 4688 [(set_attr "type" "load_byte")
0d66636f 4689 (set_attr "predicable" "yes")
cffb2a26 4690 (set_attr "pool_range" "256")
4691 (set_attr "neg_pool_range" "244")]
4692)
3fc2009e 4693
b11cae9e 4694(define_expand "extendqisi2"
ef51b8e1 4695 [(set (match_operand:SI 0 "s_register_operand" "")
4696 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 4697 "TARGET_EITHER"
ef51b8e1 4698{
4699 if (!arm_arch4 && MEM_P (operands[1]))
4700 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4701
ef51b8e1 4702 if (!arm_arch6 && !MEM_P (operands[1]))
4703 {
4704 rtx t = gen_lowpart (SImode, operands[1]);
4705 rtx tmp = gen_reg_rtx (SImode);
4706 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4707 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4708 DONE;
4709 }
4710})
a2cd141b 4711
ef51b8e1 4712(define_split
4713 [(set (match_operand:SI 0 "register_operand" "")
4714 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4715 "!arm_arch6"
4716 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4717 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4718{
4719 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4720})
f7fbdd4a 4721
a2cd141b 4722(define_insn "*arm_extendqisi"
ef51b8e1 4723 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4724 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4725 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4726 "@
4727 #
4728 ldr%(sb%)\\t%0, %1"
4729 [(set_attr "length" "8,4")
4730 (set_attr "type" "alu_shift,load_byte")
0d66636f 4731 (set_attr "predicable" "yes")
ef51b8e1 4732 (set_attr "pool_range" "*,256")
4733 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4734)
3fc2009e 4735
a2cd141b 4736(define_insn "*arm_extendqisi_v6"
4737 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4738 (sign_extend:SI
4739 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4740 "TARGET_ARM && arm_arch6"
b4e8a300 4741 "@
4742 sxtb%?\\t%0, %1
25f905c2 4743 ldr%(sb%)\\t%0, %1"
a2cd141b 4744 [(set_attr "type" "alu_shift,load_byte")
4745 (set_attr "predicable" "yes")
a2cd141b 4746 (set_attr "pool_range" "*,256")
4747 (set_attr "neg_pool_range" "*,244")]
4748)
4749
4750(define_insn "*arm_extendqisi2addsi"
4751 [(set (match_operand:SI 0 "s_register_operand" "=r")
4752 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4753 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4754 "TARGET_INT_SIMD"
a2cd141b 4755 "sxtab%?\\t%0, %2, %1"
4756 [(set_attr "type" "alu_shift")
bcaec148 4757 (set_attr "insn" "xtab")
a2cd141b 4758 (set_attr "predicable" "yes")]
4759)
4760
ef51b8e1 4761(define_split
4762 [(set (match_operand:SI 0 "register_operand" "")
4763 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4764 "TARGET_THUMB1 && reload_completed"
4765 [(set (match_dup 0) (match_dup 2))
4766 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4767{
4768 rtx addr = XEXP (operands[1], 0);
cffb2a26 4769
ef51b8e1 4770 if (GET_CODE (addr) == CONST)
4771 addr = XEXP (addr, 0);
cffb2a26 4772
ef51b8e1 4773 if (GET_CODE (addr) == PLUS
4774 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4775 /* No split necessary. */
4776 FAIL;
4777
4778 if (GET_CODE (addr) == PLUS
4779 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4780 FAIL;
4781
4782 if (reg_overlap_mentioned_p (operands[0], addr))
4783 {
4784 rtx t = gen_lowpart (QImode, operands[0]);
4785 emit_move_insn (t, operands[1]);
4786 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4787 DONE;
4788 }
4789
4790 if (REG_P (addr))
4791 {
4792 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4793 operands[2] = const0_rtx;
4794 }
4795 else if (GET_CODE (addr) != PLUS)
4796 FAIL;
4797 else if (REG_P (XEXP (addr, 0)))
4798 {
4799 operands[2] = XEXP (addr, 1);
4800 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4801 }
4802 else
4803 {
4804 operands[2] = XEXP (addr, 0);
4805 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4806 }
cffb2a26 4807
ef51b8e1 4808 operands[3] = change_address (operands[1], QImode, addr);
4809})
4810
8a3b73a1 4811(define_peephole2
4812 [(set (match_operand:SI 0 "register_operand" "")
4813 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4814 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4815 (set (match_operand:SI 3 "register_operand" "")
4816 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4817 "TARGET_THUMB1
4818 && GET_CODE (XEXP (operands[4], 0)) == PLUS
4819 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4820 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4821 && (peep2_reg_dead_p (3, operands[0])
4822 || rtx_equal_p (operands[0], operands[3]))
4823 && (peep2_reg_dead_p (3, operands[2])
4824 || rtx_equal_p (operands[2], operands[3]))"
4825 [(set (match_dup 2) (match_dup 1))
4826 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4827{
4828 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4829 operands[4] = change_address (operands[4], QImode, addr);
4830})
4831
ef51b8e1 4832(define_insn "thumb1_extendqisi2"
a2cd141b 4833 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4834 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 4835 "TARGET_THUMB1"
4836{
4837 rtx addr;
a2cd141b 4838
ef51b8e1 4839 if (which_alternative == 0 && arm_arch6)
4840 return "sxtb\\t%0, %1";
4841 if (which_alternative == 0)
4842 return "#";
a2cd141b 4843
ef51b8e1 4844 addr = XEXP (operands[1], 0);
4845 if (GET_CODE (addr) == PLUS
4846 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4847 return "ldrsb\\t%0, %1";
a2cd141b 4848
ef51b8e1 4849 return "#";
4850}
4851 [(set_attr_alternative "length"
4852 [(if_then_else (eq_attr "is_arch6" "yes")
4853 (const_int 2) (const_int 4))
4854 (const_int 2)
4855 (if_then_else (eq_attr "is_arch6" "yes")
4856 (const_int 4) (const_int 6))])
4857 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 4858)
4859
caedf871 4860(define_expand "extendsfdf2"
4861 [(set (match_operand:DF 0 "s_register_operand" "")
4862 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4863 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4864 ""
4865)
9b8516be 4866
4867/* HFmode -> DFmode conversions have to go through SFmode. */
4868(define_expand "extendhfdf2"
4869 [(set (match_operand:DF 0 "general_operand" "")
4870 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4871 "TARGET_EITHER"
4872 "
4873 {
4874 rtx op1;
4875 op1 = convert_to_mode (SFmode, operands[1], 0);
4876 op1 = convert_to_mode (DFmode, op1, 0);
4877 emit_insn (gen_movdf (operands[0], op1));
4878 DONE;
4879 }"
4880)
b11cae9e 4881\f
4882;; Move insns (including loads and stores)
4883
4884;; XXX Just some ideas about movti.
9c08d1fa 4885;; I don't think these are a good idea on the arm, there just aren't enough
4886;; registers
b11cae9e 4887;;(define_expand "loadti"
9c08d1fa 4888;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4889;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4890;; "" "")
4891
4892;;(define_expand "storeti"
4893;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4894;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4895;; "" "")
4896
4897;;(define_expand "movti"
4898;; [(set (match_operand:TI 0 "general_operand" "")
4899;; (match_operand:TI 1 "general_operand" ""))]
4900;; ""
4901;; "
4902;;{
4903;; rtx insn;
4904;;
4905;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4906;; operands[1] = copy_to_reg (operands[1]);
4907;; if (GET_CODE (operands[0]) == MEM)
4908;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4909;; else if (GET_CODE (operands[1]) == MEM)
4910;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4911;; else
4912;; FAIL;
4913;;
4914;; emit_insn (insn);
4915;; DONE;
4916;;}")
4917
a2f10574 4918;; Recognize garbage generated above.
b11cae9e 4919
4920;;(define_insn ""
4921;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4922;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4923;; ""
4924;; "*
4925;; {
4926;; register mem = (which_alternative < 3);
0d66636f 4927;; register const char *template;
b11cae9e 4928;;
4929;; operands[mem] = XEXP (operands[mem], 0);
4930;; switch (which_alternative)
4931;; {
4932;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4933;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4934;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4935;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4936;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4937;; case 5: template = \"stmia\\t%0, %M1\"; break;
4938;; }
e2348bcb 4939;; output_asm_insn (template, operands);
4940;; return \"\";
b11cae9e 4941;; }")
4942
cffb2a26 4943(define_expand "movdi"
4944 [(set (match_operand:DI 0 "general_operand" "")
4945 (match_operand:DI 1 "general_operand" ""))]
4946 "TARGET_EITHER"
4947 "
e1ba4a27 4948 if (can_create_pseudo_p ())
cffb2a26 4949 {
b2778788 4950 if (GET_CODE (operands[0]) != REG)
4951 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4952 }
4953 "
4954)
b11cae9e 4955
cffb2a26 4956(define_insn "*arm_movdi"
d51f92df 4957 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4958 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 4959 "TARGET_32BIT
b2778788 4960 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4961 && !TARGET_IWMMXT
4962 && ( register_operand (operands[0], DImode)
4963 || register_operand (operands[1], DImode))"
b11cae9e 4964 "*
d51f92df 4965 switch (which_alternative)
4966 {
4967 case 0:
4968 case 1:
4969 case 2:
4970 return \"#\";
4971 default:
4972 return output_move_double (operands);
4973 }
cffb2a26 4974 "
359a6e9f 4975 [(set_attr "length" "8,12,16,8,8")
4976 (set_attr "type" "*,*,*,load2,store2")
cde1623a 4977 (set_attr "arm_pool_range" "*,*,*,1020,*")
4978 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
4979 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
4980 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 4981)
4982
d51f92df 4983(define_split
4984 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4985 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4986 "TARGET_32BIT
d51f92df 4987 && reload_completed
4988 && (arm_const_double_inline_cost (operands[1])
4989 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4990 [(const_int 0)]
4991 "
4992 arm_split_constant (SET, SImode, curr_insn,
4993 INTVAL (gen_lowpart (SImode, operands[1])),
4994 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4995 arm_split_constant (SET, SImode, curr_insn,
4996 INTVAL (gen_highpart_mode (SImode,
4997 GET_MODE (operands[0]),
4998 operands[1])),
4999 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5000 DONE;
5001 "
5002)
5003
e5ba9289 5004; If optimizing for size, or if we have load delay slots, then
5005; we want to split the constant into two separate operations.
5006; In both cases this may split a trivial part into a single data op
5007; leaving a single complex constant to load. We can also get longer
5008; offsets in a LDR which means we get better chances of sharing the pool
5009; entries. Finally, we can normally do a better job of scheduling
5010; LDR instructions than we can with LDM.
5011; This pattern will only match if the one above did not.
5012(define_split
5013 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5014 (match_operand:ANY64 1 "const_double_operand" ""))]
5015 "TARGET_ARM && reload_completed
5016 && arm_const_double_by_parts (operands[1])"
5017 [(set (match_dup 0) (match_dup 1))
5018 (set (match_dup 2) (match_dup 3))]
5019 "
5020 operands[2] = gen_highpart (SImode, operands[0]);
5021 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5022 operands[1]);
5023 operands[0] = gen_lowpart (SImode, operands[0]);
5024 operands[1] = gen_lowpart (SImode, operands[1]);
5025 "
5026)
5027
d51f92df 5028(define_split
5029 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5030 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5031 "TARGET_EITHER && reload_completed"
5032 [(set (match_dup 0) (match_dup 1))
5033 (set (match_dup 2) (match_dup 3))]
5034 "
5035 operands[2] = gen_highpart (SImode, operands[0]);
5036 operands[3] = gen_highpart (SImode, operands[1]);
5037 operands[0] = gen_lowpart (SImode, operands[0]);
5038 operands[1] = gen_lowpart (SImode, operands[1]);
5039
5040 /* Handle a partial overlap. */
5041 if (rtx_equal_p (operands[0], operands[3]))
5042 {
5043 rtx tmp0 = operands[0];
5044 rtx tmp1 = operands[1];
5045
5046 operands[0] = operands[2];
5047 operands[1] = operands[3];
5048 operands[2] = tmp0;
5049 operands[3] = tmp1;
5050 }
5051 "
5052)
5053
a8a3b539 5054;; We can't actually do base+index doubleword loads if the index and
5055;; destination overlap. Split here so that we at least have chance to
5056;; schedule.
5057(define_split
5058 [(set (match_operand:DI 0 "s_register_operand" "")
5059 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5060 (match_operand:SI 2 "s_register_operand" ""))))]
5061 "TARGET_LDRD
5062 && reg_overlap_mentioned_p (operands[0], operands[1])
5063 && reg_overlap_mentioned_p (operands[0], operands[2])"
5064 [(set (match_dup 4)
5065 (plus:SI (match_dup 1)
5066 (match_dup 2)))
5067 (set (match_dup 0)
5068 (mem:DI (match_dup 4)))]
5069 "
5070 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5071 "
5072)
5073
cffb2a26 5074;;; ??? This should have alternatives for constants.
5075;;; ??? This was originally identical to the movdf_insn pattern.
5076;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5077;;; thumb_reorg with a memory reference.
25f905c2 5078(define_insn "*thumb1_movdi_insn"
215b30b3 5079 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5080 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 5081 "TARGET_THUMB1
a2cd141b 5082 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 5083 && ( register_operand (operands[0], DImode)
5084 || register_operand (operands[1], DImode))"
5085 "*
5086 {
5087 switch (which_alternative)
5088 {
5089 default:
5090 case 0:
5091 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5092 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5093 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5094 case 1:
5095 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5096 case 2:
5097 operands[1] = GEN_INT (- INTVAL (operands[1]));
5098 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5099 case 3:
5100 return \"ldmia\\t%1, {%0, %H0}\";
5101 case 4:
5102 return \"stmia\\t%0, {%1, %H1}\";
5103 case 5:
5104 return thumb_load_double_from_address (operands);
5105 case 6:
1a83b3ff 5106 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5107 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5108 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5109 return \"\";
5110 case 7:
5111 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5112 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5113 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5114 }
5115 }"
5116 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5117 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5118 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5119 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5120)
b11cae9e 5121
9c08d1fa 5122(define_expand "movsi"
5123 [(set (match_operand:SI 0 "general_operand" "")
5124 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5125 "TARGET_EITHER"
9c08d1fa 5126 "
befb0bac 5127 {
e348ff3e 5128 rtx base, offset, tmp;
5129
25f905c2 5130 if (TARGET_32BIT)
9c08d1fa 5131 {
674a8f0b 5132 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5133 if (GET_CODE (operands[0]) == MEM)
5134 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5135 if (arm_general_register_operand (operands[0], SImode)
5136 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5137 && !(const_ok_for_arm (INTVAL (operands[1]))
5138 || const_ok_for_arm (~INTVAL (operands[1]))))
5139 {
96f57e36 5140 arm_split_constant (SET, SImode, NULL_RTX,
5141 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5142 optimize && can_create_pseudo_p ());
cffb2a26 5143 DONE;
5144 }
d0e6a121 5145
5146 if (TARGET_USE_MOVT && !target_word_relocations
5147 && GET_CODE (operands[1]) == SYMBOL_REF
5148 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5149 {
5150 arm_emit_movpair (operands[0], operands[1]);
5151 DONE;
5152 }
cffb2a26 5153 }
25f905c2 5154 else /* TARGET_THUMB1... */
cffb2a26 5155 {
e1ba4a27 5156 if (can_create_pseudo_p ())
cffb2a26 5157 {
5158 if (GET_CODE (operands[0]) != REG)
5159 operands[1] = force_reg (SImode, operands[1]);
5160 }
9c08d1fa 5161 }
f655717d 5162
e348ff3e 5163 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5164 {
5165 split_const (operands[1], &base, &offset);
5166 if (GET_CODE (base) == SYMBOL_REF
5167 && !offset_within_block_p (base, INTVAL (offset)))
5168 {
b308ddcf 5169 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5170 emit_move_insn (tmp, base);
5171 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5172 DONE;
5173 }
5174 }
5175
f655717d 5176 /* Recognize the case where operand[1] is a reference to thread-local
5177 data and load its address to a register. */
5178 if (arm_tls_referenced_p (operands[1]))
5179 {
5180 rtx tmp = operands[1];
5181 rtx addend = NULL;
5182
5183 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5184 {
5185 addend = XEXP (XEXP (tmp, 0), 1);
5186 tmp = XEXP (XEXP (tmp, 0), 0);
5187 }
5188
5189 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5190 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5191
e1ba4a27 5192 tmp = legitimize_tls_address (tmp,
5193 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5194 if (addend)
5195 {
5196 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5197 tmp = force_operand (tmp, operands[0]);
5198 }
5199 operands[1] = tmp;
5200 }
5201 else if (flag_pic
5202 && (CONSTANT_P (operands[1])
5203 || symbol_mentioned_p (operands[1])
5204 || label_mentioned_p (operands[1])))
5205 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5206 (!can_create_pseudo_p ()
5207 ? operands[0]
5208 : 0));
befb0bac 5209 }
215b30b3 5210 "
5211)
9c08d1fa 5212
d0e6a121 5213;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5214;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5215;; so this does not matter.
5216(define_insn "*arm_movt"
5217 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5218 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5219 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5220 "arm_arch_thumb2"
d0e6a121 5221 "movt%?\t%0, #:upper16:%c2"
5222 [(set_attr "predicable" "yes")
5223 (set_attr "length" "4")]
5224)
5225
cffb2a26 5226(define_insn "*arm_movsi_insn"
aaa37ad6 5227 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5228 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5229 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5230 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5231 && ( register_operand (operands[0], SImode)
5232 || register_operand (operands[1], SImode))"
f7fbdd4a 5233 "@
aaa37ad6 5234 mov%?\\t%0, %1
f7fbdd4a 5235 mov%?\\t%0, %1
5236 mvn%?\\t%0, #%B1
25f905c2 5237 movw%?\\t%0, %1
f7fbdd4a 5238 ldr%?\\t%0, %1
5239 str%?\\t%1, %0"
aaa37ad6 5240 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5241 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5242 (set_attr "predicable" "yes")
aaa37ad6 5243 (set_attr "pool_range" "*,*,*,*,4096,*")
5244 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5245)
87b22bf7 5246
5247(define_split
a2cd141b 5248 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5249 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5250 "TARGET_32BIT
215b30b3 5251 && (!(const_ok_for_arm (INTVAL (operands[1]))
5252 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5253 [(clobber (const_int 0))]
5254 "
96f57e36 5255 arm_split_constant (SET, SImode, NULL_RTX,
5256 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5257 DONE;
215b30b3 5258 "
5259)
9c08d1fa 5260
25f905c2 5261(define_insn "*thumb1_movsi_insn"
55a0d64c 5262 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5263 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 5264 "TARGET_THUMB1
cffb2a26 5265 && ( register_operand (operands[0], SImode)
5266 || register_operand (operands[1], SImode))"
5267 "@
5268 mov %0, %1
5269 mov %0, %1
5270 #
5271 #
5272 ldmia\\t%1, {%0}
5273 stmia\\t%0, {%1}
5274 ldr\\t%0, %1
5275 str\\t%1, %0
5276 mov\\t%0, %1"
5277 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5278 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5279 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5280 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5281
5282(define_split
5283 [(set (match_operand:SI 0 "register_operand" "")
5284 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5285 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5286 [(set (match_dup 2) (match_dup 1))
5287 (set (match_dup 0) (neg:SI (match_dup 2)))]
5288 "
5289 {
5290 operands[1] = GEN_INT (- INTVAL (operands[1]));
5291 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5292 }"
cffb2a26 5293)
5294
5295(define_split
5296 [(set (match_operand:SI 0 "register_operand" "")
5297 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5298 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5299 [(set (match_dup 2) (match_dup 1))
5300 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5301 "
5302 {
e4aeee53 5303 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5304 unsigned HOST_WIDE_INT mask = 0xff;
5305 int i;
5306
5307 for (i = 0; i < 25; i++)
5308 if ((val & (mask << i)) == val)
5309 break;
5310
1276f1b8 5311 /* Don't split if the shift is zero. */
cffb2a26 5312 if (i == 0)
5313 FAIL;
5314
5315 operands[1] = GEN_INT (val >> i);
1276f1b8 5316 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5317 operands[3] = GEN_INT (i);
cffb2a26 5318 }"
5319)
5320
67336bcf 5321;; When generating pic, we need to load the symbol offset into a register.
5322;; So that the optimizer does not confuse this with a normal symbol load
5323;; we use an unspec. The offset will be loaded from a constant pool entry,
5324;; since that is the only type of relocation we can use.
5325
94f8caca 5326;; Wrap calculation of the whole PIC address in a single pattern for the
5327;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5328;; a PIC address involves two loads from memory, so we want to CSE it
5329;; as often as possible.
5330;; This pattern will be split into one of the pic_load_addr_* patterns
5331;; and a move after GCSE optimizations.
5332;;
5333;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5334(define_expand "calculate_pic_address"
5335 [(set (match_operand:SI 0 "register_operand" "")
5336 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5337 (unspec:SI [(match_operand:SI 2 "" "")]
5338 UNSPEC_PIC_SYM))))]
5339 "flag_pic"
5340)
5341
5342;; Split calculate_pic_address into pic_load_addr_* and a move.
5343(define_split
5344 [(set (match_operand:SI 0 "register_operand" "")
5345 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5346 (unspec:SI [(match_operand:SI 2 "" "")]
5347 UNSPEC_PIC_SYM))))]
5348 "flag_pic"
5349 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5350 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5351 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5352)
5353
67336bcf 5354;; The rather odd constraints on the following are to force reload to leave
5355;; the insn alone, and to force the minipool generation pass to then move
5356;; the GOT symbol to memory.
849170fd 5357
b3cd5f55 5358(define_insn "pic_load_addr_32bit"
849170fd 5359 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5360 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5361 "TARGET_32BIT && flag_pic"
67336bcf 5362 "ldr%?\\t%0, %1"
a2cd141b 5363 [(set_attr "type" "load1")
b3cd5f55 5364 (set_attr "pool_range" "4096")
5365 (set (attr "neg_pool_range")
5366 (if_then_else (eq_attr "is_thumb" "no")
5367 (const_int 4084)
5368 (const_int 0)))]
8c4d8060 5369)
5370
25f905c2 5371(define_insn "pic_load_addr_thumb1"
8c4d8060 5372 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5373 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5374 "TARGET_THUMB1 && flag_pic"
8c4d8060 5375 "ldr\\t%0, %1"
a2cd141b 5376 [(set_attr "type" "load1")
8c4d8060 5377 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5378)
849170fd 5379
cffb2a26 5380(define_insn "pic_add_dot_plus_four"
15d5d060 5381 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5382 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5383 (const_int 4)
beef0fb5 5384 (match_operand 2 "" "")]
5385 UNSPEC_PIC_BASE))]
b3cd5f55 5386 "TARGET_THUMB"
cffb2a26 5387 "*
6cdcb15c 5388 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5389 INTVAL (operands[2]));
cffb2a26 5390 return \"add\\t%0, %|pc\";
5391 "
5392 [(set_attr "length" "2")]
5393)
849170fd 5394
5395(define_insn "pic_add_dot_plus_eight"
15d5d060 5396 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5397 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5398 (const_int 8)
beef0fb5 5399 (match_operand 2 "" "")]
5400 UNSPEC_PIC_BASE))]
f655717d 5401 "TARGET_ARM"
c4034607 5402 "*
6cdcb15c 5403 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5404 INTVAL (operands[2]));
15d5d060 5405 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5406 "
0d66636f 5407 [(set_attr "predicable" "yes")]
cffb2a26 5408)
849170fd 5409
f655717d 5410(define_insn "tls_load_dot_plus_eight"
cc071db6 5411 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5412 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5413 (const_int 8)
beef0fb5 5414 (match_operand 2 "" "")]
5415 UNSPEC_PIC_BASE)))]
f655717d 5416 "TARGET_ARM"
5417 "*
6cdcb15c 5418 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5419 INTVAL (operands[2]));
f655717d 5420 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5421 "
5422 [(set_attr "predicable" "yes")]
5423)
5424
5425;; PIC references to local variables can generate pic_add_dot_plus_eight
5426;; followed by a load. These sequences can be crunched down to
5427;; tls_load_dot_plus_eight by a peephole.
5428
5429(define_peephole2
c0c1fba5 5430 [(set (match_operand:SI 0 "register_operand" "")
5431 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5432 (const_int 8)
5433 (match_operand 1 "" "")]
5434 UNSPEC_PIC_BASE))
f655717d 5435 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5436 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5437 [(set (match_dup 2)
5438 (mem:SI (unspec:SI [(match_dup 3)
5439 (const_int 8)
5440 (match_dup 1)]
5441 UNSPEC_PIC_BASE)))]
f655717d 5442 ""
5443)
5444
bac7fc85 5445(define_insn "pic_offset_arm"
5446 [(set (match_operand:SI 0 "register_operand" "=r")
5447 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5448 (unspec:SI [(match_operand:SI 2 "" "X")]
5449 UNSPEC_PIC_OFFSET))))]
5450 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5451 "ldr%?\\t%0, [%1,%2]"
5452 [(set_attr "type" "load1")]
5453)
5454
95373f08 5455(define_expand "builtin_setjmp_receiver"
5456 [(label_ref (match_operand 0 "" ""))]
5457 "flag_pic"
5458 "
5459{
b935b306 5460 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5461 register. */
2cb7d577 5462 if (arm_pic_register != INVALID_REGNUM)
5463 arm_load_pic_register (1UL << 3);
95373f08 5464 DONE;
5465}")
5466
9c08d1fa 5467;; If copying one reg to another we can set the condition codes according to
5468;; its value. Such a move is common after a return from subroutine and the
5469;; result is being tested against zero.
5470
f7fbdd4a 5471(define_insn "*movsi_compare0"
bd5b4116 5472 [(set (reg:CC CC_REGNUM)
cffb2a26 5473 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5474 (const_int 0)))
5475 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5476 (match_dup 1))]
25f905c2 5477 "TARGET_32BIT"
e2348bcb 5478 "@
40dbec34 5479 cmp%?\\t%0, #0
25f905c2 5480 sub%.\\t%0, %1, #0"
cffb2a26 5481 [(set_attr "conds" "set")]
5482)
b11cae9e 5483
b11cae9e 5484;; Subroutine to store a half word from a register into memory.
5485;; Operand 0 is the source register (HImode)
c8f69309 5486;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5487
9c08d1fa 5488;; In both this routine and the next, we must be careful not to spill
01cc3b75 5489;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5490;; can generate unrecognizable rtl.
5491
b11cae9e 5492(define_expand "storehi"
c8f69309 5493 [;; store the low byte
f082f1c4 5494 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5495 ;; extract the high byte
c8f69309 5496 (set (match_dup 2)
5497 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5498 ;; store the high byte
787f8210 5499 (set (match_dup 4) (match_dup 5))]
cffb2a26 5500 "TARGET_ARM"
b11cae9e 5501 "
215b30b3 5502 {
537ffcfc 5503 rtx op1 = operands[1];
5504 rtx addr = XEXP (op1, 0);
215b30b3 5505 enum rtx_code code = GET_CODE (addr);
5506
5507 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5508 || code == MINUS)
537ffcfc 5509 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5510
537ffcfc 5511 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5512 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5513 operands[3] = gen_lowpart (QImode, operands[0]);
5514 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5515 operands[2] = gen_reg_rtx (SImode);
5516 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5517 }"
5518)
b11cae9e 5519
c7597b5d 5520(define_expand "storehi_bigend"
f082f1c4 5521 [(set (match_dup 4) (match_dup 3))
c7597b5d 5522 (set (match_dup 2)
5523 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5524 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5525 "TARGET_ARM"
b11cae9e 5526 "
215b30b3 5527 {
537ffcfc 5528 rtx op1 = operands[1];
5529 rtx addr = XEXP (op1, 0);
215b30b3 5530 enum rtx_code code = GET_CODE (addr);
5531
5532 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5533 || code == MINUS)
537ffcfc 5534 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5535
537ffcfc 5536 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5537 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5538 operands[3] = gen_lowpart (QImode, operands[0]);
5539 operands[0] = gen_lowpart (SImode, operands[0]);
5540 operands[2] = gen_reg_rtx (SImode);
787f8210 5541 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5542 }"
5543)
c7597b5d 5544
5545;; Subroutine to store a half word integer constant into memory.
5546(define_expand "storeinthi"
f082f1c4 5547 [(set (match_operand 0 "" "")
787f8210 5548 (match_operand 1 "" ""))
9e8503e6 5549 (set (match_dup 3) (match_dup 2))]
cffb2a26 5550 "TARGET_ARM"
c7597b5d 5551 "
215b30b3 5552 {
5553 HOST_WIDE_INT value = INTVAL (operands[1]);
5554 rtx addr = XEXP (operands[0], 0);
537ffcfc 5555 rtx op0 = operands[0];
215b30b3 5556 enum rtx_code code = GET_CODE (addr);
c7597b5d 5557
215b30b3 5558 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5559 || code == MINUS)
537ffcfc 5560 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5561
215b30b3 5562 operands[1] = gen_reg_rtx (SImode);
5563 if (BYTES_BIG_ENDIAN)
5564 {
5565 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5566 if ((value & 255) == ((value >> 8) & 255))
5567 operands[2] = operands[1];
5568 else
5569 {
5570 operands[2] = gen_reg_rtx (SImode);
5571 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5572 }
5573 }
5574 else
5575 {
5576 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5577 if ((value & 255) == ((value >> 8) & 255))
5578 operands[2] = operands[1];
5579 else
5580 {
5581 operands[2] = gen_reg_rtx (SImode);
5582 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5583 }
5584 }
c7597b5d 5585
537ffcfc 5586 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5587 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5588 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5589 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5590 }"
5591)
b11cae9e 5592
f7fbdd4a 5593(define_expand "storehi_single_op"
5594 [(set (match_operand:HI 0 "memory_operand" "")
5595 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5596 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5597 "
215b30b3 5598 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5599 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5600 "
5601)
f7fbdd4a 5602
b11cae9e 5603(define_expand "movhi"
5604 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5605 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5606 "TARGET_EITHER"
b11cae9e 5607 "
cffb2a26 5608 if (TARGET_ARM)
b11cae9e 5609 {
e1ba4a27 5610 if (can_create_pseudo_p ())
cffb2a26 5611 {
5612 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5613 {
cffb2a26 5614 if (arm_arch4)
5615 {
5616 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5617 DONE;
5618 }
5619 if (GET_CODE (operands[1]) == CONST_INT)
5620 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5621 else
cffb2a26 5622 {
5623 if (GET_CODE (operands[1]) == MEM)
5624 operands[1] = force_reg (HImode, operands[1]);
5625 if (BYTES_BIG_ENDIAN)
5626 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5627 else
5628 emit_insn (gen_storehi (operands[1], operands[0]));
5629 }
5630 DONE;
b11cae9e 5631 }
cffb2a26 5632 /* Sign extend a constant, and keep it in an SImode reg. */
5633 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5634 {
cffb2a26 5635 rtx reg = gen_reg_rtx (SImode);
5636 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5637
5638 /* If the constant is already valid, leave it alone. */
215b30b3 5639 if (!const_ok_for_arm (val))
cffb2a26 5640 {
5641 /* If setting all the top bits will make the constant
5642 loadable in a single instruction, then set them.
5643 Otherwise, sign extend the number. */
5644
215b30b3 5645 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5646 val |= ~0xffff;
5647 else if (val & 0x8000)
5648 val |= ~0xffff;
5649 }
5650
5651 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5652 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5653 }
e1ba4a27 5654 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5655 && GET_CODE (operands[1]) == MEM)
5656 {
5657 rtx reg = gen_reg_rtx (SImode);
5658
5659 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5660 operands[1] = gen_lowpart (HImode, reg);
5661 }
215b30b3 5662 else if (!arm_arch4)
f7fbdd4a 5663 {
cffb2a26 5664 if (GET_CODE (operands[1]) == MEM)
5665 {
c1a66faf 5666 rtx base;
5667 rtx offset = const0_rtx;
5668 rtx reg = gen_reg_rtx (SImode);
5669
5670 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5671 || (GET_CODE (base) == PLUS
5672 && (GET_CODE (offset = XEXP (base, 1))
5673 == CONST_INT)
5674 && ((INTVAL(offset) & 1) != 1)
5675 && GET_CODE (base = XEXP (base, 0)) == REG))
5676 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5677 {
8deb3959 5678 rtx new_rtx;
c1a66faf 5679
8deb3959 5680 new_rtx = widen_memory_access (operands[1], SImode,
5681 ((INTVAL (offset) & ~3)
5682 - INTVAL (offset)));
5683 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5684 if (((INTVAL (offset) & 2) != 0)
5685 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5686 {
5687 rtx reg2 = gen_reg_rtx (SImode);
5688
5689 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5690 reg = reg2;
5691 }
206ee9a2 5692 }
c1a66faf 5693 else
5694 emit_insn (gen_movhi_bytes (reg, operands[1]));
5695
5696 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5697 }
5698 }
5699 }
674a8f0b 5700 /* Handle loading a large integer during reload. */
cffb2a26 5701 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5702 && !const_ok_for_arm (INTVAL (operands[1]))
5703 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5704 {
5705 /* Writing a constant to memory needs a scratch, which should
5706 be handled with SECONDARY_RELOADs. */
ed29c566 5707 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5708
5709 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5710 emit_insn (gen_movsi (operands[0], operands[1]));
5711 DONE;
5712 }
5713 }
25f905c2 5714 else if (TARGET_THUMB2)
5715 {
5716 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5717 if (can_create_pseudo_p ())
25f905c2 5718 {
5719 if (GET_CODE (operands[0]) != REG)
5720 operands[1] = force_reg (HImode, operands[1]);
5721 /* Zero extend a constant, and keep it in an SImode reg. */
5722 else if (GET_CODE (operands[1]) == CONST_INT)
5723 {
5724 rtx reg = gen_reg_rtx (SImode);
5725 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5726
5727 emit_insn (gen_movsi (reg, GEN_INT (val)));
5728 operands[1] = gen_lowpart (HImode, reg);
5729 }
5730 }
5731 }
5732 else /* TARGET_THUMB1 */
cffb2a26 5733 {
e1ba4a27 5734 if (can_create_pseudo_p ())
cffb2a26 5735 {
6cffc037 5736 if (GET_CODE (operands[1]) == CONST_INT)
5737 {
5738 rtx reg = gen_reg_rtx (SImode);
5739
5740 emit_insn (gen_movsi (reg, operands[1]));
5741 operands[1] = gen_lowpart (HImode, reg);
5742 }
cffb2a26 5743
5744 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5745 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5746 virtual register (also rejected as illegitimate for HImode/QImode)
5747 relative address. */
cffb2a26 5748 /* ??? This should perhaps be fixed elsewhere, for instance, in
5749 fixup_stack_1, by checking for other kinds of invalid addresses,
5750 e.g. a bare reference to a virtual register. This may confuse the
5751 alpha though, which must handle this case differently. */
5752 if (GET_CODE (operands[0]) == MEM
215b30b3 5753 && !memory_address_p (GET_MODE (operands[0]),
5754 XEXP (operands[0], 0)))
537ffcfc 5755 operands[0]
5756 = replace_equiv_address (operands[0],
5757 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5758
5759 if (GET_CODE (operands[1]) == MEM
215b30b3 5760 && !memory_address_p (GET_MODE (operands[1]),
5761 XEXP (operands[1], 0)))
537ffcfc 5762 operands[1]
5763 = replace_equiv_address (operands[1],
5764 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5765
5766 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5767 {
5768 rtx reg = gen_reg_rtx (SImode);
5769
5770 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5771 operands[1] = gen_lowpart (HImode, reg);
5772 }
5773
5774 if (GET_CODE (operands[0]) == MEM)
5775 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5776 }
cffb2a26 5777 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5778 && !satisfies_constraint_I (operands[1]))
cffb2a26 5779 {
6cffc037 5780 /* Handle loading a large integer during reload. */
5781
cffb2a26 5782 /* Writing a constant to memory needs a scratch, which should
5783 be handled with SECONDARY_RELOADs. */
ed29c566 5784 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5785
1a83b3ff 5786 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5787 emit_insn (gen_movsi (operands[0], operands[1]));
5788 DONE;
5789 }
b11cae9e 5790 }
cffb2a26 5791 "
5792)
5793
25f905c2 5794(define_insn "*thumb1_movhi_insn"
a941568e 5795 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5796 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5797 "TARGET_THUMB1
cffb2a26 5798 && ( register_operand (operands[0], HImode)
5799 || register_operand (operands[1], HImode))"
5800 "*
5801 switch (which_alternative)
d79300ac 5802 {
cffb2a26 5803 case 0: return \"add %0, %1, #0\";
5804 case 2: return \"strh %1, %0\";
5805 case 3: return \"mov %0, %1\";
5806 case 4: return \"mov %0, %1\";
5807 case 5: return \"mov %0, %1\";
ed29c566 5808 default: gcc_unreachable ();
cffb2a26 5809 case 1:
5810 /* The stack pointer can end up being taken as an index register.
5811 Catch this case here and deal with it. */
5812 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5813 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5814 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5815 {
5816 rtx ops[2];
5817 ops[0] = operands[0];
5818 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5819
5820 output_asm_insn (\"mov %0, %1\", ops);
5821
5822 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5823
5824 }
5825 return \"ldrh %0, %1\";
5826 }"
5827 [(set_attr "length" "2,4,2,2,2,2")
747b7458 5828 (set_attr "type" "*,load1,store1,*,*,*")
5829 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 5830
b11cae9e 5831
25f7a26e 5832(define_expand "movhi_bytes"
eab14235 5833 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5834 (set (match_dup 3)
eab14235 5835 (zero_extend:SI (match_dup 6)))
25f7a26e 5836 (set (match_operand:SI 0 "" "")
5837 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5838 "TARGET_ARM"
25f7a26e 5839 "
215b30b3 5840 {
5841 rtx mem1, mem2;
5842 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5843
788fcce0 5844 mem1 = change_address (operands[1], QImode, addr);
5845 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5846 operands[0] = gen_lowpart (SImode, operands[0]);
5847 operands[1] = mem1;
5848 operands[2] = gen_reg_rtx (SImode);
5849 operands[3] = gen_reg_rtx (SImode);
5850 operands[6] = mem2;
25f7a26e 5851
215b30b3 5852 if (BYTES_BIG_ENDIAN)
5853 {
5854 operands[4] = operands[2];
5855 operands[5] = operands[3];
5856 }
5857 else
5858 {
5859 operands[4] = operands[3];
5860 operands[5] = operands[2];
5861 }
5862 }"
5863)
25f7a26e 5864
c7597b5d 5865(define_expand "movhi_bigend"
5866 [(set (match_dup 2)
5867 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5868 (const_int 16)))
5869 (set (match_dup 3)
5870 (ashiftrt:SI (match_dup 2) (const_int 16)))
5871 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5872 (match_dup 4))]
cffb2a26 5873 "TARGET_ARM"
c7597b5d 5874 "
5875 operands[2] = gen_reg_rtx (SImode);
5876 operands[3] = gen_reg_rtx (SImode);
787f8210 5877 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5878 "
5879)
b11cae9e 5880
a2f10574 5881;; Pattern to recognize insn generated default case above
f7fbdd4a 5882(define_insn "*movhi_insn_arch4"
cde1623a 5883 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 5884 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 5885 "TARGET_ARM
5886 && arm_arch4
85e02ccb 5887 && (register_operand (operands[0], HImode)
5888 || register_operand (operands[1], HImode))"
f7fbdd4a 5889 "@
5890 mov%?\\t%0, %1\\t%@ movhi
5891 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5892 str%(h%)\\t%1, %0\\t%@ movhi
5893 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5894 [(set_attr "type" "*,*,store1,load1")
0d66636f 5895 (set_attr "predicable" "yes")
d2a518d1 5896 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 5897 (set_attr "pool_range" "*,*,*,256")
5898 (set_attr "neg_pool_range" "*,*,*,244")]
5899)
f7fbdd4a 5900
f7fbdd4a 5901(define_insn "*movhi_bytes"
25f7a26e 5902 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5903 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5904 "TARGET_ARM"
25f7a26e 5905 "@
5906 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5907 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 5908 [(set_attr "predicable" "yes")
5909 (set_attr "insn" "mov,mvn")]
0d66636f 5910)
25f7a26e 5911
f90b51f1 5912(define_expand "thumb_movhi_clobber"
5913 [(set (match_operand:HI 0 "memory_operand" "")
5914 (match_operand:HI 1 "register_operand" ""))
5915 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5916 "TARGET_THUMB1"
f90b51f1 5917 "
5918 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5919 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5920 {
5921 emit_insn (gen_movhi (operands[0], operands[1]));
5922 DONE;
5923 }
5924 /* XXX Fixme, need to handle other cases here as well. */
5925 gcc_unreachable ();
5926 "
cffb2a26 5927)
5928
bc5c7e08 5929;; We use a DImode scratch because we may occasionally need an additional
5930;; temporary if the address isn't offsettable -- push_reload doesn't seem
5931;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5932(define_expand "reload_outhi"
cffb2a26 5933 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5934 (match_operand:HI 1 "s_register_operand" "r")
5935 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5936 "TARGET_EITHER"
5937 "if (TARGET_ARM)
5938 arm_reload_out_hi (operands);
5939 else
5940 thumb_reload_out_hi (operands);
d3373b54 5941 DONE;
cffb2a26 5942 "
5943)
d3373b54 5944
25f7a26e 5945(define_expand "reload_inhi"
5946 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5947 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5948 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5949 "TARGET_EITHER"
25f7a26e 5950 "
cffb2a26 5951 if (TARGET_ARM)
5952 arm_reload_in_hi (operands);
5953 else
5954 thumb_reload_out_hi (operands);
25f7a26e 5955 DONE;
5956")
5957
9c08d1fa 5958(define_expand "movqi"
5959 [(set (match_operand:QI 0 "general_operand" "")
5960 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5961 "TARGET_EITHER"
9c08d1fa 5962 "
6cffc037 5963 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5964
e1ba4a27 5965 if (can_create_pseudo_p ())
cffb2a26 5966 {
6cffc037 5967 if (GET_CODE (operands[1]) == CONST_INT)
5968 {
5969 rtx reg = gen_reg_rtx (SImode);
5970
03770691 5971 /* For thumb we want an unsigned immediate, then we are more likely
5972 to be able to use a movs insn. */
5973 if (TARGET_THUMB)
5974 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5975
6cffc037 5976 emit_insn (gen_movsi (reg, operands[1]));
5977 operands[1] = gen_lowpart (QImode, reg);
5978 }
cffb2a26 5979
6cffc037 5980 if (TARGET_THUMB)
5981 {
cffb2a26 5982 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5983 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5984 virtual register (also rejected as illegitimate for HImode/QImode)
5985 relative address. */
cffb2a26 5986 /* ??? This should perhaps be fixed elsewhere, for instance, in
5987 fixup_stack_1, by checking for other kinds of invalid addresses,
5988 e.g. a bare reference to a virtual register. This may confuse the
5989 alpha though, which must handle this case differently. */
5990 if (GET_CODE (operands[0]) == MEM
215b30b3 5991 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5992 XEXP (operands[0], 0)))
537ffcfc 5993 operands[0]
5994 = replace_equiv_address (operands[0],
5995 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5996 if (GET_CODE (operands[1]) == MEM
5997 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5998 XEXP (operands[1], 0)))
537ffcfc 5999 operands[1]
6000 = replace_equiv_address (operands[1],
6001 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6002 }
6003
6004 if (GET_CODE (operands[1]) == MEM && optimize > 0)
6005 {
6006 rtx reg = gen_reg_rtx (SImode);
6007
6008 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6009 operands[1] = gen_lowpart (QImode, reg);
6010 }
6011
6012 if (GET_CODE (operands[0]) == MEM)
6013 operands[1] = force_reg (QImode, operands[1]);
6014 }
6015 else if (TARGET_THUMB
6016 && GET_CODE (operands[1]) == CONST_INT
234f6557 6017 && !satisfies_constraint_I (operands[1]))
6cffc037 6018 {
674a8f0b 6019 /* Handle loading a large integer during reload. */
cffb2a26 6020
6cffc037 6021 /* Writing a constant to memory needs a scratch, which should
6022 be handled with SECONDARY_RELOADs. */
6023 gcc_assert (GET_CODE (operands[0]) == REG);
6024
6025 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6026 emit_insn (gen_movsi (operands[0], operands[1]));
6027 DONE;
cffb2a26 6028 }
6029 "
6030)
b11cae9e 6031
9c08d1fa 6032
cffb2a26 6033(define_insn "*arm_movqi_insn"
a54e3e7b 6034 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
6035 (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
25f905c2 6036 "TARGET_32BIT
cffb2a26 6037 && ( register_operand (operands[0], QImode)
6038 || register_operand (operands[1], QImode))"
5565501b 6039 "@
6040 mov%?\\t%0, %1
6041 mvn%?\\t%0, #%B1
25f905c2 6042 ldr%(b%)\\t%0, %1
a54e3e7b 6043 str%(b%)\\t%1, %0
6044 ldr%(b%)\\t%0, %1
25f905c2 6045 str%(b%)\\t%1, %0"
a54e3e7b 6046 [(set_attr "type" "*,*,load1,store1,load1,store1")
6047 (set_attr "insn" "mov,mvn,*,*,*,*")
6048 (set_attr "predicable" "yes")
6049 (set_attr "arch" "any,any,t2,t2,any,any")
6050 (set_attr "length" "4,4,2,2,4,4")]
cffb2a26 6051)
6052
25f905c2 6053(define_insn "*thumb1_movqi_insn"
cffb2a26 6054 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 6055 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 6056 "TARGET_THUMB1
cffb2a26 6057 && ( register_operand (operands[0], QImode)
6058 || register_operand (operands[1], QImode))"
6059 "@
6060 add\\t%0, %1, #0
6061 ldrb\\t%0, %1
6062 strb\\t%1, %0
6063 mov\\t%0, %1
6064 mov\\t%0, %1
6065 mov\\t%0, %1"
6066 [(set_attr "length" "2")
a2cd141b 6067 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 6068 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 6069 (set_attr "pool_range" "*,32,*,*,*,*")
6070 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 6071
9b8516be 6072;; HFmode moves
6073(define_expand "movhf"
6074 [(set (match_operand:HF 0 "general_operand" "")
6075 (match_operand:HF 1 "general_operand" ""))]
6076 "TARGET_EITHER"
6077 "
6078 if (TARGET_32BIT)
6079 {
6080 if (GET_CODE (operands[0]) == MEM)
6081 operands[1] = force_reg (HFmode, operands[1]);
6082 }
6083 else /* TARGET_THUMB1 */
6084 {
6085 if (can_create_pseudo_p ())
6086 {
6087 if (GET_CODE (operands[0]) != REG)
6088 operands[1] = force_reg (HFmode, operands[1]);
6089 }
6090 }
6091 "
6092)
6093
6094(define_insn "*arm32_movhf"
6095 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6096 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 6097 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6098 && ( s_register_operand (operands[0], HFmode)
6099 || s_register_operand (operands[1], HFmode))"
6100 "*
6101 switch (which_alternative)
6102 {
6103 case 0: /* ARM register from memory */
6104 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6105 case 1: /* memory from ARM register */
6106 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6107 case 2: /* ARM register from ARM register */
6108 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6109 case 3: /* ARM register from constant */
6110 {
6111 REAL_VALUE_TYPE r;
6112 long bits;
6113 rtx ops[4];
6114
6115 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6116 bits = real_to_target (NULL, &r, HFmode);
6117 ops[0] = operands[0];
6118 ops[1] = GEN_INT (bits);
6119 ops[2] = GEN_INT (bits & 0xff00);
6120 ops[3] = GEN_INT (bits & 0x00ff);
6121
6122 if (arm_arch_thumb2)
6123 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6124 else
6125 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6126 return \"\";
6127 }
6128 default:
6129 gcc_unreachable ();
6130 }
6131 "
6132 [(set_attr "conds" "unconditional")
6133 (set_attr "type" "load1,store1,*,*")
d2a518d1 6134 (set_attr "insn" "*,*,mov,mov")
9b8516be 6135 (set_attr "length" "4,4,4,8")
d2a518d1 6136 (set_attr "predicable" "yes")]
9b8516be 6137)
6138
6139(define_insn "*thumb1_movhf"
6140 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6141 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6142 "TARGET_THUMB1
6143 && ( s_register_operand (operands[0], HFmode)
6144 || s_register_operand (operands[1], HFmode))"
6145 "*
6146 switch (which_alternative)
6147 {
6148 case 1:
6149 {
6150 rtx addr;
6151 gcc_assert (GET_CODE(operands[1]) == MEM);
6152 addr = XEXP (operands[1], 0);
6153 if (GET_CODE (addr) == LABEL_REF
6154 || (GET_CODE (addr) == CONST
6155 && GET_CODE (XEXP (addr, 0)) == PLUS
6156 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6157 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6158 {
6159 /* Constant pool entry. */
6160 return \"ldr\\t%0, %1\";
6161 }
6162 return \"ldrh\\t%0, %1\";
6163 }
6164 case 2: return \"strh\\t%1, %0\";
6165 default: return \"mov\\t%0, %1\";
6166 }
6167 "
6168 [(set_attr "length" "2")
6169 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6170 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6171 (set_attr "pool_range" "*,1020,*,*,*")
6172 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6173
87b22bf7 6174(define_expand "movsf"
6175 [(set (match_operand:SF 0 "general_operand" "")
6176 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6177 "TARGET_EITHER"
87b22bf7 6178 "
25f905c2 6179 if (TARGET_32BIT)
cffb2a26 6180 {
6181 if (GET_CODE (operands[0]) == MEM)
6182 operands[1] = force_reg (SFmode, operands[1]);
6183 }
25f905c2 6184 else /* TARGET_THUMB1 */
cffb2a26 6185 {
e1ba4a27 6186 if (can_create_pseudo_p ())
cffb2a26 6187 {
6188 if (GET_CODE (operands[0]) != REG)
6189 operands[1] = force_reg (SFmode, operands[1]);
6190 }
6191 }
6192 "
6193)
6194
03d440a6 6195;; Transform a floating-point move of a constant into a core register into
6196;; an SImode operation.
cffb2a26 6197(define_split
03d440a6 6198 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6199 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6200 "TARGET_EITHER
cffb2a26 6201 && reload_completed
6202 && GET_CODE (operands[1]) == CONST_DOUBLE"
6203 [(set (match_dup 2) (match_dup 3))]
6204 "
6205 operands[2] = gen_lowpart (SImode, operands[0]);
6206 operands[3] = gen_lowpart (SImode, operands[1]);
6207 if (operands[2] == 0 || operands[3] == 0)
6208 FAIL;
215b30b3 6209 "
6210)
87b22bf7 6211
cffb2a26 6212(define_insn "*arm_movsf_soft_insn"
6213 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6214 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6215 "TARGET_32BIT
cffb2a26 6216 && TARGET_SOFT_FLOAT
215b30b3 6217 && (GET_CODE (operands[0]) != MEM
6218 || register_operand (operands[1], SFmode))"
9a1112d7 6219 "@
6220 mov%?\\t%0, %1
6221 ldr%?\\t%0, %1\\t%@ float
6222 str%?\\t%1, %0\\t%@ float"
cde1623a 6223 [(set_attr "predicable" "yes")
a2cd141b 6224 (set_attr "type" "*,load1,store1")
d2a518d1 6225 (set_attr "insn" "mov,*,*")
cffb2a26 6226 (set_attr "pool_range" "*,4096,*")
cde1623a 6227 (set_attr "arm_neg_pool_range" "*,4084,*")
6228 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6229)
6230
6231;;; ??? This should have alternatives for constants.
25f905c2 6232(define_insn "*thumb1_movsf_insn"
215b30b3 6233 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6234 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6235 "TARGET_THUMB1
cffb2a26 6236 && ( register_operand (operands[0], SFmode)
6237 || register_operand (operands[1], SFmode))"
6238 "@
6239 add\\t%0, %1, #0
6240 ldmia\\t%1, {%0}
6241 stmia\\t%0, {%1}
6242 ldr\\t%0, %1
6243 str\\t%1, %0
6244 mov\\t%0, %1
6245 mov\\t%0, %1"
6246 [(set_attr "length" "2")
a2cd141b 6247 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6248 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6249 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6250 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6251)
9a1112d7 6252
9c08d1fa 6253(define_expand "movdf"
87b22bf7 6254 [(set (match_operand:DF 0 "general_operand" "")
6255 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6256 "TARGET_EITHER"
9c08d1fa 6257 "
25f905c2 6258 if (TARGET_32BIT)
cffb2a26 6259 {
6260 if (GET_CODE (operands[0]) == MEM)
6261 operands[1] = force_reg (DFmode, operands[1]);
6262 }
6263 else /* TARGET_THUMB */
6264 {
e1ba4a27 6265 if (can_create_pseudo_p ())
cffb2a26 6266 {
6267 if (GET_CODE (operands[0]) != REG)
6268 operands[1] = force_reg (DFmode, operands[1]);
6269 }
6270 }
6271 "
6272)
b11cae9e 6273
9c08d1fa 6274;; Reloading a df mode value stored in integer regs to memory can require a
6275;; scratch reg.
6276(define_expand "reload_outdf"
cffb2a26 6277 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6278 (match_operand:DF 1 "s_register_operand" "r")
6279 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6280 "TARGET_THUMB2"
87b22bf7 6281 "
215b30b3 6282 {
6283 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6284
215b30b3 6285 if (code == REG)
6286 operands[2] = XEXP (operands[0], 0);
6287 else if (code == POST_INC || code == PRE_DEC)
6288 {
6289 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6290 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6291 emit_insn (gen_movdi (operands[0], operands[1]));
6292 DONE;
6293 }
6294 else if (code == PRE_INC)
6295 {
6296 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6297
215b30b3 6298 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6299 operands[2] = reg;
6300 }
6301 else if (code == POST_DEC)
6302 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6303 else
6304 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6305 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6306
788fcce0 6307 emit_insn (gen_rtx_SET (VOIDmode,
6308 replace_equiv_address (operands[0], operands[2]),
215b30b3 6309 operands[1]));
f7fbdd4a 6310
215b30b3 6311 if (code == POST_DEC)
6312 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6313
6314 DONE;
6315 }"
6316)
9c08d1fa 6317
9a1112d7 6318(define_insn "*movdf_soft_insn"
359a6e9f 6319 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6320 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6321 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6322 && ( register_operand (operands[0], DFmode)
6323 || register_operand (operands[1], DFmode))"
d51f92df 6324 "*
6325 switch (which_alternative)
6326 {
6327 case 0:
6328 case 1:
6329 case 2:
6330 return \"#\";
6331 default:
6332 return output_move_double (operands);
6333 }
6334 "
359a6e9f 6335 [(set_attr "length" "8,12,16,8,8")
6336 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6337 (set_attr "pool_range" "*,*,*,1020,*")
6338 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6339 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6340)
6341
6342;;; ??? This should have alternatives for constants.
6343;;; ??? This was originally identical to the movdi_insn pattern.
6344;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6345;;; thumb_reorg with a memory reference.
6346(define_insn "*thumb_movdf_insn"
215b30b3 6347 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6348 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6349 "TARGET_THUMB1
cffb2a26 6350 && ( register_operand (operands[0], DFmode)
6351 || register_operand (operands[1], DFmode))"
6352 "*
6353 switch (which_alternative)
6354 {
6355 default:
6356 case 0:
6357 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6358 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6359 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6360 case 1:
6361 return \"ldmia\\t%1, {%0, %H0}\";
6362 case 2:
6363 return \"stmia\\t%0, {%1, %H1}\";
6364 case 3:
6365 return thumb_load_double_from_address (operands);
6366 case 4:
1a83b3ff 6367 operands[2] = gen_rtx_MEM (SImode,
6368 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6369 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6370 return \"\";
6371 case 5:
6372 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6373 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6374 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6375 }
6376 "
6377 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6378 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6379 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6380 (set_attr "pool_range" "*,*,*,1020,*,*")]
6381)
755eb2b4 6382
ccd90aaa 6383(define_expand "movxf"
6384 [(set (match_operand:XF 0 "general_operand" "")
6385 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6386 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6387 "
6388 if (GET_CODE (operands[0]) == MEM)
6389 operands[1] = force_reg (XFmode, operands[1]);
6390 "
6391)
6392
b11cae9e 6393\f
b11cae9e 6394
9c08d1fa 6395;; load- and store-multiple insns
6396;; The arm can load/store any set of registers, provided that they are in
320ea44d 6397;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6398
9c08d1fa 6399(define_expand "load_multiple"
6400 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6401 (match_operand:SI 1 "" ""))
6402 (use (match_operand:SI 2 "" ""))])]
25f905c2 6403 "TARGET_32BIT"
9580c25f 6404{
6405 HOST_WIDE_INT offset = 0;
6406
bd5b4116 6407 /* Support only fixed point registers. */
9c08d1fa 6408 if (GET_CODE (operands[2]) != CONST_INT
6409 || INTVAL (operands[2]) > 14
6410 || INTVAL (operands[2]) < 2
6411 || GET_CODE (operands[1]) != MEM
6412 || GET_CODE (operands[0]) != REG
bd5b4116 6413 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6414 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6415 FAIL;
6416
6417 operands[3]
320ea44d 6418 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6419 INTVAL (operands[2]),
f082f1c4 6420 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6421 FALSE, operands[1], &offset);
9580c25f 6422})
b11cae9e 6423
9c08d1fa 6424(define_expand "store_multiple"
6425 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6426 (match_operand:SI 1 "" ""))
6427 (use (match_operand:SI 2 "" ""))])]
25f905c2 6428 "TARGET_32BIT"
9580c25f 6429{
6430 HOST_WIDE_INT offset = 0;
6431
674a8f0b 6432 /* Support only fixed point registers. */
9c08d1fa 6433 if (GET_CODE (operands[2]) != CONST_INT
6434 || INTVAL (operands[2]) > 14
6435 || INTVAL (operands[2]) < 2
6436 || GET_CODE (operands[1]) != REG
6437 || GET_CODE (operands[0]) != MEM
bd5b4116 6438 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6439 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6440 FAIL;
6441
6442 operands[3]
320ea44d 6443 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6444 INTVAL (operands[2]),
f082f1c4 6445 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6446 FALSE, operands[0], &offset);
9580c25f 6447})
b11cae9e 6448
9c08d1fa 6449
6450;; Move a block of memory if it is word aligned and MORE than 2 words long.
6451;; We could let this apply for blocks of less than this, but it clobbers so
6452;; many registers that there is then probably a better way.
6453
008c057d 6454(define_expand "movmemqi"
34191dd1 6455 [(match_operand:BLK 0 "general_operand" "")
6456 (match_operand:BLK 1 "general_operand" "")
6457 (match_operand:SI 2 "const_int_operand" "")
6458 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6459 "TARGET_EITHER"
9c08d1fa 6460 "
25f905c2 6461 if (TARGET_32BIT)
cffb2a26 6462 {
008c057d 6463 if (arm_gen_movmemqi (operands))
cffb2a26 6464 DONE;
6465 FAIL;
6466 }
25f905c2 6467 else /* TARGET_THUMB1 */
cffb2a26 6468 {
6469 if ( INTVAL (operands[3]) != 4
6470 || INTVAL (operands[2]) > 48)
6471 FAIL;
6472
008c057d 6473 thumb_expand_movmemqi (operands);
cffb2a26 6474 DONE;
6475 }
6476 "
6477)
6478
2162064c 6479;; Thumb block-move insns
cffb2a26 6480
6481(define_insn "movmem12b"
960f3acf 6482 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6483 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6484 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6485 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6486 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6487 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6488 (set (match_operand:SI 0 "register_operand" "=l")
6489 (plus:SI (match_dup 2) (const_int 12)))
6490 (set (match_operand:SI 1 "register_operand" "=l")
6491 (plus:SI (match_dup 3) (const_int 12)))
6492 (clobber (match_scratch:SI 4 "=&l"))
6493 (clobber (match_scratch:SI 5 "=&l"))
6494 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6495 "TARGET_THUMB1"
cffb2a26 6496 "* return thumb_output_move_mem_multiple (3, operands);"
6497 [(set_attr "length" "4")
215b30b3 6498 ; This isn't entirely accurate... It loads as well, but in terms of
6499 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6500 (set_attr "type" "store3")]
6501)
6502
6503(define_insn "movmem8b"
960f3acf 6504 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6505 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6506 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6507 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6508 (set (match_operand:SI 0 "register_operand" "=l")
6509 (plus:SI (match_dup 2) (const_int 8)))
6510 (set (match_operand:SI 1 "register_operand" "=l")
6511 (plus:SI (match_dup 3) (const_int 8)))
6512 (clobber (match_scratch:SI 4 "=&l"))
6513 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6514 "TARGET_THUMB1"
cffb2a26 6515 "* return thumb_output_move_mem_multiple (2, operands);"
6516 [(set_attr "length" "4")
215b30b3 6517 ; This isn't entirely accurate... It loads as well, but in terms of
6518 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6519 (set_attr "type" "store2")]
6520)
6521
9c08d1fa 6522\f
b11cae9e 6523
341940e8 6524;; Compare & branch insns
8d232dc7 6525;; The range calculations are based as follows:
341940e8 6526;; For forward branches, the address calculation returns the address of
6527;; the next instruction. This is 2 beyond the branch instruction.
6528;; For backward branches, the address calculation returns the address of
6529;; the first instruction in this pattern (cmp). This is 2 before the branch
6530;; instruction for the shortest sequence, and 4 before the branch instruction
6531;; if we have to jump around an unconditional branch.
6532;; To the basic branch range the PC offset must be added (this is +4).
6533;; So for forward branches we have
6534;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6535;; And for backward branches we have
6536;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6537;;
6538;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6539;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6540
aeac46d4 6541(define_expand "cbranchsi4"
6542 [(set (pc) (if_then_else
6543 (match_operator 0 "arm_comparison_operator"
6544 [(match_operand:SI 1 "s_register_operand" "")
6545 (match_operand:SI 2 "nonmemory_operand" "")])
6546 (label_ref (match_operand 3 "" ""))
6547 (pc)))]
74f4459c 6548 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6549 "
74f4459c 6550 if (!TARGET_THUMB1)
6551 {
6552 if (!arm_add_operand (operands[2], SImode))
6553 operands[2] = force_reg (SImode, operands[2]);
6554 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6555 operands[3]));
6556 DONE;
6557 }
25f905c2 6558 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6559 {
6560 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6561 operands[3], operands[0]));
6562 DONE;
6563 }
25f905c2 6564 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6565 operands[2] = force_reg (SImode, operands[2]);
6566 ")
6567
a8e6c15d 6568;; A pattern to recognize a special situation and optimize for it.
6569;; On the thumb, zero-extension from memory is preferrable to sign-extension
6570;; due to the available addressing modes. Hence, convert a signed comparison
6571;; with zero into an unsigned comparison with 127 if possible.
6572(define_expand "cbranchqi4"
6573 [(set (pc) (if_then_else
6574 (match_operator 0 "lt_ge_comparison_operator"
6575 [(match_operand:QI 1 "memory_operand" "")
6576 (match_operand:QI 2 "const0_operand" "")])
6577 (label_ref (match_operand 3 "" ""))
6578 (pc)))]
6579 "TARGET_THUMB1"
6580{
d0f6c30d 6581 rtx xops[4];
a8e6c15d 6582 xops[1] = gen_reg_rtx (SImode);
6583 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6584 xops[2] = GEN_INT (127);
6585 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6586 VOIDmode, xops[1], xops[2]);
6587 xops[3] = operands[3];
6588 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6589 DONE;
6590})
6591
74f4459c 6592(define_expand "cbranchsf4"
6593 [(set (pc) (if_then_else
6594 (match_operator 0 "arm_comparison_operator"
6595 [(match_operand:SF 1 "s_register_operand" "")
6596 (match_operand:SF 2 "arm_float_compare_operand" "")])
6597 (label_ref (match_operand 3 "" ""))
6598 (pc)))]
6599 "TARGET_32BIT && TARGET_HARD_FLOAT"
6600 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6601 operands[3])); DONE;"
6602)
6603
6604(define_expand "cbranchdf4"
6605 [(set (pc) (if_then_else
6606 (match_operator 0 "arm_comparison_operator"
6607 [(match_operand:DF 1 "s_register_operand" "")
6608 (match_operand:DF 2 "arm_float_compare_operand" "")])
6609 (label_ref (match_operand 3 "" ""))
6610 (pc)))]
a50d7267 6611 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6612 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6613 operands[3])); DONE;"
6614)
6615
74f4459c 6616(define_expand "cbranchdi4"
6617 [(set (pc) (if_then_else
6618 (match_operator 0 "arm_comparison_operator"
a8045a4f 6619 [(match_operand:DI 1 "cmpdi_operand" "")
6620 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6621 (label_ref (match_operand 3 "" ""))
6622 (pc)))]
a8045a4f 6623 "TARGET_32BIT"
6624 "{
6625 rtx swap = NULL_RTX;
6626 enum rtx_code code = GET_CODE (operands[0]);
6627
6628 /* We should not have two constants. */
6629 gcc_assert (GET_MODE (operands[1]) == DImode
6630 || GET_MODE (operands[2]) == DImode);
6631
6632 /* Flip unimplemented DImode comparisons to a form that
6633 arm_gen_compare_reg can handle. */
6634 switch (code)
6635 {
6636 case GT:
6637 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6638 case LE:
6639 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6640 case GTU:
6641 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6642 case LEU:
6643 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6644 default:
6645 break;
6646 }
6647 if (swap)
6648 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6649 operands[3]));
6650 else
6651 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6652 operands[3]));
6653 DONE;
6654 }"
74f4459c 6655)
6656
d60047aa 6657(define_insn "cbranchsi4_insn"
aeac46d4 6658 [(set (pc) (if_then_else
6659 (match_operator 0 "arm_comparison_operator"
747b7458 6660 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 6661 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6662 (label_ref (match_operand 3 "" ""))
6663 (pc)))]
25f905c2 6664 "TARGET_THUMB1"
747b7458 6665{
6666 rtx t = cfun->machine->thumb1_cc_insn;
6667 if (t != NULL_RTX)
d60047aa 6668 {
747b7458 6669 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6670 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6671 t = NULL_RTX;
6672 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6673 {
6674 if (!noov_comparison_operator (operands[0], VOIDmode))
6675 t = NULL_RTX;
6676 }
6677 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 6678 t = NULL_RTX;
6679 }
d60047aa 6680 if (t == NULL_RTX)
747b7458 6681 {
6682 output_asm_insn ("cmp\t%1, %2", operands);
6683 cfun->machine->thumb1_cc_insn = insn;
6684 cfun->machine->thumb1_cc_op0 = operands[1];
6685 cfun->machine->thumb1_cc_op1 = operands[2];
6686 cfun->machine->thumb1_cc_mode = CCmode;
6687 }
6688 else
6689 /* Ensure we emit the right type of condition code on the jump. */
6690 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6691 CC_REGNUM);
aeac46d4 6692
cffb2a26 6693 switch (get_attr_length (insn))
6694 {
6695 case 4: return \"b%d0\\t%l3\";
6696 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6697 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6698 }
747b7458 6699}
cffb2a26 6700 [(set (attr "far_jump")
6701 (if_then_else
6702 (eq_attr "length" "8")
6703 (const_string "yes")
6704 (const_string "no")))
6705 (set (attr "length")
6706 (if_then_else
6707 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6708 (le (minus (match_dup 3) (pc)) (const_int 256)))
6709 (const_int 4)
6710 (if_then_else
6711 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6712 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6713 (const_int 6)
6714 (const_int 8))))]
6715)
6716
aeac46d4 6717(define_insn "cbranchsi4_scratch"
6718 [(set (pc) (if_then_else
6719 (match_operator 4 "arm_comparison_operator"
6720 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6721 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6722 (label_ref (match_operand 3 "" ""))
6723 (pc)))
6724 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6725 "TARGET_THUMB1"
aeac46d4 6726 "*
6727 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6728
6729 switch (get_attr_length (insn))
6730 {
6731 case 4: return \"b%d4\\t%l3\";
6732 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6733 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6734 }
6735 "
6736 [(set (attr "far_jump")
6737 (if_then_else
6738 (eq_attr "length" "8")
6739 (const_string "yes")
6740 (const_string "no")))
6741 (set (attr "length")
6742 (if_then_else
6743 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6744 (le (minus (match_dup 3) (pc)) (const_int 256)))
6745 (const_int 4)
6746 (if_then_else
6747 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6748 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6749 (const_int 6)
6750 (const_int 8))))]
6751)
446a1e96 6752
747b7458 6753;; Two peepholes to generate subtract of 0 instead of a move if the
6754;; condition codes will be useful.
446a1e96 6755(define_peephole2
6756 [(set (match_operand:SI 0 "low_register_operand" "")
6757 (match_operand:SI 1 "low_register_operand" ""))
6758 (set (pc)
6759 (if_then_else (match_operator 2 "arm_comparison_operator"
6760 [(match_dup 1) (const_int 0)])
6761 (label_ref (match_operand 3 "" ""))
6762 (pc)))]
6763 "TARGET_THUMB1"
747b7458 6764 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6765 (set (pc)
6766 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6767 (label_ref (match_dup 3))
747b7458 6768 (pc)))]
6769 "")
446a1e96 6770
6771;; Sigh! This variant shouldn't be needed, but combine often fails to
6772;; merge cases like this because the op1 is a hard register in
07d32235 6773;; arm_class_likely_spilled_p.
446a1e96 6774(define_peephole2
6775 [(set (match_operand:SI 0 "low_register_operand" "")
6776 (match_operand:SI 1 "low_register_operand" ""))
6777 (set (pc)
6778 (if_then_else (match_operator 2 "arm_comparison_operator"
6779 [(match_dup 0) (const_int 0)])
6780 (label_ref (match_operand 3 "" ""))
6781 (pc)))]
6782 "TARGET_THUMB1"
747b7458 6783 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6784 (set (pc)
6785 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6786 (label_ref (match_dup 3))
747b7458 6787 (pc)))]
6788 "")
446a1e96 6789
cffb2a26 6790(define_insn "*negated_cbranchsi4"
6791 [(set (pc)
6792 (if_then_else
aed179ae 6793 (match_operator 0 "equality_operator"
aeac46d4 6794 [(match_operand:SI 1 "s_register_operand" "l")
6795 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6796 (label_ref (match_operand 3 "" ""))
215b30b3 6797 (pc)))]
25f905c2 6798 "TARGET_THUMB1"
cffb2a26 6799 "*
6800 output_asm_insn (\"cmn\\t%1, %2\", operands);
6801 switch (get_attr_length (insn))
6802 {
6803 case 4: return \"b%d0\\t%l3\";
6804 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6805 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6806 }
6807 "
6808 [(set (attr "far_jump")
6809 (if_then_else
6810 (eq_attr "length" "8")
6811 (const_string "yes")
6812 (const_string "no")))
6813 (set (attr "length")
6814 (if_then_else
6815 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6816 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6817 (const_int 4)
6818 (if_then_else
341940e8 6819 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6820 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6821 (const_int 6)
6822 (const_int 8))))]
6823)
6824
58d6528b 6825(define_insn "*tbit_cbranch"
6826 [(set (pc)
6827 (if_then_else
6828 (match_operator 0 "equality_operator"
6829 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6830 (const_int 1)
6831 (match_operand:SI 2 "const_int_operand" "i"))
6832 (const_int 0)])
6833 (label_ref (match_operand 3 "" ""))
6834 (pc)))
6835 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6836 "TARGET_THUMB1"
58d6528b 6837 "*
6838 {
6839 rtx op[3];
6840 op[0] = operands[4];
6841 op[1] = operands[1];
6842 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6843
86efa74d 6844 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6845 switch (get_attr_length (insn))
6846 {
6847 case 4: return \"b%d0\\t%l3\";
6848 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6849 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6850 }
6851 }"
6852 [(set (attr "far_jump")
6853 (if_then_else
6854 (eq_attr "length" "8")
6855 (const_string "yes")
6856 (const_string "no")))
6857 (set (attr "length")
6858 (if_then_else
6859 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6860 (le (minus (match_dup 3) (pc)) (const_int 256)))
6861 (const_int 4)
6862 (if_then_else
6863 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6864 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6865 (const_int 6)
6866 (const_int 8))))]
6867)
6868
6869(define_insn "*tlobits_cbranch"
6870 [(set (pc)
6871 (if_then_else
6872 (match_operator 0 "equality_operator"
6873 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6874 (match_operand:SI 2 "const_int_operand" "i")
6875 (const_int 0))
6876 (const_int 0)])
6877 (label_ref (match_operand 3 "" ""))
6878 (pc)))
6879 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6880 "TARGET_THUMB1"
86efa74d 6881 "*
6882 {
6883 rtx op[3];
6884 op[0] = operands[4];
6885 op[1] = operands[1];
6886 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6887
58d6528b 6888 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6889 switch (get_attr_length (insn))
6890 {
6891 case 4: return \"b%d0\\t%l3\";
6892 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6893 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6894 }
6895 }"
6896 [(set (attr "far_jump")
6897 (if_then_else
6898 (eq_attr "length" "8")
6899 (const_string "yes")
6900 (const_string "no")))
6901 (set (attr "length")
6902 (if_then_else
6903 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6904 (le (minus (match_dup 3) (pc)) (const_int 256)))
6905 (const_int 4)
6906 (if_then_else
6907 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6908 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6909 (const_int 6)
6910 (const_int 8))))]
6911)
747b7458 6912
aeac46d4 6913(define_insn "*tstsi3_cbranch"
58d6528b 6914 [(set (pc)
6915 (if_then_else
aeac46d4 6916 (match_operator 3 "equality_operator"
6917 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6918 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6919 (const_int 0)])
aeac46d4 6920 (label_ref (match_operand 2 "" ""))
6921 (pc)))]
25f905c2 6922 "TARGET_THUMB1"
58d6528b 6923 "*
6924 {
aeac46d4 6925 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6926 switch (get_attr_length (insn))
6927 {
aeac46d4 6928 case 4: return \"b%d3\\t%l2\";
6929 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6930 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6931 }
6932 }"
6933 [(set (attr "far_jump")
6934 (if_then_else
6935 (eq_attr "length" "8")
6936 (const_string "yes")
6937 (const_string "no")))
6938 (set (attr "length")
6939 (if_then_else
aeac46d4 6940 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6941 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6942 (const_int 4)
6943 (if_then_else
aeac46d4 6944 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6945 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6946 (const_int 6)
6947 (const_int 8))))]
6948)
6949
203c488f 6950(define_insn "*cbranchne_decr1"
6951 [(set (pc)
6952 (if_then_else (match_operator 3 "equality_operator"
6953 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6954 (const_int 0)])
6955 (label_ref (match_operand 4 "" ""))
6956 (pc)))
aeac46d4 6957 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6958 (plus:SI (match_dup 2) (const_int -1)))
6959 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6960 "TARGET_THUMB1"
203c488f 6961 "*
6962 {
6963 rtx cond[2];
6964 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6965 ? GEU : LTU),
58d6528b 6966 VOIDmode, operands[2], const1_rtx);
203c488f 6967 cond[1] = operands[4];
6968
6969 if (which_alternative == 0)
6970 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6971 else if (which_alternative == 1)
6972 {
6973 /* We must provide an alternative for a hi reg because reload
6974 cannot handle output reloads on a jump instruction, but we
6975 can't subtract into that. Fortunately a mov from lo to hi
6976 does not clobber the condition codes. */
6977 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6978 output_asm_insn (\"mov\\t%0, %1\", operands);
6979 }
6980 else
6981 {
6982 /* Similarly, but the target is memory. */
6983 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6984 output_asm_insn (\"str\\t%1, %0\", operands);
6985 }
6986
6987 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6988 {
6989 case 4:
8aea555f 6990 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6991 return \"\";
6992 case 6:
8aea555f 6993 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6994 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6995 default:
8aea555f 6996 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6997 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6998 }
6999 }
7000 "
7001 [(set (attr "far_jump")
7002 (if_then_else
7003 (ior (and (eq (symbol_ref ("which_alternative"))
7004 (const_int 0))
7005 (eq_attr "length" "8"))
7006 (eq_attr "length" "10"))
7007 (const_string "yes")
7008 (const_string "no")))
7009 (set_attr_alternative "length"
7010 [
7011 ;; Alternative 0
7012 (if_then_else
7013 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7014 (le (minus (match_dup 4) (pc)) (const_int 256)))
7015 (const_int 4)
7016 (if_then_else
7017 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7018 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7019 (const_int 6)
7020 (const_int 8)))
7021 ;; Alternative 1
7022 (if_then_else
7023 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7024 (le (minus (match_dup 4) (pc)) (const_int 256)))
7025 (const_int 6)
7026 (if_then_else
7027 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7028 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7029 (const_int 8)
7030 (const_int 10)))
7031 ;; Alternative 2
7032 (if_then_else
7033 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7034 (le (minus (match_dup 4) (pc)) (const_int 256)))
7035 (const_int 6)
7036 (if_then_else
7037 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7038 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7039 (const_int 8)
7040 (const_int 10)))
7041 ;; Alternative 3
7042 (if_then_else
7043 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7044 (le (minus (match_dup 4) (pc)) (const_int 256)))
7045 (const_int 6)
7046 (if_then_else
7047 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7048 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7049 (const_int 8)
7050 (const_int 10)))])]
7051)
cffb2a26 7052
58d6528b 7053(define_insn "*addsi3_cbranch"
7054 [(set (pc)
7055 (if_then_else
b0694be0 7056 (match_operator 4 "arm_comparison_operator"
58d6528b 7057 [(plus:SI
e54011cb 7058 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7059 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 7060 (const_int 0)])
7061 (label_ref (match_operand 5 "" ""))
7062 (pc)))
aeac46d4 7063 (set
7064 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7065 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 7066 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 7067 "TARGET_THUMB1
58d6528b 7068 && (GET_CODE (operands[4]) == EQ
7069 || GET_CODE (operands[4]) == NE
7070 || GET_CODE (operands[4]) == GE
7071 || GET_CODE (operands[4]) == LT)"
7072 "*
7073 {
7074 rtx cond[3];
7075
956a6170 7076 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 7077 cond[1] = operands[2];
7078 cond[2] = operands[3];
7079
7080 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7081 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7082 else
7083 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7084
956a6170 7085 if (which_alternative >= 2
58d6528b 7086 && which_alternative < 4)
7087 output_asm_insn (\"mov\\t%0, %1\", operands);
7088 else if (which_alternative >= 4)
7089 output_asm_insn (\"str\\t%1, %0\", operands);
7090
d0f6c30d 7091 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 7092 {
7093 case 4:
7094 return \"b%d4\\t%l5\";
7095 case 6:
7096 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7097 default:
7098 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7099 }
7100 }
7101 "
7102 [(set (attr "far_jump")
7103 (if_then_else
7104 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7105 (const_int 2))
58d6528b 7106 (eq_attr "length" "8"))
7107 (eq_attr "length" "10"))
7108 (const_string "yes")
7109 (const_string "no")))
7110 (set (attr "length")
7111 (if_then_else
7112 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7113 (const_int 2))
58d6528b 7114 (if_then_else
7115 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7116 (le (minus (match_dup 5) (pc)) (const_int 256)))
7117 (const_int 4)
7118 (if_then_else
7119 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7120 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7121 (const_int 6)
7122 (const_int 8)))
7123 (if_then_else
7124 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7125 (le (minus (match_dup 5) (pc)) (const_int 256)))
7126 (const_int 6)
7127 (if_then_else
7128 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7129 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7130 (const_int 8)
7131 (const_int 10)))))]
7132)
7133
7134(define_insn "*addsi3_cbranch_scratch"
7135 [(set (pc)
7136 (if_then_else
b0694be0 7137 (match_operator 3 "arm_comparison_operator"
58d6528b 7138 [(plus:SI
7139 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7140 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7141 (const_int 0)])
7142 (label_ref (match_operand 4 "" ""))
7143 (pc)))
7144 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7145 "TARGET_THUMB1
58d6528b 7146 && (GET_CODE (operands[3]) == EQ
7147 || GET_CODE (operands[3]) == NE
7148 || GET_CODE (operands[3]) == GE
7149 || GET_CODE (operands[3]) == LT)"
7150 "*
7151 {
7152 switch (which_alternative)
7153 {
7154 case 0:
7155 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7156 break;
7157 case 1:
7158 output_asm_insn (\"cmn\t%1, %2\", operands);
7159 break;
0f5e9701 7160 case 2:
3a445a04 7161 if (INTVAL (operands[2]) < 0)
7162 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7163 else
7164 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7165 break;
0f5e9701 7166 case 3:
3a445a04 7167 if (INTVAL (operands[2]) < 0)
7168 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7169 else
7170 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7171 break;
7172 }
7173
7174 switch (get_attr_length (insn))
7175 {
7176 case 4:
7177 return \"b%d3\\t%l4\";
7178 case 6:
7179 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7180 default:
7181 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7182 }
7183 }
7184 "
7185 [(set (attr "far_jump")
7186 (if_then_else
7187 (eq_attr "length" "8")
7188 (const_string "yes")
7189 (const_string "no")))
7190 (set (attr "length")
7191 (if_then_else
7192 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7193 (le (minus (match_dup 4) (pc)) (const_int 256)))
7194 (const_int 4)
7195 (if_then_else
7196 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7197 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7198 (const_int 6)
7199 (const_int 8))))]
7200)
7201
58d6528b 7202
9c08d1fa 7203;; Comparison and test insns
7204
cffb2a26 7205(define_insn "*arm_cmpsi_insn"
bd5b4116 7206 [(set (reg:CC CC_REGNUM)
a6864a24 7207 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7208 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
25f905c2 7209 "TARGET_32BIT"
5565501b 7210 "@
a6864a24 7211 cmp%?\\t%0, %1
7212 cmp%?\\t%0, %1
aea4c774 7213 cmp%?\\t%0, %1
7214 cmn%?\\t%0, #%n1"
a6864a24 7215 [(set_attr "conds" "set")
7216 (set_attr "arch" "t2,t2,any,any")
7217 (set_attr "length" "2,2,4,4")]
cffb2a26 7218)
b11cae9e 7219
d5d4dc8d 7220(define_insn "*cmpsi_shiftsi"
bd5b4116 7221 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7222 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7223 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7224 [(match_operand:SI 1 "s_register_operand" "r,r")
7225 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7226 "TARGET_32BIT"
aea4c774 7227 "cmp%?\\t%0, %1%S3"
344495ea 7228 [(set_attr "conds" "set")
331beb1a 7229 (set_attr "shift" "1")
d5d4dc8d 7230 (set_attr "arch" "32,a")
7231 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7232
d5d4dc8d 7233(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7234 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7235 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7236 [(match_operand:SI 1 "s_register_operand" "r,r")
7237 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7238 (match_operand:SI 0 "s_register_operand" "r,r")))]
7239 "TARGET_32BIT"
aea4c774 7240 "cmp%?\\t%0, %1%S3"
344495ea 7241 [(set_attr "conds" "set")
331beb1a 7242 (set_attr "shift" "1")
d5d4dc8d 7243 (set_attr "arch" "32,a")
7244 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7245
25f905c2 7246(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7247 [(set (reg:CC_Z CC_REGNUM)
7248 (compare:CC_Z
7249 (neg:SI (match_operator:SI 1 "shift_operator"
7250 [(match_operand:SI 2 "s_register_operand" "r")
7251 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7252 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7253 "TARGET_ARM"
aed179ae 7254 "cmn%?\\t%0, %2%S1"
344495ea 7255 [(set_attr "conds" "set")
aed179ae 7256 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7257 (const_string "alu_shift")
7258 (const_string "alu_shift_reg")))]
0d66636f 7259)
b11cae9e 7260
a8045a4f 7261;; DImode comparisons. The generic code generates branches that
7262;; if-conversion can not reduce to a conditional compare, so we do
7263;; that directly.
7264
7265(define_insn "*arm_cmpdi_insn"
7266 [(set (reg:CC_NCV CC_REGNUM)
7267 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7268 (match_operand:DI 1 "arm_di_operand" "rDi")))
7269 (clobber (match_scratch:SI 2 "=r"))]
7270 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7271 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7272 [(set_attr "conds" "set")
7273 (set_attr "length" "8")]
7274)
7275
7276(define_insn "*arm_cmpdi_unsigned"
7277 [(set (reg:CC_CZ CC_REGNUM)
7278 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7279 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7280 "TARGET_ARM"
7281 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7282 [(set_attr "conds" "set")
7283 (set_attr "length" "8")]
7284)
7285
7286(define_insn "*arm_cmpdi_zero"
7287 [(set (reg:CC_Z CC_REGNUM)
7288 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7289 (const_int 0)))
7290 (clobber (match_scratch:SI 1 "=r"))]
7291 "TARGET_32BIT"
7292 "orr%.\\t%1, %Q0, %R0"
7293 [(set_attr "conds" "set")]
7294)
7295
7296(define_insn "*thumb_cmpdi_zero"
7297 [(set (reg:CC_Z CC_REGNUM)
7298 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7299 (const_int 0)))
7300 (clobber (match_scratch:SI 1 "=l"))]
7301 "TARGET_THUMB1"
7302 "orr\\t%1, %Q0, %R0"
7303 [(set_attr "conds" "set")
7304 (set_attr "length" "2")]
7305)
7306
7d57ec45 7307;; Cirrus SF compare instruction
7308(define_insn "*cirrus_cmpsf"
7309 [(set (reg:CCFP CC_REGNUM)
7310 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7311 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7312 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7313 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7314 [(set_attr "type" "mav_farith")
7d57ec45 7315 (set_attr "cirrus" "compare")]
7316)
7317
7318;; Cirrus DF compare instruction
7319(define_insn "*cirrus_cmpdf"
7320 [(set (reg:CCFP CC_REGNUM)
7321 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7322 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7323 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7324 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7325 [(set_attr "type" "mav_farith")
7d57ec45 7326 (set_attr "cirrus" "compare")]
7327)
7328
7d57ec45 7329(define_insn "*cirrus_cmpdi"
7330 [(set (reg:CC CC_REGNUM)
7331 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7332 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7333 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7334 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7335 [(set_attr "type" "mav_farith")
7d57ec45 7336 (set_attr "cirrus" "compare")]
7337)
7338
9c08d1fa 7339; This insn allows redundant compares to be removed by cse, nothing should
7340; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7341; is deleted later on. The match_dup will match the mode here, so that
7342; mode changes of the condition codes aren't lost by this even though we don't
7343; specify what they are.
7344
8a18b90c 7345(define_insn "*deleted_compare"
9c08d1fa 7346 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7347 "TARGET_32BIT"
40dbec34 7348 "\\t%@ deleted compare"
cffb2a26 7349 [(set_attr "conds" "set")
7350 (set_attr "length" "0")]
7351)
9c08d1fa 7352
7353\f
7354;; Conditional branch insns
7355
74f4459c 7356(define_expand "cbranch_cc"
9c08d1fa 7357 [(set (pc)
74f4459c 7358 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7359 (match_operand 2 "" "")])
7360 (label_ref (match_operand 3 "" ""))
9c08d1fa 7361 (pc)))]
25f905c2 7362 "TARGET_32BIT"
74f4459c 7363 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7364 operands[1], operands[2]);
7365 operands[2] = const0_rtx;"
8fa3ba89 7366)
7367
7368;;
7369;; Patterns to match conditional branch insns.
7370;;
7371
cffb2a26 7372(define_insn "*arm_cond_branch"
9c08d1fa 7373 [(set (pc)
8fa3ba89 7374 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7375 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7376 (label_ref (match_operand 0 "" ""))
7377 (pc)))]
25f905c2 7378 "TARGET_32BIT"
d75350ce 7379 "*
9c08d1fa 7380 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7381 {
7382 arm_ccfsm_state += 2;
7383 return \"\";
7384 }
e2348bcb 7385 return \"b%d1\\t%l0\";
cffb2a26 7386 "
a2cd141b 7387 [(set_attr "conds" "use")
a6864a24 7388 (set_attr "type" "branch")
7389 (set (attr "length")
7390 (if_then_else
7391 (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7392 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7393 (le (minus (match_dup 0) (pc)) (const_int 256))))
7394 (const_int 2)
7395 (const_int 4)))]
cffb2a26 7396)
d75350ce 7397
cffb2a26 7398(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7399 [(set (pc)
8fa3ba89 7400 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7401 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7402 (pc)
7403 (label_ref (match_operand 0 "" ""))))]
25f905c2 7404 "TARGET_32BIT"
d75350ce 7405 "*
9c08d1fa 7406 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7407 {
7408 arm_ccfsm_state += 2;
7409 return \"\";
7410 }
e2348bcb 7411 return \"b%D1\\t%l0\";
cffb2a26 7412 "
a2cd141b 7413 [(set_attr "conds" "use")
a6864a24 7414 (set_attr "type" "branch")
7415 (set (attr "length")
7416 (if_then_else
7417 (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7418 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7419 (le (minus (match_dup 0) (pc)) (const_int 256))))
7420 (const_int 2)
7421 (const_int 4)))]
cffb2a26 7422)
7423
b11cae9e 7424\f
9c08d1fa 7425
7426; scc insns
7427
74f4459c 7428(define_expand "cstore_cc"
7db9af5d 7429 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7430 (match_operator:SI 1 "" [(match_operand 2 "" "")
7431 (match_operand 3 "" "")]))]
25f905c2 7432 "TARGET_32BIT"
74f4459c 7433 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7434 operands[2], operands[3]);
7435 operands[3] = const0_rtx;"
8fa3ba89 7436)
7437
f7fbdd4a 7438(define_insn "*mov_scc"
9c08d1fa 7439 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7440 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7441 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7442 "TARGET_ARM"
4d61e570 7443 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7444 [(set_attr "conds" "use")
d2a518d1 7445 (set_attr "insn" "mov")
cffb2a26 7446 (set_attr "length" "8")]
7447)
9c08d1fa 7448
f7fbdd4a 7449(define_insn "*mov_negscc"
9c08d1fa 7450 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7451 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7452 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7453 "TARGET_ARM"
4d61e570 7454 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7455 [(set_attr "conds" "use")
d2a518d1 7456 (set_attr "insn" "mov")
cffb2a26 7457 (set_attr "length" "8")]
7458)
9c08d1fa 7459
f7fbdd4a 7460(define_insn "*mov_notscc"
9c08d1fa 7461 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7462 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7463 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7464 "TARGET_ARM"
4d61e570 7465 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7466 [(set_attr "conds" "use")
d2a518d1 7467 (set_attr "insn" "mov")
cffb2a26 7468 (set_attr "length" "8")]
7469)
9c08d1fa 7470
595d88b5 7471(define_expand "cstoresi4"
7472 [(set (match_operand:SI 0 "s_register_operand" "")
7473 (match_operator:SI 1 "arm_comparison_operator"
7474 [(match_operand:SI 2 "s_register_operand" "")
7475 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7476 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7477 "{
7478 rtx op3, scratch, scratch2;
7479
74f4459c 7480 if (!TARGET_THUMB1)
7481 {
7482 if (!arm_add_operand (operands[3], SImode))
7483 operands[3] = force_reg (SImode, operands[3]);
7484 emit_insn (gen_cstore_cc (operands[0], operands[1],
7485 operands[2], operands[3]));
7486 DONE;
7487 }
7488
595d88b5 7489 if (operands[3] == const0_rtx)
7490 {
7491 switch (GET_CODE (operands[1]))
7492 {
7493 case EQ:
25f905c2 7494 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7495 break;
7496
7497 case NE:
25f905c2 7498 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7499 break;
7500
7501 case LE:
7502 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7503 NULL_RTX, 0, OPTAB_WIDEN);
7504 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7505 NULL_RTX, 0, OPTAB_WIDEN);
7506 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7507 operands[0], 1, OPTAB_WIDEN);
7508 break;
7509
7510 case GE:
7511 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7512 NULL_RTX, 1);
7513 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7514 NULL_RTX, 1, OPTAB_WIDEN);
7515 break;
7516
7517 case GT:
7518 scratch = expand_binop (SImode, ashr_optab, operands[2],
7519 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7520 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7521 NULL_RTX, 0, OPTAB_WIDEN);
7522 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7523 0, OPTAB_WIDEN);
7524 break;
7525
7526 /* LT is handled by generic code. No need for unsigned with 0. */
7527 default:
7528 FAIL;
7529 }
7530 DONE;
7531 }
7532
7533 switch (GET_CODE (operands[1]))
7534 {
7535 case EQ:
7536 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7537 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7538 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7539 break;
7540
7541 case NE:
7542 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7543 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7544 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7545 break;
7546
7547 case LE:
7548 op3 = force_reg (SImode, operands[3]);
7549
7550 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7551 NULL_RTX, 1, OPTAB_WIDEN);
7552 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7553 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7554 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7555 op3, operands[2]));
7556 break;
7557
7558 case GE:
7559 op3 = operands[3];
25f905c2 7560 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7561 op3 = force_reg (SImode, op3);
7562 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7563 NULL_RTX, 0, OPTAB_WIDEN);
7564 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7565 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7566 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7567 operands[2], op3));
7568 break;
7569
7570 case LEU:
7571 op3 = force_reg (SImode, operands[3]);
7572 scratch = force_reg (SImode, const0_rtx);
25f905c2 7573 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7574 op3, operands[2]));
7575 break;
7576
7577 case GEU:
7578 op3 = operands[3];
25f905c2 7579 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7580 op3 = force_reg (SImode, op3);
7581 scratch = force_reg (SImode, const0_rtx);
25f905c2 7582 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7583 operands[2], op3));
7584 break;
7585
7586 case LTU:
7587 op3 = operands[3];
25f905c2 7588 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7589 op3 = force_reg (SImode, op3);
7590 scratch = gen_reg_rtx (SImode);
408b7ae5 7591 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7592 break;
7593
7594 case GTU:
7595 op3 = force_reg (SImode, operands[3]);
7596 scratch = gen_reg_rtx (SImode);
408b7ae5 7597 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7598 break;
7599
7600 /* No good sequences for GT, LT. */
7601 default:
7602 FAIL;
7603 }
7604 DONE;
7605}")
7606
74f4459c 7607(define_expand "cstoresf4"
7608 [(set (match_operand:SI 0 "s_register_operand" "")
7609 (match_operator:SI 1 "arm_comparison_operator"
7610 [(match_operand:SF 2 "s_register_operand" "")
7611 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7612 "TARGET_32BIT && TARGET_HARD_FLOAT"
7613 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7614 operands[2], operands[3])); DONE;"
7615)
7616
7617(define_expand "cstoredf4"
7618 [(set (match_operand:SI 0 "s_register_operand" "")
7619 (match_operator:SI 1 "arm_comparison_operator"
7620 [(match_operand:DF 2 "s_register_operand" "")
7621 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7622 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7623 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7624 operands[2], operands[3])); DONE;"
7625)
7626
74f4459c 7627(define_expand "cstoredi4"
7628 [(set (match_operand:SI 0 "s_register_operand" "")
7629 (match_operator:SI 1 "arm_comparison_operator"
a8045a4f 7630 [(match_operand:DI 2 "cmpdi_operand" "")
7631 (match_operand:DI 3 "cmpdi_operand" "")]))]
7632 "TARGET_32BIT"
7633 "{
7634 rtx swap = NULL_RTX;
7635 enum rtx_code code = GET_CODE (operands[1]);
7636
7637 /* We should not have two constants. */
7638 gcc_assert (GET_MODE (operands[2]) == DImode
7639 || GET_MODE (operands[3]) == DImode);
7640
7641 /* Flip unimplemented DImode comparisons to a form that
7642 arm_gen_compare_reg can handle. */
7643 switch (code)
7644 {
7645 case GT:
7646 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7647 case LE:
7648 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7649 case GTU:
7650 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7651 case LEU:
7652 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7653 default:
7654 break;
7655 }
7656 if (swap)
7657 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7658 operands[2]));
7659 else
7660 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7661 operands[3]));
7662 DONE;
7663 }"
74f4459c 7664)
7665
25f905c2 7666(define_expand "cstoresi_eq0_thumb1"
595d88b5 7667 [(parallel
7668 [(set (match_operand:SI 0 "s_register_operand" "")
7669 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7670 (const_int 0)))
7671 (clobber (match_dup:SI 2))])]
25f905c2 7672 "TARGET_THUMB1"
595d88b5 7673 "operands[2] = gen_reg_rtx (SImode);"
7674)
7675
25f905c2 7676(define_expand "cstoresi_ne0_thumb1"
595d88b5 7677 [(parallel
7678 [(set (match_operand:SI 0 "s_register_operand" "")
7679 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7680 (const_int 0)))
7681 (clobber (match_dup:SI 2))])]
25f905c2 7682 "TARGET_THUMB1"
595d88b5 7683 "operands[2] = gen_reg_rtx (SImode);"
7684)
7685
25f905c2 7686(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7687 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7688 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7689 (const_int 0)))
7690 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7691 "TARGET_THUMB1"
595d88b5 7692 "@
7693 neg\\t%0, %1\;adc\\t%0, %0, %1
7694 neg\\t%2, %1\;adc\\t%0, %1, %2"
7695 [(set_attr "length" "4")]
7696)
7697
25f905c2 7698(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7699 [(set (match_operand:SI 0 "s_register_operand" "=l")
7700 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7701 (const_int 0)))
7702 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7703 "TARGET_THUMB1"
595d88b5 7704 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7705 [(set_attr "length" "4")]
7706)
7707
408b7ae5 7708;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 7709(define_insn "cstoresi_nltu_thumb1"
595d88b5 7710 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7711 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7712 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7713 "TARGET_THUMB1"
595d88b5 7714 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7715 [(set_attr "length" "4")]
7716)
7717
408b7ae5 7718(define_insn_and_split "cstoresi_ltu_thumb1"
7719 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7720 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7721 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7722 "TARGET_THUMB1"
7723 "#"
7724 "TARGET_THUMB1"
7725 [(set (match_dup 3)
7726 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7727 (set (match_dup 0) (neg:SI (match_dup 3)))]
7728 "operands[3] = gen_reg_rtx (SImode);"
7729 [(set_attr "length" "4")]
7730)
7731
595d88b5 7732;; Used as part of the expansion of thumb les sequence.
25f905c2 7733(define_insn "thumb1_addsi3_addgeu"
595d88b5 7734 [(set (match_operand:SI 0 "s_register_operand" "=l")
7735 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7736 (match_operand:SI 2 "s_register_operand" "l"))
7737 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 7738 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7739 "TARGET_THUMB1"
595d88b5 7740 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7741 [(set_attr "length" "4")]
7742)
7743
9c08d1fa 7744\f
39b5e676 7745;; Conditional move insns
7746
7747(define_expand "movsicc"
8a18b90c 7748 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7749 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7750 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7751 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7752 "TARGET_32BIT"
39b5e676 7753 "
215b30b3 7754 {
7755 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7756 rtx ccreg;
7757
7758 if (code == UNEQ || code == LTGT)
7759 FAIL;
39b5e676 7760
74f4459c 7761 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7762 XEXP (operands[1], 1));
29bb088d 7763 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7764 }"
7765)
39b5e676 7766
7767(define_expand "movsfcc"
8a18b90c 7768 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7769 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7770 (match_operand:SF 2 "s_register_operand" "")
7771 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 7772 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7773 "
215b30b3 7774 {
7775 enum rtx_code code = GET_CODE (operands[1]);
7776 rtx ccreg;
f082f1c4 7777
278b301d 7778 if (code == UNEQ || code == LTGT)
7779 FAIL;
7780
215b30b3 7781 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7782 Otherwise, ensure it is a valid FP add operand */
7783 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7784 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7785 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7786
74f4459c 7787 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7788 XEXP (operands[1], 1));
29bb088d 7789 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7790 }"
7791)
39b5e676 7792
7793(define_expand "movdfcc"
8a18b90c 7794 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7795 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7796 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7797 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 7798 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 7799 "
215b30b3 7800 {
7801 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7802 rtx ccreg;
39b5e676 7803
278b301d 7804 if (code == UNEQ || code == LTGT)
7805 FAIL;
7806
74f4459c 7807 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7808 XEXP (operands[1], 1));
29bb088d 7809 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7810 }"
7811)
39b5e676 7812
7813(define_insn "*movsicc_insn"
f082f1c4 7814 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7815 (if_then_else:SI
8fa3ba89 7816 (match_operator 3 "arm_comparison_operator"
8a18b90c 7817 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7818 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7819 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7820 "TARGET_ARM"
39b5e676 7821 "@
8a18b90c 7822 mov%D3\\t%0, %2
7823 mvn%D3\\t%0, #%B2
f082f1c4 7824 mov%d3\\t%0, %1
7825 mvn%d3\\t%0, #%B1
8a18b90c 7826 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7827 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7828 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7829 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7830 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7831 (set_attr "conds" "use")
7832 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 7833)
39b5e676 7834
39b5e676 7835(define_insn "*movsfcc_soft_insn"
f082f1c4 7836 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7837 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7838 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7839 (match_operand:SF 1 "s_register_operand" "0,r")
7840 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7841 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7842 "@
7843 mov%D3\\t%0, %2
7844 mov%d3\\t%0, %1"
d2a518d1 7845 [(set_attr "conds" "use")
7846 (set_attr "insn" "mov")]
8fa3ba89 7847)
39b5e676 7848
39b5e676 7849\f
9c08d1fa 7850;; Jump and linkage insns
7851
cffb2a26 7852(define_expand "jump"
9c08d1fa 7853 [(set (pc)
7854 (label_ref (match_operand 0 "" "")))]
cffb2a26 7855 "TARGET_EITHER"
9c08d1fa 7856 ""
cffb2a26 7857)
7858
7859(define_insn "*arm_jump"
7860 [(set (pc)
7861 (label_ref (match_operand 0 "" "")))]
25f905c2 7862 "TARGET_32BIT"
9c08d1fa 7863 "*
0d66636f 7864 {
7865 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7866 {
7867 arm_ccfsm_state += 2;
7868 return \"\";
7869 }
7870 return \"b%?\\t%l0\";
7871 }
7872 "
a6864a24 7873 [(set_attr "predicable" "yes")
7874 (set (attr "length")
7875 (if_then_else
7876 (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7877 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7878 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7879 (const_int 2)
7880 (const_int 4)))]
0d66636f 7881)
9c08d1fa 7882
cffb2a26 7883(define_insn "*thumb_jump"
7884 [(set (pc)
7885 (label_ref (match_operand 0 "" "")))]
25f905c2 7886 "TARGET_THUMB1"
cffb2a26 7887 "*
7888 if (get_attr_length (insn) == 2)
7889 return \"b\\t%l0\";
7890 return \"bl\\t%l0\\t%@ far jump\";
7891 "
7892 [(set (attr "far_jump")
7893 (if_then_else
7894 (eq_attr "length" "4")
7895 (const_string "yes")
7896 (const_string "no")))
7897 (set (attr "length")
7898 (if_then_else
911ed8af 7899 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7900 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7901 (const_int 2)
7902 (const_int 4)))]
7903)
7904
d3373b54 7905(define_expand "call"
7906 [(parallel [(call (match_operand 0 "memory_operand" "")
7907 (match_operand 1 "general_operand" ""))
cffb2a26 7908 (use (match_operand 2 "" ""))
bd5b4116 7909 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7910 "TARGET_EITHER"
6c4c2133 7911 "
7912 {
bac7fc85 7913 rtx callee, pat;
bbe777ea 7914
bbe777ea 7915 /* In an untyped call, we can get NULL for operand 2. */
7916 if (operands[2] == NULL_RTX)
7917 operands[2] = const0_rtx;
7918
de55252a 7919 /* Decide if we should generate indirect calls by loading the
85c36fd1 7920 32-bit address of the callee into a register before performing the
de55252a 7921 branch and link. */
7922 callee = XEXP (operands[0], 0);
7923 if (GET_CODE (callee) == SYMBOL_REF
7924 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7925 : !REG_P (callee))
bbe777ea 7926 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7927
7928 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7929 arm_emit_call_insn (pat, XEXP (operands[0], 0));
7930 DONE;
6c4c2133 7931 }"
7932)
d3373b54 7933
bac7fc85 7934(define_expand "call_internal"
7935 [(parallel [(call (match_operand 0 "memory_operand" "")
7936 (match_operand 1 "general_operand" ""))
7937 (use (match_operand 2 "" ""))
7938 (clobber (reg:SI LR_REGNUM))])])
7939
f1039640 7940(define_insn "*call_reg_armv5"
d3373b54 7941 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7942 (match_operand 1 "" ""))
7943 (use (match_operand 2 "" ""))
bd5b4116 7944 (clobber (reg:SI LR_REGNUM))]
f1039640 7945 "TARGET_ARM && arm_arch5"
7946 "blx%?\\t%0"
7947 [(set_attr "type" "call")]
7948)
7949
7950(define_insn "*call_reg_arm"
7951 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7952 (match_operand 1 "" ""))
7953 (use (match_operand 2 "" ""))
7954 (clobber (reg:SI LR_REGNUM))]
7955 "TARGET_ARM && !arm_arch5"
9c08d1fa 7956 "*
5565501b 7957 return output_call (operands);
cffb2a26 7958 "
7959 ;; length is worst case, normally it is only two
7960 [(set_attr "length" "12")
7961 (set_attr "type" "call")]
7962)
9c08d1fa 7963
89504fc1 7964
7965;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7966;; considered a function call by the branch predictor of some cores (PR40887).
7967;; Falls back to blx rN (*call_reg_armv5).
7968
f7fbdd4a 7969(define_insn "*call_mem"
a3c63a9d 7970 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7971 (match_operand 1 "" ""))
7972 (use (match_operand 2 "" ""))
bd5b4116 7973 (clobber (reg:SI LR_REGNUM))]
89504fc1 7974 "TARGET_ARM && !arm_arch5"
9c08d1fa 7975 "*
5565501b 7976 return output_call_mem (operands);
cffb2a26 7977 "
7978 [(set_attr "length" "12")
7979 (set_attr "type" "call")]
7980)
7981
25f905c2 7982(define_insn "*call_reg_thumb1_v5"
cffb2a26 7983 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7984 (match_operand 1 "" ""))
7985 (use (match_operand 2 "" ""))
bd5b4116 7986 (clobber (reg:SI LR_REGNUM))]
25f905c2 7987 "TARGET_THUMB1 && arm_arch5"
f1039640 7988 "blx\\t%0"
7989 [(set_attr "length" "2")
7990 (set_attr "type" "call")]
cffb2a26 7991)
7992
25f905c2 7993(define_insn "*call_reg_thumb1"
f1039640 7994 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7995 (match_operand 1 "" ""))
7996 (use (match_operand 2 "" ""))
bd5b4116 7997 (clobber (reg:SI LR_REGNUM))]
25f905c2 7998 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 7999 "*
8000 {
150502c9 8001 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8002 return thumb_call_via_reg (operands[0]);
150502c9 8003 else if (operands[1] == const0_rtx)
f1039640 8004 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8005 else if (frame_pointer_needed)
8006 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8007 else
150502c9 8008 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8009 }"
8010 [(set_attr "type" "call")]
8011)
9c08d1fa 8012
d3373b54 8013(define_expand "call_value"
e0698af7 8014 [(parallel [(set (match_operand 0 "" "")
8015 (call (match_operand 1 "memory_operand" "")
8016 (match_operand 2 "general_operand" "")))
cffb2a26 8017 (use (match_operand 3 "" ""))
bd5b4116 8018 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8019 "TARGET_EITHER"
6c4c2133 8020 "
8021 {
bac7fc85 8022 rtx pat, callee;
bbe777ea 8023
8024 /* In an untyped call, we can get NULL for operand 2. */
8025 if (operands[3] == 0)
8026 operands[3] = const0_rtx;
8027
de55252a 8028 /* Decide if we should generate indirect calls by loading the
8029 32-bit address of the callee into a register before performing the
8030 branch and link. */
8031 callee = XEXP (operands[1], 0);
8032 if (GET_CODE (callee) == SYMBOL_REF
8033 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8034 : !REG_P (callee))
78fe751b 8035 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8036
8037 pat = gen_call_value_internal (operands[0], operands[1],
8038 operands[2], operands[3]);
8039 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8040 DONE;
6c4c2133 8041 }"
8042)
d3373b54 8043
bac7fc85 8044(define_expand "call_value_internal"
8045 [(parallel [(set (match_operand 0 "" "")
8046 (call (match_operand 1 "memory_operand" "")
8047 (match_operand 2 "general_operand" "")))
8048 (use (match_operand 3 "" ""))
8049 (clobber (reg:SI LR_REGNUM))])])
8050
f1039640 8051(define_insn "*call_value_reg_armv5"
27ed6835 8052 [(set (match_operand 0 "" "")
755eb2b4 8053 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8054 (match_operand 2 "" "")))
bbe777ea 8055 (use (match_operand 3 "" ""))
bd5b4116 8056 (clobber (reg:SI LR_REGNUM))]
f1039640 8057 "TARGET_ARM && arm_arch5"
8058 "blx%?\\t%1"
8059 [(set_attr "type" "call")]
8060)
8061
8062(define_insn "*call_value_reg_arm"
8063 [(set (match_operand 0 "" "")
8064 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8065 (match_operand 2 "" "")))
8066 (use (match_operand 3 "" ""))
8067 (clobber (reg:SI LR_REGNUM))]
8068 "TARGET_ARM && !arm_arch5"
9c08d1fa 8069 "*
215b30b3 8070 return output_call (&operands[1]);
cffb2a26 8071 "
8072 [(set_attr "length" "12")
8073 (set_attr "type" "call")]
8074)
9c08d1fa 8075
89504fc1 8076;; Note: see *call_mem
8077
f7fbdd4a 8078(define_insn "*call_value_mem"
27ed6835 8079 [(set (match_operand 0 "" "")
a3c63a9d 8080 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8081 (match_operand 2 "" "")))
bbe777ea 8082 (use (match_operand 3 "" ""))
bd5b4116 8083 (clobber (reg:SI LR_REGNUM))]
89504fc1 8084 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8085 "*
215b30b3 8086 return output_call_mem (&operands[1]);
cffb2a26 8087 "
8088 [(set_attr "length" "12")
8089 (set_attr "type" "call")]
8090)
9c08d1fa 8091
25f905c2 8092(define_insn "*call_value_reg_thumb1_v5"
f1039640 8093 [(set (match_operand 0 "" "")
8094 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8095 (match_operand 2 "" "")))
8096 (use (match_operand 3 "" ""))
8097 (clobber (reg:SI LR_REGNUM))]
25f905c2 8098 "TARGET_THUMB1 && arm_arch5"
f1039640 8099 "blx\\t%1"
8100 [(set_attr "length" "2")
8101 (set_attr "type" "call")]
8102)
8103
25f905c2 8104(define_insn "*call_value_reg_thumb1"
f1039640 8105 [(set (match_operand 0 "" "")
8106 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8107 (match_operand 2 "" "")))
8108 (use (match_operand 3 "" ""))
8109 (clobber (reg:SI LR_REGNUM))]
25f905c2 8110 "TARGET_THUMB1 && !arm_arch5"
f1039640 8111 "*
8112 {
150502c9 8113 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8114 return thumb_call_via_reg (operands[1]);
150502c9 8115 else if (operands[2] == const0_rtx)
f1039640 8116 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8117 else if (frame_pointer_needed)
8118 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8119 else
150502c9 8120 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8121 }"
8122 [(set_attr "type" "call")]
8123)
8124
9c08d1fa 8125;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8126;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8127
f7fbdd4a 8128(define_insn "*call_symbol"
27ed6835 8129 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8130 (match_operand 1 "" ""))
bbe777ea 8131 (use (match_operand 2 "" ""))
bd5b4116 8132 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8133 "TARGET_32BIT
cffb2a26 8134 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8135 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8136 "*
8137 {
55c1e470 8138 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8139 }"
cffb2a26 8140 [(set_attr "type" "call")]
8141)
9c08d1fa 8142
f7fbdd4a 8143(define_insn "*call_value_symbol"
ccd90aaa 8144 [(set (match_operand 0 "" "")
27ed6835 8145 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8146 (match_operand:SI 2 "" "")))
bbe777ea 8147 (use (match_operand 3 "" ""))
bd5b4116 8148 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8149 "TARGET_32BIT
cffb2a26 8150 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8151 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8152 "*
8153 {
55c1e470 8154 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8155 }"
cffb2a26 8156 [(set_attr "type" "call")]
8157)
8158
8159(define_insn "*call_insn"
27ed6835 8160 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8161 (match_operand:SI 1 "" ""))
8162 (use (match_operand 2 "" ""))
bd5b4116 8163 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8164 "TARGET_THUMB1
1675c6e9 8165 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8166 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8167 "bl\\t%a0"
8168 [(set_attr "length" "4")
8169 (set_attr "type" "call")]
8170)
8171
8172(define_insn "*call_value_insn"
ccd90aaa 8173 [(set (match_operand 0 "" "")
27ed6835 8174 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8175 (match_operand 2 "" "")))
8176 (use (match_operand 3 "" ""))
bd5b4116 8177 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8178 "TARGET_THUMB1
1675c6e9 8179 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8180 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8181 "bl\\t%a1"
8182 [(set_attr "length" "4")
8183 (set_attr "type" "call")]
8184)
9c08d1fa 8185
1c494086 8186;; We may also be able to do sibcalls for Thumb, but it's much harder...
8187(define_expand "sibcall"
8188 [(parallel [(call (match_operand 0 "memory_operand" "")
8189 (match_operand 1 "general_operand" ""))
2ba80634 8190 (return)
8191 (use (match_operand 2 "" ""))])]
d68c2c10 8192 "TARGET_32BIT"
1c494086 8193 "
8194 {
8195 if (operands[2] == NULL_RTX)
8196 operands[2] = const0_rtx;
1c494086 8197 }"
8198)
8199
8200(define_expand "sibcall_value"
ccd90aaa 8201 [(parallel [(set (match_operand 0 "" "")
1c494086 8202 (call (match_operand 1 "memory_operand" "")
8203 (match_operand 2 "general_operand" "")))
2ba80634 8204 (return)
8205 (use (match_operand 3 "" ""))])]
d68c2c10 8206 "TARGET_32BIT"
1c494086 8207 "
8208 {
8209 if (operands[3] == NULL_RTX)
8210 operands[3] = const0_rtx;
1c494086 8211 }"
8212)
8213
8214(define_insn "*sibcall_insn"
8215 [(call (mem:SI (match_operand:SI 0 "" "X"))
8216 (match_operand 1 "" ""))
2ba80634 8217 (return)
8218 (use (match_operand 2 "" ""))]
d68c2c10 8219 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8220 "*
8221 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8222 "
8223 [(set_attr "type" "call")]
8224)
8225
8226(define_insn "*sibcall_value_insn"
ccd90aaa 8227 [(set (match_operand 0 "" "")
755eb2b4 8228 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8229 (match_operand 2 "" "")))
2ba80634 8230 (return)
8231 (use (match_operand 3 "" ""))]
d68c2c10 8232 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8233 "*
8234 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8235 "
8236 [(set_attr "type" "call")]
8237)
8238
d68c2c10 8239(define_expand "return"
8240 [(return)]
8241 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8242 "")
8243
9c08d1fa 8244;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8245(define_insn "*arm_return"
9c08d1fa 8246 [(return)]
cffb2a26 8247 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8248 "*
9c08d1fa 8249 {
cffb2a26 8250 if (arm_ccfsm_state == 2)
8251 {
8252 arm_ccfsm_state += 2;
8253 return \"\";
8254 }
5db468b7 8255 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8256 }"
a2cd141b 8257 [(set_attr "type" "load1")
755eb2b4 8258 (set_attr "length" "12")
0d66636f 8259 (set_attr "predicable" "yes")]
cffb2a26 8260)
9c08d1fa 8261
f7fbdd4a 8262(define_insn "*cond_return"
9c08d1fa 8263 [(set (pc)
8fa3ba89 8264 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8265 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8266 (return)
8267 (pc)))]
cffb2a26 8268 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8269 "*
8fa3ba89 8270 {
8271 if (arm_ccfsm_state == 2)
8272 {
8273 arm_ccfsm_state += 2;
8274 return \"\";
8275 }
8276 return output_return_instruction (operands[0], TRUE, FALSE);
8277 }"
8278 [(set_attr "conds" "use")
755eb2b4 8279 (set_attr "length" "12")
a2cd141b 8280 (set_attr "type" "load1")]
8fa3ba89 8281)
9c08d1fa 8282
f7fbdd4a 8283(define_insn "*cond_return_inverted"
9c08d1fa 8284 [(set (pc)
8fa3ba89 8285 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8286 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8287 (pc)
8288 (return)))]
cffb2a26 8289 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8290 "*
8fa3ba89 8291 {
8292 if (arm_ccfsm_state == 2)
8293 {
8294 arm_ccfsm_state += 2;
8295 return \"\";
8296 }
8297 return output_return_instruction (operands[0], TRUE, TRUE);
8298 }"
8299 [(set_attr "conds" "use")
37a1317b 8300 (set_attr "length" "12")
a2cd141b 8301 (set_attr "type" "load1")]
8fa3ba89 8302)
9c08d1fa 8303
68121397 8304;; Generate a sequence of instructions to determine if the processor is
8305;; in 26-bit or 32-bit mode, and return the appropriate return address
8306;; mask.
8307
8308(define_expand "return_addr_mask"
8309 [(set (match_dup 1)
8310 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8311 (const_int 0)))
8312 (set (match_operand:SI 0 "s_register_operand" "")
8313 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8314 (const_int -1)
8315 (const_int 67108860)))] ; 0x03fffffc
8316 "TARGET_ARM"
8317 "
62eddbd4 8318 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8319 ")
8320
8321(define_insn "*check_arch2"
8322 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8323 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8324 (const_int 0)))]
8325 "TARGET_ARM"
8326 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8327 [(set_attr "length" "8")
8328 (set_attr "conds" "set")]
8329)
8330
9c08d1fa 8331;; Call subroutine returning any type.
8332
8333(define_expand "untyped_call"
8334 [(parallel [(call (match_operand 0 "" "")
8335 (const_int 0))
8336 (match_operand 1 "" "")
8337 (match_operand 2 "" "")])]
ccd90aaa 8338 "TARGET_EITHER"
9c08d1fa 8339 "
215b30b3 8340 {
8341 int i;
ccd90aaa 8342 rtx par = gen_rtx_PARALLEL (VOIDmode,
8343 rtvec_alloc (XVECLEN (operands[2], 0)));
8344 rtx addr = gen_reg_rtx (Pmode);
8345 rtx mem;
8346 int size = 0;
9c08d1fa 8347
ccd90aaa 8348 emit_move_insn (addr, XEXP (operands[1], 0));
8349 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8350
215b30b3 8351 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8352 {
ccd90aaa 8353 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8354
ccd90aaa 8355 /* Default code only uses r0 as a return value, but we could
8356 be using anything up to 4 registers. */
8357 if (REGNO (src) == R0_REGNUM)
8358 src = gen_rtx_REG (TImode, R0_REGNUM);
8359
8360 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8361 GEN_INT (size));
8362 size += GET_MODE_SIZE (GET_MODE (src));
8363 }
8364
8365 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8366 const0_rtx));
8367
8368 size = 0;
8369
8370 for (i = 0; i < XVECLEN (par, 0); i++)
8371 {
8372 HOST_WIDE_INT offset = 0;
8373 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8374
8375 if (size != 0)
8376 emit_move_insn (addr, plus_constant (addr, size));
8377
8378 mem = change_address (mem, GET_MODE (reg), NULL);
8379 if (REGNO (reg) == R0_REGNUM)
8380 {
8381 /* On thumb we have to use a write-back instruction. */
320ea44d 8382 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8383 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8384 size = TARGET_ARM ? 16 : 0;
8385 }
8386 else
8387 {
8388 emit_move_insn (mem, reg);
8389 size = GET_MODE_SIZE (GET_MODE (reg));
8390 }
215b30b3 8391 }
9c08d1fa 8392
215b30b3 8393 /* The optimizer does not know that the call sets the function value
8394 registers we stored in the result block. We avoid problems by
8395 claiming that all hard registers are used and clobbered at this
8396 point. */
8397 emit_insn (gen_blockage ());
8398
8399 DONE;
8400 }"
8401)
9c08d1fa 8402
ccd90aaa 8403(define_expand "untyped_return"
8404 [(match_operand:BLK 0 "memory_operand" "")
8405 (match_operand 1 "" "")]
8406 "TARGET_EITHER"
8407 "
8408 {
8409 int i;
8410 rtx addr = gen_reg_rtx (Pmode);
8411 rtx mem;
8412 int size = 0;
8413
8414 emit_move_insn (addr, XEXP (operands[0], 0));
8415 mem = change_address (operands[0], BLKmode, addr);
8416
8417 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8418 {
8419 HOST_WIDE_INT offset = 0;
8420 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8421
8422 if (size != 0)
8423 emit_move_insn (addr, plus_constant (addr, size));
8424
8425 mem = change_address (mem, GET_MODE (reg), NULL);
8426 if (REGNO (reg) == R0_REGNUM)
8427 {
8428 /* On thumb we have to use a write-back instruction. */
320ea44d 8429 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8430 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8431 size = TARGET_ARM ? 16 : 0;
8432 }
8433 else
8434 {
8435 emit_move_insn (reg, mem);
8436 size = GET_MODE_SIZE (GET_MODE (reg));
8437 }
8438 }
8439
8440 /* Emit USE insns before the return. */
8441 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8442 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8443
8444 /* Construct the return. */
8445 expand_naked_return ();
8446
8447 DONE;
8448 }"
8449)
8450
9c08d1fa 8451;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8452;; all of memory. This blocks insns from being moved across this point.
8453
8454(define_insn "blockage"
e1159bbe 8455 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8456 "TARGET_EITHER"
9c08d1fa 8457 ""
cffb2a26 8458 [(set_attr "length" "0")
8459 (set_attr "type" "block")]
8460)
9c08d1fa 8461
f7fbdd4a 8462(define_expand "casesi"
8463 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8464 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8465 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8466 (match_operand:SI 3 "" "") ; table label
8467 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8468 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8469 "
215b30b3 8470 {
e6ac8414 8471 enum insn_code code;
215b30b3 8472 if (operands[1] != const0_rtx)
8473 {
e6ac8414 8474 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8475
215b30b3 8476 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8477 gen_int_mode (-INTVAL (operands[1]),
8478 SImode)));
215b30b3 8479 operands[0] = reg;
8480 }
9c08d1fa 8481
25f905c2 8482 if (TARGET_ARM)
e6ac8414 8483 code = CODE_FOR_arm_casesi_internal;
3db2019b 8484 else if (TARGET_THUMB1)
e6ac8414 8485 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8486 else if (flag_pic)
e6ac8414 8487 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8488 else
e6ac8414 8489 code = CODE_FOR_thumb2_casesi_internal;
8490
8491 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8492 operands[2] = force_reg (SImode, operands[2]);
8493
8494 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8495 operands[3], operands[4]));
215b30b3 8496 DONE;
8497 }"
8498)
f7fbdd4a 8499
f082f1c4 8500;; The USE in this pattern is needed to tell flow analysis that this is
8501;; a CASESI insn. It has no other purpose.
25f905c2 8502(define_insn "arm_casesi_internal"
f082f1c4 8503 [(parallel [(set (pc)
8504 (if_then_else
8505 (leu (match_operand:SI 0 "s_register_operand" "r")
8506 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8507 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8508 (label_ref (match_operand 2 "" ""))))
8509 (label_ref (match_operand 3 "" ""))))
bd5b4116 8510 (clobber (reg:CC CC_REGNUM))
f082f1c4 8511 (use (label_ref (match_dup 2)))])]
cffb2a26 8512 "TARGET_ARM"
f7fbdd4a 8513 "*
0d66636f 8514 if (flag_pic)
8515 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8516 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8517 "
8518 [(set_attr "conds" "clob")
8519 (set_attr "length" "12")]
8520)
9c08d1fa 8521
e6ac8414 8522(define_expand "thumb1_casesi_internal_pic"
8523 [(match_operand:SI 0 "s_register_operand" "")
8524 (match_operand:SI 1 "thumb1_cmp_operand" "")
8525 (match_operand 2 "" "")
8526 (match_operand 3 "" "")]
3db2019b 8527 "TARGET_THUMB1"
e6ac8414 8528 {
8529 rtx reg0;
8530 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8531 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8532 operands[3]));
8533 reg0 = gen_rtx_REG (SImode, 0);
8534 emit_move_insn (reg0, operands[0]);
8535 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8536 DONE;
8537 }
8538)
8539
8540(define_insn "thumb1_casesi_dispatch"
8541 [(parallel [(set (pc) (unspec [(reg:SI 0)
8542 (label_ref (match_operand 0 "" ""))
8543;; (label_ref (match_operand 1 "" ""))
8544]
8545 UNSPEC_THUMB1_CASESI))
8546 (clobber (reg:SI IP_REGNUM))
8547 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8548 "TARGET_THUMB1"
e6ac8414 8549 "* return thumb1_output_casesi(operands);"
8550 [(set_attr "length" "4")]
8551)
8552
cffb2a26 8553(define_expand "indirect_jump"
9c08d1fa 8554 [(set (pc)
cffb2a26 8555 (match_operand:SI 0 "s_register_operand" ""))]
8556 "TARGET_EITHER"
25f905c2 8557 "
8558 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8559 address and use bx. */
8560 if (TARGET_THUMB2)
8561 {
8562 rtx tmp;
8563 tmp = gen_reg_rtx (SImode);
8564 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8565 operands[0] = tmp;
8566 }
8567 "
cffb2a26 8568)
8569
f1039640 8570;; NB Never uses BX.
cffb2a26 8571(define_insn "*arm_indirect_jump"
8572 [(set (pc)
8573 (match_operand:SI 0 "s_register_operand" "r"))]
8574 "TARGET_ARM"
8575 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8576 [(set_attr "predicable" "yes")]
cffb2a26 8577)
9c08d1fa 8578
f7fbdd4a 8579(define_insn "*load_indirect_jump"
9c08d1fa 8580 [(set (pc)
8581 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8582 "TARGET_ARM"
8583 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8584 [(set_attr "type" "load1")
61a2d04c 8585 (set_attr "pool_range" "4096")
8586 (set_attr "neg_pool_range" "4084")
0d66636f 8587 (set_attr "predicable" "yes")]
cffb2a26 8588)
8589
f1039640 8590;; NB Never uses BX.
25f905c2 8591(define_insn "*thumb1_indirect_jump"
cffb2a26 8592 [(set (pc)
8593 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8594 "TARGET_THUMB1"
cffb2a26 8595 "mov\\tpc, %0"
8596 [(set_attr "conds" "clob")
8597 (set_attr "length" "2")]
8598)
8599
9c08d1fa 8600\f
8601;; Misc insns
8602
8603(define_insn "nop"
8604 [(const_int 0)]
cffb2a26 8605 "TARGET_EITHER"
8606 "*
25f905c2 8607 if (TARGET_UNIFIED_ASM)
8608 return \"nop\";
cffb2a26 8609 if (TARGET_ARM)
8610 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8611 return \"mov\\tr8, r8\";
8612 "
8613 [(set (attr "length")
8614 (if_then_else (eq_attr "is_thumb" "yes")
8615 (const_int 2)
8616 (const_int 4)))]
8617)
8618
9c08d1fa 8619\f
8620;; Patterns to allow combination of arithmetic, cond code and shifts
8621
f7fbdd4a 8622(define_insn "*arith_shiftsi"
d5d4dc8d 8623 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8624 (match_operator:SI 1 "shiftable_operator"
8625 [(match_operator:SI 3 "shift_operator"
d5d4dc8d 8626 [(match_operand:SI 4 "s_register_operand" "r,r")
8627 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8628 (match_operand:SI 2 "s_register_operand" "rk,rk")]))]
8629 "TARGET_32BIT"
6c4c2133 8630 "%i1%?\\t%0, %2, %4%S3"
344495ea 8631 [(set_attr "predicable" "yes")
331beb1a 8632 (set_attr "shift" "4")
d5d4dc8d 8633 (set_attr "arch" "32,a")
8634 ;; We have to make sure to disable the second alternative if
8635 ;; the shift_operator is MULT, since otherwise the insn will
8636 ;; also match a multiply_accumulate pattern and validate_change
8637 ;; will allow a replacement of the constant with a register
8638 ;; despite the checks done in shift_operator.
8639 (set_attr_alternative "insn_enabled"
8640 [(const_string "yes")
8641 (if_then_else
8642 (match_operand:SI 3 "mult_operator" "")
8643 (const_string "no") (const_string "yes"))])
8644 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8645
d7863cfe 8646(define_split
8647 [(set (match_operand:SI 0 "s_register_operand" "")
8648 (match_operator:SI 1 "shiftable_operator"
8649 [(match_operator:SI 2 "shiftable_operator"
8650 [(match_operator:SI 3 "shift_operator"
8651 [(match_operand:SI 4 "s_register_operand" "")
8652 (match_operand:SI 5 "reg_or_int_operand" "")])
8653 (match_operand:SI 6 "s_register_operand" "")])
8654 (match_operand:SI 7 "arm_rhs_operand" "")]))
8655 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8656 "TARGET_32BIT"
d7863cfe 8657 [(set (match_dup 8)
8658 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8659 (match_dup 6)]))
8660 (set (match_dup 0)
8661 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8662 "")
8663
f7fbdd4a 8664(define_insn "*arith_shiftsi_compare0"
bd5b4116 8665 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8666 (compare:CC_NOOV
8667 (match_operator:SI 1 "shiftable_operator"
8668 [(match_operator:SI 3 "shift_operator"
8669 [(match_operand:SI 4 "s_register_operand" "r,r")
8670 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8671 (match_operand:SI 2 "s_register_operand" "r,r")])
8672 (const_int 0)))
8673 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8674 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8675 (match_dup 2)]))]
d5d4dc8d 8676 "TARGET_32BIT"
25f905c2 8677 "%i1%.\\t%0, %2, %4%S3"
344495ea 8678 [(set_attr "conds" "set")
331beb1a 8679 (set_attr "shift" "4")
d5d4dc8d 8680 (set_attr "arch" "32,a")
8681 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8682
f7fbdd4a 8683(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8684 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8685 (compare:CC_NOOV
8686 (match_operator:SI 1 "shiftable_operator"
8687 [(match_operator:SI 3 "shift_operator"
8688 [(match_operand:SI 4 "s_register_operand" "r,r")
8689 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8690 (match_operand:SI 2 "s_register_operand" "r,r")])
8691 (const_int 0)))
8692 (clobber (match_scratch:SI 0 "=r,r"))]
8693 "TARGET_32BIT"
25f905c2 8694 "%i1%.\\t%0, %2, %4%S3"
344495ea 8695 [(set_attr "conds" "set")
331beb1a 8696 (set_attr "shift" "4")
d5d4dc8d 8697 (set_attr "arch" "32,a")
8698 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8699
f7fbdd4a 8700(define_insn "*sub_shiftsi"
d5d4dc8d 8701 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8702 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8703 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8704 [(match_operand:SI 3 "s_register_operand" "r,r")
8705 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8706 "TARGET_32BIT"
6c4c2133 8707 "sub%?\\t%0, %1, %3%S2"
344495ea 8708 [(set_attr "predicable" "yes")
331beb1a 8709 (set_attr "shift" "3")
d5d4dc8d 8710 (set_attr "arch" "32,a")
8711 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8712
f7fbdd4a 8713(define_insn "*sub_shiftsi_compare0"
bd5b4116 8714 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8715 (compare:CC_NOOV
d5d4dc8d 8716 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8717 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8718 [(match_operand:SI 3 "s_register_operand" "r,r")
8719 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8720 (const_int 0)))
d5d4dc8d 8721 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8722 (minus:SI (match_dup 1)
8723 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8724 "TARGET_32BIT"
25f905c2 8725 "sub%.\\t%0, %1, %3%S2"
344495ea 8726 [(set_attr "conds" "set")
a2cd141b 8727 (set_attr "shift" "3")
d5d4dc8d 8728 (set_attr "arch" "32,a")
8729 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8730
f7fbdd4a 8731(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8732 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8733 (compare:CC_NOOV
d5d4dc8d 8734 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8735 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8736 [(match_operand:SI 3 "s_register_operand" "r,r")
8737 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8738 (const_int 0)))
d5d4dc8d 8739 (clobber (match_scratch:SI 0 "=r,r"))]
8740 "TARGET_32BIT"
25f905c2 8741 "sub%.\\t%0, %1, %3%S2"
344495ea 8742 [(set_attr "conds" "set")
a2cd141b 8743 (set_attr "shift" "3")
d5d4dc8d 8744 (set_attr "arch" "32,a")
8745 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8746\f
8747
f7fbdd4a 8748(define_insn "*and_scc"
9c08d1fa 8749 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8750 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8751 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8752 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8753 "TARGET_ARM"
e2348bcb 8754 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8755 [(set_attr "conds" "use")
d2a518d1 8756 (set_attr "insn" "mov")
8fa3ba89 8757 (set_attr "length" "8")]
8758)
9c08d1fa 8759
f7fbdd4a 8760(define_insn "*ior_scc"
9c08d1fa 8761 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8762 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8763 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8764 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8765 "TARGET_ARM"
e2348bcb 8766 "@
899850b0 8767 orr%d2\\t%0, %1, #1
8768 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8769 [(set_attr "conds" "use")
8770 (set_attr "length" "4,8")]
8771)
9c08d1fa 8772
2df9477b 8773; A series of splitters for the compare_scc pattern below. Note that
8774; order is important.
8775(define_split
8776 [(set (match_operand:SI 0 "s_register_operand" "")
8777 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8778 (const_int 0)))
8779 (clobber (reg:CC CC_REGNUM))]
8780 "TARGET_32BIT && reload_completed"
8781 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8782
8783(define_split
8784 [(set (match_operand:SI 0 "s_register_operand" "")
8785 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8786 (const_int 0)))
8787 (clobber (reg:CC CC_REGNUM))]
8788 "TARGET_32BIT && reload_completed"
8789 [(set (match_dup 0) (not:SI (match_dup 1)))
8790 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8791
8792(define_split
8793 [(set (match_operand:SI 0 "s_register_operand" "")
8794 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8795 (const_int 0)))
8796 (clobber (reg:CC CC_REGNUM))]
8797 "TARGET_32BIT && reload_completed"
8798 [(parallel
080c0b9a 8799 [(set (reg:CC CC_REGNUM)
8800 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8801 (set (match_dup 0)
8802 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8803 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8804 (set (match_dup 0) (const_int 0)))])
8805
8806(define_split
8807 [(set (match_operand:SI 0 "s_register_operand" "")
8808 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8809 (match_operand:SI 2 "const_int_operand" "")))
8810 (clobber (reg:CC CC_REGNUM))]
8811 "TARGET_32BIT && reload_completed"
8812 [(parallel
8813 [(set (reg:CC CC_REGNUM)
8814 (compare:CC (match_dup 1) (match_dup 2)))
8815 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8816 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8817 (set (match_dup 0) (const_int 1)))]
8818{
8819 operands[3] = GEN_INT (-INTVAL (operands[2]));
8820})
8821
8822(define_split
8823 [(set (match_operand:SI 0 "s_register_operand" "")
8824 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8825 (match_operand:SI 2 "arm_add_operand" "")))
8826 (clobber (reg:CC CC_REGNUM))]
8827 "TARGET_32BIT && reload_completed"
8828 [(parallel
8829 [(set (reg:CC_NOOV CC_REGNUM)
8830 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8831 (const_int 0)))
8832 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8833 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8834 (set (match_dup 0) (const_int 1)))])
8835
8836(define_insn_and_split "*compare_scc"
5565501b 8837 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8838 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8839 [(match_operand:SI 2 "s_register_operand" "r,r")
8840 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8841 (clobber (reg:CC CC_REGNUM))]
2df9477b 8842 "TARGET_32BIT"
8843 "#"
8844 "&& reload_completed"
8845 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8846 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8847 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8848{
8849 rtx tmp1;
8850 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8851 operands[2], operands[3]);
8852 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8853
2df9477b 8854 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8855
2df9477b 8856 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8857 if (mode == CCFPmode || mode == CCFPEmode)
8858 rc = reverse_condition_maybe_unordered (rc);
8859 else
8860 rc = reverse_condition (rc);
8861 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8862})
9c08d1fa 8863
080c0b9a 8864;; Attempt to improve the sequence generated by the compare_scc splitters
8865;; not to use conditional execution.
8866(define_peephole2
8867 [(set (reg:CC CC_REGNUM)
8868 (compare:CC (match_operand:SI 1 "register_operand" "")
8869 (match_operand:SI 2 "arm_rhs_operand" "")))
8870 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8871 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8872 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8873 (set (match_dup 0) (const_int 1)))
8874 (match_scratch:SI 3 "r")]
8875 "TARGET_32BIT"
8876 [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
8877 (parallel
8878 [(set (reg:CC CC_REGNUM)
8879 (compare:CC (const_int 0) (match_dup 3)))
8880 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8881 (set (match_dup 0)
8882 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8883 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
8884
f7fbdd4a 8885(define_insn "*cond_move"
9c08d1fa 8886 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8887 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8888 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8889 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8890 (const_int 0)])
8891 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8892 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8893 "TARGET_ARM"
9c08d1fa 8894 "*
8fa3ba89 8895 if (GET_CODE (operands[3]) == NE)
8896 {
8897 if (which_alternative != 1)
8898 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8899 if (which_alternative != 0)
8900 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8901 return \"\";
8902 }
8903 if (which_alternative != 0)
8904 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8905 if (which_alternative != 1)
8906 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8907 return \"\";
8908 "
8909 [(set_attr "conds" "use")
d2a518d1 8910 (set_attr "insn" "mov")
8fa3ba89 8911 (set_attr "length" "4,4,8")]
8912)
9c08d1fa 8913
f7fbdd4a 8914(define_insn "*cond_arith"
9c08d1fa 8915 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8916 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8917 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8918 [(match_operand:SI 2 "s_register_operand" "r,r")
8919 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8920 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8921 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8922 "TARGET_ARM"
9c08d1fa 8923 "*
8fa3ba89 8924 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8925 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8926
8fa3ba89 8927 output_asm_insn (\"cmp\\t%2, %3\", operands);
8928 if (GET_CODE (operands[5]) == AND)
8929 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8930 else if (GET_CODE (operands[5]) == MINUS)
8931 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8932 else if (which_alternative != 0)
8933 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8934 return \"%i5%d4\\t%0, %1, #1\";
8935 "
8936 [(set_attr "conds" "clob")
8937 (set_attr "length" "12")]
8938)
9c08d1fa 8939
f7fbdd4a 8940(define_insn "*cond_sub"
9c08d1fa 8941 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8942 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8943 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8944 [(match_operand:SI 2 "s_register_operand" "r,r")
8945 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8946 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8947 "TARGET_ARM"
9c08d1fa 8948 "*
8fa3ba89 8949 output_asm_insn (\"cmp\\t%2, %3\", operands);
8950 if (which_alternative != 0)
8951 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8952 return \"sub%d4\\t%0, %1, #1\";
8953 "
8954 [(set_attr "conds" "clob")
8955 (set_attr "length" "8,12")]
8956)
9c08d1fa 8957
25f905c2 8958;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 8959(define_insn "*cmp_ite0"
cffb2a26 8960 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8961 (compare
8962 (if_then_else:SI
8fa3ba89 8963 (match_operator 4 "arm_comparison_operator"
aea4c774 8964 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8965 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8966 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8967 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8968 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8969 (const_int 0))
8970 (const_int 0)))]
cffb2a26 8971 "TARGET_ARM"
9c08d1fa 8972 "*
aea4c774 8973 {
8fa3ba89 8974 static const char * const opcodes[4][2] =
8975 {
8976 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8977 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8978 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8979 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8980 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8981 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8982 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8983 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8984 };
8985 int swap =
8986 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8987
8988 return opcodes[which_alternative][swap];
8989 }"
8990 [(set_attr "conds" "set")
8991 (set_attr "length" "8")]
8992)
9c08d1fa 8993
aea4c774 8994(define_insn "*cmp_ite1"
cffb2a26 8995 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8996 (compare
8997 (if_then_else:SI
8fa3ba89 8998 (match_operator 4 "arm_comparison_operator"
aea4c774 8999 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 9000 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9001 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9002 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 9003 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 9004 (const_int 1))
9005 (const_int 0)))]
cffb2a26 9006 "TARGET_ARM"
9c08d1fa 9007 "*
9c08d1fa 9008 {
215b30b3 9009 static const char * const opcodes[4][2] =
9010 {
9011 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9012 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9013 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9014 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9015 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9016 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9017 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9018 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9019 };
9020 int swap =
9021 comparison_dominates_p (GET_CODE (operands[5]),
9022 reverse_condition (GET_CODE (operands[4])));
9023
9024 return opcodes[which_alternative][swap];
9025 }"
8fa3ba89 9026 [(set_attr "conds" "set")
9027 (set_attr "length" "8")]
9028)
9c08d1fa 9029
f6c53574 9030(define_insn "*cmp_and"
9031 [(set (match_operand 6 "dominant_cc_register" "")
9032 (compare
9033 (and:SI
9034 (match_operator 4 "arm_comparison_operator"
9035 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9036 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9037 (match_operator:SI 5 "arm_comparison_operator"
9038 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9039 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9040 (const_int 0)))]
9041 "TARGET_ARM"
9042 "*
9043 {
35823b64 9044 static const char *const opcodes[4][2] =
f6c53574 9045 {
9046 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9047 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9048 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9049 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9050 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9051 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9052 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9053 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9054 };
9055 int swap =
9056 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9057
9058 return opcodes[which_alternative][swap];
9059 }"
9060 [(set_attr "conds" "set")
9061 (set_attr "predicable" "no")
9062 (set_attr "length" "8")]
9063)
9064
9065(define_insn "*cmp_ior"
9066 [(set (match_operand 6 "dominant_cc_register" "")
9067 (compare
9068 (ior:SI
9069 (match_operator 4 "arm_comparison_operator"
9070 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9071 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9072 (match_operator:SI 5 "arm_comparison_operator"
9073 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9074 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9075 (const_int 0)))]
9076 "TARGET_ARM"
9077 "*
9078{
35823b64 9079 static const char *const opcodes[4][2] =
f6c53574 9080 {
9081 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9082 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9083 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9084 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9085 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9086 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9087 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9088 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9089 };
9090 int swap =
9091 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9092
9093 return opcodes[which_alternative][swap];
9094}
9095"
9096 [(set_attr "conds" "set")
9097 (set_attr "length" "8")]
9098)
9099
3c5afce6 9100(define_insn_and_split "*ior_scc_scc"
9101 [(set (match_operand:SI 0 "s_register_operand" "=r")
9102 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9103 [(match_operand:SI 1 "s_register_operand" "r")
9104 (match_operand:SI 2 "arm_add_operand" "rIL")])
9105 (match_operator:SI 6 "arm_comparison_operator"
9106 [(match_operand:SI 4 "s_register_operand" "r")
9107 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9108 (clobber (reg:CC CC_REGNUM))]
9109 "TARGET_ARM
9110 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9111 != CCmode)"
9112 "#"
9113 "TARGET_ARM && reload_completed"
9114 [(set (match_dup 7)
9115 (compare
9116 (ior:SI
9117 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9118 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9119 (const_int 0)))
9120 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9121 "operands[7]
9122 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9123 DOM_CC_X_OR_Y),
601f584c 9124 CC_REGNUM);"
9125 [(set_attr "conds" "clob")
9126 (set_attr "length" "16")])
9127
9128; If the above pattern is followed by a CMP insn, then the compare is
9129; redundant, since we can rework the conditional instruction that follows.
9130(define_insn_and_split "*ior_scc_scc_cmp"
9131 [(set (match_operand 0 "dominant_cc_register" "")
9132 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9133 [(match_operand:SI 1 "s_register_operand" "r")
9134 (match_operand:SI 2 "arm_add_operand" "rIL")])
9135 (match_operator:SI 6 "arm_comparison_operator"
9136 [(match_operand:SI 4 "s_register_operand" "r")
9137 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9138 (const_int 0)))
9139 (set (match_operand:SI 7 "s_register_operand" "=r")
9140 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9141 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9142 "TARGET_ARM"
9143 "#"
9144 "TARGET_ARM && reload_completed"
9145 [(set (match_dup 0)
9146 (compare
9147 (ior:SI
9148 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9149 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9150 (const_int 0)))
9151 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9152 ""
9153 [(set_attr "conds" "set")
9154 (set_attr "length" "16")])
3c5afce6 9155
9156(define_insn_and_split "*and_scc_scc"
9157 [(set (match_operand:SI 0 "s_register_operand" "=r")
9158 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9159 [(match_operand:SI 1 "s_register_operand" "r")
9160 (match_operand:SI 2 "arm_add_operand" "rIL")])
9161 (match_operator:SI 6 "arm_comparison_operator"
9162 [(match_operand:SI 4 "s_register_operand" "r")
9163 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9164 (clobber (reg:CC CC_REGNUM))]
9165 "TARGET_ARM
9166 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9167 != CCmode)"
9168 "#"
601f584c 9169 "TARGET_ARM && reload_completed
9170 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9171 != CCmode)"
3c5afce6 9172 [(set (match_dup 7)
9173 (compare
9174 (and:SI
9175 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9176 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9177 (const_int 0)))
9178 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9179 "operands[7]
9180 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9181 DOM_CC_X_AND_Y),
601f584c 9182 CC_REGNUM);"
9183 [(set_attr "conds" "clob")
9184 (set_attr "length" "16")])
9185
9186; If the above pattern is followed by a CMP insn, then the compare is
9187; redundant, since we can rework the conditional instruction that follows.
9188(define_insn_and_split "*and_scc_scc_cmp"
9189 [(set (match_operand 0 "dominant_cc_register" "")
9190 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9191 [(match_operand:SI 1 "s_register_operand" "r")
9192 (match_operand:SI 2 "arm_add_operand" "rIL")])
9193 (match_operator:SI 6 "arm_comparison_operator"
9194 [(match_operand:SI 4 "s_register_operand" "r")
9195 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9196 (const_int 0)))
9197 (set (match_operand:SI 7 "s_register_operand" "=r")
9198 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9199 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9200 "TARGET_ARM"
9201 "#"
9202 "TARGET_ARM && reload_completed"
9203 [(set (match_dup 0)
9204 (compare
9205 (and:SI
9206 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9207 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9208 (const_int 0)))
9209 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9210 ""
9211 [(set_attr "conds" "set")
9212 (set_attr "length" "16")])
9213
9214;; If there is no dominance in the comparison, then we can still save an
9215;; instruction in the AND case, since we can know that the second compare
9216;; need only zero the value if false (if true, then the value is already
9217;; correct).
9218(define_insn_and_split "*and_scc_scc_nodom"
9219 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9220 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9221 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9222 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9223 (match_operator:SI 6 "arm_comparison_operator"
9224 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9225 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9226 (clobber (reg:CC CC_REGNUM))]
9227 "TARGET_ARM
9228 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9229 == CCmode)"
9230 "#"
9231 "TARGET_ARM && reload_completed"
9232 [(parallel [(set (match_dup 0)
9233 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9234 (clobber (reg:CC CC_REGNUM))])
9235 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9236 (set (match_dup 0)
9237 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9238 (match_dup 0)
9239 (const_int 0)))]
9240 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9241 operands[4], operands[5]),
9242 CC_REGNUM);
9243 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9244 operands[5]);"
9245 [(set_attr "conds" "clob")
9246 (set_attr "length" "20")])
3c5afce6 9247
3a0bdee0 9248(define_split
9249 [(set (reg:CC_NOOV CC_REGNUM)
9250 (compare:CC_NOOV (ior:SI
9251 (and:SI (match_operand:SI 0 "s_register_operand" "")
9252 (const_int 1))
b0694be0 9253 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9254 [(match_operand:SI 2 "s_register_operand" "")
9255 (match_operand:SI 3 "arm_add_operand" "")]))
9256 (const_int 0)))
9257 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9258 "TARGET_ARM"
9259 [(set (match_dup 4)
9260 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9261 (match_dup 0)))
9262 (set (reg:CC_NOOV CC_REGNUM)
9263 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9264 (const_int 0)))]
9265 "")
9266
9267(define_split
9268 [(set (reg:CC_NOOV CC_REGNUM)
9269 (compare:CC_NOOV (ior:SI
b0694be0 9270 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9271 [(match_operand:SI 2 "s_register_operand" "")
9272 (match_operand:SI 3 "arm_add_operand" "")])
9273 (and:SI (match_operand:SI 0 "s_register_operand" "")
9274 (const_int 1)))
9275 (const_int 0)))
9276 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9277 "TARGET_ARM"
9278 [(set (match_dup 4)
9279 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9280 (match_dup 0)))
9281 (set (reg:CC_NOOV CC_REGNUM)
9282 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9283 (const_int 0)))]
9284 "")
25f905c2 9285;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9286
f7fbdd4a 9287(define_insn "*negscc"
9c08d1fa 9288 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9289 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9290 [(match_operand:SI 1 "s_register_operand" "r")
9291 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9292 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9293 "TARGET_ARM"
9c08d1fa 9294 "*
2ca2ec2e 9295 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9296 return \"mov\\t%0, %1, asr #31\";
9297
9c08d1fa 9298 if (GET_CODE (operands[3]) == NE)
e2348bcb 9299 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9300
e2348bcb 9301 output_asm_insn (\"cmp\\t%1, %2\", operands);
9302 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9303 return \"mvn%d3\\t%0, #0\";
215b30b3 9304 "
8fa3ba89 9305 [(set_attr "conds" "clob")
9306 (set_attr "length" "12")]
9307)
9c08d1fa 9308
9309(define_insn "movcond"
9310 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9311 (if_then_else:SI
8fa3ba89 9312 (match_operator 5 "arm_comparison_operator"
5565501b 9313 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9314 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9315 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9316 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9317 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9318 "TARGET_ARM"
9c08d1fa 9319 "*
9320 if (GET_CODE (operands[5]) == LT
9321 && (operands[4] == const0_rtx))
9322 {
5565501b 9323 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9324 {
9c08d1fa 9325 if (operands[2] == const0_rtx)
e2348bcb 9326 return \"and\\t%0, %1, %3, asr #31\";
9327 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9328 }
9329 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9330 {
9c08d1fa 9331 if (operands[1] == const0_rtx)
e2348bcb 9332 return \"bic\\t%0, %2, %3, asr #31\";
9333 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9334 }
9335 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9336 are constants. */
9c08d1fa 9337 }
e2348bcb 9338
9c08d1fa 9339 if (GET_CODE (operands[5]) == GE
9340 && (operands[4] == const0_rtx))
9341 {
9342 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9343 {
9c08d1fa 9344 if (operands[2] == const0_rtx)
e2348bcb 9345 return \"bic\\t%0, %1, %3, asr #31\";
9346 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9347 }
9348 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9349 {
9c08d1fa 9350 if (operands[1] == const0_rtx)
e2348bcb 9351 return \"and\\t%0, %2, %3, asr #31\";
9352 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9353 }
9354 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9355 are constants. */
9c08d1fa 9356 }
9357 if (GET_CODE (operands[4]) == CONST_INT
9358 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9359 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9360 else
e2348bcb 9361 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9362 if (which_alternative != 0)
e2348bcb 9363 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9364 if (which_alternative != 1)
e2348bcb 9365 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9366 return \"\";
215b30b3 9367 "
8fa3ba89 9368 [(set_attr "conds" "clob")
9369 (set_attr "length" "8,8,12")]
9370)
9c08d1fa 9371
25f905c2 9372;; ??? The patterns below need checking for Thumb-2 usefulness.
9373
8a18b90c 9374(define_insn "*ifcompare_plus_move"
9375 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9376 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9377 [(match_operand:SI 4 "s_register_operand" "r,r")
9378 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9379 (plus:SI
9380 (match_operand:SI 2 "s_register_operand" "r,r")
9381 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9382 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9383 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9384 "TARGET_ARM"
8a18b90c 9385 "#"
8fa3ba89 9386 [(set_attr "conds" "clob")
9387 (set_attr "length" "8,12")]
9388)
8a18b90c 9389
9390(define_insn "*if_plus_move"
129a2fe4 9391 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9392 (if_then_else:SI
8fa3ba89 9393 (match_operator 4 "arm_comparison_operator"
8a18b90c 9394 [(match_operand 5 "cc_register" "") (const_int 0)])
9395 (plus:SI
129a2fe4 9396 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9397 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9398 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9399 "TARGET_ARM"
8a18b90c 9400 "@
9401 add%d4\\t%0, %2, %3
9402 sub%d4\\t%0, %2, #%n3
9403 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9404 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9405 [(set_attr "conds" "use")
9406 (set_attr "length" "4,4,8,8")
9407 (set_attr "type" "*,*,*,*")]
9408)
8a18b90c 9409
9410(define_insn "*ifcompare_move_plus"
5565501b 9411 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9412 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9413 [(match_operand:SI 4 "s_register_operand" "r,r")
9414 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9415 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9416 (plus:SI
9417 (match_operand:SI 2 "s_register_operand" "r,r")
9418 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9419 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9420 "TARGET_ARM"
8a18b90c 9421 "#"
8fa3ba89 9422 [(set_attr "conds" "clob")
9423 (set_attr "length" "8,12")]
9424)
8a18b90c 9425
9426(define_insn "*if_move_plus"
129a2fe4 9427 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9428 (if_then_else:SI
8fa3ba89 9429 (match_operator 4 "arm_comparison_operator"
8a18b90c 9430 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9431 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9432 (plus:SI
129a2fe4 9433 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9434 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9435 "TARGET_ARM"
8a18b90c 9436 "@
9437 add%D4\\t%0, %2, %3
9438 sub%D4\\t%0, %2, #%n3
9439 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9440 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9441 [(set_attr "conds" "use")
9442 (set_attr "length" "4,4,8,8")
9443 (set_attr "type" "*,*,*,*")]
9444)
8a18b90c 9445
9446(define_insn "*ifcompare_arith_arith"
9447 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9448 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9449 [(match_operand:SI 5 "s_register_operand" "r")
9450 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9451 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9452 [(match_operand:SI 1 "s_register_operand" "r")
9453 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9454 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9455 [(match_operand:SI 3 "s_register_operand" "r")
9456 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9457 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9458 "TARGET_ARM"
8a18b90c 9459 "#"
8fa3ba89 9460 [(set_attr "conds" "clob")
9461 (set_attr "length" "12")]
9462)
9c08d1fa 9463
8a18b90c 9464(define_insn "*if_arith_arith"
9465 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9466 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9467 [(match_operand 8 "cc_register" "") (const_int 0)])
9468 (match_operator:SI 6 "shiftable_operator"
9469 [(match_operand:SI 1 "s_register_operand" "r")
9470 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9471 (match_operator:SI 7 "shiftable_operator"
9472 [(match_operand:SI 3 "s_register_operand" "r")
9473 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9474 "TARGET_ARM"
8a18b90c 9475 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9476 [(set_attr "conds" "use")
9477 (set_attr "length" "8")]
9478)
8a18b90c 9479
f7fbdd4a 9480(define_insn "*ifcompare_arith_move"
9c08d1fa 9481 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9482 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9483 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9484 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9485 (match_operator:SI 7 "shiftable_operator"
9486 [(match_operand:SI 4 "s_register_operand" "r,r")
9487 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9488 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9489 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9490 "TARGET_ARM"
9c08d1fa 9491 "*
9c08d1fa 9492 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9493 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9494 everything is in registers then we can do this in two instructions. */
9c08d1fa 9495 if (operands[3] == const0_rtx
9496 && GET_CODE (operands[7]) != AND
9497 && GET_CODE (operands[5]) == REG
9498 && GET_CODE (operands[1]) == REG
9499 && REGNO (operands[1]) == REGNO (operands[4])
9500 && REGNO (operands[4]) != REGNO (operands[0]))
9501 {
9502 if (GET_CODE (operands[6]) == LT)
40dbec34 9503 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9504 else if (GET_CODE (operands[6]) == GE)
40dbec34 9505 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9506 }
9507 if (GET_CODE (operands[3]) == CONST_INT
9508 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9509 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9510 else
e2348bcb 9511 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9512 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9513 if (which_alternative != 0)
129a2fe4 9514 return \"mov%D6\\t%0, %1\";
9c08d1fa 9515 return \"\";
215b30b3 9516 "
8fa3ba89 9517 [(set_attr "conds" "clob")
9518 (set_attr "length" "8,12")]
9519)
9c08d1fa 9520
8a18b90c 9521(define_insn "*if_arith_move"
129a2fe4 9522 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9523 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9524 [(match_operand 6 "cc_register" "") (const_int 0)])
9525 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9526 [(match_operand:SI 2 "s_register_operand" "r,r")
9527 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9528 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9529 "TARGET_ARM"
8a18b90c 9530 "@
9531 %I5%d4\\t%0, %2, %3
129a2fe4 9532 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9533 [(set_attr "conds" "use")
9534 (set_attr "length" "4,8")
9535 (set_attr "type" "*,*")]
9536)
8a18b90c 9537
f7fbdd4a 9538(define_insn "*ifcompare_move_arith"
9c08d1fa 9539 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9540 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9541 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9542 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9543 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9544 (match_operator:SI 7 "shiftable_operator"
9545 [(match_operand:SI 2 "s_register_operand" "r,r")
9546 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9547 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9548 "TARGET_ARM"
9c08d1fa 9549 "*
9c08d1fa 9550 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9551 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9552 everything is in registers then we can do this in two instructions */
9553 if (operands[5] == const0_rtx
9554 && GET_CODE (operands[7]) != AND
9555 && GET_CODE (operands[3]) == REG
9556 && GET_CODE (operands[1]) == REG
9557 && REGNO (operands[1]) == REGNO (operands[2])
9558 && REGNO (operands[2]) != REGNO (operands[0]))
9559 {
9560 if (GET_CODE (operands[6]) == GE)
40dbec34 9561 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9562 else if (GET_CODE (operands[6]) == LT)
40dbec34 9563 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9564 }
40dbec34 9565
9c08d1fa 9566 if (GET_CODE (operands[5]) == CONST_INT
9567 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9568 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9569 else
e2348bcb 9570 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9571
9c08d1fa 9572 if (which_alternative != 0)
129a2fe4 9573 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9574 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9575 "
8fa3ba89 9576 [(set_attr "conds" "clob")
9577 (set_attr "length" "8,12")]
9578)
9c08d1fa 9579
8a18b90c 9580(define_insn "*if_move_arith"
129a2fe4 9581 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9582 (if_then_else:SI
8fa3ba89 9583 (match_operator 4 "arm_comparison_operator"
8a18b90c 9584 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9585 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9586 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9587 [(match_operand:SI 2 "s_register_operand" "r,r")
9588 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9589 "TARGET_ARM"
8a18b90c 9590 "@
9591 %I5%D4\\t%0, %2, %3
129a2fe4 9592 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9593 [(set_attr "conds" "use")
9594 (set_attr "length" "4,8")
9595 (set_attr "type" "*,*")]
9596)
8a18b90c 9597
9598(define_insn "*ifcompare_move_not"
9c08d1fa 9599 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9600 (if_then_else:SI
8fa3ba89 9601 (match_operator 5 "arm_comparison_operator"
8a18b90c 9602 [(match_operand:SI 3 "s_register_operand" "r,r")
9603 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9604 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9605 (not:SI
9606 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9607 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9608 "TARGET_ARM"
8a18b90c 9609 "#"
8fa3ba89 9610 [(set_attr "conds" "clob")
9611 (set_attr "length" "8,12")]
9612)
9c08d1fa 9613
8a18b90c 9614(define_insn "*if_move_not"
9615 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9616 (if_then_else:SI
8fa3ba89 9617 (match_operator 4 "arm_comparison_operator"
8a18b90c 9618 [(match_operand 3 "cc_register" "") (const_int 0)])
9619 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9620 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9621 "TARGET_ARM"
8a18b90c 9622 "@
9623 mvn%D4\\t%0, %2
9624 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9625 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9626 [(set_attr "conds" "use")
d2a518d1 9627 (set_attr "insn" "mvn")
8fa3ba89 9628 (set_attr "length" "4,8,8")]
9629)
8a18b90c 9630
9631(define_insn "*ifcompare_not_move"
9c08d1fa 9632 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9633 (if_then_else:SI
8fa3ba89 9634 (match_operator 5 "arm_comparison_operator"
8a18b90c 9635 [(match_operand:SI 3 "s_register_operand" "r,r")
9636 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9637 (not:SI
9638 (match_operand:SI 2 "s_register_operand" "r,r"))
9639 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9640 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9641 "TARGET_ARM"
8a18b90c 9642 "#"
8fa3ba89 9643 [(set_attr "conds" "clob")
9644 (set_attr "length" "8,12")]
9645)
9c08d1fa 9646
8a18b90c 9647(define_insn "*if_not_move"
9648 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9649 (if_then_else:SI
8fa3ba89 9650 (match_operator 4 "arm_comparison_operator"
8a18b90c 9651 [(match_operand 3 "cc_register" "") (const_int 0)])
9652 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9653 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9654 "TARGET_ARM"
8a18b90c 9655 "@
9656 mvn%d4\\t%0, %2
9657 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9658 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9659 [(set_attr "conds" "use")
d2a518d1 9660 (set_attr "insn" "mvn")
8fa3ba89 9661 (set_attr "length" "4,8,8")]
9662)
8a18b90c 9663
9664(define_insn "*ifcompare_shift_move"
9c08d1fa 9665 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9666 (if_then_else:SI
8fa3ba89 9667 (match_operator 6 "arm_comparison_operator"
8a18b90c 9668 [(match_operand:SI 4 "s_register_operand" "r,r")
9669 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9670 (match_operator:SI 7 "shift_operator"
9671 [(match_operand:SI 2 "s_register_operand" "r,r")
9672 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9673 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9674 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9675 "TARGET_ARM"
9c08d1fa 9676 "#"
8fa3ba89 9677 [(set_attr "conds" "clob")
9678 (set_attr "length" "8,12")]
9679)
9c08d1fa 9680
8a18b90c 9681(define_insn "*if_shift_move"
9682 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9683 (if_then_else:SI
8fa3ba89 9684 (match_operator 5 "arm_comparison_operator"
8a18b90c 9685 [(match_operand 6 "cc_register" "") (const_int 0)])
9686 (match_operator:SI 4 "shift_operator"
9687 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9688 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9689 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9690 "TARGET_ARM"
5565501b 9691 "@
8a18b90c 9692 mov%d5\\t%0, %2%S4
9693 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9694 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9695 [(set_attr "conds" "use")
331beb1a 9696 (set_attr "shift" "2")
a2cd141b 9697 (set_attr "length" "4,8,8")
d2a518d1 9698 (set_attr "insn" "mov")
a2cd141b 9699 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9700 (const_string "alu_shift")
9701 (const_string "alu_shift_reg")))]
8fa3ba89 9702)
5565501b 9703
8a18b90c 9704(define_insn "*ifcompare_move_shift"
9705 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9706 (if_then_else:SI
8fa3ba89 9707 (match_operator 6 "arm_comparison_operator"
8a18b90c 9708 [(match_operand:SI 4 "s_register_operand" "r,r")
9709 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9710 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9711 (match_operator:SI 7 "shift_operator"
8a18b90c 9712 [(match_operand:SI 2 "s_register_operand" "r,r")
9713 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9714 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9715 "TARGET_ARM"
8a18b90c 9716 "#"
8fa3ba89 9717 [(set_attr "conds" "clob")
9718 (set_attr "length" "8,12")]
9719)
5565501b 9720
8a18b90c 9721(define_insn "*if_move_shift"
9722 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9723 (if_then_else:SI
8fa3ba89 9724 (match_operator 5 "arm_comparison_operator"
8a18b90c 9725 [(match_operand 6 "cc_register" "") (const_int 0)])
9726 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9727 (match_operator:SI 4 "shift_operator"
9728 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9729 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9730 "TARGET_ARM"
5565501b 9731 "@
8a18b90c 9732 mov%D5\\t%0, %2%S4
9733 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9734 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9735 [(set_attr "conds" "use")
331beb1a 9736 (set_attr "shift" "2")
a2cd141b 9737 (set_attr "length" "4,8,8")
d2a518d1 9738 (set_attr "insn" "mov")
a2cd141b 9739 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9740 (const_string "alu_shift")
9741 (const_string "alu_shift_reg")))]
8fa3ba89 9742)
9c08d1fa 9743
f7fbdd4a 9744(define_insn "*ifcompare_shift_shift"
8a18b90c 9745 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9746 (if_then_else:SI
8fa3ba89 9747 (match_operator 7 "arm_comparison_operator"
8a18b90c 9748 [(match_operand:SI 5 "s_register_operand" "r")
9749 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9750 (match_operator:SI 8 "shift_operator"
8a18b90c 9751 [(match_operand:SI 1 "s_register_operand" "r")
9752 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9753 (match_operator:SI 9 "shift_operator"
8a18b90c 9754 [(match_operand:SI 3 "s_register_operand" "r")
9755 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9756 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9757 "TARGET_ARM"
8a18b90c 9758 "#"
8fa3ba89 9759 [(set_attr "conds" "clob")
9760 (set_attr "length" "12")]
9761)
9c08d1fa 9762
8a18b90c 9763(define_insn "*if_shift_shift"
9764 [(set (match_operand:SI 0 "s_register_operand" "=r")
9765 (if_then_else:SI
8fa3ba89 9766 (match_operator 5 "arm_comparison_operator"
8a18b90c 9767 [(match_operand 8 "cc_register" "") (const_int 0)])
9768 (match_operator:SI 6 "shift_operator"
9769 [(match_operand:SI 1 "s_register_operand" "r")
9770 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9771 (match_operator:SI 7 "shift_operator"
9772 [(match_operand:SI 3 "s_register_operand" "r")
9773 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9774 "TARGET_ARM"
8a18b90c 9775 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9776 [(set_attr "conds" "use")
331beb1a 9777 (set_attr "shift" "1")
a2cd141b 9778 (set_attr "length" "8")
d2a518d1 9779 (set_attr "insn" "mov")
a2cd141b 9780 (set (attr "type") (if_then_else
9781 (and (match_operand 2 "const_int_operand" "")
9782 (match_operand 4 "const_int_operand" ""))
9783 (const_string "alu_shift")
9784 (const_string "alu_shift_reg")))]
8fa3ba89 9785)
8a18b90c 9786
f7fbdd4a 9787(define_insn "*ifcompare_not_arith"
8a18b90c 9788 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9789 (if_then_else:SI
8fa3ba89 9790 (match_operator 6 "arm_comparison_operator"
8a18b90c 9791 [(match_operand:SI 4 "s_register_operand" "r")
9792 (match_operand:SI 5 "arm_add_operand" "rIL")])
9793 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9794 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9795 [(match_operand:SI 2 "s_register_operand" "r")
9796 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9797 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9798 "TARGET_ARM"
8a18b90c 9799 "#"
8fa3ba89 9800 [(set_attr "conds" "clob")
9801 (set_attr "length" "12")]
9802)
9c08d1fa 9803
8a18b90c 9804(define_insn "*if_not_arith"
9805 [(set (match_operand:SI 0 "s_register_operand" "=r")
9806 (if_then_else:SI
8fa3ba89 9807 (match_operator 5 "arm_comparison_operator"
8a18b90c 9808 [(match_operand 4 "cc_register" "") (const_int 0)])
9809 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9810 (match_operator:SI 6 "shiftable_operator"
9811 [(match_operand:SI 2 "s_register_operand" "r")
9812 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9813 "TARGET_ARM"
8a18b90c 9814 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9815 [(set_attr "conds" "use")
d2a518d1 9816 (set_attr "insn" "mvn")
8fa3ba89 9817 (set_attr "length" "8")]
9818)
8a18b90c 9819
9820(define_insn "*ifcompare_arith_not"
9821 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9822 (if_then_else:SI
8fa3ba89 9823 (match_operator 6 "arm_comparison_operator"
8a18b90c 9824 [(match_operand:SI 4 "s_register_operand" "r")
9825 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9826 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9827 [(match_operand:SI 2 "s_register_operand" "r")
9828 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9829 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9830 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9831 "TARGET_ARM"
8a18b90c 9832 "#"
8fa3ba89 9833 [(set_attr "conds" "clob")
9834 (set_attr "length" "12")]
9835)
9c08d1fa 9836
8a18b90c 9837(define_insn "*if_arith_not"
9838 [(set (match_operand:SI 0 "s_register_operand" "=r")
9839 (if_then_else:SI
8fa3ba89 9840 (match_operator 5 "arm_comparison_operator"
8a18b90c 9841 [(match_operand 4 "cc_register" "") (const_int 0)])
9842 (match_operator:SI 6 "shiftable_operator"
9843 [(match_operand:SI 2 "s_register_operand" "r")
9844 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9845 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9846 "TARGET_ARM"
8a18b90c 9847 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9848 [(set_attr "conds" "use")
d2a518d1 9849 (set_attr "insn" "mvn")
8fa3ba89 9850 (set_attr "length" "8")]
9851)
8a18b90c 9852
f7fbdd4a 9853(define_insn "*ifcompare_neg_move"
8a18b90c 9854 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9855 (if_then_else:SI
8fa3ba89 9856 (match_operator 5 "arm_comparison_operator"
8a18b90c 9857 [(match_operand:SI 3 "s_register_operand" "r,r")
9858 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9859 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9860 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9861 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9862 "TARGET_ARM"
8a18b90c 9863 "#"
8fa3ba89 9864 [(set_attr "conds" "clob")
9865 (set_attr "length" "8,12")]
9866)
8a18b90c 9867
9868(define_insn "*if_neg_move"
9869 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9870 (if_then_else:SI
8fa3ba89 9871 (match_operator 4 "arm_comparison_operator"
8a18b90c 9872 [(match_operand 3 "cc_register" "") (const_int 0)])
9873 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9874 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9875 "TARGET_ARM"
8a18b90c 9876 "@
9877 rsb%d4\\t%0, %2, #0
9878 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9879 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9880 [(set_attr "conds" "use")
9881 (set_attr "length" "4,8,8")]
9882)
9c08d1fa 9883
f7fbdd4a 9884(define_insn "*ifcompare_move_neg"
8a18b90c 9885 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9886 (if_then_else:SI
8fa3ba89 9887 (match_operator 5 "arm_comparison_operator"
8a18b90c 9888 [(match_operand:SI 3 "s_register_operand" "r,r")
9889 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9890 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9891 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9892 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9893 "TARGET_ARM"
8a18b90c 9894 "#"
8fa3ba89 9895 [(set_attr "conds" "clob")
9896 (set_attr "length" "8,12")]
9897)
8a18b90c 9898
9899(define_insn "*if_move_neg"
9900 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9901 (if_then_else:SI
8fa3ba89 9902 (match_operator 4 "arm_comparison_operator"
8a18b90c 9903 [(match_operand 3 "cc_register" "") (const_int 0)])
9904 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9905 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9906 "TARGET_ARM"
8a18b90c 9907 "@
9908 rsb%D4\\t%0, %2, #0
9909 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9910 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9911 [(set_attr "conds" "use")
9912 (set_attr "length" "4,8,8")]
9913)
9c08d1fa 9914
f7fbdd4a 9915(define_insn "*arith_adjacentmem"
9c08d1fa 9916 [(set (match_operand:SI 0 "s_register_operand" "=r")
9917 (match_operator:SI 1 "shiftable_operator"
9918 [(match_operand:SI 2 "memory_operand" "m")
9919 (match_operand:SI 3 "memory_operand" "m")]))
9920 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9921 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9922 "*
215b30b3 9923 {
9924 rtx ldm[3];
9925 rtx arith[4];
94dee231 9926 rtx base_reg;
9927 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9928
215b30b3 9929 if (REGNO (operands[0]) > REGNO (operands[4]))
9930 {
9931 ldm[1] = operands[4];
9932 ldm[2] = operands[0];
9933 }
9934 else
9935 {
9936 ldm[1] = operands[0];
9937 ldm[2] = operands[4];
9938 }
94dee231 9939
9940 base_reg = XEXP (operands[2], 0);
9941
9942 if (!REG_P (base_reg))
9943 {
9944 val1 = INTVAL (XEXP (base_reg, 1));
9945 base_reg = XEXP (base_reg, 0);
9946 }
9947
9948 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9949 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9950
215b30b3 9951 arith[0] = operands[0];
9952 arith[3] = operands[1];
94dee231 9953
215b30b3 9954 if (val1 < val2)
9955 {
9956 arith[1] = ldm[1];
9957 arith[2] = ldm[2];
9958 }
9959 else
9960 {
9961 arith[1] = ldm[2];
9962 arith[2] = ldm[1];
9963 }
94dee231 9964
9965 ldm[0] = base_reg;
9966 if (val1 !=0 && val2 != 0)
215b30b3 9967 {
cdb1295a 9968 rtx ops[3];
9969
94dee231 9970 if (val1 == 4 || val2 == 4)
9971 /* Other val must be 8, since we know they are adjacent and neither
9972 is zero. */
25f905c2 9973 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 9974 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 9975 {
94dee231 9976 ldm[0] = ops[0] = operands[4];
9977 ops[1] = base_reg;
9978 ops[2] = GEN_INT (val1);
9979 output_add_immediate (ops);
9980 if (val1 < val2)
25f905c2 9981 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 9982 else
25f905c2 9983 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 9984 }
cdb1295a 9985 else
9986 {
9987 /* Offset is out of range for a single add, so use two ldr. */
9988 ops[0] = ldm[1];
9989 ops[1] = base_reg;
9990 ops[2] = GEN_INT (val1);
9991 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9992 ops[0] = ldm[2];
9993 ops[2] = GEN_INT (val2);
9994 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9995 }
215b30b3 9996 }
94dee231 9997 else if (val1 != 0)
215b30b3 9998 {
215b30b3 9999 if (val1 < val2)
25f905c2 10000 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10001 else
25f905c2 10002 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10003 }
10004 else
10005 {
215b30b3 10006 if (val1 < val2)
25f905c2 10007 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10008 else
25f905c2 10009 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10010 }
10011 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10012 return \"\";
10013 }"
10014 [(set_attr "length" "12")
10015 (set_attr "predicable" "yes")
a2cd141b 10016 (set_attr "type" "load1")]
215b30b3 10017)
9c08d1fa 10018
9c08d1fa 10019; This pattern is never tried by combine, so do it as a peephole
10020
a0f94409 10021(define_peephole2
372575c7 10022 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10023 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10024 (set (reg:CC CC_REGNUM)
aea4c774 10025 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10026 "TARGET_ARM"
a0f94409 10027 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10028 (set (match_dup 0) (match_dup 1))])]
10029 ""
0d66636f 10030)
9c08d1fa 10031
9c08d1fa 10032(define_split
10033 [(set (match_operand:SI 0 "s_register_operand" "")
10034 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10035 (const_int 0))
8fa3ba89 10036 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10037 [(match_operand:SI 3 "s_register_operand" "")
10038 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10039 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10040 "TARGET_ARM"
9c08d1fa 10041 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10042 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10043 (match_dup 5)))]
215b30b3 10044 ""
10045)
9c08d1fa 10046
aea4c774 10047;; This split can be used because CC_Z mode implies that the following
10048;; branch will be an equality, or an unsigned inequality, so the sign
10049;; extension is not needed.
9c08d1fa 10050
aea4c774 10051(define_split
bd5b4116 10052 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10053 (compare:CC_Z
10054 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10055 (const_int 24))
aea4c774 10056 (match_operand 1 "const_int_operand" "")))
10057 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10058 "TARGET_ARM
10059 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10060 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10061 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10062 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10063 "
9c08d1fa 10064 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10065 "
10066)
25f905c2 10067;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10068
87b22bf7 10069(define_expand "prologue"
10070 [(clobber (const_int 0))]
cffb2a26 10071 "TARGET_EITHER"
25f905c2 10072 "if (TARGET_32BIT)
cffb2a26 10073 arm_expand_prologue ();
10074 else
25f905c2 10075 thumb1_expand_prologue ();
87b22bf7 10076 DONE;
cffb2a26 10077 "
10078)
87b22bf7 10079
56d27660 10080(define_expand "epilogue"
4c44712e 10081 [(clobber (const_int 0))]
cffb2a26 10082 "TARGET_EITHER"
56d27660 10083 "
18d50ae6 10084 if (crtl->calls_eh_return)
4c44712e 10085 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10086 if (TARGET_THUMB1)
10087 thumb1_expand_epilogue ();
cffb2a26 10088 else if (USE_RETURN_INSN (FALSE))
56d27660 10089 {
10090 emit_jump_insn (gen_return ());
10091 DONE;
10092 }
cffb2a26 10093 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
1a860023 10094 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
cffb2a26 10095 DONE;
10096 "
10097)
56d27660 10098
ef5651d0 10099;; Note - although unspec_volatile's USE all hard registers,
10100;; USEs are ignored after relaod has completed. Thus we need
10101;; to add an unspec of the link register to ensure that flow
10102;; does not think that it is unused by the sibcall branch that
10103;; will replace the standard function epilogue.
1c494086 10104(define_insn "sibcall_epilogue"
ef5651d0 10105 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10106 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10107 "TARGET_32BIT"
1c494086 10108 "*
ffc9d00c 10109 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10110 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10111 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10112 "
10113;; Length is absolute worst case
10114 [(set_attr "length" "44")
defc47cf 10115 (set_attr "type" "block")
10116 ;; We don't clobber the conditions, but the potential length of this
10117 ;; operation is sufficient to make conditionalizing the sequence
10118 ;; unlikely to be profitable.
10119 (set_attr "conds" "clob")]
1c494086 10120)
10121
cffb2a26 10122(define_insn "*epilogue_insns"
e1159bbe 10123 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10124 "TARGET_EITHER"
56d27660 10125 "*
25f905c2 10126 if (TARGET_32BIT)
ffc9d00c 10127 return arm_output_epilogue (NULL);
25f905c2 10128 else /* TARGET_THUMB1 */
cffb2a26 10129 return thumb_unexpanded_epilogue ();
10130 "
215b30b3 10131 ; Length is absolute worst case
cffb2a26 10132 [(set_attr "length" "44")
defc47cf 10133 (set_attr "type" "block")
10134 ;; We don't clobber the conditions, but the potential length of this
10135 ;; operation is sufficient to make conditionalizing the sequence
10136 ;; unlikely to be profitable.
10137 (set_attr "conds" "clob")]
cffb2a26 10138)
10139
10140(define_expand "eh_epilogue"
7db9af5d 10141 [(use (match_operand:SI 0 "register_operand" ""))
10142 (use (match_operand:SI 1 "register_operand" ""))
10143 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10144 "TARGET_EITHER"
10145 "
215b30b3 10146 {
10147 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10148 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10149 {
10150 rtx ra = gen_rtx_REG (Pmode, 2);
10151
10152 emit_move_insn (ra, operands[2]);
10153 operands[2] = ra;
10154 }
5cf3595a 10155 /* This is a hack -- we may have crystalized the function type too
10156 early. */
10157 cfun->machine->func_type = 0;
215b30b3 10158 }"
10159)
56d27660 10160
9c08d1fa 10161;; This split is only used during output to reduce the number of patterns
10162;; that need assembler instructions adding to them. We allowed the setting
10163;; of the conditions to be implicit during rtl generation so that
10164;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10165;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10166;; up again here.
10167
25f905c2 10168;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10169;; conditional execution sufficient?
10170
9c08d1fa 10171(define_split
10172 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10173 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10174 [(match_operand 2 "" "") (match_operand 3 "" "")])
10175 (match_dup 0)
10176 (match_operand 4 "" "")))
bd5b4116 10177 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10178 "TARGET_ARM && reload_completed"
8fa3ba89 10179 [(set (match_dup 5) (match_dup 6))
10180 (cond_exec (match_dup 7)
10181 (set (match_dup 0) (match_dup 4)))]
10182 "
10183 {
10184 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10185 operands[2], operands[3]);
10186 enum rtx_code rc = GET_CODE (operands[1]);
10187
bd5b4116 10188 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10189 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10190 if (mode == CCFPmode || mode == CCFPEmode)
10191 rc = reverse_condition_maybe_unordered (rc);
10192 else
10193 rc = reverse_condition (rc);
10194
10195 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10196 }"
10197)
10198
10199(define_split
10200 [(set (match_operand:SI 0 "s_register_operand" "")
10201 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10202 [(match_operand 2 "" "") (match_operand 3 "" "")])
10203 (match_operand 4 "" "")
10204 (match_dup 0)))
bd5b4116 10205 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10206 "TARGET_ARM && reload_completed"
8fa3ba89 10207 [(set (match_dup 5) (match_dup 6))
10208 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10209 (set (match_dup 0) (match_dup 4)))]
10210 "
10211 {
10212 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10213 operands[2], operands[3]);
10214
bd5b4116 10215 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10216 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10217 }"
10218)
10219
10220(define_split
10221 [(set (match_operand:SI 0 "s_register_operand" "")
10222 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10223 [(match_operand 2 "" "") (match_operand 3 "" "")])
10224 (match_operand 4 "" "")
10225 (match_operand 5 "" "")))
bd5b4116 10226 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10227 "TARGET_ARM && reload_completed"
8fa3ba89 10228 [(set (match_dup 6) (match_dup 7))
10229 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10230 (set (match_dup 0) (match_dup 4)))
10231 (cond_exec (match_dup 8)
10232 (set (match_dup 0) (match_dup 5)))]
10233 "
10234 {
10235 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10236 operands[2], operands[3]);
10237 enum rtx_code rc = GET_CODE (operands[1]);
10238
bd5b4116 10239 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10240 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10241 if (mode == CCFPmode || mode == CCFPEmode)
10242 rc = reverse_condition_maybe_unordered (rc);
10243 else
10244 rc = reverse_condition (rc);
10245
10246 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10247 }"
10248)
10249
cffb2a26 10250(define_split
10251 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10252 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10253 [(match_operand:SI 2 "s_register_operand" "")
10254 (match_operand:SI 3 "arm_add_operand" "")])
10255 (match_operand:SI 4 "arm_rhs_operand" "")
10256 (not:SI
10257 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10258 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10259 "TARGET_ARM && reload_completed"
cffb2a26 10260 [(set (match_dup 6) (match_dup 7))
f6c53574 10261 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10262 (set (match_dup 0) (match_dup 4)))
10263 (cond_exec (match_dup 8)
10264 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10265 "
215b30b3 10266 {
10267 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10268 operands[2], operands[3]);
f6c53574 10269 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10270
bd5b4116 10271 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10272 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10273 if (mode == CCFPmode || mode == CCFPEmode)
10274 rc = reverse_condition_maybe_unordered (rc);
10275 else
10276 rc = reverse_condition (rc);
10277
10278 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10279 }"
10280)
cffb2a26 10281
10282(define_insn "*cond_move_not"
10283 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10284 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10285 [(match_operand 3 "cc_register" "") (const_int 0)])
10286 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10287 (not:SI
10288 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10289 "TARGET_ARM"
10290 "@
10291 mvn%D4\\t%0, %2
10292 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10293 [(set_attr "conds" "use")
d2a518d1 10294 (set_attr "insn" "mvn")
0d66636f 10295 (set_attr "length" "4,8")]
10296)
cffb2a26 10297
9c08d1fa 10298;; The next two patterns occur when an AND operation is followed by a
10299;; scc insn sequence
10300
f7fbdd4a 10301(define_insn "*sign_extract_onebit"
9c08d1fa 10302 [(set (match_operand:SI 0 "s_register_operand" "=r")
10303 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10304 (const_int 1)
ed750274 10305 (match_operand:SI 2 "const_int_operand" "n")))
10306 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10307 "TARGET_ARM"
9c08d1fa 10308 "*
0d66636f 10309 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10310 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10311 return \"mvnne\\t%0, #0\";
10312 "
10313 [(set_attr "conds" "clob")
10314 (set_attr "length" "8")]
10315)
9c08d1fa 10316
f7fbdd4a 10317(define_insn "*not_signextract_onebit"
9c08d1fa 10318 [(set (match_operand:SI 0 "s_register_operand" "=r")
10319 (not:SI
10320 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10321 (const_int 1)
ed750274 10322 (match_operand:SI 2 "const_int_operand" "n"))))
10323 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10324 "TARGET_ARM"
9c08d1fa 10325 "*
0d66636f 10326 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10327 output_asm_insn (\"tst\\t%1, %2\", operands);
10328 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10329 return \"movne\\t%0, #0\";
10330 "
10331 [(set_attr "conds" "clob")
10332 (set_attr "length" "12")]
10333)
25f905c2 10334;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10335
0d66636f 10336;; Push multiple registers to the stack. Registers are in parallel (use ...)
10337;; expressions. For simplicity, the first register is also in the unspec
10338;; part.
08508cbf 10339;; To avoid the usage of GNU extension, the length attribute is computed
10340;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10341(define_insn "*push_multi"
87b22bf7 10342 [(match_parallel 2 "multi_register_push"
10343 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10344 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10345 UNSPEC_PUSH_MULT))])]
25f905c2 10346 "TARGET_32BIT"
87b22bf7 10347 "*
215b30b3 10348 {
10349 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10350
215b30b3 10351 /* For the StrongARM at least it is faster to
25f905c2 10352 use STR to store only a single register.
542d5028 10353 In Thumb mode always use push, and the assembler will pick
10354 something appropriate. */
25f905c2 10355 if (num_saves == 1 && TARGET_ARM)
215b30b3 10356 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10357 else
10358 {
10359 int i;
10360 char pattern[100];
ed593f11 10361
25f905c2 10362 if (TARGET_ARM)
10363 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10364 else
10365 strcpy (pattern, \"push\\t{%1\");
215b30b3 10366
6079f055 10367 for (i = 1; i < num_saves; i++)
215b30b3 10368 {
10369 strcat (pattern, \", %|\");
10370 strcat (pattern,
10371 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10372 }
10373
10374 strcat (pattern, \"}\");
10375 output_asm_insn (pattern, operands);
10376 }
10377
10378 return \"\";
10379 }"
a6864a24 10380 [(set_attr "type" "store4")
10381 (set (attr "length")
08508cbf 10382 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10383)
f7fbdd4a 10384
4c58c898 10385(define_insn "stack_tie"
10386 [(set (mem:BLK (scratch))
aaa37ad6 10387 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10388 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10389 UNSPEC_PRLG_STK))]
10390 ""
10391 ""
10392 [(set_attr "length" "0")]
10393)
10394
3398e91d 10395;; Similarly for the floating point registers
7b1d2fc4 10396(define_insn "*push_fp_multi"
10397 [(match_parallel 2 "multi_register_push"
10398 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10399 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10400 UNSPEC_PUSH_MULT))])]
25f905c2 10401 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10402 "*
215b30b3 10403 {
10404 char pattern[100];
7b1d2fc4 10405
215b30b3 10406 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10407 output_asm_insn (pattern, operands);
10408 return \"\";
10409 }"
013b9671 10410 [(set_attr "type" "f_fpa_store")]
215b30b3 10411)
7b1d2fc4 10412
f7fbdd4a 10413;; Special patterns for dealing with the constant pool
10414
cffb2a26 10415(define_insn "align_4"
e1159bbe 10416 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10417 "TARGET_EITHER"
f7fbdd4a 10418 "*
cffb2a26 10419 assemble_align (32);
f7fbdd4a 10420 return \"\";
cffb2a26 10421 "
10422)
f7fbdd4a 10423
755eb2b4 10424(define_insn "align_8"
10425 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10426 "TARGET_EITHER"
755eb2b4 10427 "*
10428 assemble_align (64);
10429 return \"\";
10430 "
10431)
10432
cffb2a26 10433(define_insn "consttable_end"
e1159bbe 10434 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10435 "TARGET_EITHER"
f7fbdd4a 10436 "*
cffb2a26 10437 making_const_table = FALSE;
f7fbdd4a 10438 return \"\";
cffb2a26 10439 "
10440)
f7fbdd4a 10441
cffb2a26 10442(define_insn "consttable_1"
e1159bbe 10443 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10444 "TARGET_THUMB1"
f7fbdd4a 10445 "*
cffb2a26 10446 making_const_table = TRUE;
09d688ff 10447 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10448 assemble_zeros (3);
f7fbdd4a 10449 return \"\";
cffb2a26 10450 "
10451 [(set_attr "length" "4")]
10452)
f7fbdd4a 10453
cffb2a26 10454(define_insn "consttable_2"
e1159bbe 10455 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10456 "TARGET_THUMB1"
f7fbdd4a 10457 "*
cffb2a26 10458 making_const_table = TRUE;
9b8516be 10459 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10460 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10461 assemble_zeros (2);
f7fbdd4a 10462 return \"\";
cffb2a26 10463 "
10464 [(set_attr "length" "4")]
10465)
10466
10467(define_insn "consttable_4"
e1159bbe 10468 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10469 "TARGET_EITHER"
10470 "*
10471 {
9b8516be 10472 rtx x = operands[0];
cffb2a26 10473 making_const_table = TRUE;
9b8516be 10474 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10475 {
10476 case MODE_FLOAT:
9b8516be 10477 if (GET_MODE (x) == HFmode)
10478 arm_emit_fp16_const (x);
10479 else
10480 {
10481 REAL_VALUE_TYPE r;
10482 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10483 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10484 }
10485 break;
cffb2a26 10486 default:
7b04c5d5 10487 /* XXX: Sometimes gcc does something really dumb and ends up with
10488 a HIGH in a constant pool entry, usually because it's trying to
10489 load into a VFP register. We know this will always be used in
10490 combination with a LO_SUM which ignores the high bits, so just
10491 strip off the HIGH. */
10492 if (GET_CODE (x) == HIGH)
10493 x = XEXP (x, 0);
9b8516be 10494 assemble_integer (x, 4, BITS_PER_WORD, 1);
10495 mark_symbol_refs_as_used (x);
cffb2a26 10496 break;
10497 }
10498 return \"\";
10499 }"
10500 [(set_attr "length" "4")]
10501)
10502
10503(define_insn "consttable_8"
e1159bbe 10504 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10505 "TARGET_EITHER"
10506 "*
10507 {
10508 making_const_table = TRUE;
10509 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10510 {
10511 case MODE_FLOAT:
10512 {
badfe841 10513 REAL_VALUE_TYPE r;
10514 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10515 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10516 break;
10517 }
10518 default:
09d688ff 10519 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10520 break;
10521 }
10522 return \"\";
10523 }"
10524 [(set_attr "length" "8")]
10525)
10526
d98a3884 10527(define_insn "consttable_16"
10528 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10529 "TARGET_EITHER"
10530 "*
10531 {
10532 making_const_table = TRUE;
10533 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10534 {
10535 case MODE_FLOAT:
10536 {
10537 REAL_VALUE_TYPE r;
10538 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10539 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10540 break;
10541 }
10542 default:
10543 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10544 break;
10545 }
10546 return \"\";
10547 }"
10548 [(set_attr "length" "16")]
10549)
10550
cffb2a26 10551;; Miscellaneous Thumb patterns
10552
fd957ef3 10553(define_expand "tablejump"
7db9af5d 10554 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10555 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10556 "TARGET_THUMB1"
fd957ef3 10557 "
10558 if (flag_pic)
10559 {
10560 /* Hopefully, CSE will eliminate this copy. */
10561 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10562 rtx reg2 = gen_reg_rtx (SImode);
10563
10564 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10565 operands[0] = reg2;
10566 }
10567 "
10568)
10569
f1039640 10570;; NB never uses BX.
25f905c2 10571(define_insn "*thumb1_tablejump"
cffb2a26 10572 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10573 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10574 "TARGET_THUMB1"
fd957ef3 10575 "mov\\t%|pc, %0"
cffb2a26 10576 [(set_attr "length" "2")]
10577)
0d66636f 10578
331beb1a 10579;; V5 Instructions,
10580
8f4be2be 10581(define_insn "clzsi2"
10582 [(set (match_operand:SI 0 "s_register_operand" "=r")
10583 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10584 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10585 "clz%?\\t%0, %1"
bcaec148 10586 [(set_attr "predicable" "yes")
10587 (set_attr "insn" "clz")])
331beb1a 10588
099ad98b 10589(define_insn "rbitsi2"
10590 [(set (match_operand:SI 0 "s_register_operand" "=r")
10591 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10592 "TARGET_32BIT && arm_arch_thumb2"
10593 "rbit%?\\t%0, %1"
10594 [(set_attr "predicable" "yes")
10595 (set_attr "insn" "clz")])
10596
10597(define_expand "ctzsi2"
10598 [(set (match_operand:SI 0 "s_register_operand" "")
10599 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10600 "TARGET_32BIT && arm_arch_thumb2"
10601 "
30191172 10602 {
10603 rtx tmp = gen_reg_rtx (SImode);
10604 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10605 emit_insn (gen_clzsi2 (operands[0], tmp));
10606 }
099ad98b 10607 DONE;
10608 "
10609)
10610
e1159bbe 10611;; V5E instructions.
331beb1a 10612
10613(define_insn "prefetch"
f4e79814 10614 [(prefetch (match_operand:SI 0 "address_operand" "p")
10615 (match_operand:SI 1 "" "")
10616 (match_operand:SI 2 "" ""))]
25f905c2 10617 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10618 "pld\\t%a0")
331beb1a 10619
0d66636f 10620;; General predication pattern
10621
10622(define_cond_exec
10623 [(match_operator 0 "arm_comparison_operator"
10624 [(match_operand 1 "cc_register" "")
10625 (const_int 0)])]
25f905c2 10626 "TARGET_32BIT"
0d66636f 10627 ""
10628)
10629
063a05c7 10630(define_insn "prologue_use"
10631 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10632 ""
10633 "%@ %0 needed for prologue"
02cfc9c9 10634 [(set_attr "length" "0")]
063a05c7 10635)
7db9af5d 10636
4c44712e 10637
10638;; Patterns for exception handling
10639
10640(define_expand "eh_return"
10641 [(use (match_operand 0 "general_operand" ""))]
10642 "TARGET_EITHER"
10643 "
10644 {
25f905c2 10645 if (TARGET_32BIT)
4c44712e 10646 emit_insn (gen_arm_eh_return (operands[0]));
10647 else
10648 emit_insn (gen_thumb_eh_return (operands[0]));
10649 DONE;
10650 }"
10651)
10652
10653;; We can't expand this before we know where the link register is stored.
10654(define_insn_and_split "arm_eh_return"
10655 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10656 VUNSPEC_EH_RETURN)
10657 (clobber (match_scratch:SI 1 "=&r"))]
10658 "TARGET_ARM"
10659 "#"
10660 "&& reload_completed"
10661 [(const_int 0)]
10662 "
10663 {
10664 arm_set_return_address (operands[0], operands[1]);
10665 DONE;
10666 }"
10667)
10668
10669(define_insn_and_split "thumb_eh_return"
10670 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10671 VUNSPEC_EH_RETURN)
10672 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10673 "TARGET_THUMB1"
4c44712e 10674 "#"
10675 "&& reload_completed"
10676 [(const_int 0)]
10677 "
10678 {
10679 thumb_set_return_address (operands[0], operands[1]);
10680 DONE;
10681 }"
10682)
10683
f655717d 10684\f
10685;; TLS support
10686
10687(define_insn "load_tp_hard"
10688 [(set (match_operand:SI 0 "register_operand" "=r")
10689 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10690 "TARGET_HARD_TP"
10691 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10692 [(set_attr "predicable" "yes")]
10693)
10694
10695;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10696(define_insn "load_tp_soft"
10697 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10698 (clobber (reg:SI LR_REGNUM))
10699 (clobber (reg:SI IP_REGNUM))
10700 (clobber (reg:CC CC_REGNUM))]
10701 "TARGET_SOFT_TP"
10702 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10703 [(set_attr "conds" "clob")]
10704)
10705
aabe09ac 10706;; We only care about the lower 16 bits of the constant
10707;; being inserted into the upper 16 bits of the register.
eca5c984 10708(define_insn "*arm_movtas_ze"
10709 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10710 (const_int 16)
10711 (const_int 16))
10712 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10713 "arm_arch_thumb2"
aabe09ac 10714 "movt%?\t%0, %L1"
eca5c984 10715 [(set_attr "predicable" "yes")
10716 (set_attr "length" "4")]
10717)
10718
c0fc3696 10719(define_insn "*arm_rev"
ff82f757 10720 [(set (match_operand:SI 0 "s_register_operand" "=r")
10721 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 10722 "TARGET_32BIT && arm_arch6"
10723 "rev%?\t%0, %1"
10724 [(set_attr "predicable" "yes")
10725 (set_attr "length" "4")]
10726)
10727
10728(define_insn "*thumb1_rev"
10729 [(set (match_operand:SI 0 "s_register_operand" "=l")
10730 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10731 "TARGET_THUMB1 && arm_arch6"
10732 "rev\t%0, %1"
10733 [(set_attr "length" "2")]
ff82f757 10734)
10735
10736(define_expand "arm_legacy_rev"
10737 [(set (match_operand:SI 2 "s_register_operand" "")
10738 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10739 (const_int 16))
10740 (match_dup 1)))
10741 (set (match_dup 2)
10742 (lshiftrt:SI (match_dup 2)
10743 (const_int 8)))
10744 (set (match_operand:SI 3 "s_register_operand" "")
10745 (rotatert:SI (match_dup 1)
10746 (const_int 8)))
10747 (set (match_dup 2)
10748 (and:SI (match_dup 2)
10749 (const_int -65281)))
10750 (set (match_operand:SI 0 "s_register_operand" "")
10751 (xor:SI (match_dup 3)
10752 (match_dup 2)))]
10753 "TARGET_32BIT"
10754 ""
10755)
10756
10757;; Reuse temporaries to keep register pressure down.
10758(define_expand "thumb_legacy_rev"
10759 [(set (match_operand:SI 2 "s_register_operand" "")
10760 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10761 (const_int 24)))
10762 (set (match_operand:SI 3 "s_register_operand" "")
10763 (lshiftrt:SI (match_dup 1)
10764 (const_int 24)))
10765 (set (match_dup 3)
10766 (ior:SI (match_dup 3)
10767 (match_dup 2)))
10768 (set (match_operand:SI 4 "s_register_operand" "")
10769 (const_int 16))
10770 (set (match_operand:SI 5 "s_register_operand" "")
10771 (rotatert:SI (match_dup 1)
10772 (match_dup 4)))
10773 (set (match_dup 2)
10774 (ashift:SI (match_dup 5)
10775 (const_int 24)))
10776 (set (match_dup 5)
10777 (lshiftrt:SI (match_dup 5)
10778 (const_int 24)))
10779 (set (match_dup 5)
10780 (ior:SI (match_dup 5)
10781 (match_dup 2)))
10782 (set (match_dup 5)
10783 (rotatert:SI (match_dup 5)
10784 (match_dup 4)))
10785 (set (match_operand:SI 0 "s_register_operand" "")
10786 (ior:SI (match_dup 5)
10787 (match_dup 3)))]
10788 "TARGET_THUMB"
10789 ""
10790)
10791
10792(define_expand "bswapsi2"
10793 [(set (match_operand:SI 0 "s_register_operand" "=r")
10794 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10795"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10796"
8d1af482 10797 if (!arm_arch6)
10798 {
10799 rtx op2 = gen_reg_rtx (SImode);
10800 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10801
8d1af482 10802 if (TARGET_THUMB)
10803 {
10804 rtx op4 = gen_reg_rtx (SImode);
10805 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10806
8d1af482 10807 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10808 op2, op3, op4, op5));
10809 }
10810 else
10811 {
10812 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10813 op2, op3));
10814 }
ff82f757 10815
8d1af482 10816 DONE;
10817 }
ff82f757 10818 "
10819)
10820
320ea44d 10821;; Load the load/store multiple patterns
10822(include "ldmstm.md")
7db9af5d 10823;; Load the FPA co-processor patterns
10824(include "fpa.md")
10825;; Load the Maverick co-processor patterns
10826(include "cirrus.md")
d98a3884 10827;; Vector bits common to IWMMXT and Neon
10828(include "vec-common.md")
755eb2b4 10829;; Load the Intel Wireless Multimedia Extension patterns
10830(include "iwmmxt.md")
a2cd141b 10831;; Load the VFP co-processor patterns
10832(include "vfp.md")
25f905c2 10833;; Thumb-2 patterns
10834(include "thumb2.md")
d98a3884 10835;; Neon patterns
10836(include "neon.md")
06df6b17 10837;; Synchronization Primitives
10838(include "sync.md")