]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
PR target/47755
[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
499 (eq_attr "tune" "cortexr4,cortexr4f")
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
f7fbdd4a 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
5cdca009 1818(define_insn "*maddhidi4"
331beb1a 1819 [(set (match_operand:DI 0 "s_register_operand" "=r")
1820 (plus:DI
331beb1a 1821 (mult:DI (sign_extend:DI
cfa6c608 1822 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1823 (sign_extend:DI
cfa6c608 1824 (match_operand:HI 2 "s_register_operand" "r")))
1825 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1826 "TARGET_DSP_MULTIPLY"
5cdca009 1827 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1828 [(set_attr "insn" "smlalxy")
fec538d9 1829 (set_attr "predicable" "yes")])
331beb1a 1830
604f3a0a 1831(define_expand "mulsf3"
1832 [(set (match_operand:SF 0 "s_register_operand" "")
1833 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1834 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1835 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1836 "
a2cd141b 1837 if (TARGET_MAVERICK
604f3a0a 1838 && !cirrus_fp_register (operands[2], SFmode))
1839 operands[2] = force_reg (SFmode, operands[2]);
1840")
1841
604f3a0a 1842(define_expand "muldf3"
1843 [(set (match_operand:DF 0 "s_register_operand" "")
1844 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1845 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1846 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1847 "
a2cd141b 1848 if (TARGET_MAVERICK
604f3a0a 1849 && !cirrus_fp_register (operands[2], DFmode))
1850 operands[2] = force_reg (DFmode, operands[2]);
1851")
b11cae9e 1852\f
1853;; Division insns
1854
7db9af5d 1855(define_expand "divsf3"
1856 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1857 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1858 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1859 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1860 "")
9c08d1fa 1861
7db9af5d 1862(define_expand "divdf3"
1863 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1864 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1865 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1866 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1867 "")
b11cae9e 1868\f
1869;; Modulo insns
1870
7db9af5d 1871(define_expand "modsf3"
1872 [(set (match_operand:SF 0 "s_register_operand" "")
1873 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1874 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1875 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1876 "")
9c08d1fa 1877
7db9af5d 1878(define_expand "moddf3"
1879 [(set (match_operand:DF 0 "s_register_operand" "")
1880 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1881 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1882 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1883 "")
b11cae9e 1884\f
1885;; Boolean and,ior,xor insns
1886
f6ebffac 1887;; Split up double word logical operations
1888
1889;; Split up simple DImode logical operations. Simply perform the logical
1890;; operation on the upper and lower halves of the registers.
1891(define_split
1892 [(set (match_operand:DI 0 "s_register_operand" "")
1893 (match_operator:DI 6 "logical_binary_operator"
1894 [(match_operand:DI 1 "s_register_operand" "")
1895 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1896 "TARGET_32BIT && reload_completed
e2669ea7 1897 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1898 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1899 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1900 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1901 "
215b30b3 1902 {
1903 operands[3] = gen_highpart (SImode, operands[0]);
1904 operands[0] = gen_lowpart (SImode, operands[0]);
1905 operands[4] = gen_highpart (SImode, operands[1]);
1906 operands[1] = gen_lowpart (SImode, operands[1]);
1907 operands[5] = gen_highpart (SImode, operands[2]);
1908 operands[2] = gen_lowpart (SImode, operands[2]);
1909 }"
1910)
f6ebffac 1911
f6ebffac 1912(define_split
1913 [(set (match_operand:DI 0 "s_register_operand" "")
1914 (match_operator:DI 6 "logical_binary_operator"
1915 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1916 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1917 "TARGET_32BIT && reload_completed"
f6ebffac 1918 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1919 (set (match_dup 3) (match_op_dup:SI 6
1920 [(ashiftrt:SI (match_dup 2) (const_int 31))
1921 (match_dup 4)]))]
1922 "
215b30b3 1923 {
1924 operands[3] = gen_highpart (SImode, operands[0]);
1925 operands[0] = gen_lowpart (SImode, operands[0]);
1926 operands[4] = gen_highpart (SImode, operands[1]);
1927 operands[1] = gen_lowpart (SImode, operands[1]);
1928 operands[5] = gen_highpart (SImode, operands[2]);
1929 operands[2] = gen_lowpart (SImode, operands[2]);
1930 }"
1931)
f6ebffac 1932
f6ebffac 1933;; The zero extend of operand 2 means we can just copy the high part of
1934;; operand1 into operand0.
1935(define_split
1936 [(set (match_operand:DI 0 "s_register_operand" "")
1937 (ior:DI
1938 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1939 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1940 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1941 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1942 (set (match_dup 3) (match_dup 4))]
1943 "
215b30b3 1944 {
1945 operands[4] = gen_highpart (SImode, operands[1]);
1946 operands[3] = gen_highpart (SImode, operands[0]);
1947 operands[0] = gen_lowpart (SImode, operands[0]);
1948 operands[1] = gen_lowpart (SImode, operands[1]);
1949 }"
1950)
f6ebffac 1951
1952;; The zero extend of operand 2 means we can just copy the high part of
1953;; operand1 into operand0.
1954(define_split
1955 [(set (match_operand:DI 0 "s_register_operand" "")
1956 (xor:DI
1957 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1958 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1959 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1960 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1961 (set (match_dup 3) (match_dup 4))]
1962 "
215b30b3 1963 {
1964 operands[4] = gen_highpart (SImode, operands[1]);
1965 operands[3] = gen_highpart (SImode, operands[0]);
1966 operands[0] = gen_lowpart (SImode, operands[0]);
1967 operands[1] = gen_lowpart (SImode, operands[1]);
1968 }"
1969)
f6ebffac 1970
e2669ea7 1971(define_expand "anddi3"
1972 [(set (match_operand:DI 0 "s_register_operand" "")
1973 (and:DI (match_operand:DI 1 "s_register_operand" "")
1974 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1975 "TARGET_32BIT"
1976 ""
1977)
1978
1979(define_insn "*anddi3_insn"
cffb2a26 1980 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1981 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1982 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 1983 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 1984 "#"
215b30b3 1985 [(set_attr "length" "8")]
1986)
b11cae9e 1987
a0f94409 1988(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1989 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1990 (and:DI (zero_extend:DI
1991 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1992 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1993 "TARGET_32BIT"
f6ebffac 1994 "#"
25f905c2 1995 "TARGET_32BIT && reload_completed"
a0f94409 1996 ; The zero extend of operand 2 clears the high word of the output
1997 ; operand.
1998 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1999 (set (match_dup 3) (const_int 0))]
2000 "
2001 {
2002 operands[3] = gen_highpart (SImode, operands[0]);
2003 operands[0] = gen_lowpart (SImode, operands[0]);
2004 operands[1] = gen_lowpart (SImode, operands[1]);
2005 }"
215b30b3 2006 [(set_attr "length" "8")]
2007)
b11cae9e 2008
f7fbdd4a 2009(define_insn "*anddi_sesdi_di"
cffb2a26 2010 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2011 (and:DI (sign_extend:DI
2012 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2013 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2014 "TARGET_32BIT"
f6ebffac 2015 "#"
cffb2a26 2016 [(set_attr "length" "8")]
2017)
b11cae9e 2018
87b22bf7 2019(define_expand "andsi3"
cffb2a26 2020 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2021 (and:SI (match_operand:SI 1 "s_register_operand" "")
2022 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2023 "TARGET_EITHER"
87b22bf7 2024 "
25f905c2 2025 if (TARGET_32BIT)
87b22bf7 2026 {
cffb2a26 2027 if (GET_CODE (operands[2]) == CONST_INT)
2028 {
47b5b27b 2029 if (INTVAL (operands[2]) == 255 && arm_arch6)
2030 {
2031 operands[1] = convert_to_mode (QImode, operands[1], 1);
2032 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2033 operands[1]));
2034 }
2035 else
2036 arm_split_constant (AND, SImode, NULL_RTX,
2037 INTVAL (operands[2]), operands[0],
2038 operands[1],
2039 optimize && can_create_pseudo_p ());
615caa51 2040
cffb2a26 2041 DONE;
2042 }
87b22bf7 2043 }
25f905c2 2044 else /* TARGET_THUMB1 */
cffb2a26 2045 {
2046 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2047 {
2048 rtx tmp = force_reg (SImode, operands[2]);
2049 if (rtx_equal_p (operands[0], operands[1]))
2050 operands[2] = tmp;
2051 else
2052 {
2053 operands[2] = operands[1];
2054 operands[1] = tmp;
2055 }
2056 }
cffb2a26 2057 else
2058 {
2059 int i;
2060
215b30b3 2061 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2062 {
215b30b3 2063 operands[2] = force_reg (SImode,
2064 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2065
747b7458 2066 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2067
2068 DONE;
2069 }
87b22bf7 2070
cffb2a26 2071 for (i = 9; i <= 31; i++)
2072 {
2073 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2074 {
2075 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2076 const0_rtx));
2077 DONE;
2078 }
215b30b3 2079 else if ((((HOST_WIDE_INT) 1) << i) - 1
2080 == ~INTVAL (operands[2]))
cffb2a26 2081 {
2082 rtx shift = GEN_INT (i);
2083 rtx reg = gen_reg_rtx (SImode);
2084
2085 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2086 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2087
2088 DONE;
2089 }
2090 }
2091
2092 operands[2] = force_reg (SImode, operands[2]);
2093 }
215b30b3 2094 }
2095 "
cffb2a26 2096)
2097
25f905c2 2098; ??? Check split length for Thumb-2
a0f94409 2099(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2100 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2101 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2102 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2103 "TARGET_32BIT"
5565501b 2104 "@
2105 and%?\\t%0, %1, %2
87b22bf7 2106 bic%?\\t%0, %1, #%B2
2107 #"
25f905c2 2108 "TARGET_32BIT
a0f94409 2109 && GET_CODE (operands[2]) == CONST_INT
2110 && !(const_ok_for_arm (INTVAL (operands[2]))
2111 || const_ok_for_arm (~INTVAL (operands[2])))"
2112 [(clobber (const_int 0))]
2113 "
96f57e36 2114 arm_split_constant (AND, SImode, curr_insn,
2115 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2116 DONE;
2117 "
0d66636f 2118 [(set_attr "length" "4,4,16")
2119 (set_attr "predicable" "yes")]
cffb2a26 2120)
2121
25f905c2 2122(define_insn "*thumb1_andsi3_insn"
cffb2a26 2123 [(set (match_operand:SI 0 "register_operand" "=l")
2124 (and:SI (match_operand:SI 1 "register_operand" "%0")
2125 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2126 "TARGET_THUMB1"
747b7458 2127 "and\\t%0, %2"
2128 [(set_attr "length" "2")
2129 (set_attr "conds" "set")])
87b22bf7 2130
f7fbdd4a 2131(define_insn "*andsi3_compare0"
bd5b4116 2132 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2133 (compare:CC_NOOV
2134 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2135 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2136 (const_int 0)))
cffb2a26 2137 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2138 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2139 "TARGET_32BIT"
5565501b 2140 "@
25f905c2 2141 and%.\\t%0, %1, %2
2142 bic%.\\t%0, %1, #%B2"
cffb2a26 2143 [(set_attr "conds" "set")]
2144)
9c08d1fa 2145
f7fbdd4a 2146(define_insn "*andsi3_compare0_scratch"
bd5b4116 2147 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2148 (compare:CC_NOOV
2149 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2150 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2151 (const_int 0)))
dd193d7c 2152 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2153 "TARGET_32BIT"
5565501b 2154 "@
2155 tst%?\\t%0, %1
25f905c2 2156 bic%.\\t%2, %0, #%B1"
0d66636f 2157 [(set_attr "conds" "set")]
2158)
9c08d1fa 2159
f7fbdd4a 2160(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2161 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2162 (compare:CC_NOOV (zero_extract:SI
2163 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2164 (match_operand 1 "const_int_operand" "n")
2165 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2166 (const_int 0)))]
25f905c2 2167 "TARGET_32BIT
cffb2a26 2168 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2169 && INTVAL (operands[1]) > 0
2170 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2171 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2172 "*
5c49a439 2173 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2174 << INTVAL (operands[2]));
40dbec34 2175 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2176 return \"\";
0d66636f 2177 "
2178 [(set_attr "conds" "set")]
2179)
9c08d1fa 2180
f4462328 2181(define_insn_and_split "*ne_zeroextractsi"
c4034607 2182 [(set (match_operand:SI 0 "s_register_operand" "=r")
2183 (ne:SI (zero_extract:SI
2184 (match_operand:SI 1 "s_register_operand" "r")
2185 (match_operand:SI 2 "const_int_operand" "n")
2186 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2187 (const_int 0)))
2188 (clobber (reg:CC CC_REGNUM))]
25f905c2 2189 "TARGET_32BIT
cffb2a26 2190 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2191 && INTVAL (operands[2]) > 0
2192 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2193 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2194 "#"
25f905c2 2195 "TARGET_32BIT
f4462328 2196 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2197 && INTVAL (operands[2]) > 0
2198 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2199 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2200 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2201 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2202 (const_int 0)))
2203 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2204 (set (match_dup 0)
2205 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2206 (match_dup 0) (const_int 1)))]
2207 "
2208 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2209 << INTVAL (operands[3]));
2210 "
2211 [(set_attr "conds" "clob")
25f905c2 2212 (set (attr "length")
2213 (if_then_else (eq_attr "is_thumb" "yes")
2214 (const_int 12)
2215 (const_int 8)))]
f4462328 2216)
2217
2218(define_insn_and_split "*ne_zeroextractsi_shifted"
2219 [(set (match_operand:SI 0 "s_register_operand" "=r")
2220 (ne:SI (zero_extract:SI
2221 (match_operand:SI 1 "s_register_operand" "r")
2222 (match_operand:SI 2 "const_int_operand" "n")
2223 (const_int 0))
2224 (const_int 0)))
2225 (clobber (reg:CC CC_REGNUM))]
2226 "TARGET_ARM"
2227 "#"
2228 "TARGET_ARM"
2229 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2230 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2231 (const_int 0)))
2232 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2233 (set (match_dup 0)
2234 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2235 (match_dup 0) (const_int 1)))]
2236 "
2237 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2238 "
2239 [(set_attr "conds" "clob")
2240 (set_attr "length" "8")]
2241)
2242
2243(define_insn_and_split "*ite_ne_zeroextractsi"
2244 [(set (match_operand:SI 0 "s_register_operand" "=r")
2245 (if_then_else:SI (ne (zero_extract:SI
2246 (match_operand:SI 1 "s_register_operand" "r")
2247 (match_operand:SI 2 "const_int_operand" "n")
2248 (match_operand:SI 3 "const_int_operand" "n"))
2249 (const_int 0))
2250 (match_operand:SI 4 "arm_not_operand" "rIK")
2251 (const_int 0)))
2252 (clobber (reg:CC CC_REGNUM))]
2253 "TARGET_ARM
2254 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2255 && INTVAL (operands[2]) > 0
2256 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2257 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2258 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2259 "#"
2260 "TARGET_ARM
2261 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2262 && INTVAL (operands[2]) > 0
2263 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2264 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2265 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2266 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2267 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2268 (const_int 0)))
2269 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2270 (set (match_dup 0)
2271 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2272 (match_dup 0) (match_dup 4)))]
2273 "
c4034607 2274 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2275 << INTVAL (operands[3]));
2276 "
2277 [(set_attr "conds" "clob")
2278 (set_attr "length" "8")]
2279)
2280
2281(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2282 [(set (match_operand:SI 0 "s_register_operand" "=r")
2283 (if_then_else:SI (ne (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 (match_operand:SI 3 "arm_not_operand" "rIK")
2289 (const_int 0)))
2290 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2291 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2292 "#"
f8d7bf2f 2293 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2294 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2295 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2296 (const_int 0)))
2297 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2298 (set (match_dup 0)
2299 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2300 (match_dup 0) (match_dup 3)))]
2301 "
2302 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2303 "
2304 [(set_attr "conds" "clob")
215b30b3 2305 (set_attr "length" "8")]
2306)
9c08d1fa 2307
58d6528b 2308(define_split
2309 [(set (match_operand:SI 0 "s_register_operand" "")
2310 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2311 (match_operand:SI 2 "const_int_operand" "")
2312 (match_operand:SI 3 "const_int_operand" "")))
2313 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2314 "TARGET_THUMB1"
58d6528b 2315 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2316 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2317 "{
2318 HOST_WIDE_INT temp = INTVAL (operands[2]);
2319
2320 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2321 operands[3] = GEN_INT (32 - temp);
2322 }"
2323)
2324
25f905c2 2325;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2326(define_split
2327 [(set (match_operand:SI 0 "s_register_operand" "")
2328 (match_operator:SI 1 "shiftable_operator"
2329 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2330 (match_operand:SI 3 "const_int_operand" "")
2331 (match_operand:SI 4 "const_int_operand" ""))
2332 (match_operand:SI 5 "s_register_operand" "")]))
2333 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2334 "TARGET_ARM"
2335 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2336 (set (match_dup 0)
2337 (match_op_dup 1
2338 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2339 (match_dup 5)]))]
2340 "{
2341 HOST_WIDE_INT temp = INTVAL (operands[3]);
2342
2343 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2344 operands[4] = GEN_INT (32 - temp);
2345 }"
2346)
2347
58d6528b 2348(define_split
2349 [(set (match_operand:SI 0 "s_register_operand" "")
2350 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2351 (match_operand:SI 2 "const_int_operand" "")
2352 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2353 "TARGET_THUMB1"
58d6528b 2354 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2355 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2356 "{
2357 HOST_WIDE_INT temp = INTVAL (operands[2]);
2358
2359 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2360 operands[3] = GEN_INT (32 - temp);
2361 }"
2362)
2363
d7863cfe 2364(define_split
2365 [(set (match_operand:SI 0 "s_register_operand" "")
2366 (match_operator:SI 1 "shiftable_operator"
2367 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2368 (match_operand:SI 3 "const_int_operand" "")
2369 (match_operand:SI 4 "const_int_operand" ""))
2370 (match_operand:SI 5 "s_register_operand" "")]))
2371 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2372 "TARGET_ARM"
2373 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2374 (set (match_dup 0)
2375 (match_op_dup 1
2376 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2377 (match_dup 5)]))]
2378 "{
2379 HOST_WIDE_INT temp = INTVAL (operands[3]);
2380
2381 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2382 operands[4] = GEN_INT (32 - temp);
2383 }"
2384)
2385
a42059fd 2386;;; ??? This pattern is bogus. If operand3 has bits outside the range
2387;;; represented by the bitfield, then this will produce incorrect results.
2388;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2389;;; which have a real bit-field insert instruction, the truncation happens
2390;;; in the bit-field insert instruction itself. Since arm does not have a
2391;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2392;;; the value before we insert. This loses some of the advantage of having
2393;;; this insv pattern, so this pattern needs to be reevalutated.
2394
8a18b90c 2395(define_expand "insv"
2396 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2397 (match_operand:SI 1 "general_operand" "")
2398 (match_operand:SI 2 "general_operand" ""))
19335226 2399 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2400 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2401 "
215b30b3 2402 {
2403 int start_bit = INTVAL (operands[2]);
2404 int width = INTVAL (operands[1]);
2405 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2406 rtx target, subtarget;
2407
8b054d5a 2408 if (arm_arch_thumb2)
2409 {
2410 bool use_bfi = TRUE;
2411
2412 if (GET_CODE (operands[3]) == CONST_INT)
2413 {
2414 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2415
2416 if (val == 0)
2417 {
2418 emit_insn (gen_insv_zero (operands[0], operands[1],
2419 operands[2]));
2420 DONE;
2421 }
2422
2423 /* See if the set can be done with a single orr instruction. */
2424 if (val == mask && const_ok_for_arm (val << start_bit))
2425 use_bfi = FALSE;
2426 }
2427
2428 if (use_bfi)
2429 {
2430 if (GET_CODE (operands[3]) != REG)
2431 operands[3] = force_reg (SImode, operands[3]);
2432
2433 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2434 operands[3]));
2435 DONE;
2436 }
2437 }
2438
3f8fde42 2439 target = copy_rtx (operands[0]);
215b30b3 2440 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2441 subreg as the final target. */
2442 if (GET_CODE (target) == SUBREG)
2443 {
2444 subtarget = gen_reg_rtx (SImode);
2445 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2446 < GET_MODE_SIZE (SImode))
2447 target = SUBREG_REG (target);
2448 }
2449 else
2450 subtarget = target;
8a18b90c 2451
215b30b3 2452 if (GET_CODE (operands[3]) == CONST_INT)
2453 {
2454 /* Since we are inserting a known constant, we may be able to
2455 reduce the number of bits that we have to clear so that
2456 the mask becomes simple. */
2457 /* ??? This code does not check to see if the new mask is actually
2458 simpler. It may not be. */
2459 rtx op1 = gen_reg_rtx (SImode);
2460 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2461 start of this pattern. */
2462 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2463 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2464
c5b3a71b 2465 emit_insn (gen_andsi3 (op1, operands[0],
2466 gen_int_mode (~mask2, SImode)));
215b30b3 2467 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2468 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2469 }
2470 else if (start_bit == 0
2471 && !(const_ok_for_arm (mask)
2472 || const_ok_for_arm (~mask)))
2473 {
2474 /* A Trick, since we are setting the bottom bits in the word,
2475 we can shift operand[3] up, operand[0] down, OR them together
2476 and rotate the result back again. This takes 3 insns, and
5910bb95 2477 the third might be mergeable into another op. */
215b30b3 2478 /* The shift up copes with the possibility that operand[3] is
2479 wider than the bitfield. */
2480 rtx op0 = gen_reg_rtx (SImode);
2481 rtx op1 = gen_reg_rtx (SImode);
2482
2483 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2484 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2485 emit_insn (gen_iorsi3 (op1, op1, op0));
2486 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2487 }
2488 else if ((width + start_bit == 32)
2489 && !(const_ok_for_arm (mask)
2490 || const_ok_for_arm (~mask)))
2491 {
2492 /* Similar trick, but slightly less efficient. */
8a18b90c 2493
215b30b3 2494 rtx op0 = gen_reg_rtx (SImode);
2495 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2496
215b30b3 2497 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2498 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2499 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2500 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2501 }
2502 else
2503 {
c5b3a71b 2504 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2505 rtx op1 = gen_reg_rtx (SImode);
2506 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2507
215b30b3 2508 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2509 {
2510 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2511
215b30b3 2512 emit_insn (gen_movsi (tmp, op0));
2513 op0 = tmp;
2514 }
8a18b90c 2515
215b30b3 2516 /* Mask out any bits in operand[3] that are not needed. */
2517 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2518
215b30b3 2519 if (GET_CODE (op0) == CONST_INT
2520 && (const_ok_for_arm (mask << start_bit)
2521 || const_ok_for_arm (~(mask << start_bit))))
2522 {
c5b3a71b 2523 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2524 emit_insn (gen_andsi3 (op2, operands[0], op0));
2525 }
2526 else
2527 {
2528 if (GET_CODE (op0) == CONST_INT)
2529 {
2530 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2531
215b30b3 2532 emit_insn (gen_movsi (tmp, op0));
2533 op0 = tmp;
2534 }
2535
2536 if (start_bit != 0)
2537 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2538
215b30b3 2539 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2540 }
8a18b90c 2541
215b30b3 2542 if (start_bit != 0)
2543 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2544
215b30b3 2545 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2546 }
f082f1c4 2547
215b30b3 2548 if (subtarget != target)
2549 {
2550 /* If TARGET is still a SUBREG, then it must be wider than a word,
2551 so we must be careful only to set the subword we were asked to. */
2552 if (GET_CODE (target) == SUBREG)
2553 emit_move_insn (target, subtarget);
2554 else
2555 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2556 }
8a18b90c 2557
215b30b3 2558 DONE;
2559 }"
2560)
8a18b90c 2561
8b054d5a 2562(define_insn "insv_zero"
2563 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2564 (match_operand:SI 1 "const_int_operand" "M")
2565 (match_operand:SI 2 "const_int_operand" "M"))
2566 (const_int 0))]
2567 "arm_arch_thumb2"
2568 "bfc%?\t%0, %2, %1"
2569 [(set_attr "length" "4")
2570 (set_attr "predicable" "yes")]
2571)
2572
2573(define_insn "insv_t2"
2574 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2575 (match_operand:SI 1 "const_int_operand" "M")
2576 (match_operand:SI 2 "const_int_operand" "M"))
2577 (match_operand:SI 3 "s_register_operand" "r"))]
2578 "arm_arch_thumb2"
2579 "bfi%?\t%0, %3, %2, %1"
2580 [(set_attr "length" "4")
2581 (set_attr "predicable" "yes")]
2582)
2583
215b30b3 2584; constants for op 2 will never be given to these patterns.
a0f94409 2585(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2586 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2587 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2588 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2589 "TARGET_32BIT"
f6ebffac 2590 "#"
e2669ea7 2591 "TARGET_32BIT && reload_completed
2592 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2593 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2594 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2595 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2596 "
2597 {
2598 operands[3] = gen_highpart (SImode, operands[0]);
2599 operands[0] = gen_lowpart (SImode, operands[0]);
2600 operands[4] = gen_highpart (SImode, operands[1]);
2601 operands[1] = gen_lowpart (SImode, operands[1]);
2602 operands[5] = gen_highpart (SImode, operands[2]);
2603 operands[2] = gen_lowpart (SImode, operands[2]);
2604 }"
0d66636f 2605 [(set_attr "length" "8")
2606 (set_attr "predicable" "yes")]
2607)
9c08d1fa 2608
a0f94409 2609(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2610 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2611 (and:DI (not:DI (zero_extend:DI
2612 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2613 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2614 "TARGET_32BIT"
e2348bcb 2615 "@
97499065 2616 bic%?\\t%Q0, %Q1, %2
f6ebffac 2617 #"
a0f94409 2618 ; (not (zero_extend ...)) allows us to just copy the high word from
2619 ; operand1 to operand0.
25f905c2 2620 "TARGET_32BIT
a0f94409 2621 && reload_completed
2622 && operands[0] != operands[1]"
5a097f7d 2623 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2624 (set (match_dup 3) (match_dup 4))]
2625 "
2626 {
2627 operands[3] = gen_highpart (SImode, operands[0]);
2628 operands[0] = gen_lowpart (SImode, operands[0]);
2629 operands[4] = gen_highpart (SImode, operands[1]);
2630 operands[1] = gen_lowpart (SImode, operands[1]);
2631 }"
0d66636f 2632 [(set_attr "length" "4,8")
2633 (set_attr "predicable" "yes")]
2634)
9c08d1fa 2635
a0f94409 2636(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2637 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2638 (and:DI (not:DI (sign_extend:DI
2639 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2640 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2641 "TARGET_32BIT"
f6ebffac 2642 "#"
25f905c2 2643 "TARGET_32BIT && reload_completed"
5a097f7d 2644 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2645 (set (match_dup 3) (and:SI (not:SI
2646 (ashiftrt:SI (match_dup 2) (const_int 31)))
2647 (match_dup 4)))]
2648 "
2649 {
2650 operands[3] = gen_highpart (SImode, operands[0]);
2651 operands[0] = gen_lowpart (SImode, operands[0]);
2652 operands[4] = gen_highpart (SImode, operands[1]);
2653 operands[1] = gen_lowpart (SImode, operands[1]);
2654 }"
0d66636f 2655 [(set_attr "length" "8")
2656 (set_attr "predicable" "yes")]
2657)
9c08d1fa 2658
8a18b90c 2659(define_insn "andsi_notsi_si"
9c08d1fa 2660 [(set (match_operand:SI 0 "s_register_operand" "=r")
2661 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2662 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2663 "TARGET_32BIT"
0d66636f 2664 "bic%?\\t%0, %1, %2"
2665 [(set_attr "predicable" "yes")]
2666)
b11cae9e 2667
747b7458 2668(define_insn "thumb1_bicsi3"
cffb2a26 2669 [(set (match_operand:SI 0 "register_operand" "=l")
2670 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2671 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2672 "TARGET_THUMB1"
747b7458 2673 "bic\\t%0, %1"
2674 [(set_attr "length" "2")
2675 (set_attr "conds" "set")])
cffb2a26 2676
8a18b90c 2677(define_insn "andsi_not_shiftsi_si"
a2cd141b 2678 [(set (match_operand:SI 0 "s_register_operand" "=r")
2679 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2680 [(match_operand:SI 2 "s_register_operand" "r")
2681 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2682 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2683 "TARGET_ARM"
6c4c2133 2684 "bic%?\\t%0, %1, %2%S4"
344495ea 2685 [(set_attr "predicable" "yes")
331beb1a 2686 (set_attr "shift" "2")
a2cd141b 2687 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2688 (const_string "alu_shift")
2689 (const_string "alu_shift_reg")))]
6c4c2133 2690)
8a18b90c 2691
f7fbdd4a 2692(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2693 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2694 (compare:CC_NOOV
2695 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2696 (match_operand:SI 1 "s_register_operand" "r"))
2697 (const_int 0)))
9c08d1fa 2698 (set (match_operand:SI 0 "s_register_operand" "=r")
2699 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2700 "TARGET_32BIT"
2701 "bic%.\\t%0, %1, %2"
0d66636f 2702 [(set_attr "conds" "set")]
2703)
9c08d1fa 2704
f7fbdd4a 2705(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2706 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2707 (compare:CC_NOOV
2708 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2709 (match_operand:SI 1 "s_register_operand" "r"))
2710 (const_int 0)))
9c08d1fa 2711 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2712 "TARGET_32BIT"
2713 "bic%.\\t%0, %1, %2"
0d66636f 2714 [(set_attr "conds" "set")]
2715)
9c08d1fa 2716
e2669ea7 2717(define_expand "iordi3"
2718 [(set (match_operand:DI 0 "s_register_operand" "")
2719 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2720 (match_operand:DI 2 "neon_logic_op2" "")))]
2721 "TARGET_32BIT"
2722 ""
2723)
2724
2725(define_insn "*iordi3_insn"
cffb2a26 2726 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2727 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2728 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2729 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2730 "#"
0d66636f 2731 [(set_attr "length" "8")
2732 (set_attr "predicable" "yes")]
cffb2a26 2733)
9c08d1fa 2734
f7fbdd4a 2735(define_insn "*iordi_zesidi_di"
9c08d1fa 2736 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2737 (ior:DI (zero_extend:DI
2738 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2739 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2740 "TARGET_32BIT"
e2348bcb 2741 "@
97499065 2742 orr%?\\t%Q0, %Q1, %2
f6ebffac 2743 #"
0d66636f 2744 [(set_attr "length" "4,8")
2745 (set_attr "predicable" "yes")]
cffb2a26 2746)
9c08d1fa 2747
f7fbdd4a 2748(define_insn "*iordi_sesidi_di"
9c08d1fa 2749 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2750 (ior:DI (sign_extend:DI
2751 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2752 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2753 "TARGET_32BIT"
f6ebffac 2754 "#"
0d66636f 2755 [(set_attr "length" "8")
2756 (set_attr "predicable" "yes")]
cffb2a26 2757)
9c08d1fa 2758
87b22bf7 2759(define_expand "iorsi3"
cffb2a26 2760 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2761 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2762 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2763 "TARGET_EITHER"
87b22bf7 2764 "
2765 if (GET_CODE (operands[2]) == CONST_INT)
2766 {
25f905c2 2767 if (TARGET_32BIT)
cffb2a26 2768 {
96f57e36 2769 arm_split_constant (IOR, SImode, NULL_RTX,
2770 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2771 optimize && can_create_pseudo_p ());
cffb2a26 2772 DONE;
2773 }
25f905c2 2774 else /* TARGET_THUMB1 */
923ffadb 2775 {
2776 rtx tmp = force_reg (SImode, operands[2]);
2777 if (rtx_equal_p (operands[0], operands[1]))
2778 operands[2] = tmp;
2779 else
2780 {
2781 operands[2] = operands[1];
2782 operands[1] = tmp;
2783 }
2784 }
87b22bf7 2785 }
cffb2a26 2786 "
2787)
87b22bf7 2788
d5d4dc8d 2789(define_insn_and_split "*iorsi3_insn"
2790 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2791 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2792 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2793 "TARGET_32BIT"
87b22bf7 2794 "@
2795 orr%?\\t%0, %1, %2
d5d4dc8d 2796 orn%?\\t%0, %1, #%B2
87b22bf7 2797 #"
d5d4dc8d 2798 "TARGET_32BIT
a0f94409 2799 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2800 && !(const_ok_for_arm (INTVAL (operands[2]))
2801 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2802 [(clobber (const_int 0))]
d5d4dc8d 2803{
96f57e36 2804 arm_split_constant (IOR, SImode, curr_insn,
2805 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2806 DONE;
d5d4dc8d 2807}
2808 [(set_attr "length" "4,4,16")
2809 (set_attr "arch" "32,t2,32")
2810 (set_attr "predicable" "yes")])
cffb2a26 2811
747b7458 2812(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2813 [(set (match_operand:SI 0 "register_operand" "=l")
2814 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2815 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2816 "TARGET_THUMB1"
747b7458 2817 "orr\\t%0, %2"
2818 [(set_attr "length" "2")
2819 (set_attr "conds" "set")])
9c08d1fa 2820
a0f94409 2821(define_peephole2
2822 [(match_scratch:SI 3 "r")
372575c7 2823 (set (match_operand:SI 0 "arm_general_register_operand" "")
2824 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2825 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2826 "TARGET_ARM
a0f94409 2827 && !const_ok_for_arm (INTVAL (operands[2]))
2828 && const_ok_for_arm (~INTVAL (operands[2]))"
2829 [(set (match_dup 3) (match_dup 2))
2830 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2831 ""
215b30b3 2832)
a0f94409 2833
f7fbdd4a 2834(define_insn "*iorsi3_compare0"
bd5b4116 2835 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2836 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2837 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2838 (const_int 0)))
2839 (set (match_operand:SI 0 "s_register_operand" "=r")
2840 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2841 "TARGET_32BIT"
2842 "orr%.\\t%0, %1, %2"
cffb2a26 2843 [(set_attr "conds" "set")]
2844)
9c08d1fa 2845
f7fbdd4a 2846(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2847 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2848 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2849 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2850 (const_int 0)))
2851 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2852 "TARGET_32BIT"
2853 "orr%.\\t%0, %1, %2"
0d66636f 2854 [(set_attr "conds" "set")]
2855)
9c08d1fa 2856
e2669ea7 2857(define_expand "xordi3"
2858 [(set (match_operand:DI 0 "s_register_operand" "")
2859 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2860 (match_operand:DI 2 "s_register_operand" "")))]
2861 "TARGET_32BIT"
2862 ""
2863)
2864
2865(define_insn "*xordi3_insn"
cffb2a26 2866 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2867 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2868 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2869 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2870 "#"
0d66636f 2871 [(set_attr "length" "8")
2872 (set_attr "predicable" "yes")]
cffb2a26 2873)
9c08d1fa 2874
f7fbdd4a 2875(define_insn "*xordi_zesidi_di"
9c08d1fa 2876 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2877 (xor:DI (zero_extend:DI
2878 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2879 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2880 "TARGET_32BIT"
e2348bcb 2881 "@
97499065 2882 eor%?\\t%Q0, %Q1, %2
f6ebffac 2883 #"
0d66636f 2884 [(set_attr "length" "4,8")
2885 (set_attr "predicable" "yes")]
cffb2a26 2886)
9c08d1fa 2887
f7fbdd4a 2888(define_insn "*xordi_sesidi_di"
9c08d1fa 2889 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2890 (xor:DI (sign_extend:DI
2891 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2892 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2893 "TARGET_32BIT"
f6ebffac 2894 "#"
0d66636f 2895 [(set_attr "length" "8")
2896 (set_attr "predicable" "yes")]
cffb2a26 2897)
9c08d1fa 2898
cffb2a26 2899(define_expand "xorsi3"
2900 [(set (match_operand:SI 0 "s_register_operand" "")
2901 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2902 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2903 "TARGET_EITHER"
923ffadb 2904 "if (GET_CODE (operands[2]) == CONST_INT)
2905 {
2906 if (TARGET_32BIT)
2907 {
2908 arm_split_constant (XOR, SImode, NULL_RTX,
2909 INTVAL (operands[2]), operands[0], operands[1],
2910 optimize && can_create_pseudo_p ());
2911 DONE;
2912 }
2913 else /* TARGET_THUMB1 */
2914 {
2915 rtx tmp = force_reg (SImode, operands[2]);
2916 if (rtx_equal_p (operands[0], operands[1]))
2917 operands[2] = tmp;
2918 else
2919 {
2920 operands[2] = operands[1];
2921 operands[1] = tmp;
2922 }
2923 }
2924 }"
cffb2a26 2925)
2926
2927(define_insn "*arm_xorsi3"
2928 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2929 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2930 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2931 "TARGET_32BIT"
cffb2a26 2932 "eor%?\\t%0, %1, %2"
0d66636f 2933 [(set_attr "predicable" "yes")]
cffb2a26 2934)
2935
747b7458 2936(define_insn "*thumb1_xorsi3_insn"
cffb2a26 2937 [(set (match_operand:SI 0 "register_operand" "=l")
2938 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2939 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2940 "TARGET_THUMB1"
747b7458 2941 "eor\\t%0, %2"
2942 [(set_attr "length" "2")
2943 (set_attr "conds" "set")])
9c08d1fa 2944
f7fbdd4a 2945(define_insn "*xorsi3_compare0"
bd5b4116 2946 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2947 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2948 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2949 (const_int 0)))
2950 (set (match_operand:SI 0 "s_register_operand" "=r")
2951 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2952 "TARGET_32BIT"
2953 "eor%.\\t%0, %1, %2"
0d66636f 2954 [(set_attr "conds" "set")]
2955)
9c08d1fa 2956
f7fbdd4a 2957(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2958 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2959 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2960 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2961 (const_int 0)))]
25f905c2 2962 "TARGET_32BIT"
40dbec34 2963 "teq%?\\t%0, %1"
cffb2a26 2964 [(set_attr "conds" "set")]
2965)
9c08d1fa 2966
215b30b3 2967; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2968; (NOT D) we can sometimes merge the final NOT into one of the following
2969; insns.
9c08d1fa 2970
2971(define_split
a058e94a 2972 [(set (match_operand:SI 0 "s_register_operand" "")
2973 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2974 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2975 (match_operand:SI 3 "arm_rhs_operand" "")))
2976 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2977 "TARGET_32BIT"
9c08d1fa 2978 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2979 (not:SI (match_dup 3))))
2980 (set (match_dup 0) (not:SI (match_dup 4)))]
2981 ""
2982)
2983
f7fbdd4a 2984(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2985 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 2986 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 2987 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2988 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2989 "TARGET_32BIT"
40dbec34 2990 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2991 [(set_attr "length" "8")
25f905c2 2992 (set_attr "ce_count" "2")
0d66636f 2993 (set_attr "predicable" "yes")]
cffb2a26 2994)
9c08d1fa 2995
25f905c2 2996; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2997; insns are available?
d7863cfe 2998(define_split
2999 [(set (match_operand:SI 0 "s_register_operand" "")
3000 (match_operator:SI 1 "logical_binary_operator"
3001 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3002 (match_operand:SI 3 "const_int_operand" "")
3003 (match_operand:SI 4 "const_int_operand" ""))
3004 (match_operator:SI 9 "logical_binary_operator"
3005 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3006 (match_operand:SI 6 "const_int_operand" ""))
3007 (match_operand:SI 7 "s_register_operand" "")])]))
3008 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3009 "TARGET_32BIT
d7863cfe 3010 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3011 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3012 [(set (match_dup 8)
3013 (match_op_dup 1
3014 [(ashift:SI (match_dup 2) (match_dup 4))
3015 (match_dup 5)]))
3016 (set (match_dup 0)
3017 (match_op_dup 1
3018 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3019 (match_dup 7)]))]
3020 "
3021 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3022")
3023
3024(define_split
3025 [(set (match_operand:SI 0 "s_register_operand" "")
3026 (match_operator:SI 1 "logical_binary_operator"
3027 [(match_operator:SI 9 "logical_binary_operator"
3028 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3029 (match_operand:SI 6 "const_int_operand" ""))
3030 (match_operand:SI 7 "s_register_operand" "")])
3031 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3032 (match_operand:SI 3 "const_int_operand" "")
3033 (match_operand:SI 4 "const_int_operand" ""))]))
3034 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3035 "TARGET_32BIT
d7863cfe 3036 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3037 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3038 [(set (match_dup 8)
3039 (match_op_dup 1
3040 [(ashift:SI (match_dup 2) (match_dup 4))
3041 (match_dup 5)]))
3042 (set (match_dup 0)
3043 (match_op_dup 1
3044 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3045 (match_dup 7)]))]
3046 "
3047 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3048")
3049
3050(define_split
3051 [(set (match_operand:SI 0 "s_register_operand" "")
3052 (match_operator:SI 1 "logical_binary_operator"
3053 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3054 (match_operand:SI 3 "const_int_operand" "")
3055 (match_operand:SI 4 "const_int_operand" ""))
3056 (match_operator:SI 9 "logical_binary_operator"
3057 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3058 (match_operand:SI 6 "const_int_operand" ""))
3059 (match_operand:SI 7 "s_register_operand" "")])]))
3060 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3061 "TARGET_32BIT
d7863cfe 3062 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3063 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3064 [(set (match_dup 8)
3065 (match_op_dup 1
3066 [(ashift:SI (match_dup 2) (match_dup 4))
3067 (match_dup 5)]))
3068 (set (match_dup 0)
3069 (match_op_dup 1
3070 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3071 (match_dup 7)]))]
3072 "
3073 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3074")
3075
3076(define_split
3077 [(set (match_operand:SI 0 "s_register_operand" "")
3078 (match_operator:SI 1 "logical_binary_operator"
3079 [(match_operator:SI 9 "logical_binary_operator"
3080 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3081 (match_operand:SI 6 "const_int_operand" ""))
3082 (match_operand:SI 7 "s_register_operand" "")])
3083 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3084 (match_operand:SI 3 "const_int_operand" "")
3085 (match_operand:SI 4 "const_int_operand" ""))]))
3086 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3087 "TARGET_32BIT
d7863cfe 3088 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3089 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3090 [(set (match_dup 8)
3091 (match_op_dup 1
3092 [(ashift:SI (match_dup 2) (match_dup 4))
3093 (match_dup 5)]))
3094 (set (match_dup 0)
3095 (match_op_dup 1
3096 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3097 (match_dup 7)]))]
3098 "
3099 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3100")
9c08d1fa 3101\f
3102
3103;; Minimum and maximum insns
3104
8b9dc177 3105(define_expand "smaxsi3"
3106 [(parallel [
3107 (set (match_operand:SI 0 "s_register_operand" "")
3108 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3109 (match_operand:SI 2 "arm_rhs_operand" "")))
3110 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3111 "TARGET_32BIT"
8b9dc177 3112 "
8774928b 3113 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3114 {
3115 /* No need for a clobber of the condition code register here. */
3116 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3117 gen_rtx_SMAX (SImode, operands[1],
3118 operands[2])));
3119 DONE;
3120 }
3121")
3122
3123(define_insn "*smax_0"
3124 [(set (match_operand:SI 0 "s_register_operand" "=r")
3125 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3126 (const_int 0)))]
25f905c2 3127 "TARGET_32BIT"
8b9dc177 3128 "bic%?\\t%0, %1, %1, asr #31"
3129 [(set_attr "predicable" "yes")]
3130)
3131
8774928b 3132(define_insn "*smax_m1"
3133 [(set (match_operand:SI 0 "s_register_operand" "=r")
3134 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3135 (const_int -1)))]
25f905c2 3136 "TARGET_32BIT"
8774928b 3137 "orr%?\\t%0, %1, %1, asr #31"
3138 [(set_attr "predicable" "yes")]
3139)
3140
25f905c2 3141(define_insn "*arm_smax_insn"
8b9dc177 3142 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3143 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3144 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3145 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3146 "TARGET_ARM"
e2348bcb 3147 "@
3148 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3149 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3150 [(set_attr "conds" "clob")
8b9dc177 3151 (set_attr "length" "8,12")]
cffb2a26 3152)
9c08d1fa 3153
8b9dc177 3154(define_expand "sminsi3"
3155 [(parallel [
3156 (set (match_operand:SI 0 "s_register_operand" "")
3157 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3158 (match_operand:SI 2 "arm_rhs_operand" "")))
3159 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3160 "TARGET_32BIT"
8b9dc177 3161 "
3162 if (operands[2] == const0_rtx)
3163 {
3164 /* No need for a clobber of the condition code register here. */
3165 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3166 gen_rtx_SMIN (SImode, operands[1],
3167 operands[2])));
3168 DONE;
3169 }
3170")
3171
3172(define_insn "*smin_0"
3173 [(set (match_operand:SI 0 "s_register_operand" "=r")
3174 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3175 (const_int 0)))]
25f905c2 3176 "TARGET_32BIT"
8b9dc177 3177 "and%?\\t%0, %1, %1, asr #31"
3178 [(set_attr "predicable" "yes")]
3179)
3180
25f905c2 3181(define_insn "*arm_smin_insn"
8b9dc177 3182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3183 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3184 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3185 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3186 "TARGET_ARM"
e2348bcb 3187 "@
3188 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3189 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3190 [(set_attr "conds" "clob")
8b9dc177 3191 (set_attr "length" "8,12")]
0d66636f 3192)
9c08d1fa 3193
25f905c2 3194(define_expand "umaxsi3"
3195 [(parallel [
3196 (set (match_operand:SI 0 "s_register_operand" "")
3197 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3198 (match_operand:SI 2 "arm_rhs_operand" "")))
3199 (clobber (reg:CC CC_REGNUM))])]
3200 "TARGET_32BIT"
3201 ""
3202)
3203
3204(define_insn "*arm_umaxsi3"
9c08d1fa 3205 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3206 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3207 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3208 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3209 "TARGET_ARM"
e2348bcb 3210 "@
3211 cmp\\t%1, %2\;movcc\\t%0, %2
3212 cmp\\t%1, %2\;movcs\\t%0, %1
3213 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3214 [(set_attr "conds" "clob")
3215 (set_attr "length" "8,8,12")]
3216)
9c08d1fa 3217
25f905c2 3218(define_expand "uminsi3"
3219 [(parallel [
3220 (set (match_operand:SI 0 "s_register_operand" "")
3221 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3222 (match_operand:SI 2 "arm_rhs_operand" "")))
3223 (clobber (reg:CC CC_REGNUM))])]
3224 "TARGET_32BIT"
3225 ""
3226)
3227
3228(define_insn "*arm_uminsi3"
9c08d1fa 3229 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3230 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3231 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3232 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3233 "TARGET_ARM"
e2348bcb 3234 "@
3235 cmp\\t%1, %2\;movcs\\t%0, %2
3236 cmp\\t%1, %2\;movcc\\t%0, %1
3237 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3238 [(set_attr "conds" "clob")
3239 (set_attr "length" "8,8,12")]
3240)
9c08d1fa 3241
8a18b90c 3242(define_insn "*store_minmaxsi"
9c08d1fa 3243 [(set (match_operand:SI 0 "memory_operand" "=m")
3244 (match_operator:SI 3 "minmax_operator"
3245 [(match_operand:SI 1 "s_register_operand" "r")
3246 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3247 (clobber (reg:CC CC_REGNUM))]
25f905c2 3248 "TARGET_32BIT"
9c08d1fa 3249 "*
dc55b8a9 3250 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3251 operands[1], operands[2]);
e2348bcb 3252 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3253 if (TARGET_THUMB2)
3254 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3255 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3256 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3257 return \"\";
0d66636f 3258 "
3259 [(set_attr "conds" "clob")
25f905c2 3260 (set (attr "length")
3261 (if_then_else (eq_attr "is_thumb" "yes")
3262 (const_int 14)
3263 (const_int 12)))
0d66636f 3264 (set_attr "type" "store1")]
3265)
9c08d1fa 3266
8a18b90c 3267; Reject the frame pointer in operand[1], since reloading this after
3268; it has been eliminated can cause carnage.
f7fbdd4a 3269(define_insn "*minmax_arithsi"
9c08d1fa 3270 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3271 (match_operator:SI 4 "shiftable_operator"
3272 [(match_operator:SI 5 "minmax_operator"
3273 [(match_operand:SI 2 "s_register_operand" "r,r")
3274 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3275 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3276 (clobber (reg:CC CC_REGNUM))]
25f905c2 3277 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3278 "*
0d66636f 3279 {
3280 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3281 bool need_else;
3282
3283 if (which_alternative != 0 || operands[3] != const0_rtx
3284 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3285 need_else = true;
3286 else
3287 need_else = false;
0d66636f 3288
dc55b8a9 3289 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3290 operands[2], operands[3]);
0d66636f 3291 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3292 if (TARGET_THUMB2)
3293 {
3294 if (need_else)
3295 output_asm_insn (\"ite\\t%d5\", operands);
3296 else
3297 output_asm_insn (\"it\\t%d5\", operands);
3298 }
0d66636f 3299 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3300 if (need_else)
0d66636f 3301 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3302 return \"\";
215b30b3 3303 }"
0d66636f 3304 [(set_attr "conds" "clob")
25f905c2 3305 (set (attr "length")
3306 (if_then_else (eq_attr "is_thumb" "yes")
3307 (const_int 14)
3308 (const_int 12)))]
0d66636f 3309)
9c08d1fa 3310
b11cae9e 3311\f
3312;; Shift and rotation insns
3313
a2cd141b 3314(define_expand "ashldi3"
3315 [(set (match_operand:DI 0 "s_register_operand" "")
3316 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3317 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3318 "TARGET_32BIT"
a2cd141b 3319 "
3320 if (GET_CODE (operands[2]) == CONST_INT)
3321 {
3322 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3323 {
3324 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3325 DONE;
3326 }
3327 /* Ideally we shouldn't fail here if we could know that operands[1]
3328 ends up already living in an iwmmxt register. Otherwise it's
3329 cheaper to have the alternate code being generated than moving
1d60d981 3330 values to iwmmxt regs and back. */
a2cd141b 3331 FAIL;
3332 }
3333 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3334 FAIL;
3335 "
3336)
3337
3338(define_insn "arm_ashldi3_1bit"
50ad1bf9 3339 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3340 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3341 (const_int 1)))
3342 (clobber (reg:CC CC_REGNUM))]
25f905c2 3343 "TARGET_32BIT"
a2cd141b 3344 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3345 [(set_attr "conds" "clob")
3346 (set_attr "length" "8")]
3347)
3348
87b22bf7 3349(define_expand "ashlsi3"
cffb2a26 3350 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3351 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3352 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3353 "TARGET_EITHER"
87b22bf7 3354 "
3355 if (GET_CODE (operands[2]) == CONST_INT
3356 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3357 {
3358 emit_insn (gen_movsi (operands[0], const0_rtx));
3359 DONE;
3360 }
cffb2a26 3361 "
3362)
3363
25f905c2 3364(define_insn "*thumb1_ashlsi3"
cffb2a26 3365 [(set (match_operand:SI 0 "register_operand" "=l,l")
3366 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3367 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3368 "TARGET_THUMB1"
cffb2a26 3369 "lsl\\t%0, %1, %2"
747b7458 3370 [(set_attr "length" "2")
3371 (set_attr "conds" "set")])
b11cae9e 3372
a2cd141b 3373(define_expand "ashrdi3"
3374 [(set (match_operand:DI 0 "s_register_operand" "")
3375 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3376 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3377 "TARGET_32BIT"
a2cd141b 3378 "
3379 if (GET_CODE (operands[2]) == CONST_INT)
3380 {
3381 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3382 {
3383 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3384 DONE;
3385 }
3386 /* Ideally we shouldn't fail here if we could know that operands[1]
3387 ends up already living in an iwmmxt register. Otherwise it's
3388 cheaper to have the alternate code being generated than moving
1d60d981 3389 values to iwmmxt regs and back. */
a2cd141b 3390 FAIL;
3391 }
3392 else if (!TARGET_REALLY_IWMMXT)
3393 FAIL;
3394 "
3395)
3396
3397(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3398 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3399 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3400 (const_int 1)))
3401 (clobber (reg:CC CC_REGNUM))]
25f905c2 3402 "TARGET_32BIT"
a2cd141b 3403 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3404 [(set_attr "conds" "clob")
d2a518d1 3405 (set_attr "insn" "mov")
a2cd141b 3406 (set_attr "length" "8")]
3407)
3408
87b22bf7 3409(define_expand "ashrsi3"
cffb2a26 3410 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3411 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3412 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3413 "TARGET_EITHER"
87b22bf7 3414 "
3415 if (GET_CODE (operands[2]) == CONST_INT
3416 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3417 operands[2] = GEN_INT (31);
cffb2a26 3418 "
3419)
3420
25f905c2 3421(define_insn "*thumb1_ashrsi3"
cffb2a26 3422 [(set (match_operand:SI 0 "register_operand" "=l,l")
3423 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3424 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3425 "TARGET_THUMB1"
cffb2a26 3426 "asr\\t%0, %1, %2"
747b7458 3427 [(set_attr "length" "2")
3428 (set_attr "conds" "set")])
b11cae9e 3429
a2cd141b 3430(define_expand "lshrdi3"
3431 [(set (match_operand:DI 0 "s_register_operand" "")
3432 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3433 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3434 "TARGET_32BIT"
a2cd141b 3435 "
3436 if (GET_CODE (operands[2]) == CONST_INT)
3437 {
3438 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3439 {
3440 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3441 DONE;
3442 }
3443 /* Ideally we shouldn't fail here if we could know that operands[1]
3444 ends up already living in an iwmmxt register. Otherwise it's
3445 cheaper to have the alternate code being generated than moving
1d60d981 3446 values to iwmmxt regs and back. */
a2cd141b 3447 FAIL;
3448 }
3449 else if (!TARGET_REALLY_IWMMXT)
3450 FAIL;
3451 "
3452)
3453
3454(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3455 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3456 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3457 (const_int 1)))
3458 (clobber (reg:CC CC_REGNUM))]
25f905c2 3459 "TARGET_32BIT"
a2cd141b 3460 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3461 [(set_attr "conds" "clob")
d2a518d1 3462 (set_attr "insn" "mov")
a2cd141b 3463 (set_attr "length" "8")]
3464)
3465
87b22bf7 3466(define_expand "lshrsi3"
cffb2a26 3467 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3468 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3469 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3470 "TARGET_EITHER"
87b22bf7 3471 "
3472 if (GET_CODE (operands[2]) == CONST_INT
3473 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3474 {
3475 emit_insn (gen_movsi (operands[0], const0_rtx));
3476 DONE;
3477 }
cffb2a26 3478 "
3479)
3480
25f905c2 3481(define_insn "*thumb1_lshrsi3"
cffb2a26 3482 [(set (match_operand:SI 0 "register_operand" "=l,l")
3483 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3484 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3485 "TARGET_THUMB1"
cffb2a26 3486 "lsr\\t%0, %1, %2"
747b7458 3487 [(set_attr "length" "2")
3488 (set_attr "conds" "set")])
b11cae9e 3489
87b22bf7 3490(define_expand "rotlsi3"
cffb2a26 3491 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3492 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3493 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3494 "TARGET_32BIT"
87b22bf7 3495 "
3496 if (GET_CODE (operands[2]) == CONST_INT)
3497 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3498 else
b11cae9e 3499 {
87b22bf7 3500 rtx reg = gen_reg_rtx (SImode);
3501 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3502 operands[2] = reg;
b11cae9e 3503 }
cffb2a26 3504 "
3505)
9c08d1fa 3506
87b22bf7 3507(define_expand "rotrsi3"
cffb2a26 3508 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3509 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3510 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3511 "TARGET_EITHER"
87b22bf7 3512 "
25f905c2 3513 if (TARGET_32BIT)
cffb2a26 3514 {
3515 if (GET_CODE (operands[2]) == CONST_INT
3516 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3517 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3518 }
25f905c2 3519 else /* TARGET_THUMB1 */
cffb2a26 3520 {
3521 if (GET_CODE (operands [2]) == CONST_INT)
3522 operands [2] = force_reg (SImode, operands[2]);
3523 }
3524 "
3525)
87b22bf7 3526
25f905c2 3527(define_insn "*thumb1_rotrsi3"
cffb2a26 3528 [(set (match_operand:SI 0 "register_operand" "=l")
3529 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3530 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3531 "TARGET_THUMB1"
cffb2a26 3532 "ror\\t%0, %0, %2"
3533 [(set_attr "length" "2")]
3534)
3535
3536(define_insn "*arm_shiftsi3"
3537 [(set (match_operand:SI 0 "s_register_operand" "=r")
3538 (match_operator:SI 3 "shift_operator"
3539 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3540 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3541 "TARGET_32BIT"
3542 "* return arm_output_shift(operands, 0);"
344495ea 3543 [(set_attr "predicable" "yes")
331beb1a 3544 (set_attr "shift" "1")
a2cd141b 3545 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3546 (const_string "alu_shift")
3547 (const_string "alu_shift_reg")))]
6c4c2133 3548)
87b22bf7 3549
f7fbdd4a 3550(define_insn "*shiftsi3_compare0"
bd5b4116 3551 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3552 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3553 [(match_operand:SI 1 "s_register_operand" "r")
3554 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3555 (const_int 0)))
3556 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3557 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3558 "TARGET_32BIT"
3559 "* return arm_output_shift(operands, 1);"
344495ea 3560 [(set_attr "conds" "set")
331beb1a 3561 (set_attr "shift" "1")
a2cd141b 3562 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3563 (const_string "alu_shift")
3564 (const_string "alu_shift_reg")))]
0d66636f 3565)
9c08d1fa 3566
f7fbdd4a 3567(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3568 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3569 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3570 [(match_operand:SI 1 "s_register_operand" "r")
3571 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3572 (const_int 0)))
3573 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3574 "TARGET_32BIT"
3575 "* return arm_output_shift(operands, 1);"
344495ea 3576 [(set_attr "conds" "set")
a2cd141b 3577 (set_attr "shift" "1")]
0d66636f 3578)
9c08d1fa 3579
d5d4dc8d 3580(define_insn "*not_shiftsi"
3581 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3582 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3583 [(match_operand:SI 1 "s_register_operand" "r,r")
3584 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3585 "TARGET_32BIT"
6c4c2133 3586 "mvn%?\\t%0, %1%S3"
344495ea 3587 [(set_attr "predicable" "yes")
331beb1a 3588 (set_attr "shift" "1")
d2a518d1 3589 (set_attr "insn" "mvn")
d5d4dc8d 3590 (set_attr "arch" "32,a")
3591 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3592
d5d4dc8d 3593(define_insn "*not_shiftsi_compare0"
bd5b4116 3594 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3595 (compare:CC_NOOV
3596 (not:SI (match_operator:SI 3 "shift_operator"
3597 [(match_operand:SI 1 "s_register_operand" "r,r")
3598 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3599 (const_int 0)))
3600 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3601 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3602 "TARGET_32BIT"
25f905c2 3603 "mvn%.\\t%0, %1%S3"
344495ea 3604 [(set_attr "conds" "set")
331beb1a 3605 (set_attr "shift" "1")
d2a518d1 3606 (set_attr "insn" "mvn")
d5d4dc8d 3607 (set_attr "arch" "32,a")
3608 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3609
d5d4dc8d 3610(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3611 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3612 (compare:CC_NOOV
3613 (not:SI (match_operator:SI 3 "shift_operator"
3614 [(match_operand:SI 1 "s_register_operand" "r,r")
3615 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3616 (const_int 0)))
3617 (clobber (match_scratch:SI 0 "=r,r"))]
3618 "TARGET_32BIT"
25f905c2 3619 "mvn%.\\t%0, %1%S3"
344495ea 3620 [(set_attr "conds" "set")
331beb1a 3621 (set_attr "shift" "1")
d2a518d1 3622 (set_attr "insn" "mvn")
d5d4dc8d 3623 (set_attr "arch" "32,a")
3624 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3625
cffb2a26 3626;; We don't really have extzv, but defining this using shifts helps
3627;; to reduce register pressure later on.
3628
3629(define_expand "extzv"
3630 [(set (match_dup 4)
3631 (ashift:SI (match_operand:SI 1 "register_operand" "")
3632 (match_operand:SI 2 "const_int_operand" "")))
3633 (set (match_operand:SI 0 "register_operand" "")
3634 (lshiftrt:SI (match_dup 4)
215b30b3 3635 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3636 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3637 "
3638 {
3639 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3640 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3641
8b054d5a 3642 if (arm_arch_thumb2)
3643 {
3644 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3645 operands[3]));
3646 DONE;
3647 }
3648
cffb2a26 3649 operands[3] = GEN_INT (rshift);
3650
3651 if (lshift == 0)
3652 {
3653 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3654 DONE;
3655 }
3656
3657 operands[2] = GEN_INT (lshift);
3658 operands[4] = gen_reg_rtx (SImode);
215b30b3 3659 }"
cffb2a26 3660)
3661
8b054d5a 3662(define_insn "extv"
3663 [(set (match_operand:SI 0 "s_register_operand" "=r")
3664 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3665 (match_operand:SI 2 "const_int_operand" "M")
3666 (match_operand:SI 3 "const_int_operand" "M")))]
3667 "arm_arch_thumb2"
3668 "sbfx%?\t%0, %1, %3, %2"
3669 [(set_attr "length" "4")
3670 (set_attr "predicable" "yes")]
3671)
3672
3673(define_insn "extzv_t2"
3674 [(set (match_operand:SI 0 "s_register_operand" "=r")
3675 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3676 (match_operand:SI 2 "const_int_operand" "M")
3677 (match_operand:SI 3 "const_int_operand" "M")))]
3678 "arm_arch_thumb2"
3679 "ubfx%?\t%0, %1, %3, %2"
3680 [(set_attr "length" "4")
3681 (set_attr "predicable" "yes")]
3682)
3683
b11cae9e 3684\f
3685;; Unary arithmetic insns
3686
cffb2a26 3687(define_expand "negdi2"
3688 [(parallel
8135a42b 3689 [(set (match_operand:DI 0 "s_register_operand" "")
3690 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3691 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3692 "TARGET_EITHER"
8135a42b 3693 ""
cffb2a26 3694)
3695
3696;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 3697;; The first alternative allows the common case of a *full* overlap.
cffb2a26 3698(define_insn "*arm_negdi2"
458a8706 3699 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3700 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 3701 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3702 "TARGET_ARM"
97499065 3703 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3704 [(set_attr "conds" "clob")
3705 (set_attr "length" "8")]
3706)
b11cae9e 3707
25f905c2 3708(define_insn "*thumb1_negdi2"
8135a42b 3709 [(set (match_operand:DI 0 "register_operand" "=&l")
3710 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3711 (clobber (reg:CC CC_REGNUM))]
25f905c2 3712 "TARGET_THUMB1"
cffb2a26 3713 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3714 [(set_attr "length" "6")]
3715)
3716
3717(define_expand "negsi2"
3718 [(set (match_operand:SI 0 "s_register_operand" "")
3719 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3720 "TARGET_EITHER"
b11cae9e 3721 ""
cffb2a26 3722)
3723
3724(define_insn "*arm_negsi2"
3725 [(set (match_operand:SI 0 "s_register_operand" "=r")
3726 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3727 "TARGET_32BIT"
cffb2a26 3728 "rsb%?\\t%0, %1, #0"
0d66636f 3729 [(set_attr "predicable" "yes")]
cffb2a26 3730)
3731
25f905c2 3732(define_insn "*thumb1_negsi2"
cffb2a26 3733 [(set (match_operand:SI 0 "register_operand" "=l")
3734 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3735 "TARGET_THUMB1"
cffb2a26 3736 "neg\\t%0, %1"
3737 [(set_attr "length" "2")]
3738)
b11cae9e 3739
604f3a0a 3740(define_expand "negsf2"
3741 [(set (match_operand:SF 0 "s_register_operand" "")
3742 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3743 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3744 ""
3745)
3746
3747(define_expand "negdf2"
3748 [(set (match_operand:DF 0 "s_register_operand" "")
3749 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3750 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3751 "")
3752
9c08d1fa 3753;; abssi2 doesn't really clobber the condition codes if a different register
3754;; is being set. To keep things simple, assume during rtl manipulations that
3755;; it does, but tell the final scan operator the truth. Similarly for
3756;; (neg (abs...))
3757
604f3a0a 3758(define_expand "abssi2"
3759 [(parallel
3760 [(set (match_operand:SI 0 "s_register_operand" "")
3761 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3762 (clobber (match_dup 2))])]
3763 "TARGET_EITHER"
3764 "
25f905c2 3765 if (TARGET_THUMB1)
ba156559 3766 operands[2] = gen_rtx_SCRATCH (SImode);
3767 else
3768 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3769")
604f3a0a 3770
7d57ec45 3771(define_insn "*arm_abssi2"
ba156559 3772 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3773 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3774 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3775 "TARGET_ARM"
e2348bcb 3776 "@
3777 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3778 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3779 [(set_attr "conds" "clob,*")
331beb1a 3780 (set_attr "shift" "1")
0d66636f 3781 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3782 (set_attr "length" "8")]
3783)
9c08d1fa 3784
25f905c2 3785(define_insn_and_split "*thumb1_abssi2"
ba156559 3786 [(set (match_operand:SI 0 "s_register_operand" "=l")
3787 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3788 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3789 "TARGET_THUMB1"
ba156559 3790 "#"
25f905c2 3791 "TARGET_THUMB1 && reload_completed"
ba156559 3792 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3793 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3794 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3795 ""
3796 [(set_attr "length" "6")]
3797)
3798
3799(define_insn "*arm_neg_abssi2"
9c08d1fa 3800 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3801 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3802 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3803 "TARGET_ARM"
e2348bcb 3804 "@
3805 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3806 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3807 [(set_attr "conds" "clob,*")
331beb1a 3808 (set_attr "shift" "1")
0d66636f 3809 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3810 (set_attr "length" "8")]
3811)
b11cae9e 3812
25f905c2 3813(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3814 [(set (match_operand:SI 0 "s_register_operand" "=l")
3815 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3816 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3817 "TARGET_THUMB1"
ba156559 3818 "#"
25f905c2 3819 "TARGET_THUMB1 && reload_completed"
ba156559 3820 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3821 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3822 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3823 ""
3824 [(set_attr "length" "6")]
3825)
3826
604f3a0a 3827(define_expand "abssf2"
3828 [(set (match_operand:SF 0 "s_register_operand" "")
3829 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3830 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3831 "")
3832
604f3a0a 3833(define_expand "absdf2"
3834 [(set (match_operand:DF 0 "s_register_operand" "")
3835 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3836 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3837 "")
3838
7db9af5d 3839(define_expand "sqrtsf2"
3840 [(set (match_operand:SF 0 "s_register_operand" "")
3841 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3842 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3843 "")
9c08d1fa 3844
7db9af5d 3845(define_expand "sqrtdf2"
3846 [(set (match_operand:DF 0 "s_register_operand" "")
3847 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3848 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3849 "")
9c08d1fa 3850
a0f94409 3851(define_insn_and_split "one_cmpldi2"
9c08d1fa 3852 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3853 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3854 "TARGET_32BIT"
f6ebffac 3855 "#"
25f905c2 3856 "TARGET_32BIT && reload_completed"
a0f94409 3857 [(set (match_dup 0) (not:SI (match_dup 1)))
3858 (set (match_dup 2) (not:SI (match_dup 3)))]
3859 "
3860 {
3861 operands[2] = gen_highpart (SImode, operands[0]);
3862 operands[0] = gen_lowpart (SImode, operands[0]);
3863 operands[3] = gen_highpart (SImode, operands[1]);
3864 operands[1] = gen_lowpart (SImode, operands[1]);
3865 }"
0d66636f 3866 [(set_attr "length" "8")
3867 (set_attr "predicable" "yes")]
cffb2a26 3868)
b11cae9e 3869
cffb2a26 3870(define_expand "one_cmplsi2"
3871 [(set (match_operand:SI 0 "s_register_operand" "")
3872 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3873 "TARGET_EITHER"
b11cae9e 3874 ""
cffb2a26 3875)
3876
3877(define_insn "*arm_one_cmplsi2"
3878 [(set (match_operand:SI 0 "s_register_operand" "=r")
3879 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3880 "TARGET_32BIT"
cffb2a26 3881 "mvn%?\\t%0, %1"
d2a518d1 3882 [(set_attr "predicable" "yes")
3883 (set_attr "insn" "mvn")]
cffb2a26 3884)
3885
25f905c2 3886(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3887 [(set (match_operand:SI 0 "register_operand" "=l")
3888 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3889 "TARGET_THUMB1"
cffb2a26 3890 "mvn\\t%0, %1"
d2a518d1 3891 [(set_attr "length" "2")
3892 (set_attr "insn" "mvn")]
cffb2a26 3893)
9c08d1fa 3894
f7fbdd4a 3895(define_insn "*notsi_compare0"
bd5b4116 3896 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3897 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3898 (const_int 0)))
3899 (set (match_operand:SI 0 "s_register_operand" "=r")
3900 (not:SI (match_dup 1)))]
25f905c2 3901 "TARGET_32BIT"
3902 "mvn%.\\t%0, %1"
d2a518d1 3903 [(set_attr "conds" "set")
3904 (set_attr "insn" "mvn")]
cffb2a26 3905)
9c08d1fa 3906
f7fbdd4a 3907(define_insn "*notsi_compare0_scratch"
bd5b4116 3908 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3909 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3910 (const_int 0)))
3911 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3912 "TARGET_32BIT"
3913 "mvn%.\\t%0, %1"
d2a518d1 3914 [(set_attr "conds" "set")
3915 (set_attr "insn" "mvn")]
cffb2a26 3916)
b11cae9e 3917\f
3918;; Fixed <--> Floating conversion insns
3919
9b8516be 3920(define_expand "floatsihf2"
3921 [(set (match_operand:HF 0 "general_operand" "")
3922 (float:HF (match_operand:SI 1 "general_operand" "")))]
3923 "TARGET_EITHER"
3924 "
3925 {
3926 rtx op1 = gen_reg_rtx (SFmode);
3927 expand_float (op1, operands[1], 0);
3928 op1 = convert_to_mode (HFmode, op1, 0);
3929 emit_move_insn (operands[0], op1);
3930 DONE;
3931 }"
3932)
3933
3934(define_expand "floatdihf2"
3935 [(set (match_operand:HF 0 "general_operand" "")
3936 (float:HF (match_operand:DI 1 "general_operand" "")))]
3937 "TARGET_EITHER"
3938 "
3939 {
3940 rtx op1 = gen_reg_rtx (SFmode);
3941 expand_float (op1, operands[1], 0);
3942 op1 = convert_to_mode (HFmode, op1, 0);
3943 emit_move_insn (operands[0], op1);
3944 DONE;
3945 }"
3946)
3947
604f3a0a 3948(define_expand "floatsisf2"
3949 [(set (match_operand:SF 0 "s_register_operand" "")
3950 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3951 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3952 "
a2cd141b 3953 if (TARGET_MAVERICK)
604f3a0a 3954 {
3955 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3956 DONE;
3957 }
3958")
3959
604f3a0a 3960(define_expand "floatsidf2"
3961 [(set (match_operand:DF 0 "s_register_operand" "")
3962 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 3963 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3964 "
a2cd141b 3965 if (TARGET_MAVERICK)
604f3a0a 3966 {
3967 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3968 DONE;
3969 }
3970")
3971
9b8516be 3972(define_expand "fix_trunchfsi2"
3973 [(set (match_operand:SI 0 "general_operand" "")
3974 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3975 "TARGET_EITHER"
3976 "
3977 {
3978 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3979 expand_fix (operands[0], op1, 0);
3980 DONE;
3981 }"
3982)
3983
3984(define_expand "fix_trunchfdi2"
3985 [(set (match_operand:DI 0 "general_operand" "")
3986 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3987 "TARGET_EITHER"
3988 "
3989 {
3990 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3991 expand_fix (operands[0], op1, 0);
3992 DONE;
3993 }"
3994)
3995
604f3a0a 3996(define_expand "fix_truncsfsi2"
3997 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3998 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3999 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4000 "
a2cd141b 4001 if (TARGET_MAVERICK)
604f3a0a 4002 {
4003 if (!cirrus_fp_register (operands[0], SImode))
4004 operands[0] = force_reg (SImode, operands[0]);
4005 if (!cirrus_fp_register (operands[1], SFmode))
4006 operands[1] = force_reg (SFmode, operands[0]);
4007 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4008 DONE;
4009 }
4010")
4011
604f3a0a 4012(define_expand "fix_truncdfsi2"
4013 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4014 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4015 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4016 "
a2cd141b 4017 if (TARGET_MAVERICK)
604f3a0a 4018 {
4019 if (!cirrus_fp_register (operands[1], DFmode))
4020 operands[1] = force_reg (DFmode, operands[0]);
4021 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4022 DONE;
4023 }
4024")
4025
f544c6d2 4026;; Truncation insns
b11cae9e 4027
604f3a0a 4028(define_expand "truncdfsf2"
4029 [(set (match_operand:SF 0 "s_register_operand" "")
4030 (float_truncate:SF
4031 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4032 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4033 ""
4034)
9b8516be 4035
4036/* DFmode -> HFmode conversions have to go through SFmode. */
4037(define_expand "truncdfhf2"
4038 [(set (match_operand:HF 0 "general_operand" "")
4039 (float_truncate:HF
4040 (match_operand:DF 1 "general_operand" "")))]
4041 "TARGET_EITHER"
4042 "
4043 {
4044 rtx op1;
4045 op1 = convert_to_mode (SFmode, operands[1], 0);
4046 op1 = convert_to_mode (HFmode, op1, 0);
4047 emit_move_insn (operands[0], op1);
4048 DONE;
4049 }"
4050)
b11cae9e 4051\f
9c08d1fa 4052;; Zero and sign extension instructions.
b11cae9e 4053
848e66ac 4054(define_insn "zero_extend<mode>di2"
4055 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4056 (zero_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4057 "<qhs_extenddi_cstr>")))]
848e66ac 4058 "TARGET_32BIT <qhs_zextenddi_cond>"
4059 "#"
4060 [(set_attr "length" "8")
4061 (set_attr "ce_count" "2")
4062 (set_attr "predicable" "yes")]
25f905c2 4063)
4064
848e66ac 4065(define_insn "extend<mode>di2"
9c08d1fa 4066 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4067 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4068 "<qhs_extenddi_cstr>")))]
848e66ac 4069 "TARGET_32BIT <qhs_sextenddi_cond>"
4070 "#"
0d66636f 4071 [(set_attr "length" "8")
848e66ac 4072 (set_attr "ce_count" "2")
4073 (set_attr "shift" "1")
0d66636f 4074 (set_attr "predicable" "yes")]
4075)
9c08d1fa 4076
848e66ac 4077;; Splits for all extensions to DImode
4078(define_split
4079 [(set (match_operand:DI 0 "s_register_operand" "")
4080 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4081 "TARGET_32BIT"
848e66ac 4082 [(set (match_dup 0) (match_dup 1))]
4083{
848e66ac 4084 rtx lo_part = gen_lowpart (SImode, operands[0]);
4085 enum machine_mode src_mode = GET_MODE (operands[1]);
4086
4087 if (REG_P (operands[0])
4088 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4089 emit_clobber (operands[0]);
4090 if (!REG_P (lo_part) || src_mode != SImode
4091 || !rtx_equal_p (lo_part, operands[1]))
4092 {
4093 if (src_mode == SImode)
4094 emit_move_insn (lo_part, operands[1]);
4095 else
4096 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4097 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4098 operands[1] = lo_part;
4099 }
4100 operands[0] = gen_highpart (SImode, operands[0]);
4101 operands[1] = const0_rtx;
4102})
9c08d1fa 4103
848e66ac 4104(define_split
25f905c2 4105 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4106 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4107 "TARGET_32BIT"
848e66ac 4108 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4109{
4110 rtx lo_part = gen_lowpart (SImode, operands[0]);
4111 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4112
848e66ac 4113 if (REG_P (operands[0])
4114 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4115 emit_clobber (operands[0]);
4116
4117 if (!REG_P (lo_part) || src_mode != SImode
4118 || !rtx_equal_p (lo_part, operands[1]))
4119 {
4120 if (src_mode == SImode)
4121 emit_move_insn (lo_part, operands[1]);
4122 else
4123 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4124 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4125 operands[1] = lo_part;
4126 }
4127 operands[0] = gen_highpart (SImode, operands[0]);
4128})
9c08d1fa 4129
4130(define_expand "zero_extendhisi2"
ef51b8e1 4131 [(set (match_operand:SI 0 "s_register_operand" "")
4132 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4133 "TARGET_EITHER"
ef51b8e1 4134{
4135 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4136 {
ef51b8e1 4137 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4138 DONE;
25f7a26e 4139 }
ef51b8e1 4140 if (!arm_arch6 && !MEM_P (operands[1]))
4141 {
4142 rtx t = gen_lowpart (SImode, operands[1]);
4143 rtx tmp = gen_reg_rtx (SImode);
4144 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4145 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4146 DONE;
4147 }
4148})
9c08d1fa 4149
ef51b8e1 4150(define_split
b146458f 4151 [(set (match_operand:SI 0 "s_register_operand" "")
4152 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4153 "!TARGET_THUMB2 && !arm_arch6"
4154 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4155 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4156{
4157 operands[2] = gen_lowpart (SImode, operands[1]);
4158})
4159
4160(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4161 [(set (match_operand:SI 0 "register_operand" "=l,l")
4162 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4163 "TARGET_THUMB1"
848e66ac 4164{
a2cd141b 4165 rtx mem;
4166
ef51b8e1 4167 if (which_alternative == 0 && arm_arch6)
848e66ac 4168 return "uxth\t%0, %1";
ef51b8e1 4169 if (which_alternative == 0)
848e66ac 4170 return "#";
a2cd141b 4171
4172 mem = XEXP (operands[1], 0);
4173
4174 if (GET_CODE (mem) == CONST)
4175 mem = XEXP (mem, 0);
4176
a2cd141b 4177 if (GET_CODE (mem) == PLUS)
4178 {
4179 rtx a = XEXP (mem, 0);
a2cd141b 4180
4181 /* This can happen due to bugs in reload. */
4182 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4183 {
4184 rtx ops[2];
4185 ops[0] = operands[0];
4186 ops[1] = a;
4187
848e66ac 4188 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4189
4190 XEXP (mem, 0) = operands[0];
4191 }
a2cd141b 4192 }
4193
848e66ac 4194 return "ldrh\t%0, %1";
4195}
ef51b8e1 4196 [(set_attr_alternative "length"
4197 [(if_then_else (eq_attr "is_arch6" "yes")
4198 (const_int 2) (const_int 4))
4199 (const_int 4)])
848e66ac 4200 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4201)
4202
cffb2a26 4203(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4204 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4205 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4206 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4207 "@
4208 #
4209 ldr%(h%)\\t%0, %1"
4210 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4211 (set_attr "predicable" "yes")]
cffb2a26 4212)
f7fbdd4a 4213
a2cd141b 4214(define_insn "*arm_zero_extendhisi2_v6"
4215 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4216 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4217 "TARGET_ARM && arm_arch6"
4218 "@
4219 uxth%?\\t%0, %1
25f905c2 4220 ldr%(h%)\\t%0, %1"
a2cd141b 4221 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4222 (set_attr "predicable" "yes")]
a2cd141b 4223)
4224
4225(define_insn "*arm_zero_extendhisi2addsi"
4226 [(set (match_operand:SI 0 "s_register_operand" "=r")
4227 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4228 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4229 "TARGET_INT_SIMD"
a2cd141b 4230 "uxtah%?\\t%0, %2, %1"
4231 [(set_attr "type" "alu_shift")
4232 (set_attr "predicable" "yes")]
4233)
4234
87b22bf7 4235(define_expand "zero_extendqisi2"
cffb2a26 4236 [(set (match_operand:SI 0 "s_register_operand" "")
4237 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4238 "TARGET_EITHER"
ef51b8e1 4239{
4240 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4241 {
ef51b8e1 4242 emit_insn (gen_andsi3 (operands[0],
4243 gen_lowpart (SImode, operands[1]),
4244 GEN_INT (255)));
4245 DONE;
4246 }
4247 if (!arm_arch6 && !MEM_P (operands[1]))
4248 {
4249 rtx t = gen_lowpart (SImode, operands[1]);
4250 rtx tmp = gen_reg_rtx (SImode);
4251 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4252 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4253 DONE;
4254 }
4255})
cffb2a26 4256
ef51b8e1 4257(define_split
b146458f 4258 [(set (match_operand:SI 0 "s_register_operand" "")
4259 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4260 "!arm_arch6"
4261 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4262 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4263{
4264 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4265 if (TARGET_ARM)
4266 {
4267 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4268 DONE;
4269 }
ef51b8e1 4270})
9c08d1fa 4271
25f905c2 4272(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4273 [(set (match_operand:SI 0 "register_operand" "=l,l")
4274 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4275 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4276 "@
4277 #
4278 ldrb\\t%0, %1"
4279 [(set_attr "length" "4,2")
4280 (set_attr "type" "alu_shift,load_byte")
4281 (set_attr "pool_range" "*,32")]
cffb2a26 4282)
4283
25f905c2 4284(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4285 [(set (match_operand:SI 0 "register_operand" "=l,l")
4286 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4287 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4288 "@
4289 uxtb\\t%0, %1
4290 ldrb\\t%0, %1"
848e66ac 4291 [(set_attr "length" "2")
4292 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4293)
4294
cffb2a26 4295(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4296 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4297 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4298 "TARGET_ARM && !arm_arch6"
ef51b8e1 4299 "@
4300 #
4301 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4302 [(set_attr "length" "8,4")
4303 (set_attr "type" "alu_shift,load_byte")
848e66ac 4304 (set_attr "predicable" "yes")]
cffb2a26 4305)
87b22bf7 4306
a2cd141b 4307(define_insn "*arm_zero_extendqisi2_v6"
4308 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4309 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4310 "TARGET_ARM && arm_arch6"
4311 "@
25f905c2 4312 uxtb%(%)\\t%0, %1
4313 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4314 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4315 (set_attr "predicable" "yes")]
a2cd141b 4316)
4317
4318(define_insn "*arm_zero_extendqisi2addsi"
4319 [(set (match_operand:SI 0 "s_register_operand" "=r")
4320 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4321 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4322 "TARGET_INT_SIMD"
a2cd141b 4323 "uxtab%?\\t%0, %2, %1"
4324 [(set_attr "predicable" "yes")
bcaec148 4325 (set_attr "insn" "xtab")
a2cd141b 4326 (set_attr "type" "alu_shift")]
4327)
4328
87b22bf7 4329(define_split
4330 [(set (match_operand:SI 0 "s_register_operand" "")
4331 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4332 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4333 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4334 [(set (match_dup 2) (match_dup 1))
4335 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4336 ""
4337)
9c08d1fa 4338
8a4d25d6 4339(define_split
4340 [(set (match_operand:SI 0 "s_register_operand" "")
4341 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4342 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4343 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4344 [(set (match_dup 2) (match_dup 1))
4345 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4346 ""
4347)
4348
1c274529 4349
4350(define_split
4351 [(set (match_operand:SI 0 "s_register_operand" "")
4352 (ior_xor:SI (and:SI (ashift:SI
4353 (match_operand:SI 1 "s_register_operand" "")
4354 (match_operand:SI 2 "const_int_operand" ""))
4355 (match_operand:SI 3 "const_int_operand" ""))
4356 (zero_extend:SI
4357 (match_operator 5 "subreg_lowpart_operator"
4358 [(match_operand:SI 4 "s_register_operand" "")]))))]
4359 "TARGET_32BIT
63787642 4360 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4361 == (GET_MODE_MASK (GET_MODE (operands[5]))
4362 & (GET_MODE_MASK (GET_MODE (operands[5]))
4363 << (INTVAL (operands[2])))))"
4364 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4365 (match_dup 4)))
4366 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4367 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4368)
4369
f7fbdd4a 4370(define_insn "*compareqi_eq0"
bd5b4116 4371 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4372 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4373 (const_int 0)))]
25f905c2 4374 "TARGET_32BIT"
87b22bf7 4375 "tst\\t%0, #255"
cffb2a26 4376 [(set_attr "conds" "set")]
4377)
b11cae9e 4378
b11cae9e 4379(define_expand "extendhisi2"
ef51b8e1 4380 [(set (match_operand:SI 0 "s_register_operand" "")
4381 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4382 "TARGET_EITHER"
ef51b8e1 4383{
4384 if (TARGET_THUMB1)
4385 {
4386 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4387 DONE;
4388 }
4389 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4390 {
4391 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4392 DONE;
4393 }
ed29c566 4394
ef51b8e1 4395 if (!arm_arch6 && !MEM_P (operands[1]))
4396 {
4397 rtx t = gen_lowpart (SImode, operands[1]);
4398 rtx tmp = gen_reg_rtx (SImode);
4399 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4400 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4401 DONE;
4402 }
4403})
cffb2a26 4404
ef51b8e1 4405(define_split
4406 [(parallel
4407 [(set (match_operand:SI 0 "register_operand" "")
4408 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4409 (clobber (match_scratch:SI 2 ""))])]
4410 "!arm_arch6"
4411 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4412 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4413{
4414 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4415})
25f7a26e 4416
a2cd141b 4417;; We used to have an early-clobber on the scratch register here.
4418;; However, there's a bug somewhere in reload which means that this
4419;; can be partially ignored during spill allocation if the memory
ed29c566 4420;; address also needs reloading; this causes us to die later on when
a2cd141b 4421;; we try to verify the operands. Fortunately, we don't really need
4422;; the early-clobber: we can always use operand 0 if operand 2
4423;; overlaps the address.
ef51b8e1 4424(define_insn "thumb1_extendhisi2"
a2cd141b 4425 [(set (match_operand:SI 0 "register_operand" "=l,l")
4426 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4427 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4428 "TARGET_THUMB1"
a2cd141b 4429 "*
4430 {
4431 rtx ops[4];
4432 rtx mem;
4433
ef51b8e1 4434 if (which_alternative == 0 && !arm_arch6)
4435 return \"#\";
a2cd141b 4436 if (which_alternative == 0)
4437 return \"sxth\\t%0, %1\";
4438
4439 mem = XEXP (operands[1], 0);
4440
4441 /* This code used to try to use 'V', and fix the address only if it was
4442 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4443 range of QImode offsets, and offsettable_address_p does a QImode
4444 address check. */
4445
4446 if (GET_CODE (mem) == CONST)
4447 mem = XEXP (mem, 0);
4448
4449 if (GET_CODE (mem) == LABEL_REF)
4450 return \"ldr\\t%0, %1\";
4451
4452 if (GET_CODE (mem) == PLUS)
4453 {
4454 rtx a = XEXP (mem, 0);
4455 rtx b = XEXP (mem, 1);
4456
4457 if (GET_CODE (a) == LABEL_REF
4458 && GET_CODE (b) == CONST_INT)
4459 return \"ldr\\t%0, %1\";
4460
4461 if (GET_CODE (b) == REG)
4462 return \"ldrsh\\t%0, %1\";
4463
4464 ops[1] = a;
4465 ops[2] = b;
4466 }
4467 else
4468 {
4469 ops[1] = mem;
4470 ops[2] = const0_rtx;
4471 }
4472
ed29c566 4473 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4474
4475 ops[0] = operands[0];
4476 if (reg_mentioned_p (operands[2], ops[1]))
4477 ops[3] = ops[0];
4478 else
4479 ops[3] = operands[2];
4480 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4481 return \"\";
4482 }"
ef51b8e1 4483 [(set_attr_alternative "length"
4484 [(if_then_else (eq_attr "is_arch6" "yes")
4485 (const_int 2) (const_int 4))
4486 (const_int 4)])
a2cd141b 4487 (set_attr "type" "alu_shift,load_byte")
4488 (set_attr "pool_range" "*,1020")]
4489)
4490
25f905c2 4491;; This pattern will only be used when ldsh is not available
25f7a26e 4492(define_expand "extendhisi2_mem"
eab14235 4493 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4494 (set (match_dup 3)
eab14235 4495 (zero_extend:SI (match_dup 7)))
25f7a26e 4496 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4497 (set (match_operand:SI 0 "" "")
4498 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4499 "TARGET_ARM"
25f7a26e 4500 "
215b30b3 4501 {
4502 rtx mem1, mem2;
4503 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4504
788fcce0 4505 mem1 = change_address (operands[1], QImode, addr);
4506 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4507 operands[0] = gen_lowpart (SImode, operands[0]);
4508 operands[1] = mem1;
4509 operands[2] = gen_reg_rtx (SImode);
4510 operands[3] = gen_reg_rtx (SImode);
4511 operands[6] = gen_reg_rtx (SImode);
4512 operands[7] = mem2;
25f7a26e 4513
215b30b3 4514 if (BYTES_BIG_ENDIAN)
4515 {
4516 operands[4] = operands[2];
4517 operands[5] = operands[3];
4518 }
4519 else
4520 {
4521 operands[4] = operands[3];
4522 operands[5] = operands[2];
4523 }
4524 }"
4525)
b11cae9e 4526
ef51b8e1 4527(define_split
4528 [(set (match_operand:SI 0 "register_operand" "")
4529 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4530 "!arm_arch6"
4531 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4532 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4533{
4534 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4535})
4536
a2cd141b 4537(define_insn "*arm_extendhisi2"
ef51b8e1 4538 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4539 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4540 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4541 "@
4542 #
4543 ldr%(sh%)\\t%0, %1"
4544 [(set_attr "length" "8,4")
4545 (set_attr "type" "alu_shift,load_byte")
0d66636f 4546 (set_attr "predicable" "yes")
ef51b8e1 4547 (set_attr "pool_range" "*,256")
4548 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4549)
f7fbdd4a 4550
25f905c2 4551;; ??? Check Thumb-2 pool range
a2cd141b 4552(define_insn "*arm_extendhisi2_v6"
4553 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4554 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4555 "TARGET_32BIT && arm_arch6"
a2cd141b 4556 "@
4557 sxth%?\\t%0, %1
25f905c2 4558 ldr%(sh%)\\t%0, %1"
a2cd141b 4559 [(set_attr "type" "alu_shift,load_byte")
4560 (set_attr "predicable" "yes")
4561 (set_attr "pool_range" "*,256")
4562 (set_attr "neg_pool_range" "*,244")]
4563)
4564
4565(define_insn "*arm_extendhisi2addsi"
4566 [(set (match_operand:SI 0 "s_register_operand" "=r")
4567 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4568 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4569 "TARGET_INT_SIMD"
a2cd141b 4570 "sxtah%?\\t%0, %2, %1"
4571)
4572
c8f69309 4573(define_expand "extendqihi2"
4574 [(set (match_dup 2)
bed7d9a5 4575 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4576 (const_int 24)))
9c08d1fa 4577 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4578 (ashiftrt:SI (match_dup 2)
4579 (const_int 24)))]
cffb2a26 4580 "TARGET_ARM"
c8f69309 4581 "
215b30b3 4582 {
4583 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4584 {
4585 emit_insn (gen_rtx_SET (VOIDmode,
4586 operands[0],
4587 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4588 DONE;
4589 }
4590 if (!s_register_operand (operands[1], QImode))
4591 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4592 operands[0] = gen_lowpart (SImode, operands[0]);
4593 operands[1] = gen_lowpart (SImode, operands[1]);
4594 operands[2] = gen_reg_rtx (SImode);
4595 }"
4596)
f7fbdd4a 4597
25f905c2 4598(define_insn "*arm_extendqihi_insn"
b4e8a300 4599 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4600 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4601 "TARGET_ARM && arm_arch4"
25f905c2 4602 "ldr%(sb%)\\t%0, %1"
a2cd141b 4603 [(set_attr "type" "load_byte")
0d66636f 4604 (set_attr "predicable" "yes")
cffb2a26 4605 (set_attr "pool_range" "256")
4606 (set_attr "neg_pool_range" "244")]
4607)
3fc2009e 4608
b11cae9e 4609(define_expand "extendqisi2"
ef51b8e1 4610 [(set (match_operand:SI 0 "s_register_operand" "")
4611 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 4612 "TARGET_EITHER"
ef51b8e1 4613{
4614 if (!arm_arch4 && MEM_P (operands[1]))
4615 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4616
ef51b8e1 4617 if (!arm_arch6 && !MEM_P (operands[1]))
4618 {
4619 rtx t = gen_lowpart (SImode, operands[1]);
4620 rtx tmp = gen_reg_rtx (SImode);
4621 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4622 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4623 DONE;
4624 }
4625})
a2cd141b 4626
ef51b8e1 4627(define_split
4628 [(set (match_operand:SI 0 "register_operand" "")
4629 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4630 "!arm_arch6"
4631 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4632 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4633{
4634 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4635})
f7fbdd4a 4636
a2cd141b 4637(define_insn "*arm_extendqisi"
ef51b8e1 4638 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4639 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4640 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4641 "@
4642 #
4643 ldr%(sb%)\\t%0, %1"
4644 [(set_attr "length" "8,4")
4645 (set_attr "type" "alu_shift,load_byte")
0d66636f 4646 (set_attr "predicable" "yes")
ef51b8e1 4647 (set_attr "pool_range" "*,256")
4648 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4649)
3fc2009e 4650
a2cd141b 4651(define_insn "*arm_extendqisi_v6"
4652 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4653 (sign_extend:SI
4654 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4655 "TARGET_ARM && arm_arch6"
b4e8a300 4656 "@
4657 sxtb%?\\t%0, %1
25f905c2 4658 ldr%(sb%)\\t%0, %1"
a2cd141b 4659 [(set_attr "type" "alu_shift,load_byte")
4660 (set_attr "predicable" "yes")
a2cd141b 4661 (set_attr "pool_range" "*,256")
4662 (set_attr "neg_pool_range" "*,244")]
4663)
4664
4665(define_insn "*arm_extendqisi2addsi"
4666 [(set (match_operand:SI 0 "s_register_operand" "=r")
4667 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4668 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4669 "TARGET_INT_SIMD"
a2cd141b 4670 "sxtab%?\\t%0, %2, %1"
4671 [(set_attr "type" "alu_shift")
bcaec148 4672 (set_attr "insn" "xtab")
a2cd141b 4673 (set_attr "predicable" "yes")]
4674)
4675
ef51b8e1 4676(define_split
4677 [(set (match_operand:SI 0 "register_operand" "")
4678 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4679 "TARGET_THUMB1 && reload_completed"
4680 [(set (match_dup 0) (match_dup 2))
4681 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4682{
4683 rtx addr = XEXP (operands[1], 0);
cffb2a26 4684
ef51b8e1 4685 if (GET_CODE (addr) == CONST)
4686 addr = XEXP (addr, 0);
cffb2a26 4687
ef51b8e1 4688 if (GET_CODE (addr) == PLUS
4689 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4690 /* No split necessary. */
4691 FAIL;
4692
4693 if (GET_CODE (addr) == PLUS
4694 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4695 FAIL;
4696
4697 if (reg_overlap_mentioned_p (operands[0], addr))
4698 {
4699 rtx t = gen_lowpart (QImode, operands[0]);
4700 emit_move_insn (t, operands[1]);
4701 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4702 DONE;
4703 }
4704
4705 if (REG_P (addr))
4706 {
4707 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4708 operands[2] = const0_rtx;
4709 }
4710 else if (GET_CODE (addr) != PLUS)
4711 FAIL;
4712 else if (REG_P (XEXP (addr, 0)))
4713 {
4714 operands[2] = XEXP (addr, 1);
4715 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4716 }
4717 else
4718 {
4719 operands[2] = XEXP (addr, 0);
4720 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4721 }
cffb2a26 4722
ef51b8e1 4723 operands[3] = change_address (operands[1], QImode, addr);
4724})
4725
8a3b73a1 4726(define_peephole2
4727 [(set (match_operand:SI 0 "register_operand" "")
4728 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4729 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4730 (set (match_operand:SI 3 "register_operand" "")
4731 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4732 "TARGET_THUMB1
4733 && GET_CODE (XEXP (operands[4], 0)) == PLUS
4734 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4735 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4736 && (peep2_reg_dead_p (3, operands[0])
4737 || rtx_equal_p (operands[0], operands[3]))
4738 && (peep2_reg_dead_p (3, operands[2])
4739 || rtx_equal_p (operands[2], operands[3]))"
4740 [(set (match_dup 2) (match_dup 1))
4741 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4742{
4743 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4744 operands[4] = change_address (operands[4], QImode, addr);
4745})
4746
ef51b8e1 4747(define_insn "thumb1_extendqisi2"
a2cd141b 4748 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4749 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 4750 "TARGET_THUMB1"
4751{
4752 rtx addr;
a2cd141b 4753
ef51b8e1 4754 if (which_alternative == 0 && arm_arch6)
4755 return "sxtb\\t%0, %1";
4756 if (which_alternative == 0)
4757 return "#";
a2cd141b 4758
ef51b8e1 4759 addr = XEXP (operands[1], 0);
4760 if (GET_CODE (addr) == PLUS
4761 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4762 return "ldrsb\\t%0, %1";
a2cd141b 4763
ef51b8e1 4764 return "#";
4765}
4766 [(set_attr_alternative "length"
4767 [(if_then_else (eq_attr "is_arch6" "yes")
4768 (const_int 2) (const_int 4))
4769 (const_int 2)
4770 (if_then_else (eq_attr "is_arch6" "yes")
4771 (const_int 4) (const_int 6))])
4772 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 4773)
4774
caedf871 4775(define_expand "extendsfdf2"
4776 [(set (match_operand:DF 0 "s_register_operand" "")
4777 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4778 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4779 ""
4780)
9b8516be 4781
4782/* HFmode -> DFmode conversions have to go through SFmode. */
4783(define_expand "extendhfdf2"
4784 [(set (match_operand:DF 0 "general_operand" "")
4785 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4786 "TARGET_EITHER"
4787 "
4788 {
4789 rtx op1;
4790 op1 = convert_to_mode (SFmode, operands[1], 0);
4791 op1 = convert_to_mode (DFmode, op1, 0);
4792 emit_insn (gen_movdf (operands[0], op1));
4793 DONE;
4794 }"
4795)
b11cae9e 4796\f
4797;; Move insns (including loads and stores)
4798
4799;; XXX Just some ideas about movti.
9c08d1fa 4800;; I don't think these are a good idea on the arm, there just aren't enough
4801;; registers
b11cae9e 4802;;(define_expand "loadti"
9c08d1fa 4803;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4804;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4805;; "" "")
4806
4807;;(define_expand "storeti"
4808;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4809;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4810;; "" "")
4811
4812;;(define_expand "movti"
4813;; [(set (match_operand:TI 0 "general_operand" "")
4814;; (match_operand:TI 1 "general_operand" ""))]
4815;; ""
4816;; "
4817;;{
4818;; rtx insn;
4819;;
4820;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4821;; operands[1] = copy_to_reg (operands[1]);
4822;; if (GET_CODE (operands[0]) == MEM)
4823;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4824;; else if (GET_CODE (operands[1]) == MEM)
4825;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4826;; else
4827;; FAIL;
4828;;
4829;; emit_insn (insn);
4830;; DONE;
4831;;}")
4832
a2f10574 4833;; Recognize garbage generated above.
b11cae9e 4834
4835;;(define_insn ""
4836;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4837;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4838;; ""
4839;; "*
4840;; {
4841;; register mem = (which_alternative < 3);
0d66636f 4842;; register const char *template;
b11cae9e 4843;;
4844;; operands[mem] = XEXP (operands[mem], 0);
4845;; switch (which_alternative)
4846;; {
4847;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4848;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4849;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4850;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4851;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4852;; case 5: template = \"stmia\\t%0, %M1\"; break;
4853;; }
e2348bcb 4854;; output_asm_insn (template, operands);
4855;; return \"\";
b11cae9e 4856;; }")
4857
cffb2a26 4858(define_expand "movdi"
4859 [(set (match_operand:DI 0 "general_operand" "")
4860 (match_operand:DI 1 "general_operand" ""))]
4861 "TARGET_EITHER"
4862 "
e1ba4a27 4863 if (can_create_pseudo_p ())
cffb2a26 4864 {
b2778788 4865 if (GET_CODE (operands[0]) != REG)
4866 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4867 }
4868 "
4869)
b11cae9e 4870
cffb2a26 4871(define_insn "*arm_movdi"
d51f92df 4872 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4873 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 4874 "TARGET_32BIT
b2778788 4875 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4876 && !TARGET_IWMMXT
4877 && ( register_operand (operands[0], DImode)
4878 || register_operand (operands[1], DImode))"
b11cae9e 4879 "*
d51f92df 4880 switch (which_alternative)
4881 {
4882 case 0:
4883 case 1:
4884 case 2:
4885 return \"#\";
4886 default:
4887 return output_move_double (operands);
4888 }
cffb2a26 4889 "
359a6e9f 4890 [(set_attr "length" "8,12,16,8,8")
4891 (set_attr "type" "*,*,*,load2,store2")
cde1623a 4892 (set_attr "arm_pool_range" "*,*,*,1020,*")
4893 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
4894 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
4895 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 4896)
4897
d51f92df 4898(define_split
4899 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4900 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4901 "TARGET_32BIT
d51f92df 4902 && reload_completed
4903 && (arm_const_double_inline_cost (operands[1])
4904 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4905 [(const_int 0)]
4906 "
4907 arm_split_constant (SET, SImode, curr_insn,
4908 INTVAL (gen_lowpart (SImode, operands[1])),
4909 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4910 arm_split_constant (SET, SImode, curr_insn,
4911 INTVAL (gen_highpart_mode (SImode,
4912 GET_MODE (operands[0]),
4913 operands[1])),
4914 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4915 DONE;
4916 "
4917)
4918
e5ba9289 4919; If optimizing for size, or if we have load delay slots, then
4920; we want to split the constant into two separate operations.
4921; In both cases this may split a trivial part into a single data op
4922; leaving a single complex constant to load. We can also get longer
4923; offsets in a LDR which means we get better chances of sharing the pool
4924; entries. Finally, we can normally do a better job of scheduling
4925; LDR instructions than we can with LDM.
4926; This pattern will only match if the one above did not.
4927(define_split
4928 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4929 (match_operand:ANY64 1 "const_double_operand" ""))]
4930 "TARGET_ARM && reload_completed
4931 && arm_const_double_by_parts (operands[1])"
4932 [(set (match_dup 0) (match_dup 1))
4933 (set (match_dup 2) (match_dup 3))]
4934 "
4935 operands[2] = gen_highpart (SImode, operands[0]);
4936 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4937 operands[1]);
4938 operands[0] = gen_lowpart (SImode, operands[0]);
4939 operands[1] = gen_lowpart (SImode, operands[1]);
4940 "
4941)
4942
d51f92df 4943(define_split
4944 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4945 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4946 "TARGET_EITHER && reload_completed"
4947 [(set (match_dup 0) (match_dup 1))
4948 (set (match_dup 2) (match_dup 3))]
4949 "
4950 operands[2] = gen_highpart (SImode, operands[0]);
4951 operands[3] = gen_highpart (SImode, operands[1]);
4952 operands[0] = gen_lowpart (SImode, operands[0]);
4953 operands[1] = gen_lowpart (SImode, operands[1]);
4954
4955 /* Handle a partial overlap. */
4956 if (rtx_equal_p (operands[0], operands[3]))
4957 {
4958 rtx tmp0 = operands[0];
4959 rtx tmp1 = operands[1];
4960
4961 operands[0] = operands[2];
4962 operands[1] = operands[3];
4963 operands[2] = tmp0;
4964 operands[3] = tmp1;
4965 }
4966 "
4967)
4968
a8a3b539 4969;; We can't actually do base+index doubleword loads if the index and
4970;; destination overlap. Split here so that we at least have chance to
4971;; schedule.
4972(define_split
4973 [(set (match_operand:DI 0 "s_register_operand" "")
4974 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4975 (match_operand:SI 2 "s_register_operand" ""))))]
4976 "TARGET_LDRD
4977 && reg_overlap_mentioned_p (operands[0], operands[1])
4978 && reg_overlap_mentioned_p (operands[0], operands[2])"
4979 [(set (match_dup 4)
4980 (plus:SI (match_dup 1)
4981 (match_dup 2)))
4982 (set (match_dup 0)
4983 (mem:DI (match_dup 4)))]
4984 "
4985 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4986 "
4987)
4988
cffb2a26 4989;;; ??? This should have alternatives for constants.
4990;;; ??? This was originally identical to the movdf_insn pattern.
4991;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4992;;; thumb_reorg with a memory reference.
25f905c2 4993(define_insn "*thumb1_movdi_insn"
215b30b3 4994 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4995 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4996 "TARGET_THUMB1
a2cd141b 4997 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4998 && ( register_operand (operands[0], DImode)
4999 || register_operand (operands[1], DImode))"
5000 "*
5001 {
5002 switch (which_alternative)
5003 {
5004 default:
5005 case 0:
5006 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5007 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5008 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5009 case 1:
5010 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5011 case 2:
5012 operands[1] = GEN_INT (- INTVAL (operands[1]));
5013 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5014 case 3:
5015 return \"ldmia\\t%1, {%0, %H0}\";
5016 case 4:
5017 return \"stmia\\t%0, {%1, %H1}\";
5018 case 5:
5019 return thumb_load_double_from_address (operands);
5020 case 6:
1a83b3ff 5021 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5022 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5023 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5024 return \"\";
5025 case 7:
5026 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5027 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5028 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5029 }
5030 }"
5031 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5032 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5033 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5034 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5035)
b11cae9e 5036
9c08d1fa 5037(define_expand "movsi"
5038 [(set (match_operand:SI 0 "general_operand" "")
5039 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5040 "TARGET_EITHER"
9c08d1fa 5041 "
befb0bac 5042 {
e348ff3e 5043 rtx base, offset, tmp;
5044
25f905c2 5045 if (TARGET_32BIT)
9c08d1fa 5046 {
674a8f0b 5047 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5048 if (GET_CODE (operands[0]) == MEM)
5049 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5050 if (arm_general_register_operand (operands[0], SImode)
5051 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5052 && !(const_ok_for_arm (INTVAL (operands[1]))
5053 || const_ok_for_arm (~INTVAL (operands[1]))))
5054 {
96f57e36 5055 arm_split_constant (SET, SImode, NULL_RTX,
5056 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5057 optimize && can_create_pseudo_p ());
cffb2a26 5058 DONE;
5059 }
d0e6a121 5060
5061 if (TARGET_USE_MOVT && !target_word_relocations
5062 && GET_CODE (operands[1]) == SYMBOL_REF
5063 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5064 {
5065 arm_emit_movpair (operands[0], operands[1]);
5066 DONE;
5067 }
cffb2a26 5068 }
25f905c2 5069 else /* TARGET_THUMB1... */
cffb2a26 5070 {
e1ba4a27 5071 if (can_create_pseudo_p ())
cffb2a26 5072 {
5073 if (GET_CODE (operands[0]) != REG)
5074 operands[1] = force_reg (SImode, operands[1]);
5075 }
9c08d1fa 5076 }
f655717d 5077
e348ff3e 5078 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5079 {
5080 split_const (operands[1], &base, &offset);
5081 if (GET_CODE (base) == SYMBOL_REF
5082 && !offset_within_block_p (base, INTVAL (offset)))
5083 {
b308ddcf 5084 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5085 emit_move_insn (tmp, base);
5086 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5087 DONE;
5088 }
5089 }
5090
f655717d 5091 /* Recognize the case where operand[1] is a reference to thread-local
5092 data and load its address to a register. */
5093 if (arm_tls_referenced_p (operands[1]))
5094 {
5095 rtx tmp = operands[1];
5096 rtx addend = NULL;
5097
5098 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5099 {
5100 addend = XEXP (XEXP (tmp, 0), 1);
5101 tmp = XEXP (XEXP (tmp, 0), 0);
5102 }
5103
5104 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5105 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5106
e1ba4a27 5107 tmp = legitimize_tls_address (tmp,
5108 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5109 if (addend)
5110 {
5111 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5112 tmp = force_operand (tmp, operands[0]);
5113 }
5114 operands[1] = tmp;
5115 }
5116 else if (flag_pic
5117 && (CONSTANT_P (operands[1])
5118 || symbol_mentioned_p (operands[1])
5119 || label_mentioned_p (operands[1])))
5120 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5121 (!can_create_pseudo_p ()
5122 ? operands[0]
5123 : 0));
befb0bac 5124 }
215b30b3 5125 "
5126)
9c08d1fa 5127
d0e6a121 5128;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5129;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5130;; so this does not matter.
5131(define_insn "*arm_movt"
5132 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5133 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5134 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5135 "arm_arch_thumb2"
d0e6a121 5136 "movt%?\t%0, #:upper16:%c2"
5137 [(set_attr "predicable" "yes")
5138 (set_attr "length" "4")]
5139)
5140
cffb2a26 5141(define_insn "*arm_movsi_insn"
aaa37ad6 5142 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5143 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5144 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5145 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5146 && ( register_operand (operands[0], SImode)
5147 || register_operand (operands[1], SImode))"
f7fbdd4a 5148 "@
aaa37ad6 5149 mov%?\\t%0, %1
f7fbdd4a 5150 mov%?\\t%0, %1
5151 mvn%?\\t%0, #%B1
25f905c2 5152 movw%?\\t%0, %1
f7fbdd4a 5153 ldr%?\\t%0, %1
5154 str%?\\t%1, %0"
aaa37ad6 5155 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5156 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5157 (set_attr "predicable" "yes")
aaa37ad6 5158 (set_attr "pool_range" "*,*,*,*,4096,*")
5159 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5160)
87b22bf7 5161
5162(define_split
a2cd141b 5163 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5164 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5165 "TARGET_32BIT
215b30b3 5166 && (!(const_ok_for_arm (INTVAL (operands[1]))
5167 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5168 [(clobber (const_int 0))]
5169 "
96f57e36 5170 arm_split_constant (SET, SImode, NULL_RTX,
5171 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5172 DONE;
215b30b3 5173 "
5174)
9c08d1fa 5175
25f905c2 5176(define_insn "*thumb1_movsi_insn"
55a0d64c 5177 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5178 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 5179 "TARGET_THUMB1
cffb2a26 5180 && ( register_operand (operands[0], SImode)
5181 || register_operand (operands[1], SImode))"
5182 "@
5183 mov %0, %1
5184 mov %0, %1
5185 #
5186 #
5187 ldmia\\t%1, {%0}
5188 stmia\\t%0, {%1}
5189 ldr\\t%0, %1
5190 str\\t%1, %0
5191 mov\\t%0, %1"
5192 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5193 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5194 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5195 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5196
5197(define_split
5198 [(set (match_operand:SI 0 "register_operand" "")
5199 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5200 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5201 [(set (match_dup 2) (match_dup 1))
5202 (set (match_dup 0) (neg:SI (match_dup 2)))]
5203 "
5204 {
5205 operands[1] = GEN_INT (- INTVAL (operands[1]));
5206 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5207 }"
cffb2a26 5208)
5209
5210(define_split
5211 [(set (match_operand:SI 0 "register_operand" "")
5212 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5213 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5214 [(set (match_dup 2) (match_dup 1))
5215 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5216 "
5217 {
e4aeee53 5218 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5219 unsigned HOST_WIDE_INT mask = 0xff;
5220 int i;
5221
5222 for (i = 0; i < 25; i++)
5223 if ((val & (mask << i)) == val)
5224 break;
5225
1276f1b8 5226 /* Don't split if the shift is zero. */
cffb2a26 5227 if (i == 0)
5228 FAIL;
5229
5230 operands[1] = GEN_INT (val >> i);
1276f1b8 5231 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5232 operands[3] = GEN_INT (i);
cffb2a26 5233 }"
5234)
5235
67336bcf 5236;; When generating pic, we need to load the symbol offset into a register.
5237;; So that the optimizer does not confuse this with a normal symbol load
5238;; we use an unspec. The offset will be loaded from a constant pool entry,
5239;; since that is the only type of relocation we can use.
5240
94f8caca 5241;; Wrap calculation of the whole PIC address in a single pattern for the
5242;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5243;; a PIC address involves two loads from memory, so we want to CSE it
5244;; as often as possible.
5245;; This pattern will be split into one of the pic_load_addr_* patterns
5246;; and a move after GCSE optimizations.
5247;;
5248;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5249(define_expand "calculate_pic_address"
5250 [(set (match_operand:SI 0 "register_operand" "")
5251 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5252 (unspec:SI [(match_operand:SI 2 "" "")]
5253 UNSPEC_PIC_SYM))))]
5254 "flag_pic"
5255)
5256
5257;; Split calculate_pic_address into pic_load_addr_* and a move.
5258(define_split
5259 [(set (match_operand:SI 0 "register_operand" "")
5260 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5261 (unspec:SI [(match_operand:SI 2 "" "")]
5262 UNSPEC_PIC_SYM))))]
5263 "flag_pic"
5264 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5265 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5266 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5267)
5268
67336bcf 5269;; The rather odd constraints on the following are to force reload to leave
5270;; the insn alone, and to force the minipool generation pass to then move
5271;; the GOT symbol to memory.
849170fd 5272
b3cd5f55 5273(define_insn "pic_load_addr_32bit"
849170fd 5274 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5275 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5276 "TARGET_32BIT && flag_pic"
67336bcf 5277 "ldr%?\\t%0, %1"
a2cd141b 5278 [(set_attr "type" "load1")
b3cd5f55 5279 (set_attr "pool_range" "4096")
5280 (set (attr "neg_pool_range")
5281 (if_then_else (eq_attr "is_thumb" "no")
5282 (const_int 4084)
5283 (const_int 0)))]
8c4d8060 5284)
5285
25f905c2 5286(define_insn "pic_load_addr_thumb1"
8c4d8060 5287 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5288 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5289 "TARGET_THUMB1 && flag_pic"
8c4d8060 5290 "ldr\\t%0, %1"
a2cd141b 5291 [(set_attr "type" "load1")
8c4d8060 5292 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5293)
849170fd 5294
cffb2a26 5295(define_insn "pic_add_dot_plus_four"
15d5d060 5296 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5297 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5298 (const_int 4)
beef0fb5 5299 (match_operand 2 "" "")]
5300 UNSPEC_PIC_BASE))]
b3cd5f55 5301 "TARGET_THUMB"
cffb2a26 5302 "*
6cdcb15c 5303 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5304 INTVAL (operands[2]));
cffb2a26 5305 return \"add\\t%0, %|pc\";
5306 "
5307 [(set_attr "length" "2")]
5308)
849170fd 5309
5310(define_insn "pic_add_dot_plus_eight"
15d5d060 5311 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5312 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5313 (const_int 8)
beef0fb5 5314 (match_operand 2 "" "")]
5315 UNSPEC_PIC_BASE))]
f655717d 5316 "TARGET_ARM"
c4034607 5317 "*
6cdcb15c 5318 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5319 INTVAL (operands[2]));
15d5d060 5320 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5321 "
0d66636f 5322 [(set_attr "predicable" "yes")]
cffb2a26 5323)
849170fd 5324
f655717d 5325(define_insn "tls_load_dot_plus_eight"
cc071db6 5326 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5327 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5328 (const_int 8)
beef0fb5 5329 (match_operand 2 "" "")]
5330 UNSPEC_PIC_BASE)))]
f655717d 5331 "TARGET_ARM"
5332 "*
6cdcb15c 5333 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5334 INTVAL (operands[2]));
f655717d 5335 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5336 "
5337 [(set_attr "predicable" "yes")]
5338)
5339
5340;; PIC references to local variables can generate pic_add_dot_plus_eight
5341;; followed by a load. These sequences can be crunched down to
5342;; tls_load_dot_plus_eight by a peephole.
5343
5344(define_peephole2
c0c1fba5 5345 [(set (match_operand:SI 0 "register_operand" "")
5346 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5347 (const_int 8)
5348 (match_operand 1 "" "")]
5349 UNSPEC_PIC_BASE))
f655717d 5350 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5351 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5352 [(set (match_dup 2)
5353 (mem:SI (unspec:SI [(match_dup 3)
5354 (const_int 8)
5355 (match_dup 1)]
5356 UNSPEC_PIC_BASE)))]
f655717d 5357 ""
5358)
5359
bac7fc85 5360(define_insn "pic_offset_arm"
5361 [(set (match_operand:SI 0 "register_operand" "=r")
5362 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5363 (unspec:SI [(match_operand:SI 2 "" "X")]
5364 UNSPEC_PIC_OFFSET))))]
5365 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5366 "ldr%?\\t%0, [%1,%2]"
5367 [(set_attr "type" "load1")]
5368)
5369
95373f08 5370(define_expand "builtin_setjmp_receiver"
5371 [(label_ref (match_operand 0 "" ""))]
5372 "flag_pic"
5373 "
5374{
b935b306 5375 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5376 register. */
2cb7d577 5377 if (arm_pic_register != INVALID_REGNUM)
5378 arm_load_pic_register (1UL << 3);
95373f08 5379 DONE;
5380}")
5381
9c08d1fa 5382;; If copying one reg to another we can set the condition codes according to
5383;; its value. Such a move is common after a return from subroutine and the
5384;; result is being tested against zero.
5385
f7fbdd4a 5386(define_insn "*movsi_compare0"
bd5b4116 5387 [(set (reg:CC CC_REGNUM)
cffb2a26 5388 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5389 (const_int 0)))
5390 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5391 (match_dup 1))]
25f905c2 5392 "TARGET_32BIT"
e2348bcb 5393 "@
40dbec34 5394 cmp%?\\t%0, #0
25f905c2 5395 sub%.\\t%0, %1, #0"
cffb2a26 5396 [(set_attr "conds" "set")]
5397)
b11cae9e 5398
b11cae9e 5399;; Subroutine to store a half word from a register into memory.
5400;; Operand 0 is the source register (HImode)
c8f69309 5401;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5402
9c08d1fa 5403;; In both this routine and the next, we must be careful not to spill
01cc3b75 5404;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5405;; can generate unrecognizable rtl.
5406
b11cae9e 5407(define_expand "storehi"
c8f69309 5408 [;; store the low byte
f082f1c4 5409 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5410 ;; extract the high byte
c8f69309 5411 (set (match_dup 2)
5412 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5413 ;; store the high byte
787f8210 5414 (set (match_dup 4) (match_dup 5))]
cffb2a26 5415 "TARGET_ARM"
b11cae9e 5416 "
215b30b3 5417 {
537ffcfc 5418 rtx op1 = operands[1];
5419 rtx addr = XEXP (op1, 0);
215b30b3 5420 enum rtx_code code = GET_CODE (addr);
5421
5422 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5423 || code == MINUS)
537ffcfc 5424 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5425
537ffcfc 5426 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5427 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5428 operands[3] = gen_lowpart (QImode, operands[0]);
5429 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5430 operands[2] = gen_reg_rtx (SImode);
5431 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5432 }"
5433)
b11cae9e 5434
c7597b5d 5435(define_expand "storehi_bigend"
f082f1c4 5436 [(set (match_dup 4) (match_dup 3))
c7597b5d 5437 (set (match_dup 2)
5438 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5439 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5440 "TARGET_ARM"
b11cae9e 5441 "
215b30b3 5442 {
537ffcfc 5443 rtx op1 = operands[1];
5444 rtx addr = XEXP (op1, 0);
215b30b3 5445 enum rtx_code code = GET_CODE (addr);
5446
5447 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5448 || code == MINUS)
537ffcfc 5449 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5450
537ffcfc 5451 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5452 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5453 operands[3] = gen_lowpart (QImode, operands[0]);
5454 operands[0] = gen_lowpart (SImode, operands[0]);
5455 operands[2] = gen_reg_rtx (SImode);
787f8210 5456 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5457 }"
5458)
c7597b5d 5459
5460;; Subroutine to store a half word integer constant into memory.
5461(define_expand "storeinthi"
f082f1c4 5462 [(set (match_operand 0 "" "")
787f8210 5463 (match_operand 1 "" ""))
9e8503e6 5464 (set (match_dup 3) (match_dup 2))]
cffb2a26 5465 "TARGET_ARM"
c7597b5d 5466 "
215b30b3 5467 {
5468 HOST_WIDE_INT value = INTVAL (operands[1]);
5469 rtx addr = XEXP (operands[0], 0);
537ffcfc 5470 rtx op0 = operands[0];
215b30b3 5471 enum rtx_code code = GET_CODE (addr);
c7597b5d 5472
215b30b3 5473 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5474 || code == MINUS)
537ffcfc 5475 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5476
215b30b3 5477 operands[1] = gen_reg_rtx (SImode);
5478 if (BYTES_BIG_ENDIAN)
5479 {
5480 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5481 if ((value & 255) == ((value >> 8) & 255))
5482 operands[2] = operands[1];
5483 else
5484 {
5485 operands[2] = gen_reg_rtx (SImode);
5486 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5487 }
5488 }
5489 else
5490 {
5491 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5492 if ((value & 255) == ((value >> 8) & 255))
5493 operands[2] = operands[1];
5494 else
5495 {
5496 operands[2] = gen_reg_rtx (SImode);
5497 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5498 }
5499 }
c7597b5d 5500
537ffcfc 5501 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5502 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5503 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5504 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5505 }"
5506)
b11cae9e 5507
f7fbdd4a 5508(define_expand "storehi_single_op"
5509 [(set (match_operand:HI 0 "memory_operand" "")
5510 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5511 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5512 "
215b30b3 5513 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5514 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5515 "
5516)
f7fbdd4a 5517
b11cae9e 5518(define_expand "movhi"
5519 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5520 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5521 "TARGET_EITHER"
b11cae9e 5522 "
cffb2a26 5523 if (TARGET_ARM)
b11cae9e 5524 {
e1ba4a27 5525 if (can_create_pseudo_p ())
cffb2a26 5526 {
5527 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5528 {
cffb2a26 5529 if (arm_arch4)
5530 {
5531 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5532 DONE;
5533 }
5534 if (GET_CODE (operands[1]) == CONST_INT)
5535 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5536 else
cffb2a26 5537 {
5538 if (GET_CODE (operands[1]) == MEM)
5539 operands[1] = force_reg (HImode, operands[1]);
5540 if (BYTES_BIG_ENDIAN)
5541 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5542 else
5543 emit_insn (gen_storehi (operands[1], operands[0]));
5544 }
5545 DONE;
b11cae9e 5546 }
cffb2a26 5547 /* Sign extend a constant, and keep it in an SImode reg. */
5548 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5549 {
cffb2a26 5550 rtx reg = gen_reg_rtx (SImode);
5551 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5552
5553 /* If the constant is already valid, leave it alone. */
215b30b3 5554 if (!const_ok_for_arm (val))
cffb2a26 5555 {
5556 /* If setting all the top bits will make the constant
5557 loadable in a single instruction, then set them.
5558 Otherwise, sign extend the number. */
5559
215b30b3 5560 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5561 val |= ~0xffff;
5562 else if (val & 0x8000)
5563 val |= ~0xffff;
5564 }
5565
5566 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5567 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5568 }
e1ba4a27 5569 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5570 && GET_CODE (operands[1]) == MEM)
5571 {
5572 rtx reg = gen_reg_rtx (SImode);
5573
5574 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5575 operands[1] = gen_lowpart (HImode, reg);
5576 }
215b30b3 5577 else if (!arm_arch4)
f7fbdd4a 5578 {
cffb2a26 5579 if (GET_CODE (operands[1]) == MEM)
5580 {
c1a66faf 5581 rtx base;
5582 rtx offset = const0_rtx;
5583 rtx reg = gen_reg_rtx (SImode);
5584
5585 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5586 || (GET_CODE (base) == PLUS
5587 && (GET_CODE (offset = XEXP (base, 1))
5588 == CONST_INT)
5589 && ((INTVAL(offset) & 1) != 1)
5590 && GET_CODE (base = XEXP (base, 0)) == REG))
5591 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5592 {
8deb3959 5593 rtx new_rtx;
c1a66faf 5594
8deb3959 5595 new_rtx = widen_memory_access (operands[1], SImode,
5596 ((INTVAL (offset) & ~3)
5597 - INTVAL (offset)));
5598 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5599 if (((INTVAL (offset) & 2) != 0)
5600 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5601 {
5602 rtx reg2 = gen_reg_rtx (SImode);
5603
5604 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5605 reg = reg2;
5606 }
206ee9a2 5607 }
c1a66faf 5608 else
5609 emit_insn (gen_movhi_bytes (reg, operands[1]));
5610
5611 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5612 }
5613 }
5614 }
674a8f0b 5615 /* Handle loading a large integer during reload. */
cffb2a26 5616 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5617 && !const_ok_for_arm (INTVAL (operands[1]))
5618 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5619 {
5620 /* Writing a constant to memory needs a scratch, which should
5621 be handled with SECONDARY_RELOADs. */
ed29c566 5622 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5623
5624 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5625 emit_insn (gen_movsi (operands[0], operands[1]));
5626 DONE;
5627 }
5628 }
25f905c2 5629 else if (TARGET_THUMB2)
5630 {
5631 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5632 if (can_create_pseudo_p ())
25f905c2 5633 {
5634 if (GET_CODE (operands[0]) != REG)
5635 operands[1] = force_reg (HImode, operands[1]);
5636 /* Zero extend a constant, and keep it in an SImode reg. */
5637 else if (GET_CODE (operands[1]) == CONST_INT)
5638 {
5639 rtx reg = gen_reg_rtx (SImode);
5640 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5641
5642 emit_insn (gen_movsi (reg, GEN_INT (val)));
5643 operands[1] = gen_lowpart (HImode, reg);
5644 }
5645 }
5646 }
5647 else /* TARGET_THUMB1 */
cffb2a26 5648 {
e1ba4a27 5649 if (can_create_pseudo_p ())
cffb2a26 5650 {
6cffc037 5651 if (GET_CODE (operands[1]) == CONST_INT)
5652 {
5653 rtx reg = gen_reg_rtx (SImode);
5654
5655 emit_insn (gen_movsi (reg, operands[1]));
5656 operands[1] = gen_lowpart (HImode, reg);
5657 }
cffb2a26 5658
5659 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5660 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5661 virtual register (also rejected as illegitimate for HImode/QImode)
5662 relative address. */
cffb2a26 5663 /* ??? This should perhaps be fixed elsewhere, for instance, in
5664 fixup_stack_1, by checking for other kinds of invalid addresses,
5665 e.g. a bare reference to a virtual register. This may confuse the
5666 alpha though, which must handle this case differently. */
5667 if (GET_CODE (operands[0]) == MEM
215b30b3 5668 && !memory_address_p (GET_MODE (operands[0]),
5669 XEXP (operands[0], 0)))
537ffcfc 5670 operands[0]
5671 = replace_equiv_address (operands[0],
5672 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5673
5674 if (GET_CODE (operands[1]) == MEM
215b30b3 5675 && !memory_address_p (GET_MODE (operands[1]),
5676 XEXP (operands[1], 0)))
537ffcfc 5677 operands[1]
5678 = replace_equiv_address (operands[1],
5679 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5680
5681 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5682 {
5683 rtx reg = gen_reg_rtx (SImode);
5684
5685 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5686 operands[1] = gen_lowpart (HImode, reg);
5687 }
5688
5689 if (GET_CODE (operands[0]) == MEM)
5690 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5691 }
cffb2a26 5692 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5693 && !satisfies_constraint_I (operands[1]))
cffb2a26 5694 {
6cffc037 5695 /* Handle loading a large integer during reload. */
5696
cffb2a26 5697 /* Writing a constant to memory needs a scratch, which should
5698 be handled with SECONDARY_RELOADs. */
ed29c566 5699 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5700
1a83b3ff 5701 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5702 emit_insn (gen_movsi (operands[0], operands[1]));
5703 DONE;
5704 }
b11cae9e 5705 }
cffb2a26 5706 "
5707)
5708
25f905c2 5709(define_insn "*thumb1_movhi_insn"
a941568e 5710 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5711 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5712 "TARGET_THUMB1
cffb2a26 5713 && ( register_operand (operands[0], HImode)
5714 || register_operand (operands[1], HImode))"
5715 "*
5716 switch (which_alternative)
d79300ac 5717 {
cffb2a26 5718 case 0: return \"add %0, %1, #0\";
5719 case 2: return \"strh %1, %0\";
5720 case 3: return \"mov %0, %1\";
5721 case 4: return \"mov %0, %1\";
5722 case 5: return \"mov %0, %1\";
ed29c566 5723 default: gcc_unreachable ();
cffb2a26 5724 case 1:
5725 /* The stack pointer can end up being taken as an index register.
5726 Catch this case here and deal with it. */
5727 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5728 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5729 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5730 {
5731 rtx ops[2];
5732 ops[0] = operands[0];
5733 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5734
5735 output_asm_insn (\"mov %0, %1\", ops);
5736
5737 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5738
5739 }
5740 return \"ldrh %0, %1\";
5741 }"
5742 [(set_attr "length" "2,4,2,2,2,2")
747b7458 5743 (set_attr "type" "*,load1,store1,*,*,*")
5744 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 5745
b11cae9e 5746
25f7a26e 5747(define_expand "movhi_bytes"
eab14235 5748 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5749 (set (match_dup 3)
eab14235 5750 (zero_extend:SI (match_dup 6)))
25f7a26e 5751 (set (match_operand:SI 0 "" "")
5752 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5753 "TARGET_ARM"
25f7a26e 5754 "
215b30b3 5755 {
5756 rtx mem1, mem2;
5757 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5758
788fcce0 5759 mem1 = change_address (operands[1], QImode, addr);
5760 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5761 operands[0] = gen_lowpart (SImode, operands[0]);
5762 operands[1] = mem1;
5763 operands[2] = gen_reg_rtx (SImode);
5764 operands[3] = gen_reg_rtx (SImode);
5765 operands[6] = mem2;
25f7a26e 5766
215b30b3 5767 if (BYTES_BIG_ENDIAN)
5768 {
5769 operands[4] = operands[2];
5770 operands[5] = operands[3];
5771 }
5772 else
5773 {
5774 operands[4] = operands[3];
5775 operands[5] = operands[2];
5776 }
5777 }"
5778)
25f7a26e 5779
c7597b5d 5780(define_expand "movhi_bigend"
5781 [(set (match_dup 2)
5782 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5783 (const_int 16)))
5784 (set (match_dup 3)
5785 (ashiftrt:SI (match_dup 2) (const_int 16)))
5786 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5787 (match_dup 4))]
cffb2a26 5788 "TARGET_ARM"
c7597b5d 5789 "
5790 operands[2] = gen_reg_rtx (SImode);
5791 operands[3] = gen_reg_rtx (SImode);
787f8210 5792 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5793 "
5794)
b11cae9e 5795
a2f10574 5796;; Pattern to recognize insn generated default case above
f7fbdd4a 5797(define_insn "*movhi_insn_arch4"
cde1623a 5798 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 5799 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 5800 "TARGET_ARM
5801 && arm_arch4
85e02ccb 5802 && (register_operand (operands[0], HImode)
5803 || register_operand (operands[1], HImode))"
f7fbdd4a 5804 "@
5805 mov%?\\t%0, %1\\t%@ movhi
5806 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5807 str%(h%)\\t%1, %0\\t%@ movhi
5808 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5809 [(set_attr "type" "*,*,store1,load1")
0d66636f 5810 (set_attr "predicable" "yes")
d2a518d1 5811 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 5812 (set_attr "pool_range" "*,*,*,256")
5813 (set_attr "neg_pool_range" "*,*,*,244")]
5814)
f7fbdd4a 5815
f7fbdd4a 5816(define_insn "*movhi_bytes"
25f7a26e 5817 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5818 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5819 "TARGET_ARM"
25f7a26e 5820 "@
5821 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5822 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 5823 [(set_attr "predicable" "yes")
5824 (set_attr "insn" "mov,mvn")]
0d66636f 5825)
25f7a26e 5826
f90b51f1 5827(define_expand "thumb_movhi_clobber"
5828 [(set (match_operand:HI 0 "memory_operand" "")
5829 (match_operand:HI 1 "register_operand" ""))
5830 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5831 "TARGET_THUMB1"
f90b51f1 5832 "
5833 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5834 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5835 {
5836 emit_insn (gen_movhi (operands[0], operands[1]));
5837 DONE;
5838 }
5839 /* XXX Fixme, need to handle other cases here as well. */
5840 gcc_unreachable ();
5841 "
cffb2a26 5842)
5843
bc5c7e08 5844;; We use a DImode scratch because we may occasionally need an additional
5845;; temporary if the address isn't offsettable -- push_reload doesn't seem
5846;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5847(define_expand "reload_outhi"
cffb2a26 5848 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5849 (match_operand:HI 1 "s_register_operand" "r")
5850 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5851 "TARGET_EITHER"
5852 "if (TARGET_ARM)
5853 arm_reload_out_hi (operands);
5854 else
5855 thumb_reload_out_hi (operands);
d3373b54 5856 DONE;
cffb2a26 5857 "
5858)
d3373b54 5859
25f7a26e 5860(define_expand "reload_inhi"
5861 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5862 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5863 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5864 "TARGET_EITHER"
25f7a26e 5865 "
cffb2a26 5866 if (TARGET_ARM)
5867 arm_reload_in_hi (operands);
5868 else
5869 thumb_reload_out_hi (operands);
25f7a26e 5870 DONE;
5871")
5872
9c08d1fa 5873(define_expand "movqi"
5874 [(set (match_operand:QI 0 "general_operand" "")
5875 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5876 "TARGET_EITHER"
9c08d1fa 5877 "
6cffc037 5878 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5879
e1ba4a27 5880 if (can_create_pseudo_p ())
cffb2a26 5881 {
6cffc037 5882 if (GET_CODE (operands[1]) == CONST_INT)
5883 {
5884 rtx reg = gen_reg_rtx (SImode);
5885
03770691 5886 /* For thumb we want an unsigned immediate, then we are more likely
5887 to be able to use a movs insn. */
5888 if (TARGET_THUMB)
5889 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5890
6cffc037 5891 emit_insn (gen_movsi (reg, operands[1]));
5892 operands[1] = gen_lowpart (QImode, reg);
5893 }
cffb2a26 5894
6cffc037 5895 if (TARGET_THUMB)
5896 {
cffb2a26 5897 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5898 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5899 virtual register (also rejected as illegitimate for HImode/QImode)
5900 relative address. */
cffb2a26 5901 /* ??? This should perhaps be fixed elsewhere, for instance, in
5902 fixup_stack_1, by checking for other kinds of invalid addresses,
5903 e.g. a bare reference to a virtual register. This may confuse the
5904 alpha though, which must handle this case differently. */
5905 if (GET_CODE (operands[0]) == MEM
215b30b3 5906 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5907 XEXP (operands[0], 0)))
537ffcfc 5908 operands[0]
5909 = replace_equiv_address (operands[0],
5910 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5911 if (GET_CODE (operands[1]) == MEM
5912 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5913 XEXP (operands[1], 0)))
537ffcfc 5914 operands[1]
5915 = replace_equiv_address (operands[1],
5916 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5917 }
5918
5919 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5920 {
5921 rtx reg = gen_reg_rtx (SImode);
5922
5923 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5924 operands[1] = gen_lowpart (QImode, reg);
5925 }
5926
5927 if (GET_CODE (operands[0]) == MEM)
5928 operands[1] = force_reg (QImode, operands[1]);
5929 }
5930 else if (TARGET_THUMB
5931 && GET_CODE (operands[1]) == CONST_INT
234f6557 5932 && !satisfies_constraint_I (operands[1]))
6cffc037 5933 {
674a8f0b 5934 /* Handle loading a large integer during reload. */
cffb2a26 5935
6cffc037 5936 /* Writing a constant to memory needs a scratch, which should
5937 be handled with SECONDARY_RELOADs. */
5938 gcc_assert (GET_CODE (operands[0]) == REG);
5939
5940 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5941 emit_insn (gen_movsi (operands[0], operands[1]));
5942 DONE;
cffb2a26 5943 }
5944 "
5945)
b11cae9e 5946
9c08d1fa 5947
cffb2a26 5948(define_insn "*arm_movqi_insn"
a54e3e7b 5949 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
5950 (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
25f905c2 5951 "TARGET_32BIT
cffb2a26 5952 && ( register_operand (operands[0], QImode)
5953 || register_operand (operands[1], QImode))"
5565501b 5954 "@
5955 mov%?\\t%0, %1
5956 mvn%?\\t%0, #%B1
25f905c2 5957 ldr%(b%)\\t%0, %1
a54e3e7b 5958 str%(b%)\\t%1, %0
5959 ldr%(b%)\\t%0, %1
25f905c2 5960 str%(b%)\\t%1, %0"
a54e3e7b 5961 [(set_attr "type" "*,*,load1,store1,load1,store1")
5962 (set_attr "insn" "mov,mvn,*,*,*,*")
5963 (set_attr "predicable" "yes")
5964 (set_attr "arch" "any,any,t2,t2,any,any")
5965 (set_attr "length" "4,4,2,2,4,4")]
cffb2a26 5966)
5967
25f905c2 5968(define_insn "*thumb1_movqi_insn"
cffb2a26 5969 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5970 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5971 "TARGET_THUMB1
cffb2a26 5972 && ( register_operand (operands[0], QImode)
5973 || register_operand (operands[1], QImode))"
5974 "@
5975 add\\t%0, %1, #0
5976 ldrb\\t%0, %1
5977 strb\\t%1, %0
5978 mov\\t%0, %1
5979 mov\\t%0, %1
5980 mov\\t%0, %1"
5981 [(set_attr "length" "2")
a2cd141b 5982 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 5983 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 5984 (set_attr "pool_range" "*,32,*,*,*,*")
5985 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 5986
9b8516be 5987;; HFmode moves
5988(define_expand "movhf"
5989 [(set (match_operand:HF 0 "general_operand" "")
5990 (match_operand:HF 1 "general_operand" ""))]
5991 "TARGET_EITHER"
5992 "
5993 if (TARGET_32BIT)
5994 {
5995 if (GET_CODE (operands[0]) == MEM)
5996 operands[1] = force_reg (HFmode, operands[1]);
5997 }
5998 else /* TARGET_THUMB1 */
5999 {
6000 if (can_create_pseudo_p ())
6001 {
6002 if (GET_CODE (operands[0]) != REG)
6003 operands[1] = force_reg (HFmode, operands[1]);
6004 }
6005 }
6006 "
6007)
6008
6009(define_insn "*arm32_movhf"
6010 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6011 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 6012 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6013 && ( s_register_operand (operands[0], HFmode)
6014 || s_register_operand (operands[1], HFmode))"
6015 "*
6016 switch (which_alternative)
6017 {
6018 case 0: /* ARM register from memory */
6019 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6020 case 1: /* memory from ARM register */
6021 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6022 case 2: /* ARM register from ARM register */
6023 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6024 case 3: /* ARM register from constant */
6025 {
6026 REAL_VALUE_TYPE r;
6027 long bits;
6028 rtx ops[4];
6029
6030 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6031 bits = real_to_target (NULL, &r, HFmode);
6032 ops[0] = operands[0];
6033 ops[1] = GEN_INT (bits);
6034 ops[2] = GEN_INT (bits & 0xff00);
6035 ops[3] = GEN_INT (bits & 0x00ff);
6036
6037 if (arm_arch_thumb2)
6038 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6039 else
6040 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6041 return \"\";
6042 }
6043 default:
6044 gcc_unreachable ();
6045 }
6046 "
6047 [(set_attr "conds" "unconditional")
6048 (set_attr "type" "load1,store1,*,*")
d2a518d1 6049 (set_attr "insn" "*,*,mov,mov")
9b8516be 6050 (set_attr "length" "4,4,4,8")
d2a518d1 6051 (set_attr "predicable" "yes")]
9b8516be 6052)
6053
6054(define_insn "*thumb1_movhf"
6055 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6056 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6057 "TARGET_THUMB1
6058 && ( s_register_operand (operands[0], HFmode)
6059 || s_register_operand (operands[1], HFmode))"
6060 "*
6061 switch (which_alternative)
6062 {
6063 case 1:
6064 {
6065 rtx addr;
6066 gcc_assert (GET_CODE(operands[1]) == MEM);
6067 addr = XEXP (operands[1], 0);
6068 if (GET_CODE (addr) == LABEL_REF
6069 || (GET_CODE (addr) == CONST
6070 && GET_CODE (XEXP (addr, 0)) == PLUS
6071 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6072 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6073 {
6074 /* Constant pool entry. */
6075 return \"ldr\\t%0, %1\";
6076 }
6077 return \"ldrh\\t%0, %1\";
6078 }
6079 case 2: return \"strh\\t%1, %0\";
6080 default: return \"mov\\t%0, %1\";
6081 }
6082 "
6083 [(set_attr "length" "2")
6084 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6085 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6086 (set_attr "pool_range" "*,1020,*,*,*")
6087 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6088
87b22bf7 6089(define_expand "movsf"
6090 [(set (match_operand:SF 0 "general_operand" "")
6091 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6092 "TARGET_EITHER"
87b22bf7 6093 "
25f905c2 6094 if (TARGET_32BIT)
cffb2a26 6095 {
6096 if (GET_CODE (operands[0]) == MEM)
6097 operands[1] = force_reg (SFmode, operands[1]);
6098 }
25f905c2 6099 else /* TARGET_THUMB1 */
cffb2a26 6100 {
e1ba4a27 6101 if (can_create_pseudo_p ())
cffb2a26 6102 {
6103 if (GET_CODE (operands[0]) != REG)
6104 operands[1] = force_reg (SFmode, operands[1]);
6105 }
6106 }
6107 "
6108)
6109
03d440a6 6110;; Transform a floating-point move of a constant into a core register into
6111;; an SImode operation.
cffb2a26 6112(define_split
03d440a6 6113 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6114 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6115 "TARGET_EITHER
cffb2a26 6116 && reload_completed
6117 && GET_CODE (operands[1]) == CONST_DOUBLE"
6118 [(set (match_dup 2) (match_dup 3))]
6119 "
6120 operands[2] = gen_lowpart (SImode, operands[0]);
6121 operands[3] = gen_lowpart (SImode, operands[1]);
6122 if (operands[2] == 0 || operands[3] == 0)
6123 FAIL;
215b30b3 6124 "
6125)
87b22bf7 6126
cffb2a26 6127(define_insn "*arm_movsf_soft_insn"
6128 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6129 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6130 "TARGET_32BIT
cffb2a26 6131 && TARGET_SOFT_FLOAT
215b30b3 6132 && (GET_CODE (operands[0]) != MEM
6133 || register_operand (operands[1], SFmode))"
9a1112d7 6134 "@
6135 mov%?\\t%0, %1
6136 ldr%?\\t%0, %1\\t%@ float
6137 str%?\\t%1, %0\\t%@ float"
cde1623a 6138 [(set_attr "predicable" "yes")
a2cd141b 6139 (set_attr "type" "*,load1,store1")
d2a518d1 6140 (set_attr "insn" "mov,*,*")
cffb2a26 6141 (set_attr "pool_range" "*,4096,*")
cde1623a 6142 (set_attr "arm_neg_pool_range" "*,4084,*")
6143 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6144)
6145
6146;;; ??? This should have alternatives for constants.
25f905c2 6147(define_insn "*thumb1_movsf_insn"
215b30b3 6148 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6149 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6150 "TARGET_THUMB1
cffb2a26 6151 && ( register_operand (operands[0], SFmode)
6152 || register_operand (operands[1], SFmode))"
6153 "@
6154 add\\t%0, %1, #0
6155 ldmia\\t%1, {%0}
6156 stmia\\t%0, {%1}
6157 ldr\\t%0, %1
6158 str\\t%1, %0
6159 mov\\t%0, %1
6160 mov\\t%0, %1"
6161 [(set_attr "length" "2")
a2cd141b 6162 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6163 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6164 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6165 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6166)
9a1112d7 6167
9c08d1fa 6168(define_expand "movdf"
87b22bf7 6169 [(set (match_operand:DF 0 "general_operand" "")
6170 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6171 "TARGET_EITHER"
9c08d1fa 6172 "
25f905c2 6173 if (TARGET_32BIT)
cffb2a26 6174 {
6175 if (GET_CODE (operands[0]) == MEM)
6176 operands[1] = force_reg (DFmode, operands[1]);
6177 }
6178 else /* TARGET_THUMB */
6179 {
e1ba4a27 6180 if (can_create_pseudo_p ())
cffb2a26 6181 {
6182 if (GET_CODE (operands[0]) != REG)
6183 operands[1] = force_reg (DFmode, operands[1]);
6184 }
6185 }
6186 "
6187)
b11cae9e 6188
9c08d1fa 6189;; Reloading a df mode value stored in integer regs to memory can require a
6190;; scratch reg.
6191(define_expand "reload_outdf"
cffb2a26 6192 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6193 (match_operand:DF 1 "s_register_operand" "r")
6194 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6195 "TARGET_THUMB2"
87b22bf7 6196 "
215b30b3 6197 {
6198 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6199
215b30b3 6200 if (code == REG)
6201 operands[2] = XEXP (operands[0], 0);
6202 else if (code == POST_INC || code == PRE_DEC)
6203 {
6204 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6205 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6206 emit_insn (gen_movdi (operands[0], operands[1]));
6207 DONE;
6208 }
6209 else if (code == PRE_INC)
6210 {
6211 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6212
215b30b3 6213 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6214 operands[2] = reg;
6215 }
6216 else if (code == POST_DEC)
6217 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6218 else
6219 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6220 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6221
788fcce0 6222 emit_insn (gen_rtx_SET (VOIDmode,
6223 replace_equiv_address (operands[0], operands[2]),
215b30b3 6224 operands[1]));
f7fbdd4a 6225
215b30b3 6226 if (code == POST_DEC)
6227 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6228
6229 DONE;
6230 }"
6231)
9c08d1fa 6232
9a1112d7 6233(define_insn "*movdf_soft_insn"
359a6e9f 6234 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6235 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6236 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6237 && ( register_operand (operands[0], DFmode)
6238 || register_operand (operands[1], DFmode))"
d51f92df 6239 "*
6240 switch (which_alternative)
6241 {
6242 case 0:
6243 case 1:
6244 case 2:
6245 return \"#\";
6246 default:
6247 return output_move_double (operands);
6248 }
6249 "
359a6e9f 6250 [(set_attr "length" "8,12,16,8,8")
6251 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6252 (set_attr "pool_range" "*,*,*,1020,*")
6253 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6254 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6255)
6256
6257;;; ??? This should have alternatives for constants.
6258;;; ??? This was originally identical to the movdi_insn pattern.
6259;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6260;;; thumb_reorg with a memory reference.
6261(define_insn "*thumb_movdf_insn"
215b30b3 6262 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6263 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6264 "TARGET_THUMB1
cffb2a26 6265 && ( register_operand (operands[0], DFmode)
6266 || register_operand (operands[1], DFmode))"
6267 "*
6268 switch (which_alternative)
6269 {
6270 default:
6271 case 0:
6272 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6273 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6274 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6275 case 1:
6276 return \"ldmia\\t%1, {%0, %H0}\";
6277 case 2:
6278 return \"stmia\\t%0, {%1, %H1}\";
6279 case 3:
6280 return thumb_load_double_from_address (operands);
6281 case 4:
1a83b3ff 6282 operands[2] = gen_rtx_MEM (SImode,
6283 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6284 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6285 return \"\";
6286 case 5:
6287 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6288 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6289 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6290 }
6291 "
6292 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6293 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6294 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6295 (set_attr "pool_range" "*,*,*,1020,*,*")]
6296)
755eb2b4 6297
ccd90aaa 6298(define_expand "movxf"
6299 [(set (match_operand:XF 0 "general_operand" "")
6300 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6301 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6302 "
6303 if (GET_CODE (operands[0]) == MEM)
6304 operands[1] = force_reg (XFmode, operands[1]);
6305 "
6306)
6307
b11cae9e 6308\f
b11cae9e 6309
9c08d1fa 6310;; load- and store-multiple insns
6311;; The arm can load/store any set of registers, provided that they are in
320ea44d 6312;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6313
9c08d1fa 6314(define_expand "load_multiple"
6315 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6316 (match_operand:SI 1 "" ""))
6317 (use (match_operand:SI 2 "" ""))])]
25f905c2 6318 "TARGET_32BIT"
9580c25f 6319{
6320 HOST_WIDE_INT offset = 0;
6321
bd5b4116 6322 /* Support only fixed point registers. */
9c08d1fa 6323 if (GET_CODE (operands[2]) != CONST_INT
6324 || INTVAL (operands[2]) > 14
6325 || INTVAL (operands[2]) < 2
6326 || GET_CODE (operands[1]) != MEM
6327 || GET_CODE (operands[0]) != REG
bd5b4116 6328 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6329 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6330 FAIL;
6331
6332 operands[3]
320ea44d 6333 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6334 INTVAL (operands[2]),
f082f1c4 6335 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6336 FALSE, operands[1], &offset);
9580c25f 6337})
b11cae9e 6338
9c08d1fa 6339(define_expand "store_multiple"
6340 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6341 (match_operand:SI 1 "" ""))
6342 (use (match_operand:SI 2 "" ""))])]
25f905c2 6343 "TARGET_32BIT"
9580c25f 6344{
6345 HOST_WIDE_INT offset = 0;
6346
674a8f0b 6347 /* Support only fixed point registers. */
9c08d1fa 6348 if (GET_CODE (operands[2]) != CONST_INT
6349 || INTVAL (operands[2]) > 14
6350 || INTVAL (operands[2]) < 2
6351 || GET_CODE (operands[1]) != REG
6352 || GET_CODE (operands[0]) != MEM
bd5b4116 6353 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6354 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6355 FAIL;
6356
6357 operands[3]
320ea44d 6358 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6359 INTVAL (operands[2]),
f082f1c4 6360 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6361 FALSE, operands[0], &offset);
9580c25f 6362})
b11cae9e 6363
9c08d1fa 6364
6365;; Move a block of memory if it is word aligned and MORE than 2 words long.
6366;; We could let this apply for blocks of less than this, but it clobbers so
6367;; many registers that there is then probably a better way.
6368
008c057d 6369(define_expand "movmemqi"
34191dd1 6370 [(match_operand:BLK 0 "general_operand" "")
6371 (match_operand:BLK 1 "general_operand" "")
6372 (match_operand:SI 2 "const_int_operand" "")
6373 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6374 "TARGET_EITHER"
9c08d1fa 6375 "
25f905c2 6376 if (TARGET_32BIT)
cffb2a26 6377 {
008c057d 6378 if (arm_gen_movmemqi (operands))
cffb2a26 6379 DONE;
6380 FAIL;
6381 }
25f905c2 6382 else /* TARGET_THUMB1 */
cffb2a26 6383 {
6384 if ( INTVAL (operands[3]) != 4
6385 || INTVAL (operands[2]) > 48)
6386 FAIL;
6387
008c057d 6388 thumb_expand_movmemqi (operands);
cffb2a26 6389 DONE;
6390 }
6391 "
6392)
6393
2162064c 6394;; Thumb block-move insns
cffb2a26 6395
6396(define_insn "movmem12b"
960f3acf 6397 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6398 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6399 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6400 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6401 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6402 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6403 (set (match_operand:SI 0 "register_operand" "=l")
6404 (plus:SI (match_dup 2) (const_int 12)))
6405 (set (match_operand:SI 1 "register_operand" "=l")
6406 (plus:SI (match_dup 3) (const_int 12)))
6407 (clobber (match_scratch:SI 4 "=&l"))
6408 (clobber (match_scratch:SI 5 "=&l"))
6409 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6410 "TARGET_THUMB1"
cffb2a26 6411 "* return thumb_output_move_mem_multiple (3, operands);"
6412 [(set_attr "length" "4")
215b30b3 6413 ; This isn't entirely accurate... It loads as well, but in terms of
6414 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6415 (set_attr "type" "store3")]
6416)
6417
6418(define_insn "movmem8b"
960f3acf 6419 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6420 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6421 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6422 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6423 (set (match_operand:SI 0 "register_operand" "=l")
6424 (plus:SI (match_dup 2) (const_int 8)))
6425 (set (match_operand:SI 1 "register_operand" "=l")
6426 (plus:SI (match_dup 3) (const_int 8)))
6427 (clobber (match_scratch:SI 4 "=&l"))
6428 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6429 "TARGET_THUMB1"
cffb2a26 6430 "* return thumb_output_move_mem_multiple (2, operands);"
6431 [(set_attr "length" "4")
215b30b3 6432 ; This isn't entirely accurate... It loads as well, but in terms of
6433 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6434 (set_attr "type" "store2")]
6435)
6436
9c08d1fa 6437\f
b11cae9e 6438
341940e8 6439;; Compare & branch insns
8d232dc7 6440;; The range calculations are based as follows:
341940e8 6441;; For forward branches, the address calculation returns the address of
6442;; the next instruction. This is 2 beyond the branch instruction.
6443;; For backward branches, the address calculation returns the address of
6444;; the first instruction in this pattern (cmp). This is 2 before the branch
6445;; instruction for the shortest sequence, and 4 before the branch instruction
6446;; if we have to jump around an unconditional branch.
6447;; To the basic branch range the PC offset must be added (this is +4).
6448;; So for forward branches we have
6449;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6450;; And for backward branches we have
6451;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6452;;
6453;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6454;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6455
aeac46d4 6456(define_expand "cbranchsi4"
6457 [(set (pc) (if_then_else
6458 (match_operator 0 "arm_comparison_operator"
6459 [(match_operand:SI 1 "s_register_operand" "")
6460 (match_operand:SI 2 "nonmemory_operand" "")])
6461 (label_ref (match_operand 3 "" ""))
6462 (pc)))]
74f4459c 6463 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6464 "
74f4459c 6465 if (!TARGET_THUMB1)
6466 {
6467 if (!arm_add_operand (operands[2], SImode))
6468 operands[2] = force_reg (SImode, operands[2]);
6469 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6470 operands[3]));
6471 DONE;
6472 }
25f905c2 6473 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6474 {
6475 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6476 operands[3], operands[0]));
6477 DONE;
6478 }
25f905c2 6479 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6480 operands[2] = force_reg (SImode, operands[2]);
6481 ")
6482
a8e6c15d 6483;; A pattern to recognize a special situation and optimize for it.
6484;; On the thumb, zero-extension from memory is preferrable to sign-extension
6485;; due to the available addressing modes. Hence, convert a signed comparison
6486;; with zero into an unsigned comparison with 127 if possible.
6487(define_expand "cbranchqi4"
6488 [(set (pc) (if_then_else
6489 (match_operator 0 "lt_ge_comparison_operator"
6490 [(match_operand:QI 1 "memory_operand" "")
6491 (match_operand:QI 2 "const0_operand" "")])
6492 (label_ref (match_operand 3 "" ""))
6493 (pc)))]
6494 "TARGET_THUMB1"
6495{
d0f6c30d 6496 rtx xops[4];
a8e6c15d 6497 xops[1] = gen_reg_rtx (SImode);
6498 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6499 xops[2] = GEN_INT (127);
6500 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6501 VOIDmode, xops[1], xops[2]);
6502 xops[3] = operands[3];
6503 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6504 DONE;
6505})
6506
74f4459c 6507(define_expand "cbranchsf4"
6508 [(set (pc) (if_then_else
6509 (match_operator 0 "arm_comparison_operator"
6510 [(match_operand:SF 1 "s_register_operand" "")
6511 (match_operand:SF 2 "arm_float_compare_operand" "")])
6512 (label_ref (match_operand 3 "" ""))
6513 (pc)))]
6514 "TARGET_32BIT && TARGET_HARD_FLOAT"
6515 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6516 operands[3])); DONE;"
6517)
6518
6519(define_expand "cbranchdf4"
6520 [(set (pc) (if_then_else
6521 (match_operator 0 "arm_comparison_operator"
6522 [(match_operand:DF 1 "s_register_operand" "")
6523 (match_operand:DF 2 "arm_float_compare_operand" "")])
6524 (label_ref (match_operand 3 "" ""))
6525 (pc)))]
a50d7267 6526 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6527 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6528 operands[3])); DONE;"
6529)
6530
74f4459c 6531(define_expand "cbranchdi4"
6532 [(set (pc) (if_then_else
6533 (match_operator 0 "arm_comparison_operator"
a8045a4f 6534 [(match_operand:DI 1 "cmpdi_operand" "")
6535 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6536 (label_ref (match_operand 3 "" ""))
6537 (pc)))]
a8045a4f 6538 "TARGET_32BIT"
6539 "{
6540 rtx swap = NULL_RTX;
6541 enum rtx_code code = GET_CODE (operands[0]);
6542
6543 /* We should not have two constants. */
6544 gcc_assert (GET_MODE (operands[1]) == DImode
6545 || GET_MODE (operands[2]) == DImode);
6546
6547 /* Flip unimplemented DImode comparisons to a form that
6548 arm_gen_compare_reg can handle. */
6549 switch (code)
6550 {
6551 case GT:
6552 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6553 case LE:
6554 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6555 case GTU:
6556 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6557 case LEU:
6558 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6559 default:
6560 break;
6561 }
6562 if (swap)
6563 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6564 operands[3]));
6565 else
6566 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6567 operands[3]));
6568 DONE;
6569 }"
74f4459c 6570)
6571
d60047aa 6572(define_insn "cbranchsi4_insn"
aeac46d4 6573 [(set (pc) (if_then_else
6574 (match_operator 0 "arm_comparison_operator"
747b7458 6575 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 6576 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6577 (label_ref (match_operand 3 "" ""))
6578 (pc)))]
25f905c2 6579 "TARGET_THUMB1"
747b7458 6580{
6581 rtx t = cfun->machine->thumb1_cc_insn;
6582 if (t != NULL_RTX)
d60047aa 6583 {
747b7458 6584 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6585 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6586 t = NULL_RTX;
6587 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6588 {
6589 if (!noov_comparison_operator (operands[0], VOIDmode))
6590 t = NULL_RTX;
6591 }
6592 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 6593 t = NULL_RTX;
6594 }
d60047aa 6595 if (t == NULL_RTX)
747b7458 6596 {
6597 output_asm_insn ("cmp\t%1, %2", operands);
6598 cfun->machine->thumb1_cc_insn = insn;
6599 cfun->machine->thumb1_cc_op0 = operands[1];
6600 cfun->machine->thumb1_cc_op1 = operands[2];
6601 cfun->machine->thumb1_cc_mode = CCmode;
6602 }
6603 else
6604 /* Ensure we emit the right type of condition code on the jump. */
6605 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6606 CC_REGNUM);
aeac46d4 6607
cffb2a26 6608 switch (get_attr_length (insn))
6609 {
6610 case 4: return \"b%d0\\t%l3\";
6611 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6612 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6613 }
747b7458 6614}
cffb2a26 6615 [(set (attr "far_jump")
6616 (if_then_else
6617 (eq_attr "length" "8")
6618 (const_string "yes")
6619 (const_string "no")))
6620 (set (attr "length")
6621 (if_then_else
6622 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6623 (le (minus (match_dup 3) (pc)) (const_int 256)))
6624 (const_int 4)
6625 (if_then_else
6626 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6627 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6628 (const_int 6)
6629 (const_int 8))))]
6630)
6631
aeac46d4 6632(define_insn "cbranchsi4_scratch"
6633 [(set (pc) (if_then_else
6634 (match_operator 4 "arm_comparison_operator"
6635 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6636 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6637 (label_ref (match_operand 3 "" ""))
6638 (pc)))
6639 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6640 "TARGET_THUMB1"
aeac46d4 6641 "*
6642 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6643
6644 switch (get_attr_length (insn))
6645 {
6646 case 4: return \"b%d4\\t%l3\";
6647 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6648 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6649 }
6650 "
6651 [(set (attr "far_jump")
6652 (if_then_else
6653 (eq_attr "length" "8")
6654 (const_string "yes")
6655 (const_string "no")))
6656 (set (attr "length")
6657 (if_then_else
6658 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6659 (le (minus (match_dup 3) (pc)) (const_int 256)))
6660 (const_int 4)
6661 (if_then_else
6662 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6663 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6664 (const_int 6)
6665 (const_int 8))))]
6666)
446a1e96 6667
747b7458 6668;; Two peepholes to generate subtract of 0 instead of a move if the
6669;; condition codes will be useful.
446a1e96 6670(define_peephole2
6671 [(set (match_operand:SI 0 "low_register_operand" "")
6672 (match_operand:SI 1 "low_register_operand" ""))
6673 (set (pc)
6674 (if_then_else (match_operator 2 "arm_comparison_operator"
6675 [(match_dup 1) (const_int 0)])
6676 (label_ref (match_operand 3 "" ""))
6677 (pc)))]
6678 "TARGET_THUMB1"
747b7458 6679 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6680 (set (pc)
6681 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6682 (label_ref (match_dup 3))
747b7458 6683 (pc)))]
6684 "")
446a1e96 6685
6686;; Sigh! This variant shouldn't be needed, but combine often fails to
6687;; merge cases like this because the op1 is a hard register in
07d32235 6688;; arm_class_likely_spilled_p.
446a1e96 6689(define_peephole2
6690 [(set (match_operand:SI 0 "low_register_operand" "")
6691 (match_operand:SI 1 "low_register_operand" ""))
6692 (set (pc)
6693 (if_then_else (match_operator 2 "arm_comparison_operator"
6694 [(match_dup 0) (const_int 0)])
6695 (label_ref (match_operand 3 "" ""))
6696 (pc)))]
6697 "TARGET_THUMB1"
747b7458 6698 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6699 (set (pc)
6700 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6701 (label_ref (match_dup 3))
747b7458 6702 (pc)))]
6703 "")
446a1e96 6704
cffb2a26 6705(define_insn "*negated_cbranchsi4"
6706 [(set (pc)
6707 (if_then_else
aed179ae 6708 (match_operator 0 "equality_operator"
aeac46d4 6709 [(match_operand:SI 1 "s_register_operand" "l")
6710 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6711 (label_ref (match_operand 3 "" ""))
215b30b3 6712 (pc)))]
25f905c2 6713 "TARGET_THUMB1"
cffb2a26 6714 "*
6715 output_asm_insn (\"cmn\\t%1, %2\", operands);
6716 switch (get_attr_length (insn))
6717 {
6718 case 4: return \"b%d0\\t%l3\";
6719 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6720 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6721 }
6722 "
6723 [(set (attr "far_jump")
6724 (if_then_else
6725 (eq_attr "length" "8")
6726 (const_string "yes")
6727 (const_string "no")))
6728 (set (attr "length")
6729 (if_then_else
6730 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6731 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6732 (const_int 4)
6733 (if_then_else
341940e8 6734 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6735 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6736 (const_int 6)
6737 (const_int 8))))]
6738)
6739
58d6528b 6740(define_insn "*tbit_cbranch"
6741 [(set (pc)
6742 (if_then_else
6743 (match_operator 0 "equality_operator"
6744 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6745 (const_int 1)
6746 (match_operand:SI 2 "const_int_operand" "i"))
6747 (const_int 0)])
6748 (label_ref (match_operand 3 "" ""))
6749 (pc)))
6750 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6751 "TARGET_THUMB1"
58d6528b 6752 "*
6753 {
6754 rtx op[3];
6755 op[0] = operands[4];
6756 op[1] = operands[1];
6757 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6758
86efa74d 6759 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6760 switch (get_attr_length (insn))
6761 {
6762 case 4: return \"b%d0\\t%l3\";
6763 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6764 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6765 }
6766 }"
6767 [(set (attr "far_jump")
6768 (if_then_else
6769 (eq_attr "length" "8")
6770 (const_string "yes")
6771 (const_string "no")))
6772 (set (attr "length")
6773 (if_then_else
6774 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6775 (le (minus (match_dup 3) (pc)) (const_int 256)))
6776 (const_int 4)
6777 (if_then_else
6778 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6779 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6780 (const_int 6)
6781 (const_int 8))))]
6782)
6783
6784(define_insn "*tlobits_cbranch"
6785 [(set (pc)
6786 (if_then_else
6787 (match_operator 0 "equality_operator"
6788 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6789 (match_operand:SI 2 "const_int_operand" "i")
6790 (const_int 0))
6791 (const_int 0)])
6792 (label_ref (match_operand 3 "" ""))
6793 (pc)))
6794 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6795 "TARGET_THUMB1"
86efa74d 6796 "*
6797 {
6798 rtx op[3];
6799 op[0] = operands[4];
6800 op[1] = operands[1];
6801 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6802
58d6528b 6803 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6804 switch (get_attr_length (insn))
6805 {
6806 case 4: return \"b%d0\\t%l3\";
6807 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6808 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6809 }
6810 }"
6811 [(set (attr "far_jump")
6812 (if_then_else
6813 (eq_attr "length" "8")
6814 (const_string "yes")
6815 (const_string "no")))
6816 (set (attr "length")
6817 (if_then_else
6818 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6819 (le (minus (match_dup 3) (pc)) (const_int 256)))
6820 (const_int 4)
6821 (if_then_else
6822 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6823 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6824 (const_int 6)
6825 (const_int 8))))]
6826)
747b7458 6827
aeac46d4 6828(define_insn "*tstsi3_cbranch"
58d6528b 6829 [(set (pc)
6830 (if_then_else
aeac46d4 6831 (match_operator 3 "equality_operator"
6832 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6833 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6834 (const_int 0)])
aeac46d4 6835 (label_ref (match_operand 2 "" ""))
6836 (pc)))]
25f905c2 6837 "TARGET_THUMB1"
58d6528b 6838 "*
6839 {
aeac46d4 6840 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6841 switch (get_attr_length (insn))
6842 {
aeac46d4 6843 case 4: return \"b%d3\\t%l2\";
6844 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6845 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6846 }
6847 }"
6848 [(set (attr "far_jump")
6849 (if_then_else
6850 (eq_attr "length" "8")
6851 (const_string "yes")
6852 (const_string "no")))
6853 (set (attr "length")
6854 (if_then_else
aeac46d4 6855 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6856 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6857 (const_int 4)
6858 (if_then_else
aeac46d4 6859 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6860 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6861 (const_int 6)
6862 (const_int 8))))]
6863)
6864
203c488f 6865(define_insn "*cbranchne_decr1"
6866 [(set (pc)
6867 (if_then_else (match_operator 3 "equality_operator"
6868 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6869 (const_int 0)])
6870 (label_ref (match_operand 4 "" ""))
6871 (pc)))
aeac46d4 6872 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6873 (plus:SI (match_dup 2) (const_int -1)))
6874 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6875 "TARGET_THUMB1"
203c488f 6876 "*
6877 {
6878 rtx cond[2];
6879 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6880 ? GEU : LTU),
58d6528b 6881 VOIDmode, operands[2], const1_rtx);
203c488f 6882 cond[1] = operands[4];
6883
6884 if (which_alternative == 0)
6885 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6886 else if (which_alternative == 1)
6887 {
6888 /* We must provide an alternative for a hi reg because reload
6889 cannot handle output reloads on a jump instruction, but we
6890 can't subtract into that. Fortunately a mov from lo to hi
6891 does not clobber the condition codes. */
6892 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6893 output_asm_insn (\"mov\\t%0, %1\", operands);
6894 }
6895 else
6896 {
6897 /* Similarly, but the target is memory. */
6898 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6899 output_asm_insn (\"str\\t%1, %0\", operands);
6900 }
6901
6902 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6903 {
6904 case 4:
8aea555f 6905 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6906 return \"\";
6907 case 6:
8aea555f 6908 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6909 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6910 default:
8aea555f 6911 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6912 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6913 }
6914 }
6915 "
6916 [(set (attr "far_jump")
6917 (if_then_else
6918 (ior (and (eq (symbol_ref ("which_alternative"))
6919 (const_int 0))
6920 (eq_attr "length" "8"))
6921 (eq_attr "length" "10"))
6922 (const_string "yes")
6923 (const_string "no")))
6924 (set_attr_alternative "length"
6925 [
6926 ;; Alternative 0
6927 (if_then_else
6928 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6929 (le (minus (match_dup 4) (pc)) (const_int 256)))
6930 (const_int 4)
6931 (if_then_else
6932 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6933 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6934 (const_int 6)
6935 (const_int 8)))
6936 ;; Alternative 1
6937 (if_then_else
6938 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6939 (le (minus (match_dup 4) (pc)) (const_int 256)))
6940 (const_int 6)
6941 (if_then_else
6942 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6943 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6944 (const_int 8)
6945 (const_int 10)))
6946 ;; Alternative 2
6947 (if_then_else
6948 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6949 (le (minus (match_dup 4) (pc)) (const_int 256)))
6950 (const_int 6)
6951 (if_then_else
6952 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6953 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6954 (const_int 8)
6955 (const_int 10)))
6956 ;; Alternative 3
6957 (if_then_else
6958 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6959 (le (minus (match_dup 4) (pc)) (const_int 256)))
6960 (const_int 6)
6961 (if_then_else
6962 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6963 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6964 (const_int 8)
6965 (const_int 10)))])]
6966)
cffb2a26 6967
58d6528b 6968(define_insn "*addsi3_cbranch"
6969 [(set (pc)
6970 (if_then_else
b0694be0 6971 (match_operator 4 "arm_comparison_operator"
58d6528b 6972 [(plus:SI
e54011cb 6973 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
6974 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 6975 (const_int 0)])
6976 (label_ref (match_operand 5 "" ""))
6977 (pc)))
aeac46d4 6978 (set
6979 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6980 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 6981 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 6982 "TARGET_THUMB1
58d6528b 6983 && (GET_CODE (operands[4]) == EQ
6984 || GET_CODE (operands[4]) == NE
6985 || GET_CODE (operands[4]) == GE
6986 || GET_CODE (operands[4]) == LT)"
6987 "*
6988 {
6989 rtx cond[3];
6990
956a6170 6991 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 6992 cond[1] = operands[2];
6993 cond[2] = operands[3];
6994
6995 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6996 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6997 else
6998 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6999
956a6170 7000 if (which_alternative >= 2
58d6528b 7001 && which_alternative < 4)
7002 output_asm_insn (\"mov\\t%0, %1\", operands);
7003 else if (which_alternative >= 4)
7004 output_asm_insn (\"str\\t%1, %0\", operands);
7005
d0f6c30d 7006 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 7007 {
7008 case 4:
7009 return \"b%d4\\t%l5\";
7010 case 6:
7011 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7012 default:
7013 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7014 }
7015 }
7016 "
7017 [(set (attr "far_jump")
7018 (if_then_else
7019 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7020 (const_int 2))
58d6528b 7021 (eq_attr "length" "8"))
7022 (eq_attr "length" "10"))
7023 (const_string "yes")
7024 (const_string "no")))
7025 (set (attr "length")
7026 (if_then_else
7027 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7028 (const_int 2))
58d6528b 7029 (if_then_else
7030 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7031 (le (minus (match_dup 5) (pc)) (const_int 256)))
7032 (const_int 4)
7033 (if_then_else
7034 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7035 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7036 (const_int 6)
7037 (const_int 8)))
7038 (if_then_else
7039 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7040 (le (minus (match_dup 5) (pc)) (const_int 256)))
7041 (const_int 6)
7042 (if_then_else
7043 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7044 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7045 (const_int 8)
7046 (const_int 10)))))]
7047)
7048
7049(define_insn "*addsi3_cbranch_scratch"
7050 [(set (pc)
7051 (if_then_else
b0694be0 7052 (match_operator 3 "arm_comparison_operator"
58d6528b 7053 [(plus:SI
7054 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7055 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7056 (const_int 0)])
7057 (label_ref (match_operand 4 "" ""))
7058 (pc)))
7059 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7060 "TARGET_THUMB1
58d6528b 7061 && (GET_CODE (operands[3]) == EQ
7062 || GET_CODE (operands[3]) == NE
7063 || GET_CODE (operands[3]) == GE
7064 || GET_CODE (operands[3]) == LT)"
7065 "*
7066 {
7067 switch (which_alternative)
7068 {
7069 case 0:
7070 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7071 break;
7072 case 1:
7073 output_asm_insn (\"cmn\t%1, %2\", operands);
7074 break;
0f5e9701 7075 case 2:
3a445a04 7076 if (INTVAL (operands[2]) < 0)
7077 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7078 else
7079 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7080 break;
0f5e9701 7081 case 3:
3a445a04 7082 if (INTVAL (operands[2]) < 0)
7083 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7084 else
7085 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7086 break;
7087 }
7088
7089 switch (get_attr_length (insn))
7090 {
7091 case 4:
7092 return \"b%d3\\t%l4\";
7093 case 6:
7094 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7095 default:
7096 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7097 }
7098 }
7099 "
7100 [(set (attr "far_jump")
7101 (if_then_else
7102 (eq_attr "length" "8")
7103 (const_string "yes")
7104 (const_string "no")))
7105 (set (attr "length")
7106 (if_then_else
7107 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7108 (le (minus (match_dup 4) (pc)) (const_int 256)))
7109 (const_int 4)
7110 (if_then_else
7111 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7112 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7113 (const_int 6)
7114 (const_int 8))))]
7115)
7116
58d6528b 7117
9c08d1fa 7118;; Comparison and test insns
7119
cffb2a26 7120(define_insn "*arm_cmpsi_insn"
bd5b4116 7121 [(set (reg:CC CC_REGNUM)
a6864a24 7122 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7123 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
25f905c2 7124 "TARGET_32BIT"
5565501b 7125 "@
a6864a24 7126 cmp%?\\t%0, %1
7127 cmp%?\\t%0, %1
aea4c774 7128 cmp%?\\t%0, %1
7129 cmn%?\\t%0, #%n1"
a6864a24 7130 [(set_attr "conds" "set")
7131 (set_attr "arch" "t2,t2,any,any")
7132 (set_attr "length" "2,2,4,4")]
cffb2a26 7133)
b11cae9e 7134
d5d4dc8d 7135(define_insn "*cmpsi_shiftsi"
bd5b4116 7136 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7137 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7138 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7139 [(match_operand:SI 1 "s_register_operand" "r,r")
7140 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7141 "TARGET_32BIT"
aea4c774 7142 "cmp%?\\t%0, %1%S3"
344495ea 7143 [(set_attr "conds" "set")
331beb1a 7144 (set_attr "shift" "1")
d5d4dc8d 7145 (set_attr "arch" "32,a")
7146 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7147
d5d4dc8d 7148(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7149 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7150 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7151 [(match_operand:SI 1 "s_register_operand" "r,r")
7152 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7153 (match_operand:SI 0 "s_register_operand" "r,r")))]
7154 "TARGET_32BIT"
aea4c774 7155 "cmp%?\\t%0, %1%S3"
344495ea 7156 [(set_attr "conds" "set")
331beb1a 7157 (set_attr "shift" "1")
d5d4dc8d 7158 (set_attr "arch" "32,a")
7159 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7160
25f905c2 7161(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7162 [(set (reg:CC_Z CC_REGNUM)
7163 (compare:CC_Z
7164 (neg:SI (match_operator:SI 1 "shift_operator"
7165 [(match_operand:SI 2 "s_register_operand" "r")
7166 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7167 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7168 "TARGET_ARM"
aed179ae 7169 "cmn%?\\t%0, %2%S1"
344495ea 7170 [(set_attr "conds" "set")
aed179ae 7171 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7172 (const_string "alu_shift")
7173 (const_string "alu_shift_reg")))]
0d66636f 7174)
b11cae9e 7175
a8045a4f 7176;; DImode comparisons. The generic code generates branches that
7177;; if-conversion can not reduce to a conditional compare, so we do
7178;; that directly.
7179
7180(define_insn "*arm_cmpdi_insn"
7181 [(set (reg:CC_NCV CC_REGNUM)
7182 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7183 (match_operand:DI 1 "arm_di_operand" "rDi")))
7184 (clobber (match_scratch:SI 2 "=r"))]
7185 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7186 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7187 [(set_attr "conds" "set")
7188 (set_attr "length" "8")]
7189)
7190
7191(define_insn "*arm_cmpdi_unsigned"
7192 [(set (reg:CC_CZ CC_REGNUM)
7193 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7194 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7195 "TARGET_ARM"
7196 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7197 [(set_attr "conds" "set")
7198 (set_attr "length" "8")]
7199)
7200
7201(define_insn "*arm_cmpdi_zero"
7202 [(set (reg:CC_Z CC_REGNUM)
7203 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7204 (const_int 0)))
7205 (clobber (match_scratch:SI 1 "=r"))]
7206 "TARGET_32BIT"
7207 "orr%.\\t%1, %Q0, %R0"
7208 [(set_attr "conds" "set")]
7209)
7210
7211(define_insn "*thumb_cmpdi_zero"
7212 [(set (reg:CC_Z CC_REGNUM)
7213 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7214 (const_int 0)))
7215 (clobber (match_scratch:SI 1 "=l"))]
7216 "TARGET_THUMB1"
7217 "orr\\t%1, %Q0, %R0"
7218 [(set_attr "conds" "set")
7219 (set_attr "length" "2")]
7220)
7221
7d57ec45 7222;; Cirrus SF compare instruction
7223(define_insn "*cirrus_cmpsf"
7224 [(set (reg:CCFP CC_REGNUM)
7225 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7226 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7227 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7228 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7229 [(set_attr "type" "mav_farith")
7d57ec45 7230 (set_attr "cirrus" "compare")]
7231)
7232
7233;; Cirrus DF compare instruction
7234(define_insn "*cirrus_cmpdf"
7235 [(set (reg:CCFP CC_REGNUM)
7236 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7237 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7238 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7239 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7240 [(set_attr "type" "mav_farith")
7d57ec45 7241 (set_attr "cirrus" "compare")]
7242)
7243
7d57ec45 7244(define_insn "*cirrus_cmpdi"
7245 [(set (reg:CC CC_REGNUM)
7246 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7247 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7248 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7249 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7250 [(set_attr "type" "mav_farith")
7d57ec45 7251 (set_attr "cirrus" "compare")]
7252)
7253
9c08d1fa 7254; This insn allows redundant compares to be removed by cse, nothing should
7255; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7256; is deleted later on. The match_dup will match the mode here, so that
7257; mode changes of the condition codes aren't lost by this even though we don't
7258; specify what they are.
7259
8a18b90c 7260(define_insn "*deleted_compare"
9c08d1fa 7261 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7262 "TARGET_32BIT"
40dbec34 7263 "\\t%@ deleted compare"
cffb2a26 7264 [(set_attr "conds" "set")
7265 (set_attr "length" "0")]
7266)
9c08d1fa 7267
7268\f
7269;; Conditional branch insns
7270
74f4459c 7271(define_expand "cbranch_cc"
9c08d1fa 7272 [(set (pc)
74f4459c 7273 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7274 (match_operand 2 "" "")])
7275 (label_ref (match_operand 3 "" ""))
9c08d1fa 7276 (pc)))]
25f905c2 7277 "TARGET_32BIT"
74f4459c 7278 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7279 operands[1], operands[2]);
7280 operands[2] = const0_rtx;"
8fa3ba89 7281)
7282
7283;;
7284;; Patterns to match conditional branch insns.
7285;;
7286
cffb2a26 7287(define_insn "*arm_cond_branch"
9c08d1fa 7288 [(set (pc)
8fa3ba89 7289 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7290 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7291 (label_ref (match_operand 0 "" ""))
7292 (pc)))]
25f905c2 7293 "TARGET_32BIT"
d75350ce 7294 "*
9c08d1fa 7295 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7296 {
7297 arm_ccfsm_state += 2;
7298 return \"\";
7299 }
e2348bcb 7300 return \"b%d1\\t%l0\";
cffb2a26 7301 "
a2cd141b 7302 [(set_attr "conds" "use")
a6864a24 7303 (set_attr "type" "branch")
7304 (set (attr "length")
7305 (if_then_else
7306 (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7307 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7308 (le (minus (match_dup 0) (pc)) (const_int 256))))
7309 (const_int 2)
7310 (const_int 4)))]
cffb2a26 7311)
d75350ce 7312
cffb2a26 7313(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7314 [(set (pc)
8fa3ba89 7315 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7316 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7317 (pc)
7318 (label_ref (match_operand 0 "" ""))))]
25f905c2 7319 "TARGET_32BIT"
d75350ce 7320 "*
9c08d1fa 7321 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7322 {
7323 arm_ccfsm_state += 2;
7324 return \"\";
7325 }
e2348bcb 7326 return \"b%D1\\t%l0\";
cffb2a26 7327 "
a2cd141b 7328 [(set_attr "conds" "use")
a6864a24 7329 (set_attr "type" "branch")
7330 (set (attr "length")
7331 (if_then_else
7332 (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7333 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7334 (le (minus (match_dup 0) (pc)) (const_int 256))))
7335 (const_int 2)
7336 (const_int 4)))]
cffb2a26 7337)
7338
b11cae9e 7339\f
9c08d1fa 7340
7341; scc insns
7342
74f4459c 7343(define_expand "cstore_cc"
7db9af5d 7344 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7345 (match_operator:SI 1 "" [(match_operand 2 "" "")
7346 (match_operand 3 "" "")]))]
25f905c2 7347 "TARGET_32BIT"
74f4459c 7348 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7349 operands[2], operands[3]);
7350 operands[3] = const0_rtx;"
8fa3ba89 7351)
7352
f7fbdd4a 7353(define_insn "*mov_scc"
9c08d1fa 7354 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7355 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7356 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7357 "TARGET_ARM"
4d61e570 7358 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7359 [(set_attr "conds" "use")
d2a518d1 7360 (set_attr "insn" "mov")
cffb2a26 7361 (set_attr "length" "8")]
7362)
9c08d1fa 7363
f7fbdd4a 7364(define_insn "*mov_negscc"
9c08d1fa 7365 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7366 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7367 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7368 "TARGET_ARM"
4d61e570 7369 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7370 [(set_attr "conds" "use")
d2a518d1 7371 (set_attr "insn" "mov")
cffb2a26 7372 (set_attr "length" "8")]
7373)
9c08d1fa 7374
f7fbdd4a 7375(define_insn "*mov_notscc"
9c08d1fa 7376 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7377 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7378 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7379 "TARGET_ARM"
4d61e570 7380 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7381 [(set_attr "conds" "use")
d2a518d1 7382 (set_attr "insn" "mov")
cffb2a26 7383 (set_attr "length" "8")]
7384)
9c08d1fa 7385
595d88b5 7386(define_expand "cstoresi4"
7387 [(set (match_operand:SI 0 "s_register_operand" "")
7388 (match_operator:SI 1 "arm_comparison_operator"
7389 [(match_operand:SI 2 "s_register_operand" "")
7390 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7391 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7392 "{
7393 rtx op3, scratch, scratch2;
7394
74f4459c 7395 if (!TARGET_THUMB1)
7396 {
7397 if (!arm_add_operand (operands[3], SImode))
7398 operands[3] = force_reg (SImode, operands[3]);
7399 emit_insn (gen_cstore_cc (operands[0], operands[1],
7400 operands[2], operands[3]));
7401 DONE;
7402 }
7403
595d88b5 7404 if (operands[3] == const0_rtx)
7405 {
7406 switch (GET_CODE (operands[1]))
7407 {
7408 case EQ:
25f905c2 7409 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7410 break;
7411
7412 case NE:
25f905c2 7413 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7414 break;
7415
7416 case LE:
7417 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7418 NULL_RTX, 0, OPTAB_WIDEN);
7419 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7420 NULL_RTX, 0, OPTAB_WIDEN);
7421 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7422 operands[0], 1, OPTAB_WIDEN);
7423 break;
7424
7425 case GE:
7426 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7427 NULL_RTX, 1);
7428 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7429 NULL_RTX, 1, OPTAB_WIDEN);
7430 break;
7431
7432 case GT:
7433 scratch = expand_binop (SImode, ashr_optab, operands[2],
7434 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7435 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7436 NULL_RTX, 0, OPTAB_WIDEN);
7437 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7438 0, OPTAB_WIDEN);
7439 break;
7440
7441 /* LT is handled by generic code. No need for unsigned with 0. */
7442 default:
7443 FAIL;
7444 }
7445 DONE;
7446 }
7447
7448 switch (GET_CODE (operands[1]))
7449 {
7450 case EQ:
7451 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7452 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7453 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7454 break;
7455
7456 case NE:
7457 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7458 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7459 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7460 break;
7461
7462 case LE:
7463 op3 = force_reg (SImode, operands[3]);
7464
7465 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7466 NULL_RTX, 1, OPTAB_WIDEN);
7467 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7468 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7469 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7470 op3, operands[2]));
7471 break;
7472
7473 case GE:
7474 op3 = operands[3];
25f905c2 7475 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7476 op3 = force_reg (SImode, op3);
7477 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7478 NULL_RTX, 0, OPTAB_WIDEN);
7479 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7480 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7481 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7482 operands[2], op3));
7483 break;
7484
7485 case LEU:
7486 op3 = force_reg (SImode, operands[3]);
7487 scratch = force_reg (SImode, const0_rtx);
25f905c2 7488 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7489 op3, operands[2]));
7490 break;
7491
7492 case GEU:
7493 op3 = operands[3];
25f905c2 7494 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7495 op3 = force_reg (SImode, op3);
7496 scratch = force_reg (SImode, const0_rtx);
25f905c2 7497 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7498 operands[2], op3));
7499 break;
7500
7501 case LTU:
7502 op3 = operands[3];
25f905c2 7503 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7504 op3 = force_reg (SImode, op3);
7505 scratch = gen_reg_rtx (SImode);
408b7ae5 7506 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7507 break;
7508
7509 case GTU:
7510 op3 = force_reg (SImode, operands[3]);
7511 scratch = gen_reg_rtx (SImode);
408b7ae5 7512 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7513 break;
7514
7515 /* No good sequences for GT, LT. */
7516 default:
7517 FAIL;
7518 }
7519 DONE;
7520}")
7521
74f4459c 7522(define_expand "cstoresf4"
7523 [(set (match_operand:SI 0 "s_register_operand" "")
7524 (match_operator:SI 1 "arm_comparison_operator"
7525 [(match_operand:SF 2 "s_register_operand" "")
7526 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7527 "TARGET_32BIT && TARGET_HARD_FLOAT"
7528 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7529 operands[2], operands[3])); DONE;"
7530)
7531
7532(define_expand "cstoredf4"
7533 [(set (match_operand:SI 0 "s_register_operand" "")
7534 (match_operator:SI 1 "arm_comparison_operator"
7535 [(match_operand:DF 2 "s_register_operand" "")
7536 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7537 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7538 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7539 operands[2], operands[3])); DONE;"
7540)
7541
74f4459c 7542(define_expand "cstoredi4"
7543 [(set (match_operand:SI 0 "s_register_operand" "")
7544 (match_operator:SI 1 "arm_comparison_operator"
a8045a4f 7545 [(match_operand:DI 2 "cmpdi_operand" "")
7546 (match_operand:DI 3 "cmpdi_operand" "")]))]
7547 "TARGET_32BIT"
7548 "{
7549 rtx swap = NULL_RTX;
7550 enum rtx_code code = GET_CODE (operands[1]);
7551
7552 /* We should not have two constants. */
7553 gcc_assert (GET_MODE (operands[2]) == DImode
7554 || GET_MODE (operands[3]) == DImode);
7555
7556 /* Flip unimplemented DImode comparisons to a form that
7557 arm_gen_compare_reg can handle. */
7558 switch (code)
7559 {
7560 case GT:
7561 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7562 case LE:
7563 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7564 case GTU:
7565 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7566 case LEU:
7567 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7568 default:
7569 break;
7570 }
7571 if (swap)
7572 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7573 operands[2]));
7574 else
7575 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7576 operands[3]));
7577 DONE;
7578 }"
74f4459c 7579)
7580
25f905c2 7581(define_expand "cstoresi_eq0_thumb1"
595d88b5 7582 [(parallel
7583 [(set (match_operand:SI 0 "s_register_operand" "")
7584 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7585 (const_int 0)))
7586 (clobber (match_dup:SI 2))])]
25f905c2 7587 "TARGET_THUMB1"
595d88b5 7588 "operands[2] = gen_reg_rtx (SImode);"
7589)
7590
25f905c2 7591(define_expand "cstoresi_ne0_thumb1"
595d88b5 7592 [(parallel
7593 [(set (match_operand:SI 0 "s_register_operand" "")
7594 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7595 (const_int 0)))
7596 (clobber (match_dup:SI 2))])]
25f905c2 7597 "TARGET_THUMB1"
595d88b5 7598 "operands[2] = gen_reg_rtx (SImode);"
7599)
7600
25f905c2 7601(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7602 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7603 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7604 (const_int 0)))
7605 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7606 "TARGET_THUMB1"
595d88b5 7607 "@
7608 neg\\t%0, %1\;adc\\t%0, %0, %1
7609 neg\\t%2, %1\;adc\\t%0, %1, %2"
7610 [(set_attr "length" "4")]
7611)
7612
25f905c2 7613(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7614 [(set (match_operand:SI 0 "s_register_operand" "=l")
7615 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7616 (const_int 0)))
7617 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7618 "TARGET_THUMB1"
595d88b5 7619 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7620 [(set_attr "length" "4")]
7621)
7622
408b7ae5 7623;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 7624(define_insn "cstoresi_nltu_thumb1"
595d88b5 7625 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7626 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7627 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7628 "TARGET_THUMB1"
595d88b5 7629 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7630 [(set_attr "length" "4")]
7631)
7632
408b7ae5 7633(define_insn_and_split "cstoresi_ltu_thumb1"
7634 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7635 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7636 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7637 "TARGET_THUMB1"
7638 "#"
7639 "TARGET_THUMB1"
7640 [(set (match_dup 3)
7641 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7642 (set (match_dup 0) (neg:SI (match_dup 3)))]
7643 "operands[3] = gen_reg_rtx (SImode);"
7644 [(set_attr "length" "4")]
7645)
7646
595d88b5 7647;; Used as part of the expansion of thumb les sequence.
25f905c2 7648(define_insn "thumb1_addsi3_addgeu"
595d88b5 7649 [(set (match_operand:SI 0 "s_register_operand" "=l")
7650 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7651 (match_operand:SI 2 "s_register_operand" "l"))
7652 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 7653 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7654 "TARGET_THUMB1"
595d88b5 7655 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7656 [(set_attr "length" "4")]
7657)
7658
9c08d1fa 7659\f
39b5e676 7660;; Conditional move insns
7661
7662(define_expand "movsicc"
8a18b90c 7663 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7664 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7665 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7666 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7667 "TARGET_32BIT"
39b5e676 7668 "
215b30b3 7669 {
7670 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7671 rtx ccreg;
7672
7673 if (code == UNEQ || code == LTGT)
7674 FAIL;
39b5e676 7675
74f4459c 7676 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7677 XEXP (operands[1], 1));
29bb088d 7678 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7679 }"
7680)
39b5e676 7681
7682(define_expand "movsfcc"
8a18b90c 7683 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7684 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7685 (match_operand:SF 2 "s_register_operand" "")
7686 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 7687 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7688 "
215b30b3 7689 {
7690 enum rtx_code code = GET_CODE (operands[1]);
7691 rtx ccreg;
f082f1c4 7692
278b301d 7693 if (code == UNEQ || code == LTGT)
7694 FAIL;
7695
215b30b3 7696 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7697 Otherwise, ensure it is a valid FP add operand */
7698 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7699 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7700 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7701
74f4459c 7702 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7703 XEXP (operands[1], 1));
29bb088d 7704 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7705 }"
7706)
39b5e676 7707
7708(define_expand "movdfcc"
8a18b90c 7709 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7710 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7711 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7712 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 7713 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 7714 "
215b30b3 7715 {
7716 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7717 rtx ccreg;
39b5e676 7718
278b301d 7719 if (code == UNEQ || code == LTGT)
7720 FAIL;
7721
74f4459c 7722 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7723 XEXP (operands[1], 1));
29bb088d 7724 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7725 }"
7726)
39b5e676 7727
7728(define_insn "*movsicc_insn"
f082f1c4 7729 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7730 (if_then_else:SI
8fa3ba89 7731 (match_operator 3 "arm_comparison_operator"
8a18b90c 7732 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7733 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7734 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7735 "TARGET_ARM"
39b5e676 7736 "@
8a18b90c 7737 mov%D3\\t%0, %2
7738 mvn%D3\\t%0, #%B2
f082f1c4 7739 mov%d3\\t%0, %1
7740 mvn%d3\\t%0, #%B1
8a18b90c 7741 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7742 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7743 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7744 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7745 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7746 (set_attr "conds" "use")
7747 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 7748)
39b5e676 7749
39b5e676 7750(define_insn "*movsfcc_soft_insn"
f082f1c4 7751 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7752 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7753 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7754 (match_operand:SF 1 "s_register_operand" "0,r")
7755 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7756 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7757 "@
7758 mov%D3\\t%0, %2
7759 mov%d3\\t%0, %1"
d2a518d1 7760 [(set_attr "conds" "use")
7761 (set_attr "insn" "mov")]
8fa3ba89 7762)
39b5e676 7763
39b5e676 7764\f
9c08d1fa 7765;; Jump and linkage insns
7766
cffb2a26 7767(define_expand "jump"
9c08d1fa 7768 [(set (pc)
7769 (label_ref (match_operand 0 "" "")))]
cffb2a26 7770 "TARGET_EITHER"
9c08d1fa 7771 ""
cffb2a26 7772)
7773
7774(define_insn "*arm_jump"
7775 [(set (pc)
7776 (label_ref (match_operand 0 "" "")))]
25f905c2 7777 "TARGET_32BIT"
9c08d1fa 7778 "*
0d66636f 7779 {
7780 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7781 {
7782 arm_ccfsm_state += 2;
7783 return \"\";
7784 }
7785 return \"b%?\\t%l0\";
7786 }
7787 "
a6864a24 7788 [(set_attr "predicable" "yes")
7789 (set (attr "length")
7790 (if_then_else
7791 (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7792 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7793 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7794 (const_int 2)
7795 (const_int 4)))]
0d66636f 7796)
9c08d1fa 7797
cffb2a26 7798(define_insn "*thumb_jump"
7799 [(set (pc)
7800 (label_ref (match_operand 0 "" "")))]
25f905c2 7801 "TARGET_THUMB1"
cffb2a26 7802 "*
7803 if (get_attr_length (insn) == 2)
7804 return \"b\\t%l0\";
7805 return \"bl\\t%l0\\t%@ far jump\";
7806 "
7807 [(set (attr "far_jump")
7808 (if_then_else
7809 (eq_attr "length" "4")
7810 (const_string "yes")
7811 (const_string "no")))
7812 (set (attr "length")
7813 (if_then_else
911ed8af 7814 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7815 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7816 (const_int 2)
7817 (const_int 4)))]
7818)
7819
d3373b54 7820(define_expand "call"
7821 [(parallel [(call (match_operand 0 "memory_operand" "")
7822 (match_operand 1 "general_operand" ""))
cffb2a26 7823 (use (match_operand 2 "" ""))
bd5b4116 7824 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7825 "TARGET_EITHER"
6c4c2133 7826 "
7827 {
bac7fc85 7828 rtx callee, pat;
bbe777ea 7829
bbe777ea 7830 /* In an untyped call, we can get NULL for operand 2. */
7831 if (operands[2] == NULL_RTX)
7832 operands[2] = const0_rtx;
7833
de55252a 7834 /* Decide if we should generate indirect calls by loading the
85c36fd1 7835 32-bit address of the callee into a register before performing the
de55252a 7836 branch and link. */
7837 callee = XEXP (operands[0], 0);
7838 if (GET_CODE (callee) == SYMBOL_REF
7839 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7840 : !REG_P (callee))
bbe777ea 7841 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7842
7843 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7844 arm_emit_call_insn (pat, XEXP (operands[0], 0));
7845 DONE;
6c4c2133 7846 }"
7847)
d3373b54 7848
bac7fc85 7849(define_expand "call_internal"
7850 [(parallel [(call (match_operand 0 "memory_operand" "")
7851 (match_operand 1 "general_operand" ""))
7852 (use (match_operand 2 "" ""))
7853 (clobber (reg:SI LR_REGNUM))])])
7854
f1039640 7855(define_insn "*call_reg_armv5"
d3373b54 7856 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7857 (match_operand 1 "" ""))
7858 (use (match_operand 2 "" ""))
bd5b4116 7859 (clobber (reg:SI LR_REGNUM))]
f1039640 7860 "TARGET_ARM && arm_arch5"
7861 "blx%?\\t%0"
7862 [(set_attr "type" "call")]
7863)
7864
7865(define_insn "*call_reg_arm"
7866 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7867 (match_operand 1 "" ""))
7868 (use (match_operand 2 "" ""))
7869 (clobber (reg:SI LR_REGNUM))]
7870 "TARGET_ARM && !arm_arch5"
9c08d1fa 7871 "*
5565501b 7872 return output_call (operands);
cffb2a26 7873 "
7874 ;; length is worst case, normally it is only two
7875 [(set_attr "length" "12")
7876 (set_attr "type" "call")]
7877)
9c08d1fa 7878
89504fc1 7879
7880;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7881;; considered a function call by the branch predictor of some cores (PR40887).
7882;; Falls back to blx rN (*call_reg_armv5).
7883
f7fbdd4a 7884(define_insn "*call_mem"
a3c63a9d 7885 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7886 (match_operand 1 "" ""))
7887 (use (match_operand 2 "" ""))
bd5b4116 7888 (clobber (reg:SI LR_REGNUM))]
89504fc1 7889 "TARGET_ARM && !arm_arch5"
9c08d1fa 7890 "*
5565501b 7891 return output_call_mem (operands);
cffb2a26 7892 "
7893 [(set_attr "length" "12")
7894 (set_attr "type" "call")]
7895)
7896
25f905c2 7897(define_insn "*call_reg_thumb1_v5"
cffb2a26 7898 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7899 (match_operand 1 "" ""))
7900 (use (match_operand 2 "" ""))
bd5b4116 7901 (clobber (reg:SI LR_REGNUM))]
25f905c2 7902 "TARGET_THUMB1 && arm_arch5"
f1039640 7903 "blx\\t%0"
7904 [(set_attr "length" "2")
7905 (set_attr "type" "call")]
cffb2a26 7906)
7907
25f905c2 7908(define_insn "*call_reg_thumb1"
f1039640 7909 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7910 (match_operand 1 "" ""))
7911 (use (match_operand 2 "" ""))
bd5b4116 7912 (clobber (reg:SI LR_REGNUM))]
25f905c2 7913 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 7914 "*
7915 {
150502c9 7916 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7917 return thumb_call_via_reg (operands[0]);
150502c9 7918 else if (operands[1] == const0_rtx)
f1039640 7919 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7920 else if (frame_pointer_needed)
7921 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7922 else
150502c9 7923 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7924 }"
7925 [(set_attr "type" "call")]
7926)
9c08d1fa 7927
d3373b54 7928(define_expand "call_value"
e0698af7 7929 [(parallel [(set (match_operand 0 "" "")
7930 (call (match_operand 1 "memory_operand" "")
7931 (match_operand 2 "general_operand" "")))
cffb2a26 7932 (use (match_operand 3 "" ""))
bd5b4116 7933 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7934 "TARGET_EITHER"
6c4c2133 7935 "
7936 {
bac7fc85 7937 rtx pat, callee;
bbe777ea 7938
7939 /* In an untyped call, we can get NULL for operand 2. */
7940 if (operands[3] == 0)
7941 operands[3] = const0_rtx;
7942
de55252a 7943 /* Decide if we should generate indirect calls by loading the
7944 32-bit address of the callee into a register before performing the
7945 branch and link. */
7946 callee = XEXP (operands[1], 0);
7947 if (GET_CODE (callee) == SYMBOL_REF
7948 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7949 : !REG_P (callee))
78fe751b 7950 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7951
7952 pat = gen_call_value_internal (operands[0], operands[1],
7953 operands[2], operands[3]);
7954 arm_emit_call_insn (pat, XEXP (operands[1], 0));
7955 DONE;
6c4c2133 7956 }"
7957)
d3373b54 7958
bac7fc85 7959(define_expand "call_value_internal"
7960 [(parallel [(set (match_operand 0 "" "")
7961 (call (match_operand 1 "memory_operand" "")
7962 (match_operand 2 "general_operand" "")))
7963 (use (match_operand 3 "" ""))
7964 (clobber (reg:SI LR_REGNUM))])])
7965
f1039640 7966(define_insn "*call_value_reg_armv5"
27ed6835 7967 [(set (match_operand 0 "" "")
755eb2b4 7968 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7969 (match_operand 2 "" "")))
bbe777ea 7970 (use (match_operand 3 "" ""))
bd5b4116 7971 (clobber (reg:SI LR_REGNUM))]
f1039640 7972 "TARGET_ARM && arm_arch5"
7973 "blx%?\\t%1"
7974 [(set_attr "type" "call")]
7975)
7976
7977(define_insn "*call_value_reg_arm"
7978 [(set (match_operand 0 "" "")
7979 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7980 (match_operand 2 "" "")))
7981 (use (match_operand 3 "" ""))
7982 (clobber (reg:SI LR_REGNUM))]
7983 "TARGET_ARM && !arm_arch5"
9c08d1fa 7984 "*
215b30b3 7985 return output_call (&operands[1]);
cffb2a26 7986 "
7987 [(set_attr "length" "12")
7988 (set_attr "type" "call")]
7989)
9c08d1fa 7990
89504fc1 7991;; Note: see *call_mem
7992
f7fbdd4a 7993(define_insn "*call_value_mem"
27ed6835 7994 [(set (match_operand 0 "" "")
a3c63a9d 7995 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7996 (match_operand 2 "" "")))
bbe777ea 7997 (use (match_operand 3 "" ""))
bd5b4116 7998 (clobber (reg:SI LR_REGNUM))]
89504fc1 7999 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8000 "*
215b30b3 8001 return output_call_mem (&operands[1]);
cffb2a26 8002 "
8003 [(set_attr "length" "12")
8004 (set_attr "type" "call")]
8005)
9c08d1fa 8006
25f905c2 8007(define_insn "*call_value_reg_thumb1_v5"
f1039640 8008 [(set (match_operand 0 "" "")
8009 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8010 (match_operand 2 "" "")))
8011 (use (match_operand 3 "" ""))
8012 (clobber (reg:SI LR_REGNUM))]
25f905c2 8013 "TARGET_THUMB1 && arm_arch5"
f1039640 8014 "blx\\t%1"
8015 [(set_attr "length" "2")
8016 (set_attr "type" "call")]
8017)
8018
25f905c2 8019(define_insn "*call_value_reg_thumb1"
f1039640 8020 [(set (match_operand 0 "" "")
8021 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8022 (match_operand 2 "" "")))
8023 (use (match_operand 3 "" ""))
8024 (clobber (reg:SI LR_REGNUM))]
25f905c2 8025 "TARGET_THUMB1 && !arm_arch5"
f1039640 8026 "*
8027 {
150502c9 8028 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8029 return thumb_call_via_reg (operands[1]);
150502c9 8030 else if (operands[2] == const0_rtx)
f1039640 8031 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8032 else if (frame_pointer_needed)
8033 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8034 else
150502c9 8035 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8036 }"
8037 [(set_attr "type" "call")]
8038)
8039
9c08d1fa 8040;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8041;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8042
f7fbdd4a 8043(define_insn "*call_symbol"
27ed6835 8044 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8045 (match_operand 1 "" ""))
bbe777ea 8046 (use (match_operand 2 "" ""))
bd5b4116 8047 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8048 "TARGET_32BIT
cffb2a26 8049 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8050 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8051 "*
8052 {
55c1e470 8053 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8054 }"
cffb2a26 8055 [(set_attr "type" "call")]
8056)
9c08d1fa 8057
f7fbdd4a 8058(define_insn "*call_value_symbol"
ccd90aaa 8059 [(set (match_operand 0 "" "")
27ed6835 8060 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8061 (match_operand:SI 2 "" "")))
bbe777ea 8062 (use (match_operand 3 "" ""))
bd5b4116 8063 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8064 "TARGET_32BIT
cffb2a26 8065 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8066 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8067 "*
8068 {
55c1e470 8069 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8070 }"
cffb2a26 8071 [(set_attr "type" "call")]
8072)
8073
8074(define_insn "*call_insn"
27ed6835 8075 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8076 (match_operand:SI 1 "" ""))
8077 (use (match_operand 2 "" ""))
bd5b4116 8078 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8079 "TARGET_THUMB1
1675c6e9 8080 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8081 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8082 "bl\\t%a0"
8083 [(set_attr "length" "4")
8084 (set_attr "type" "call")]
8085)
8086
8087(define_insn "*call_value_insn"
ccd90aaa 8088 [(set (match_operand 0 "" "")
27ed6835 8089 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8090 (match_operand 2 "" "")))
8091 (use (match_operand 3 "" ""))
bd5b4116 8092 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8093 "TARGET_THUMB1
1675c6e9 8094 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8095 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8096 "bl\\t%a1"
8097 [(set_attr "length" "4")
8098 (set_attr "type" "call")]
8099)
9c08d1fa 8100
1c494086 8101;; We may also be able to do sibcalls for Thumb, but it's much harder...
8102(define_expand "sibcall"
8103 [(parallel [(call (match_operand 0 "memory_operand" "")
8104 (match_operand 1 "general_operand" ""))
2ba80634 8105 (return)
8106 (use (match_operand 2 "" ""))])]
d68c2c10 8107 "TARGET_32BIT"
1c494086 8108 "
8109 {
8110 if (operands[2] == NULL_RTX)
8111 operands[2] = const0_rtx;
1c494086 8112 }"
8113)
8114
8115(define_expand "sibcall_value"
ccd90aaa 8116 [(parallel [(set (match_operand 0 "" "")
1c494086 8117 (call (match_operand 1 "memory_operand" "")
8118 (match_operand 2 "general_operand" "")))
2ba80634 8119 (return)
8120 (use (match_operand 3 "" ""))])]
d68c2c10 8121 "TARGET_32BIT"
1c494086 8122 "
8123 {
8124 if (operands[3] == NULL_RTX)
8125 operands[3] = const0_rtx;
1c494086 8126 }"
8127)
8128
8129(define_insn "*sibcall_insn"
8130 [(call (mem:SI (match_operand:SI 0 "" "X"))
8131 (match_operand 1 "" ""))
2ba80634 8132 (return)
8133 (use (match_operand 2 "" ""))]
d68c2c10 8134 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8135 "*
8136 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8137 "
8138 [(set_attr "type" "call")]
8139)
8140
8141(define_insn "*sibcall_value_insn"
ccd90aaa 8142 [(set (match_operand 0 "" "")
755eb2b4 8143 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8144 (match_operand 2 "" "")))
2ba80634 8145 (return)
8146 (use (match_operand 3 "" ""))]
d68c2c10 8147 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8148 "*
8149 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8150 "
8151 [(set_attr "type" "call")]
8152)
8153
d68c2c10 8154(define_expand "return"
8155 [(return)]
8156 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8157 "")
8158
9c08d1fa 8159;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8160(define_insn "*arm_return"
9c08d1fa 8161 [(return)]
cffb2a26 8162 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8163 "*
9c08d1fa 8164 {
cffb2a26 8165 if (arm_ccfsm_state == 2)
8166 {
8167 arm_ccfsm_state += 2;
8168 return \"\";
8169 }
5db468b7 8170 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8171 }"
a2cd141b 8172 [(set_attr "type" "load1")
755eb2b4 8173 (set_attr "length" "12")
0d66636f 8174 (set_attr "predicable" "yes")]
cffb2a26 8175)
9c08d1fa 8176
f7fbdd4a 8177(define_insn "*cond_return"
9c08d1fa 8178 [(set (pc)
8fa3ba89 8179 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8180 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8181 (return)
8182 (pc)))]
cffb2a26 8183 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8184 "*
8fa3ba89 8185 {
8186 if (arm_ccfsm_state == 2)
8187 {
8188 arm_ccfsm_state += 2;
8189 return \"\";
8190 }
8191 return output_return_instruction (operands[0], TRUE, FALSE);
8192 }"
8193 [(set_attr "conds" "use")
755eb2b4 8194 (set_attr "length" "12")
a2cd141b 8195 (set_attr "type" "load1")]
8fa3ba89 8196)
9c08d1fa 8197
f7fbdd4a 8198(define_insn "*cond_return_inverted"
9c08d1fa 8199 [(set (pc)
8fa3ba89 8200 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8201 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8202 (pc)
8203 (return)))]
cffb2a26 8204 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8205 "*
8fa3ba89 8206 {
8207 if (arm_ccfsm_state == 2)
8208 {
8209 arm_ccfsm_state += 2;
8210 return \"\";
8211 }
8212 return output_return_instruction (operands[0], TRUE, TRUE);
8213 }"
8214 [(set_attr "conds" "use")
37a1317b 8215 (set_attr "length" "12")
a2cd141b 8216 (set_attr "type" "load1")]
8fa3ba89 8217)
9c08d1fa 8218
68121397 8219;; Generate a sequence of instructions to determine if the processor is
8220;; in 26-bit or 32-bit mode, and return the appropriate return address
8221;; mask.
8222
8223(define_expand "return_addr_mask"
8224 [(set (match_dup 1)
8225 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8226 (const_int 0)))
8227 (set (match_operand:SI 0 "s_register_operand" "")
8228 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8229 (const_int -1)
8230 (const_int 67108860)))] ; 0x03fffffc
8231 "TARGET_ARM"
8232 "
62eddbd4 8233 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8234 ")
8235
8236(define_insn "*check_arch2"
8237 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8238 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8239 (const_int 0)))]
8240 "TARGET_ARM"
8241 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8242 [(set_attr "length" "8")
8243 (set_attr "conds" "set")]
8244)
8245
9c08d1fa 8246;; Call subroutine returning any type.
8247
8248(define_expand "untyped_call"
8249 [(parallel [(call (match_operand 0 "" "")
8250 (const_int 0))
8251 (match_operand 1 "" "")
8252 (match_operand 2 "" "")])]
ccd90aaa 8253 "TARGET_EITHER"
9c08d1fa 8254 "
215b30b3 8255 {
8256 int i;
ccd90aaa 8257 rtx par = gen_rtx_PARALLEL (VOIDmode,
8258 rtvec_alloc (XVECLEN (operands[2], 0)));
8259 rtx addr = gen_reg_rtx (Pmode);
8260 rtx mem;
8261 int size = 0;
9c08d1fa 8262
ccd90aaa 8263 emit_move_insn (addr, XEXP (operands[1], 0));
8264 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8265
215b30b3 8266 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8267 {
ccd90aaa 8268 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8269
ccd90aaa 8270 /* Default code only uses r0 as a return value, but we could
8271 be using anything up to 4 registers. */
8272 if (REGNO (src) == R0_REGNUM)
8273 src = gen_rtx_REG (TImode, R0_REGNUM);
8274
8275 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8276 GEN_INT (size));
8277 size += GET_MODE_SIZE (GET_MODE (src));
8278 }
8279
8280 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8281 const0_rtx));
8282
8283 size = 0;
8284
8285 for (i = 0; i < XVECLEN (par, 0); i++)
8286 {
8287 HOST_WIDE_INT offset = 0;
8288 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8289
8290 if (size != 0)
8291 emit_move_insn (addr, plus_constant (addr, size));
8292
8293 mem = change_address (mem, GET_MODE (reg), NULL);
8294 if (REGNO (reg) == R0_REGNUM)
8295 {
8296 /* On thumb we have to use a write-back instruction. */
320ea44d 8297 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8298 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8299 size = TARGET_ARM ? 16 : 0;
8300 }
8301 else
8302 {
8303 emit_move_insn (mem, reg);
8304 size = GET_MODE_SIZE (GET_MODE (reg));
8305 }
215b30b3 8306 }
9c08d1fa 8307
215b30b3 8308 /* The optimizer does not know that the call sets the function value
8309 registers we stored in the result block. We avoid problems by
8310 claiming that all hard registers are used and clobbered at this
8311 point. */
8312 emit_insn (gen_blockage ());
8313
8314 DONE;
8315 }"
8316)
9c08d1fa 8317
ccd90aaa 8318(define_expand "untyped_return"
8319 [(match_operand:BLK 0 "memory_operand" "")
8320 (match_operand 1 "" "")]
8321 "TARGET_EITHER"
8322 "
8323 {
8324 int i;
8325 rtx addr = gen_reg_rtx (Pmode);
8326 rtx mem;
8327 int size = 0;
8328
8329 emit_move_insn (addr, XEXP (operands[0], 0));
8330 mem = change_address (operands[0], BLKmode, addr);
8331
8332 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8333 {
8334 HOST_WIDE_INT offset = 0;
8335 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8336
8337 if (size != 0)
8338 emit_move_insn (addr, plus_constant (addr, size));
8339
8340 mem = change_address (mem, GET_MODE (reg), NULL);
8341 if (REGNO (reg) == R0_REGNUM)
8342 {
8343 /* On thumb we have to use a write-back instruction. */
320ea44d 8344 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8345 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8346 size = TARGET_ARM ? 16 : 0;
8347 }
8348 else
8349 {
8350 emit_move_insn (reg, mem);
8351 size = GET_MODE_SIZE (GET_MODE (reg));
8352 }
8353 }
8354
8355 /* Emit USE insns before the return. */
8356 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8357 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8358
8359 /* Construct the return. */
8360 expand_naked_return ();
8361
8362 DONE;
8363 }"
8364)
8365
9c08d1fa 8366;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8367;; all of memory. This blocks insns from being moved across this point.
8368
8369(define_insn "blockage"
e1159bbe 8370 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8371 "TARGET_EITHER"
9c08d1fa 8372 ""
cffb2a26 8373 [(set_attr "length" "0")
8374 (set_attr "type" "block")]
8375)
9c08d1fa 8376
f7fbdd4a 8377(define_expand "casesi"
8378 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8379 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8380 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8381 (match_operand:SI 3 "" "") ; table label
8382 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8383 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8384 "
215b30b3 8385 {
e6ac8414 8386 enum insn_code code;
215b30b3 8387 if (operands[1] != const0_rtx)
8388 {
e6ac8414 8389 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8390
215b30b3 8391 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8392 gen_int_mode (-INTVAL (operands[1]),
8393 SImode)));
215b30b3 8394 operands[0] = reg;
8395 }
9c08d1fa 8396
25f905c2 8397 if (TARGET_ARM)
e6ac8414 8398 code = CODE_FOR_arm_casesi_internal;
3db2019b 8399 else if (TARGET_THUMB1)
e6ac8414 8400 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8401 else if (flag_pic)
e6ac8414 8402 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8403 else
e6ac8414 8404 code = CODE_FOR_thumb2_casesi_internal;
8405
8406 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8407 operands[2] = force_reg (SImode, operands[2]);
8408
8409 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8410 operands[3], operands[4]));
215b30b3 8411 DONE;
8412 }"
8413)
f7fbdd4a 8414
f082f1c4 8415;; The USE in this pattern is needed to tell flow analysis that this is
8416;; a CASESI insn. It has no other purpose.
25f905c2 8417(define_insn "arm_casesi_internal"
f082f1c4 8418 [(parallel [(set (pc)
8419 (if_then_else
8420 (leu (match_operand:SI 0 "s_register_operand" "r")
8421 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8422 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8423 (label_ref (match_operand 2 "" ""))))
8424 (label_ref (match_operand 3 "" ""))))
bd5b4116 8425 (clobber (reg:CC CC_REGNUM))
f082f1c4 8426 (use (label_ref (match_dup 2)))])]
cffb2a26 8427 "TARGET_ARM"
f7fbdd4a 8428 "*
0d66636f 8429 if (flag_pic)
8430 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8431 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8432 "
8433 [(set_attr "conds" "clob")
8434 (set_attr "length" "12")]
8435)
9c08d1fa 8436
e6ac8414 8437(define_expand "thumb1_casesi_internal_pic"
8438 [(match_operand:SI 0 "s_register_operand" "")
8439 (match_operand:SI 1 "thumb1_cmp_operand" "")
8440 (match_operand 2 "" "")
8441 (match_operand 3 "" "")]
3db2019b 8442 "TARGET_THUMB1"
e6ac8414 8443 {
8444 rtx reg0;
8445 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8446 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8447 operands[3]));
8448 reg0 = gen_rtx_REG (SImode, 0);
8449 emit_move_insn (reg0, operands[0]);
8450 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8451 DONE;
8452 }
8453)
8454
8455(define_insn "thumb1_casesi_dispatch"
8456 [(parallel [(set (pc) (unspec [(reg:SI 0)
8457 (label_ref (match_operand 0 "" ""))
8458;; (label_ref (match_operand 1 "" ""))
8459]
8460 UNSPEC_THUMB1_CASESI))
8461 (clobber (reg:SI IP_REGNUM))
8462 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8463 "TARGET_THUMB1"
e6ac8414 8464 "* return thumb1_output_casesi(operands);"
8465 [(set_attr "length" "4")]
8466)
8467
cffb2a26 8468(define_expand "indirect_jump"
9c08d1fa 8469 [(set (pc)
cffb2a26 8470 (match_operand:SI 0 "s_register_operand" ""))]
8471 "TARGET_EITHER"
25f905c2 8472 "
8473 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8474 address and use bx. */
8475 if (TARGET_THUMB2)
8476 {
8477 rtx tmp;
8478 tmp = gen_reg_rtx (SImode);
8479 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8480 operands[0] = tmp;
8481 }
8482 "
cffb2a26 8483)
8484
f1039640 8485;; NB Never uses BX.
cffb2a26 8486(define_insn "*arm_indirect_jump"
8487 [(set (pc)
8488 (match_operand:SI 0 "s_register_operand" "r"))]
8489 "TARGET_ARM"
8490 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8491 [(set_attr "predicable" "yes")]
cffb2a26 8492)
9c08d1fa 8493
f7fbdd4a 8494(define_insn "*load_indirect_jump"
9c08d1fa 8495 [(set (pc)
8496 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8497 "TARGET_ARM"
8498 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8499 [(set_attr "type" "load1")
61a2d04c 8500 (set_attr "pool_range" "4096")
8501 (set_attr "neg_pool_range" "4084")
0d66636f 8502 (set_attr "predicable" "yes")]
cffb2a26 8503)
8504
f1039640 8505;; NB Never uses BX.
25f905c2 8506(define_insn "*thumb1_indirect_jump"
cffb2a26 8507 [(set (pc)
8508 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8509 "TARGET_THUMB1"
cffb2a26 8510 "mov\\tpc, %0"
8511 [(set_attr "conds" "clob")
8512 (set_attr "length" "2")]
8513)
8514
9c08d1fa 8515\f
8516;; Misc insns
8517
8518(define_insn "nop"
8519 [(const_int 0)]
cffb2a26 8520 "TARGET_EITHER"
8521 "*
25f905c2 8522 if (TARGET_UNIFIED_ASM)
8523 return \"nop\";
cffb2a26 8524 if (TARGET_ARM)
8525 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8526 return \"mov\\tr8, r8\";
8527 "
8528 [(set (attr "length")
8529 (if_then_else (eq_attr "is_thumb" "yes")
8530 (const_int 2)
8531 (const_int 4)))]
8532)
8533
9c08d1fa 8534\f
8535;; Patterns to allow combination of arithmetic, cond code and shifts
8536
f7fbdd4a 8537(define_insn "*arith_shiftsi"
d5d4dc8d 8538 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8539 (match_operator:SI 1 "shiftable_operator"
8540 [(match_operator:SI 3 "shift_operator"
d5d4dc8d 8541 [(match_operand:SI 4 "s_register_operand" "r,r")
8542 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8543 (match_operand:SI 2 "s_register_operand" "rk,rk")]))]
8544 "TARGET_32BIT"
6c4c2133 8545 "%i1%?\\t%0, %2, %4%S3"
344495ea 8546 [(set_attr "predicable" "yes")
331beb1a 8547 (set_attr "shift" "4")
d5d4dc8d 8548 (set_attr "arch" "32,a")
8549 ;; We have to make sure to disable the second alternative if
8550 ;; the shift_operator is MULT, since otherwise the insn will
8551 ;; also match a multiply_accumulate pattern and validate_change
8552 ;; will allow a replacement of the constant with a register
8553 ;; despite the checks done in shift_operator.
8554 (set_attr_alternative "insn_enabled"
8555 [(const_string "yes")
8556 (if_then_else
8557 (match_operand:SI 3 "mult_operator" "")
8558 (const_string "no") (const_string "yes"))])
8559 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8560
d7863cfe 8561(define_split
8562 [(set (match_operand:SI 0 "s_register_operand" "")
8563 (match_operator:SI 1 "shiftable_operator"
8564 [(match_operator:SI 2 "shiftable_operator"
8565 [(match_operator:SI 3 "shift_operator"
8566 [(match_operand:SI 4 "s_register_operand" "")
8567 (match_operand:SI 5 "reg_or_int_operand" "")])
8568 (match_operand:SI 6 "s_register_operand" "")])
8569 (match_operand:SI 7 "arm_rhs_operand" "")]))
8570 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8571 "TARGET_32BIT"
d7863cfe 8572 [(set (match_dup 8)
8573 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8574 (match_dup 6)]))
8575 (set (match_dup 0)
8576 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8577 "")
8578
f7fbdd4a 8579(define_insn "*arith_shiftsi_compare0"
bd5b4116 8580 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8581 (compare:CC_NOOV
8582 (match_operator:SI 1 "shiftable_operator"
8583 [(match_operator:SI 3 "shift_operator"
8584 [(match_operand:SI 4 "s_register_operand" "r,r")
8585 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8586 (match_operand:SI 2 "s_register_operand" "r,r")])
8587 (const_int 0)))
8588 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8589 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8590 (match_dup 2)]))]
d5d4dc8d 8591 "TARGET_32BIT"
25f905c2 8592 "%i1%.\\t%0, %2, %4%S3"
344495ea 8593 [(set_attr "conds" "set")
331beb1a 8594 (set_attr "shift" "4")
d5d4dc8d 8595 (set_attr "arch" "32,a")
8596 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8597
f7fbdd4a 8598(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8599 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8600 (compare:CC_NOOV
8601 (match_operator:SI 1 "shiftable_operator"
8602 [(match_operator:SI 3 "shift_operator"
8603 [(match_operand:SI 4 "s_register_operand" "r,r")
8604 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8605 (match_operand:SI 2 "s_register_operand" "r,r")])
8606 (const_int 0)))
8607 (clobber (match_scratch:SI 0 "=r,r"))]
8608 "TARGET_32BIT"
25f905c2 8609 "%i1%.\\t%0, %2, %4%S3"
344495ea 8610 [(set_attr "conds" "set")
331beb1a 8611 (set_attr "shift" "4")
d5d4dc8d 8612 (set_attr "arch" "32,a")
8613 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8614
f7fbdd4a 8615(define_insn "*sub_shiftsi"
d5d4dc8d 8616 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8617 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8618 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8619 [(match_operand:SI 3 "s_register_operand" "r,r")
8620 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8621 "TARGET_32BIT"
6c4c2133 8622 "sub%?\\t%0, %1, %3%S2"
344495ea 8623 [(set_attr "predicable" "yes")
331beb1a 8624 (set_attr "shift" "3")
d5d4dc8d 8625 (set_attr "arch" "32,a")
8626 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8627
f7fbdd4a 8628(define_insn "*sub_shiftsi_compare0"
bd5b4116 8629 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8630 (compare:CC_NOOV
d5d4dc8d 8631 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8632 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8633 [(match_operand:SI 3 "s_register_operand" "r,r")
8634 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8635 (const_int 0)))
d5d4dc8d 8636 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8637 (minus:SI (match_dup 1)
8638 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8639 "TARGET_32BIT"
25f905c2 8640 "sub%.\\t%0, %1, %3%S2"
344495ea 8641 [(set_attr "conds" "set")
a2cd141b 8642 (set_attr "shift" "3")
d5d4dc8d 8643 (set_attr "arch" "32,a")
8644 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8645
f7fbdd4a 8646(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8647 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8648 (compare:CC_NOOV
d5d4dc8d 8649 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8650 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8651 [(match_operand:SI 3 "s_register_operand" "r,r")
8652 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8653 (const_int 0)))
d5d4dc8d 8654 (clobber (match_scratch:SI 0 "=r,r"))]
8655 "TARGET_32BIT"
25f905c2 8656 "sub%.\\t%0, %1, %3%S2"
344495ea 8657 [(set_attr "conds" "set")
a2cd141b 8658 (set_attr "shift" "3")
d5d4dc8d 8659 (set_attr "arch" "32,a")
8660 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8661\f
8662
f7fbdd4a 8663(define_insn "*and_scc"
9c08d1fa 8664 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8665 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8666 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8667 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8668 "TARGET_ARM"
e2348bcb 8669 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8670 [(set_attr "conds" "use")
d2a518d1 8671 (set_attr "insn" "mov")
8fa3ba89 8672 (set_attr "length" "8")]
8673)
9c08d1fa 8674
f7fbdd4a 8675(define_insn "*ior_scc"
9c08d1fa 8676 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8677 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8678 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8679 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8680 "TARGET_ARM"
e2348bcb 8681 "@
899850b0 8682 orr%d2\\t%0, %1, #1
8683 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8684 [(set_attr "conds" "use")
8685 (set_attr "length" "4,8")]
8686)
9c08d1fa 8687
2df9477b 8688; A series of splitters for the compare_scc pattern below. Note that
8689; order is important.
8690(define_split
8691 [(set (match_operand:SI 0 "s_register_operand" "")
8692 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8693 (const_int 0)))
8694 (clobber (reg:CC CC_REGNUM))]
8695 "TARGET_32BIT && reload_completed"
8696 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8697
8698(define_split
8699 [(set (match_operand:SI 0 "s_register_operand" "")
8700 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8701 (const_int 0)))
8702 (clobber (reg:CC CC_REGNUM))]
8703 "TARGET_32BIT && reload_completed"
8704 [(set (match_dup 0) (not:SI (match_dup 1)))
8705 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8706
8707(define_split
8708 [(set (match_operand:SI 0 "s_register_operand" "")
8709 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8710 (const_int 0)))
8711 (clobber (reg:CC CC_REGNUM))]
8712 "TARGET_32BIT && reload_completed"
8713 [(parallel
080c0b9a 8714 [(set (reg:CC CC_REGNUM)
8715 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8716 (set (match_dup 0)
8717 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8718 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8719 (set (match_dup 0) (const_int 0)))])
8720
8721(define_split
8722 [(set (match_operand:SI 0 "s_register_operand" "")
8723 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8724 (match_operand:SI 2 "const_int_operand" "")))
8725 (clobber (reg:CC CC_REGNUM))]
8726 "TARGET_32BIT && reload_completed"
8727 [(parallel
8728 [(set (reg:CC CC_REGNUM)
8729 (compare:CC (match_dup 1) (match_dup 2)))
8730 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8731 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8732 (set (match_dup 0) (const_int 1)))]
8733{
8734 operands[3] = GEN_INT (-INTVAL (operands[2]));
8735})
8736
8737(define_split
8738 [(set (match_operand:SI 0 "s_register_operand" "")
8739 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8740 (match_operand:SI 2 "arm_add_operand" "")))
8741 (clobber (reg:CC CC_REGNUM))]
8742 "TARGET_32BIT && reload_completed"
8743 [(parallel
8744 [(set (reg:CC_NOOV CC_REGNUM)
8745 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8746 (const_int 0)))
8747 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8748 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8749 (set (match_dup 0) (const_int 1)))])
8750
8751(define_insn_and_split "*compare_scc"
5565501b 8752 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8753 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8754 [(match_operand:SI 2 "s_register_operand" "r,r")
8755 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8756 (clobber (reg:CC CC_REGNUM))]
2df9477b 8757 "TARGET_32BIT"
8758 "#"
8759 "&& reload_completed"
8760 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8761 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8762 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8763{
8764 rtx tmp1;
8765 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8766 operands[2], operands[3]);
8767 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8768
2df9477b 8769 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8770
2df9477b 8771 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8772 if (mode == CCFPmode || mode == CCFPEmode)
8773 rc = reverse_condition_maybe_unordered (rc);
8774 else
8775 rc = reverse_condition (rc);
8776 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8777})
9c08d1fa 8778
080c0b9a 8779;; Attempt to improve the sequence generated by the compare_scc splitters
8780;; not to use conditional execution.
8781(define_peephole2
8782 [(set (reg:CC CC_REGNUM)
8783 (compare:CC (match_operand:SI 1 "register_operand" "")
8784 (match_operand:SI 2 "arm_rhs_operand" "")))
8785 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8786 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8787 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8788 (set (match_dup 0) (const_int 1)))
8789 (match_scratch:SI 3 "r")]
8790 "TARGET_32BIT"
8791 [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
8792 (parallel
8793 [(set (reg:CC CC_REGNUM)
8794 (compare:CC (const_int 0) (match_dup 3)))
8795 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8796 (set (match_dup 0)
8797 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8798 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
8799
f7fbdd4a 8800(define_insn "*cond_move"
9c08d1fa 8801 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8802 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8803 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8804 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8805 (const_int 0)])
8806 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8807 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8808 "TARGET_ARM"
9c08d1fa 8809 "*
8fa3ba89 8810 if (GET_CODE (operands[3]) == NE)
8811 {
8812 if (which_alternative != 1)
8813 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8814 if (which_alternative != 0)
8815 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8816 return \"\";
8817 }
8818 if (which_alternative != 0)
8819 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8820 if (which_alternative != 1)
8821 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8822 return \"\";
8823 "
8824 [(set_attr "conds" "use")
d2a518d1 8825 (set_attr "insn" "mov")
8fa3ba89 8826 (set_attr "length" "4,4,8")]
8827)
9c08d1fa 8828
f7fbdd4a 8829(define_insn "*cond_arith"
9c08d1fa 8830 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8831 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8832 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8833 [(match_operand:SI 2 "s_register_operand" "r,r")
8834 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8835 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8836 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8837 "TARGET_ARM"
9c08d1fa 8838 "*
8fa3ba89 8839 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8840 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8841
8fa3ba89 8842 output_asm_insn (\"cmp\\t%2, %3\", operands);
8843 if (GET_CODE (operands[5]) == AND)
8844 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8845 else if (GET_CODE (operands[5]) == MINUS)
8846 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8847 else if (which_alternative != 0)
8848 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8849 return \"%i5%d4\\t%0, %1, #1\";
8850 "
8851 [(set_attr "conds" "clob")
8852 (set_attr "length" "12")]
8853)
9c08d1fa 8854
f7fbdd4a 8855(define_insn "*cond_sub"
9c08d1fa 8856 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8857 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8858 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8859 [(match_operand:SI 2 "s_register_operand" "r,r")
8860 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8861 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8862 "TARGET_ARM"
9c08d1fa 8863 "*
8fa3ba89 8864 output_asm_insn (\"cmp\\t%2, %3\", operands);
8865 if (which_alternative != 0)
8866 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8867 return \"sub%d4\\t%0, %1, #1\";
8868 "
8869 [(set_attr "conds" "clob")
8870 (set_attr "length" "8,12")]
8871)
9c08d1fa 8872
25f905c2 8873;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 8874(define_insn "*cmp_ite0"
cffb2a26 8875 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8876 (compare
8877 (if_then_else:SI
8fa3ba89 8878 (match_operator 4 "arm_comparison_operator"
aea4c774 8879 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8880 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8881 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8882 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8883 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8884 (const_int 0))
8885 (const_int 0)))]
cffb2a26 8886 "TARGET_ARM"
9c08d1fa 8887 "*
aea4c774 8888 {
8fa3ba89 8889 static const char * const opcodes[4][2] =
8890 {
8891 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8892 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8893 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8894 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8895 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8896 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8897 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8898 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8899 };
8900 int swap =
8901 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8902
8903 return opcodes[which_alternative][swap];
8904 }"
8905 [(set_attr "conds" "set")
8906 (set_attr "length" "8")]
8907)
9c08d1fa 8908
aea4c774 8909(define_insn "*cmp_ite1"
cffb2a26 8910 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8911 (compare
8912 (if_then_else:SI
8fa3ba89 8913 (match_operator 4 "arm_comparison_operator"
aea4c774 8914 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8915 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8916 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8917 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8918 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8919 (const_int 1))
8920 (const_int 0)))]
cffb2a26 8921 "TARGET_ARM"
9c08d1fa 8922 "*
9c08d1fa 8923 {
215b30b3 8924 static const char * const opcodes[4][2] =
8925 {
8926 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8927 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8928 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8929 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8930 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8931 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8932 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8933 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8934 };
8935 int swap =
8936 comparison_dominates_p (GET_CODE (operands[5]),
8937 reverse_condition (GET_CODE (operands[4])));
8938
8939 return opcodes[which_alternative][swap];
8940 }"
8fa3ba89 8941 [(set_attr "conds" "set")
8942 (set_attr "length" "8")]
8943)
9c08d1fa 8944
f6c53574 8945(define_insn "*cmp_and"
8946 [(set (match_operand 6 "dominant_cc_register" "")
8947 (compare
8948 (and:SI
8949 (match_operator 4 "arm_comparison_operator"
8950 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8951 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8952 (match_operator:SI 5 "arm_comparison_operator"
8953 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8954 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8955 (const_int 0)))]
8956 "TARGET_ARM"
8957 "*
8958 {
35823b64 8959 static const char *const opcodes[4][2] =
f6c53574 8960 {
8961 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8962 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8963 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8964 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8965 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8966 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8967 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8968 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8969 };
8970 int swap =
8971 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8972
8973 return opcodes[which_alternative][swap];
8974 }"
8975 [(set_attr "conds" "set")
8976 (set_attr "predicable" "no")
8977 (set_attr "length" "8")]
8978)
8979
8980(define_insn "*cmp_ior"
8981 [(set (match_operand 6 "dominant_cc_register" "")
8982 (compare
8983 (ior:SI
8984 (match_operator 4 "arm_comparison_operator"
8985 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8986 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8987 (match_operator:SI 5 "arm_comparison_operator"
8988 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8989 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8990 (const_int 0)))]
8991 "TARGET_ARM"
8992 "*
8993{
35823b64 8994 static const char *const opcodes[4][2] =
f6c53574 8995 {
8996 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8997 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8998 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8999 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9000 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9001 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9002 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9003 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9004 };
9005 int swap =
9006 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9007
9008 return opcodes[which_alternative][swap];
9009}
9010"
9011 [(set_attr "conds" "set")
9012 (set_attr "length" "8")]
9013)
9014
3c5afce6 9015(define_insn_and_split "*ior_scc_scc"
9016 [(set (match_operand:SI 0 "s_register_operand" "=r")
9017 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9018 [(match_operand:SI 1 "s_register_operand" "r")
9019 (match_operand:SI 2 "arm_add_operand" "rIL")])
9020 (match_operator:SI 6 "arm_comparison_operator"
9021 [(match_operand:SI 4 "s_register_operand" "r")
9022 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9023 (clobber (reg:CC CC_REGNUM))]
9024 "TARGET_ARM
9025 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9026 != CCmode)"
9027 "#"
9028 "TARGET_ARM && reload_completed"
9029 [(set (match_dup 7)
9030 (compare
9031 (ior:SI
9032 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9033 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9034 (const_int 0)))
9035 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9036 "operands[7]
9037 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9038 DOM_CC_X_OR_Y),
601f584c 9039 CC_REGNUM);"
9040 [(set_attr "conds" "clob")
9041 (set_attr "length" "16")])
9042
9043; If the above pattern is followed by a CMP insn, then the compare is
9044; redundant, since we can rework the conditional instruction that follows.
9045(define_insn_and_split "*ior_scc_scc_cmp"
9046 [(set (match_operand 0 "dominant_cc_register" "")
9047 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9048 [(match_operand:SI 1 "s_register_operand" "r")
9049 (match_operand:SI 2 "arm_add_operand" "rIL")])
9050 (match_operator:SI 6 "arm_comparison_operator"
9051 [(match_operand:SI 4 "s_register_operand" "r")
9052 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9053 (const_int 0)))
9054 (set (match_operand:SI 7 "s_register_operand" "=r")
9055 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9056 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9057 "TARGET_ARM"
9058 "#"
9059 "TARGET_ARM && reload_completed"
9060 [(set (match_dup 0)
9061 (compare
9062 (ior:SI
9063 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9064 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9065 (const_int 0)))
9066 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9067 ""
9068 [(set_attr "conds" "set")
9069 (set_attr "length" "16")])
3c5afce6 9070
9071(define_insn_and_split "*and_scc_scc"
9072 [(set (match_operand:SI 0 "s_register_operand" "=r")
9073 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9074 [(match_operand:SI 1 "s_register_operand" "r")
9075 (match_operand:SI 2 "arm_add_operand" "rIL")])
9076 (match_operator:SI 6 "arm_comparison_operator"
9077 [(match_operand:SI 4 "s_register_operand" "r")
9078 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9079 (clobber (reg:CC CC_REGNUM))]
9080 "TARGET_ARM
9081 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9082 != CCmode)"
9083 "#"
601f584c 9084 "TARGET_ARM && reload_completed
9085 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9086 != CCmode)"
3c5afce6 9087 [(set (match_dup 7)
9088 (compare
9089 (and:SI
9090 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9091 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9092 (const_int 0)))
9093 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9094 "operands[7]
9095 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9096 DOM_CC_X_AND_Y),
601f584c 9097 CC_REGNUM);"
9098 [(set_attr "conds" "clob")
9099 (set_attr "length" "16")])
9100
9101; If the above pattern is followed by a CMP insn, then the compare is
9102; redundant, since we can rework the conditional instruction that follows.
9103(define_insn_and_split "*and_scc_scc_cmp"
9104 [(set (match_operand 0 "dominant_cc_register" "")
9105 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9106 [(match_operand:SI 1 "s_register_operand" "r")
9107 (match_operand:SI 2 "arm_add_operand" "rIL")])
9108 (match_operator:SI 6 "arm_comparison_operator"
9109 [(match_operand:SI 4 "s_register_operand" "r")
9110 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9111 (const_int 0)))
9112 (set (match_operand:SI 7 "s_register_operand" "=r")
9113 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9114 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9115 "TARGET_ARM"
9116 "#"
9117 "TARGET_ARM && reload_completed"
9118 [(set (match_dup 0)
9119 (compare
9120 (and:SI
9121 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9122 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9123 (const_int 0)))
9124 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9125 ""
9126 [(set_attr "conds" "set")
9127 (set_attr "length" "16")])
9128
9129;; If there is no dominance in the comparison, then we can still save an
9130;; instruction in the AND case, since we can know that the second compare
9131;; need only zero the value if false (if true, then the value is already
9132;; correct).
9133(define_insn_and_split "*and_scc_scc_nodom"
9134 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9135 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9136 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9137 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9138 (match_operator:SI 6 "arm_comparison_operator"
9139 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9140 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9141 (clobber (reg:CC CC_REGNUM))]
9142 "TARGET_ARM
9143 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9144 == CCmode)"
9145 "#"
9146 "TARGET_ARM && reload_completed"
9147 [(parallel [(set (match_dup 0)
9148 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9149 (clobber (reg:CC CC_REGNUM))])
9150 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9151 (set (match_dup 0)
9152 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9153 (match_dup 0)
9154 (const_int 0)))]
9155 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9156 operands[4], operands[5]),
9157 CC_REGNUM);
9158 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9159 operands[5]);"
9160 [(set_attr "conds" "clob")
9161 (set_attr "length" "20")])
3c5afce6 9162
3a0bdee0 9163(define_split
9164 [(set (reg:CC_NOOV CC_REGNUM)
9165 (compare:CC_NOOV (ior:SI
9166 (and:SI (match_operand:SI 0 "s_register_operand" "")
9167 (const_int 1))
b0694be0 9168 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9169 [(match_operand:SI 2 "s_register_operand" "")
9170 (match_operand:SI 3 "arm_add_operand" "")]))
9171 (const_int 0)))
9172 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9173 "TARGET_ARM"
9174 [(set (match_dup 4)
9175 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9176 (match_dup 0)))
9177 (set (reg:CC_NOOV CC_REGNUM)
9178 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9179 (const_int 0)))]
9180 "")
9181
9182(define_split
9183 [(set (reg:CC_NOOV CC_REGNUM)
9184 (compare:CC_NOOV (ior:SI
b0694be0 9185 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9186 [(match_operand:SI 2 "s_register_operand" "")
9187 (match_operand:SI 3 "arm_add_operand" "")])
9188 (and:SI (match_operand:SI 0 "s_register_operand" "")
9189 (const_int 1)))
9190 (const_int 0)))
9191 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9192 "TARGET_ARM"
9193 [(set (match_dup 4)
9194 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9195 (match_dup 0)))
9196 (set (reg:CC_NOOV CC_REGNUM)
9197 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9198 (const_int 0)))]
9199 "")
25f905c2 9200;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9201
f7fbdd4a 9202(define_insn "*negscc"
9c08d1fa 9203 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9204 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9205 [(match_operand:SI 1 "s_register_operand" "r")
9206 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9207 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9208 "TARGET_ARM"
9c08d1fa 9209 "*
2ca2ec2e 9210 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9211 return \"mov\\t%0, %1, asr #31\";
9212
9c08d1fa 9213 if (GET_CODE (operands[3]) == NE)
e2348bcb 9214 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9215
e2348bcb 9216 output_asm_insn (\"cmp\\t%1, %2\", operands);
9217 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9218 return \"mvn%d3\\t%0, #0\";
215b30b3 9219 "
8fa3ba89 9220 [(set_attr "conds" "clob")
9221 (set_attr "length" "12")]
9222)
9c08d1fa 9223
9224(define_insn "movcond"
9225 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9226 (if_then_else:SI
8fa3ba89 9227 (match_operator 5 "arm_comparison_operator"
5565501b 9228 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9229 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9230 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9231 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9232 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9233 "TARGET_ARM"
9c08d1fa 9234 "*
9235 if (GET_CODE (operands[5]) == LT
9236 && (operands[4] == const0_rtx))
9237 {
5565501b 9238 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9239 {
9c08d1fa 9240 if (operands[2] == const0_rtx)
e2348bcb 9241 return \"and\\t%0, %1, %3, asr #31\";
9242 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9243 }
9244 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9245 {
9c08d1fa 9246 if (operands[1] == const0_rtx)
e2348bcb 9247 return \"bic\\t%0, %2, %3, asr #31\";
9248 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9249 }
9250 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9251 are constants. */
9c08d1fa 9252 }
e2348bcb 9253
9c08d1fa 9254 if (GET_CODE (operands[5]) == GE
9255 && (operands[4] == const0_rtx))
9256 {
9257 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9258 {
9c08d1fa 9259 if (operands[2] == const0_rtx)
e2348bcb 9260 return \"bic\\t%0, %1, %3, asr #31\";
9261 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9262 }
9263 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9264 {
9c08d1fa 9265 if (operands[1] == const0_rtx)
e2348bcb 9266 return \"and\\t%0, %2, %3, asr #31\";
9267 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9268 }
9269 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9270 are constants. */
9c08d1fa 9271 }
9272 if (GET_CODE (operands[4]) == CONST_INT
9273 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9274 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9275 else
e2348bcb 9276 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9277 if (which_alternative != 0)
e2348bcb 9278 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9279 if (which_alternative != 1)
e2348bcb 9280 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9281 return \"\";
215b30b3 9282 "
8fa3ba89 9283 [(set_attr "conds" "clob")
9284 (set_attr "length" "8,8,12")]
9285)
9c08d1fa 9286
25f905c2 9287;; ??? The patterns below need checking for Thumb-2 usefulness.
9288
8a18b90c 9289(define_insn "*ifcompare_plus_move"
9290 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9291 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9292 [(match_operand:SI 4 "s_register_operand" "r,r")
9293 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9294 (plus:SI
9295 (match_operand:SI 2 "s_register_operand" "r,r")
9296 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9297 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9298 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9299 "TARGET_ARM"
8a18b90c 9300 "#"
8fa3ba89 9301 [(set_attr "conds" "clob")
9302 (set_attr "length" "8,12")]
9303)
8a18b90c 9304
9305(define_insn "*if_plus_move"
129a2fe4 9306 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9307 (if_then_else:SI
8fa3ba89 9308 (match_operator 4 "arm_comparison_operator"
8a18b90c 9309 [(match_operand 5 "cc_register" "") (const_int 0)])
9310 (plus:SI
129a2fe4 9311 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9312 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9313 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9314 "TARGET_ARM"
8a18b90c 9315 "@
9316 add%d4\\t%0, %2, %3
9317 sub%d4\\t%0, %2, #%n3
9318 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9319 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9320 [(set_attr "conds" "use")
9321 (set_attr "length" "4,4,8,8")
9322 (set_attr "type" "*,*,*,*")]
9323)
8a18b90c 9324
9325(define_insn "*ifcompare_move_plus"
5565501b 9326 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9327 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9328 [(match_operand:SI 4 "s_register_operand" "r,r")
9329 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9330 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9331 (plus:SI
9332 (match_operand:SI 2 "s_register_operand" "r,r")
9333 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9334 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9335 "TARGET_ARM"
8a18b90c 9336 "#"
8fa3ba89 9337 [(set_attr "conds" "clob")
9338 (set_attr "length" "8,12")]
9339)
8a18b90c 9340
9341(define_insn "*if_move_plus"
129a2fe4 9342 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9343 (if_then_else:SI
8fa3ba89 9344 (match_operator 4 "arm_comparison_operator"
8a18b90c 9345 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9346 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9347 (plus:SI
129a2fe4 9348 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9349 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9350 "TARGET_ARM"
8a18b90c 9351 "@
9352 add%D4\\t%0, %2, %3
9353 sub%D4\\t%0, %2, #%n3
9354 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9355 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9356 [(set_attr "conds" "use")
9357 (set_attr "length" "4,4,8,8")
9358 (set_attr "type" "*,*,*,*")]
9359)
8a18b90c 9360
9361(define_insn "*ifcompare_arith_arith"
9362 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9363 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9364 [(match_operand:SI 5 "s_register_operand" "r")
9365 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9366 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9367 [(match_operand:SI 1 "s_register_operand" "r")
9368 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9369 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9370 [(match_operand:SI 3 "s_register_operand" "r")
9371 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9372 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9373 "TARGET_ARM"
8a18b90c 9374 "#"
8fa3ba89 9375 [(set_attr "conds" "clob")
9376 (set_attr "length" "12")]
9377)
9c08d1fa 9378
8a18b90c 9379(define_insn "*if_arith_arith"
9380 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9381 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9382 [(match_operand 8 "cc_register" "") (const_int 0)])
9383 (match_operator:SI 6 "shiftable_operator"
9384 [(match_operand:SI 1 "s_register_operand" "r")
9385 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9386 (match_operator:SI 7 "shiftable_operator"
9387 [(match_operand:SI 3 "s_register_operand" "r")
9388 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9389 "TARGET_ARM"
8a18b90c 9390 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9391 [(set_attr "conds" "use")
9392 (set_attr "length" "8")]
9393)
8a18b90c 9394
f7fbdd4a 9395(define_insn "*ifcompare_arith_move"
9c08d1fa 9396 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9397 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9398 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9399 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9400 (match_operator:SI 7 "shiftable_operator"
9401 [(match_operand:SI 4 "s_register_operand" "r,r")
9402 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9403 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9404 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9405 "TARGET_ARM"
9c08d1fa 9406 "*
9c08d1fa 9407 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9408 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9409 everything is in registers then we can do this in two instructions. */
9c08d1fa 9410 if (operands[3] == const0_rtx
9411 && GET_CODE (operands[7]) != AND
9412 && GET_CODE (operands[5]) == REG
9413 && GET_CODE (operands[1]) == REG
9414 && REGNO (operands[1]) == REGNO (operands[4])
9415 && REGNO (operands[4]) != REGNO (operands[0]))
9416 {
9417 if (GET_CODE (operands[6]) == LT)
40dbec34 9418 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9419 else if (GET_CODE (operands[6]) == GE)
40dbec34 9420 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9421 }
9422 if (GET_CODE (operands[3]) == CONST_INT
9423 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9424 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9425 else
e2348bcb 9426 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9427 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9428 if (which_alternative != 0)
129a2fe4 9429 return \"mov%D6\\t%0, %1\";
9c08d1fa 9430 return \"\";
215b30b3 9431 "
8fa3ba89 9432 [(set_attr "conds" "clob")
9433 (set_attr "length" "8,12")]
9434)
9c08d1fa 9435
8a18b90c 9436(define_insn "*if_arith_move"
129a2fe4 9437 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9438 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9439 [(match_operand 6 "cc_register" "") (const_int 0)])
9440 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9441 [(match_operand:SI 2 "s_register_operand" "r,r")
9442 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9443 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9444 "TARGET_ARM"
8a18b90c 9445 "@
9446 %I5%d4\\t%0, %2, %3
129a2fe4 9447 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9448 [(set_attr "conds" "use")
9449 (set_attr "length" "4,8")
9450 (set_attr "type" "*,*")]
9451)
8a18b90c 9452
f7fbdd4a 9453(define_insn "*ifcompare_move_arith"
9c08d1fa 9454 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9455 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9456 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9457 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9458 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9459 (match_operator:SI 7 "shiftable_operator"
9460 [(match_operand:SI 2 "s_register_operand" "r,r")
9461 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9462 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9463 "TARGET_ARM"
9c08d1fa 9464 "*
9c08d1fa 9465 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9466 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9467 everything is in registers then we can do this in two instructions */
9468 if (operands[5] == const0_rtx
9469 && GET_CODE (operands[7]) != AND
9470 && GET_CODE (operands[3]) == REG
9471 && GET_CODE (operands[1]) == REG
9472 && REGNO (operands[1]) == REGNO (operands[2])
9473 && REGNO (operands[2]) != REGNO (operands[0]))
9474 {
9475 if (GET_CODE (operands[6]) == GE)
40dbec34 9476 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9477 else if (GET_CODE (operands[6]) == LT)
40dbec34 9478 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9479 }
40dbec34 9480
9c08d1fa 9481 if (GET_CODE (operands[5]) == CONST_INT
9482 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9483 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9484 else
e2348bcb 9485 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9486
9c08d1fa 9487 if (which_alternative != 0)
129a2fe4 9488 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9489 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9490 "
8fa3ba89 9491 [(set_attr "conds" "clob")
9492 (set_attr "length" "8,12")]
9493)
9c08d1fa 9494
8a18b90c 9495(define_insn "*if_move_arith"
129a2fe4 9496 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9497 (if_then_else:SI
8fa3ba89 9498 (match_operator 4 "arm_comparison_operator"
8a18b90c 9499 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9500 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9501 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9502 [(match_operand:SI 2 "s_register_operand" "r,r")
9503 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9504 "TARGET_ARM"
8a18b90c 9505 "@
9506 %I5%D4\\t%0, %2, %3
129a2fe4 9507 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9508 [(set_attr "conds" "use")
9509 (set_attr "length" "4,8")
9510 (set_attr "type" "*,*")]
9511)
8a18b90c 9512
9513(define_insn "*ifcompare_move_not"
9c08d1fa 9514 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9515 (if_then_else:SI
8fa3ba89 9516 (match_operator 5 "arm_comparison_operator"
8a18b90c 9517 [(match_operand:SI 3 "s_register_operand" "r,r")
9518 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9519 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9520 (not:SI
9521 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9522 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9523 "TARGET_ARM"
8a18b90c 9524 "#"
8fa3ba89 9525 [(set_attr "conds" "clob")
9526 (set_attr "length" "8,12")]
9527)
9c08d1fa 9528
8a18b90c 9529(define_insn "*if_move_not"
9530 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9531 (if_then_else:SI
8fa3ba89 9532 (match_operator 4 "arm_comparison_operator"
8a18b90c 9533 [(match_operand 3 "cc_register" "") (const_int 0)])
9534 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9535 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9536 "TARGET_ARM"
8a18b90c 9537 "@
9538 mvn%D4\\t%0, %2
9539 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9540 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9541 [(set_attr "conds" "use")
d2a518d1 9542 (set_attr "insn" "mvn")
8fa3ba89 9543 (set_attr "length" "4,8,8")]
9544)
8a18b90c 9545
9546(define_insn "*ifcompare_not_move"
9c08d1fa 9547 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9548 (if_then_else:SI
8fa3ba89 9549 (match_operator 5 "arm_comparison_operator"
8a18b90c 9550 [(match_operand:SI 3 "s_register_operand" "r,r")
9551 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9552 (not:SI
9553 (match_operand:SI 2 "s_register_operand" "r,r"))
9554 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9555 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9556 "TARGET_ARM"
8a18b90c 9557 "#"
8fa3ba89 9558 [(set_attr "conds" "clob")
9559 (set_attr "length" "8,12")]
9560)
9c08d1fa 9561
8a18b90c 9562(define_insn "*if_not_move"
9563 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9564 (if_then_else:SI
8fa3ba89 9565 (match_operator 4 "arm_comparison_operator"
8a18b90c 9566 [(match_operand 3 "cc_register" "") (const_int 0)])
9567 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9568 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9569 "TARGET_ARM"
8a18b90c 9570 "@
9571 mvn%d4\\t%0, %2
9572 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9573 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9574 [(set_attr "conds" "use")
d2a518d1 9575 (set_attr "insn" "mvn")
8fa3ba89 9576 (set_attr "length" "4,8,8")]
9577)
8a18b90c 9578
9579(define_insn "*ifcompare_shift_move"
9c08d1fa 9580 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9581 (if_then_else:SI
8fa3ba89 9582 (match_operator 6 "arm_comparison_operator"
8a18b90c 9583 [(match_operand:SI 4 "s_register_operand" "r,r")
9584 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9585 (match_operator:SI 7 "shift_operator"
9586 [(match_operand:SI 2 "s_register_operand" "r,r")
9587 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9588 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9589 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9590 "TARGET_ARM"
9c08d1fa 9591 "#"
8fa3ba89 9592 [(set_attr "conds" "clob")
9593 (set_attr "length" "8,12")]
9594)
9c08d1fa 9595
8a18b90c 9596(define_insn "*if_shift_move"
9597 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9598 (if_then_else:SI
8fa3ba89 9599 (match_operator 5 "arm_comparison_operator"
8a18b90c 9600 [(match_operand 6 "cc_register" "") (const_int 0)])
9601 (match_operator:SI 4 "shift_operator"
9602 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9603 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9604 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9605 "TARGET_ARM"
5565501b 9606 "@
8a18b90c 9607 mov%d5\\t%0, %2%S4
9608 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9609 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9610 [(set_attr "conds" "use")
331beb1a 9611 (set_attr "shift" "2")
a2cd141b 9612 (set_attr "length" "4,8,8")
d2a518d1 9613 (set_attr "insn" "mov")
a2cd141b 9614 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9615 (const_string "alu_shift")
9616 (const_string "alu_shift_reg")))]
8fa3ba89 9617)
5565501b 9618
8a18b90c 9619(define_insn "*ifcompare_move_shift"
9620 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9621 (if_then_else:SI
8fa3ba89 9622 (match_operator 6 "arm_comparison_operator"
8a18b90c 9623 [(match_operand:SI 4 "s_register_operand" "r,r")
9624 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9625 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9626 (match_operator:SI 7 "shift_operator"
8a18b90c 9627 [(match_operand:SI 2 "s_register_operand" "r,r")
9628 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9629 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9630 "TARGET_ARM"
8a18b90c 9631 "#"
8fa3ba89 9632 [(set_attr "conds" "clob")
9633 (set_attr "length" "8,12")]
9634)
5565501b 9635
8a18b90c 9636(define_insn "*if_move_shift"
9637 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9638 (if_then_else:SI
8fa3ba89 9639 (match_operator 5 "arm_comparison_operator"
8a18b90c 9640 [(match_operand 6 "cc_register" "") (const_int 0)])
9641 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9642 (match_operator:SI 4 "shift_operator"
9643 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9644 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9645 "TARGET_ARM"
5565501b 9646 "@
8a18b90c 9647 mov%D5\\t%0, %2%S4
9648 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9649 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9650 [(set_attr "conds" "use")
331beb1a 9651 (set_attr "shift" "2")
a2cd141b 9652 (set_attr "length" "4,8,8")
d2a518d1 9653 (set_attr "insn" "mov")
a2cd141b 9654 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9655 (const_string "alu_shift")
9656 (const_string "alu_shift_reg")))]
8fa3ba89 9657)
9c08d1fa 9658
f7fbdd4a 9659(define_insn "*ifcompare_shift_shift"
8a18b90c 9660 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9661 (if_then_else:SI
8fa3ba89 9662 (match_operator 7 "arm_comparison_operator"
8a18b90c 9663 [(match_operand:SI 5 "s_register_operand" "r")
9664 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9665 (match_operator:SI 8 "shift_operator"
8a18b90c 9666 [(match_operand:SI 1 "s_register_operand" "r")
9667 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9668 (match_operator:SI 9 "shift_operator"
8a18b90c 9669 [(match_operand:SI 3 "s_register_operand" "r")
9670 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9671 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9672 "TARGET_ARM"
8a18b90c 9673 "#"
8fa3ba89 9674 [(set_attr "conds" "clob")
9675 (set_attr "length" "12")]
9676)
9c08d1fa 9677
8a18b90c 9678(define_insn "*if_shift_shift"
9679 [(set (match_operand:SI 0 "s_register_operand" "=r")
9680 (if_then_else:SI
8fa3ba89 9681 (match_operator 5 "arm_comparison_operator"
8a18b90c 9682 [(match_operand 8 "cc_register" "") (const_int 0)])
9683 (match_operator:SI 6 "shift_operator"
9684 [(match_operand:SI 1 "s_register_operand" "r")
9685 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9686 (match_operator:SI 7 "shift_operator"
9687 [(match_operand:SI 3 "s_register_operand" "r")
9688 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9689 "TARGET_ARM"
8a18b90c 9690 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9691 [(set_attr "conds" "use")
331beb1a 9692 (set_attr "shift" "1")
a2cd141b 9693 (set_attr "length" "8")
d2a518d1 9694 (set_attr "insn" "mov")
a2cd141b 9695 (set (attr "type") (if_then_else
9696 (and (match_operand 2 "const_int_operand" "")
9697 (match_operand 4 "const_int_operand" ""))
9698 (const_string "alu_shift")
9699 (const_string "alu_shift_reg")))]
8fa3ba89 9700)
8a18b90c 9701
f7fbdd4a 9702(define_insn "*ifcompare_not_arith"
8a18b90c 9703 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9704 (if_then_else:SI
8fa3ba89 9705 (match_operator 6 "arm_comparison_operator"
8a18b90c 9706 [(match_operand:SI 4 "s_register_operand" "r")
9707 (match_operand:SI 5 "arm_add_operand" "rIL")])
9708 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9709 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9710 [(match_operand:SI 2 "s_register_operand" "r")
9711 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9712 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9713 "TARGET_ARM"
8a18b90c 9714 "#"
8fa3ba89 9715 [(set_attr "conds" "clob")
9716 (set_attr "length" "12")]
9717)
9c08d1fa 9718
8a18b90c 9719(define_insn "*if_not_arith"
9720 [(set (match_operand:SI 0 "s_register_operand" "=r")
9721 (if_then_else:SI
8fa3ba89 9722 (match_operator 5 "arm_comparison_operator"
8a18b90c 9723 [(match_operand 4 "cc_register" "") (const_int 0)])
9724 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9725 (match_operator:SI 6 "shiftable_operator"
9726 [(match_operand:SI 2 "s_register_operand" "r")
9727 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9728 "TARGET_ARM"
8a18b90c 9729 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9730 [(set_attr "conds" "use")
d2a518d1 9731 (set_attr "insn" "mvn")
8fa3ba89 9732 (set_attr "length" "8")]
9733)
8a18b90c 9734
9735(define_insn "*ifcompare_arith_not"
9736 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9737 (if_then_else:SI
8fa3ba89 9738 (match_operator 6 "arm_comparison_operator"
8a18b90c 9739 [(match_operand:SI 4 "s_register_operand" "r")
9740 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9741 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9742 [(match_operand:SI 2 "s_register_operand" "r")
9743 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9744 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9745 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9746 "TARGET_ARM"
8a18b90c 9747 "#"
8fa3ba89 9748 [(set_attr "conds" "clob")
9749 (set_attr "length" "12")]
9750)
9c08d1fa 9751
8a18b90c 9752(define_insn "*if_arith_not"
9753 [(set (match_operand:SI 0 "s_register_operand" "=r")
9754 (if_then_else:SI
8fa3ba89 9755 (match_operator 5 "arm_comparison_operator"
8a18b90c 9756 [(match_operand 4 "cc_register" "") (const_int 0)])
9757 (match_operator:SI 6 "shiftable_operator"
9758 [(match_operand:SI 2 "s_register_operand" "r")
9759 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9760 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9761 "TARGET_ARM"
8a18b90c 9762 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9763 [(set_attr "conds" "use")
d2a518d1 9764 (set_attr "insn" "mvn")
8fa3ba89 9765 (set_attr "length" "8")]
9766)
8a18b90c 9767
f7fbdd4a 9768(define_insn "*ifcompare_neg_move"
8a18b90c 9769 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9770 (if_then_else:SI
8fa3ba89 9771 (match_operator 5 "arm_comparison_operator"
8a18b90c 9772 [(match_operand:SI 3 "s_register_operand" "r,r")
9773 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9774 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9775 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9776 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9777 "TARGET_ARM"
8a18b90c 9778 "#"
8fa3ba89 9779 [(set_attr "conds" "clob")
9780 (set_attr "length" "8,12")]
9781)
8a18b90c 9782
9783(define_insn "*if_neg_move"
9784 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9785 (if_then_else:SI
8fa3ba89 9786 (match_operator 4 "arm_comparison_operator"
8a18b90c 9787 [(match_operand 3 "cc_register" "") (const_int 0)])
9788 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9789 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9790 "TARGET_ARM"
8a18b90c 9791 "@
9792 rsb%d4\\t%0, %2, #0
9793 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9794 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9795 [(set_attr "conds" "use")
9796 (set_attr "length" "4,8,8")]
9797)
9c08d1fa 9798
f7fbdd4a 9799(define_insn "*ifcompare_move_neg"
8a18b90c 9800 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9801 (if_then_else:SI
8fa3ba89 9802 (match_operator 5 "arm_comparison_operator"
8a18b90c 9803 [(match_operand:SI 3 "s_register_operand" "r,r")
9804 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9805 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9806 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9807 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9808 "TARGET_ARM"
8a18b90c 9809 "#"
8fa3ba89 9810 [(set_attr "conds" "clob")
9811 (set_attr "length" "8,12")]
9812)
8a18b90c 9813
9814(define_insn "*if_move_neg"
9815 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9816 (if_then_else:SI
8fa3ba89 9817 (match_operator 4 "arm_comparison_operator"
8a18b90c 9818 [(match_operand 3 "cc_register" "") (const_int 0)])
9819 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9820 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9821 "TARGET_ARM"
8a18b90c 9822 "@
9823 rsb%D4\\t%0, %2, #0
9824 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9825 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9826 [(set_attr "conds" "use")
9827 (set_attr "length" "4,8,8")]
9828)
9c08d1fa 9829
f7fbdd4a 9830(define_insn "*arith_adjacentmem"
9c08d1fa 9831 [(set (match_operand:SI 0 "s_register_operand" "=r")
9832 (match_operator:SI 1 "shiftable_operator"
9833 [(match_operand:SI 2 "memory_operand" "m")
9834 (match_operand:SI 3 "memory_operand" "m")]))
9835 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9836 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9837 "*
215b30b3 9838 {
9839 rtx ldm[3];
9840 rtx arith[4];
94dee231 9841 rtx base_reg;
9842 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9843
215b30b3 9844 if (REGNO (operands[0]) > REGNO (operands[4]))
9845 {
9846 ldm[1] = operands[4];
9847 ldm[2] = operands[0];
9848 }
9849 else
9850 {
9851 ldm[1] = operands[0];
9852 ldm[2] = operands[4];
9853 }
94dee231 9854
9855 base_reg = XEXP (operands[2], 0);
9856
9857 if (!REG_P (base_reg))
9858 {
9859 val1 = INTVAL (XEXP (base_reg, 1));
9860 base_reg = XEXP (base_reg, 0);
9861 }
9862
9863 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9864 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9865
215b30b3 9866 arith[0] = operands[0];
9867 arith[3] = operands[1];
94dee231 9868
215b30b3 9869 if (val1 < val2)
9870 {
9871 arith[1] = ldm[1];
9872 arith[2] = ldm[2];
9873 }
9874 else
9875 {
9876 arith[1] = ldm[2];
9877 arith[2] = ldm[1];
9878 }
94dee231 9879
9880 ldm[0] = base_reg;
9881 if (val1 !=0 && val2 != 0)
215b30b3 9882 {
cdb1295a 9883 rtx ops[3];
9884
94dee231 9885 if (val1 == 4 || val2 == 4)
9886 /* Other val must be 8, since we know they are adjacent and neither
9887 is zero. */
25f905c2 9888 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 9889 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 9890 {
94dee231 9891 ldm[0] = ops[0] = operands[4];
9892 ops[1] = base_reg;
9893 ops[2] = GEN_INT (val1);
9894 output_add_immediate (ops);
9895 if (val1 < val2)
25f905c2 9896 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 9897 else
25f905c2 9898 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 9899 }
cdb1295a 9900 else
9901 {
9902 /* Offset is out of range for a single add, so use two ldr. */
9903 ops[0] = ldm[1];
9904 ops[1] = base_reg;
9905 ops[2] = GEN_INT (val1);
9906 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9907 ops[0] = ldm[2];
9908 ops[2] = GEN_INT (val2);
9909 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9910 }
215b30b3 9911 }
94dee231 9912 else if (val1 != 0)
215b30b3 9913 {
215b30b3 9914 if (val1 < val2)
25f905c2 9915 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9916 else
25f905c2 9917 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9918 }
9919 else
9920 {
215b30b3 9921 if (val1 < val2)
25f905c2 9922 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9923 else
25f905c2 9924 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9925 }
9926 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9927 return \"\";
9928 }"
9929 [(set_attr "length" "12")
9930 (set_attr "predicable" "yes")
a2cd141b 9931 (set_attr "type" "load1")]
215b30b3 9932)
9c08d1fa 9933
9c08d1fa 9934; This pattern is never tried by combine, so do it as a peephole
9935
a0f94409 9936(define_peephole2
372575c7 9937 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9938 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9939 (set (reg:CC CC_REGNUM)
aea4c774 9940 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9941 "TARGET_ARM"
a0f94409 9942 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9943 (set (match_dup 0) (match_dup 1))])]
9944 ""
0d66636f 9945)
9c08d1fa 9946
9c08d1fa 9947(define_split
9948 [(set (match_operand:SI 0 "s_register_operand" "")
9949 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9950 (const_int 0))
8fa3ba89 9951 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9952 [(match_operand:SI 3 "s_register_operand" "")
9953 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9954 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9955 "TARGET_ARM"
9c08d1fa 9956 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9957 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9958 (match_dup 5)))]
215b30b3 9959 ""
9960)
9c08d1fa 9961
aea4c774 9962;; This split can be used because CC_Z mode implies that the following
9963;; branch will be an equality, or an unsigned inequality, so the sign
9964;; extension is not needed.
9c08d1fa 9965
aea4c774 9966(define_split
bd5b4116 9967 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9968 (compare:CC_Z
9969 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9970 (const_int 24))
aea4c774 9971 (match_operand 1 "const_int_operand" "")))
9972 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9973 "TARGET_ARM
9974 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9975 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9976 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9977 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9978 "
9c08d1fa 9979 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9980 "
9981)
25f905c2 9982;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 9983
87b22bf7 9984(define_expand "prologue"
9985 [(clobber (const_int 0))]
cffb2a26 9986 "TARGET_EITHER"
25f905c2 9987 "if (TARGET_32BIT)
cffb2a26 9988 arm_expand_prologue ();
9989 else
25f905c2 9990 thumb1_expand_prologue ();
87b22bf7 9991 DONE;
cffb2a26 9992 "
9993)
87b22bf7 9994
56d27660 9995(define_expand "epilogue"
4c44712e 9996 [(clobber (const_int 0))]
cffb2a26 9997 "TARGET_EITHER"
56d27660 9998 "
18d50ae6 9999 if (crtl->calls_eh_return)
4c44712e 10000 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10001 if (TARGET_THUMB1)
10002 thumb1_expand_epilogue ();
cffb2a26 10003 else if (USE_RETURN_INSN (FALSE))
56d27660 10004 {
10005 emit_jump_insn (gen_return ());
10006 DONE;
10007 }
cffb2a26 10008 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
1a860023 10009 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
cffb2a26 10010 DONE;
10011 "
10012)
56d27660 10013
ef5651d0 10014;; Note - although unspec_volatile's USE all hard registers,
10015;; USEs are ignored after relaod has completed. Thus we need
10016;; to add an unspec of the link register to ensure that flow
10017;; does not think that it is unused by the sibcall branch that
10018;; will replace the standard function epilogue.
1c494086 10019(define_insn "sibcall_epilogue"
ef5651d0 10020 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10021 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10022 "TARGET_32BIT"
1c494086 10023 "*
ffc9d00c 10024 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10025 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10026 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10027 "
10028;; Length is absolute worst case
10029 [(set_attr "length" "44")
defc47cf 10030 (set_attr "type" "block")
10031 ;; We don't clobber the conditions, but the potential length of this
10032 ;; operation is sufficient to make conditionalizing the sequence
10033 ;; unlikely to be profitable.
10034 (set_attr "conds" "clob")]
1c494086 10035)
10036
cffb2a26 10037(define_insn "*epilogue_insns"
e1159bbe 10038 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10039 "TARGET_EITHER"
56d27660 10040 "*
25f905c2 10041 if (TARGET_32BIT)
ffc9d00c 10042 return arm_output_epilogue (NULL);
25f905c2 10043 else /* TARGET_THUMB1 */
cffb2a26 10044 return thumb_unexpanded_epilogue ();
10045 "
215b30b3 10046 ; Length is absolute worst case
cffb2a26 10047 [(set_attr "length" "44")
defc47cf 10048 (set_attr "type" "block")
10049 ;; We don't clobber the conditions, but the potential length of this
10050 ;; operation is sufficient to make conditionalizing the sequence
10051 ;; unlikely to be profitable.
10052 (set_attr "conds" "clob")]
cffb2a26 10053)
10054
10055(define_expand "eh_epilogue"
7db9af5d 10056 [(use (match_operand:SI 0 "register_operand" ""))
10057 (use (match_operand:SI 1 "register_operand" ""))
10058 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10059 "TARGET_EITHER"
10060 "
215b30b3 10061 {
10062 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10063 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10064 {
10065 rtx ra = gen_rtx_REG (Pmode, 2);
10066
10067 emit_move_insn (ra, operands[2]);
10068 operands[2] = ra;
10069 }
5cf3595a 10070 /* This is a hack -- we may have crystalized the function type too
10071 early. */
10072 cfun->machine->func_type = 0;
215b30b3 10073 }"
10074)
56d27660 10075
9c08d1fa 10076;; This split is only used during output to reduce the number of patterns
10077;; that need assembler instructions adding to them. We allowed the setting
10078;; of the conditions to be implicit during rtl generation so that
10079;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10080;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10081;; up again here.
10082
25f905c2 10083;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10084;; conditional execution sufficient?
10085
9c08d1fa 10086(define_split
10087 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10088 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10089 [(match_operand 2 "" "") (match_operand 3 "" "")])
10090 (match_dup 0)
10091 (match_operand 4 "" "")))
bd5b4116 10092 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10093 "TARGET_ARM && reload_completed"
8fa3ba89 10094 [(set (match_dup 5) (match_dup 6))
10095 (cond_exec (match_dup 7)
10096 (set (match_dup 0) (match_dup 4)))]
10097 "
10098 {
10099 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10100 operands[2], operands[3]);
10101 enum rtx_code rc = GET_CODE (operands[1]);
10102
bd5b4116 10103 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10104 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10105 if (mode == CCFPmode || mode == CCFPEmode)
10106 rc = reverse_condition_maybe_unordered (rc);
10107 else
10108 rc = reverse_condition (rc);
10109
10110 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10111 }"
10112)
10113
10114(define_split
10115 [(set (match_operand:SI 0 "s_register_operand" "")
10116 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10117 [(match_operand 2 "" "") (match_operand 3 "" "")])
10118 (match_operand 4 "" "")
10119 (match_dup 0)))
bd5b4116 10120 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10121 "TARGET_ARM && reload_completed"
8fa3ba89 10122 [(set (match_dup 5) (match_dup 6))
10123 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10124 (set (match_dup 0) (match_dup 4)))]
10125 "
10126 {
10127 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10128 operands[2], operands[3]);
10129
bd5b4116 10130 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10131 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10132 }"
10133)
10134
10135(define_split
10136 [(set (match_operand:SI 0 "s_register_operand" "")
10137 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10138 [(match_operand 2 "" "") (match_operand 3 "" "")])
10139 (match_operand 4 "" "")
10140 (match_operand 5 "" "")))
bd5b4116 10141 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10142 "TARGET_ARM && reload_completed"
8fa3ba89 10143 [(set (match_dup 6) (match_dup 7))
10144 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10145 (set (match_dup 0) (match_dup 4)))
10146 (cond_exec (match_dup 8)
10147 (set (match_dup 0) (match_dup 5)))]
10148 "
10149 {
10150 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10151 operands[2], operands[3]);
10152 enum rtx_code rc = GET_CODE (operands[1]);
10153
bd5b4116 10154 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10155 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10156 if (mode == CCFPmode || mode == CCFPEmode)
10157 rc = reverse_condition_maybe_unordered (rc);
10158 else
10159 rc = reverse_condition (rc);
10160
10161 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10162 }"
10163)
10164
cffb2a26 10165(define_split
10166 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10167 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10168 [(match_operand:SI 2 "s_register_operand" "")
10169 (match_operand:SI 3 "arm_add_operand" "")])
10170 (match_operand:SI 4 "arm_rhs_operand" "")
10171 (not:SI
10172 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10173 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10174 "TARGET_ARM && reload_completed"
cffb2a26 10175 [(set (match_dup 6) (match_dup 7))
f6c53574 10176 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10177 (set (match_dup 0) (match_dup 4)))
10178 (cond_exec (match_dup 8)
10179 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10180 "
215b30b3 10181 {
10182 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10183 operands[2], operands[3]);
f6c53574 10184 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10185
bd5b4116 10186 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10187 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10188 if (mode == CCFPmode || mode == CCFPEmode)
10189 rc = reverse_condition_maybe_unordered (rc);
10190 else
10191 rc = reverse_condition (rc);
10192
10193 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10194 }"
10195)
cffb2a26 10196
10197(define_insn "*cond_move_not"
10198 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10199 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10200 [(match_operand 3 "cc_register" "") (const_int 0)])
10201 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10202 (not:SI
10203 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10204 "TARGET_ARM"
10205 "@
10206 mvn%D4\\t%0, %2
10207 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10208 [(set_attr "conds" "use")
d2a518d1 10209 (set_attr "insn" "mvn")
0d66636f 10210 (set_attr "length" "4,8")]
10211)
cffb2a26 10212
9c08d1fa 10213;; The next two patterns occur when an AND operation is followed by a
10214;; scc insn sequence
10215
f7fbdd4a 10216(define_insn "*sign_extract_onebit"
9c08d1fa 10217 [(set (match_operand:SI 0 "s_register_operand" "=r")
10218 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10219 (const_int 1)
ed750274 10220 (match_operand:SI 2 "const_int_operand" "n")))
10221 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10222 "TARGET_ARM"
9c08d1fa 10223 "*
0d66636f 10224 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10225 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10226 return \"mvnne\\t%0, #0\";
10227 "
10228 [(set_attr "conds" "clob")
10229 (set_attr "length" "8")]
10230)
9c08d1fa 10231
f7fbdd4a 10232(define_insn "*not_signextract_onebit"
9c08d1fa 10233 [(set (match_operand:SI 0 "s_register_operand" "=r")
10234 (not:SI
10235 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10236 (const_int 1)
ed750274 10237 (match_operand:SI 2 "const_int_operand" "n"))))
10238 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10239 "TARGET_ARM"
9c08d1fa 10240 "*
0d66636f 10241 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10242 output_asm_insn (\"tst\\t%1, %2\", operands);
10243 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10244 return \"movne\\t%0, #0\";
10245 "
10246 [(set_attr "conds" "clob")
10247 (set_attr "length" "12")]
10248)
25f905c2 10249;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10250
0d66636f 10251;; Push multiple registers to the stack. Registers are in parallel (use ...)
10252;; expressions. For simplicity, the first register is also in the unspec
10253;; part.
08508cbf 10254;; To avoid the usage of GNU extension, the length attribute is computed
10255;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10256(define_insn "*push_multi"
87b22bf7 10257 [(match_parallel 2 "multi_register_push"
10258 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10259 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10260 UNSPEC_PUSH_MULT))])]
25f905c2 10261 "TARGET_32BIT"
87b22bf7 10262 "*
215b30b3 10263 {
10264 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10265
215b30b3 10266 /* For the StrongARM at least it is faster to
25f905c2 10267 use STR to store only a single register.
542d5028 10268 In Thumb mode always use push, and the assembler will pick
10269 something appropriate. */
25f905c2 10270 if (num_saves == 1 && TARGET_ARM)
215b30b3 10271 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10272 else
10273 {
10274 int i;
10275 char pattern[100];
ed593f11 10276
25f905c2 10277 if (TARGET_ARM)
10278 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10279 else
10280 strcpy (pattern, \"push\\t{%1\");
215b30b3 10281
6079f055 10282 for (i = 1; i < num_saves; i++)
215b30b3 10283 {
10284 strcat (pattern, \", %|\");
10285 strcat (pattern,
10286 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10287 }
10288
10289 strcat (pattern, \"}\");
10290 output_asm_insn (pattern, operands);
10291 }
10292
10293 return \"\";
10294 }"
a6864a24 10295 [(set_attr "type" "store4")
10296 (set (attr "length")
08508cbf 10297 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10298)
f7fbdd4a 10299
4c58c898 10300(define_insn "stack_tie"
10301 [(set (mem:BLK (scratch))
aaa37ad6 10302 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10303 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10304 UNSPEC_PRLG_STK))]
10305 ""
10306 ""
10307 [(set_attr "length" "0")]
10308)
10309
3398e91d 10310;; Similarly for the floating point registers
7b1d2fc4 10311(define_insn "*push_fp_multi"
10312 [(match_parallel 2 "multi_register_push"
10313 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10314 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10315 UNSPEC_PUSH_MULT))])]
25f905c2 10316 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10317 "*
215b30b3 10318 {
10319 char pattern[100];
7b1d2fc4 10320
215b30b3 10321 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10322 output_asm_insn (pattern, operands);
10323 return \"\";
10324 }"
013b9671 10325 [(set_attr "type" "f_fpa_store")]
215b30b3 10326)
7b1d2fc4 10327
f7fbdd4a 10328;; Special patterns for dealing with the constant pool
10329
cffb2a26 10330(define_insn "align_4"
e1159bbe 10331 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10332 "TARGET_EITHER"
f7fbdd4a 10333 "*
cffb2a26 10334 assemble_align (32);
f7fbdd4a 10335 return \"\";
cffb2a26 10336 "
10337)
f7fbdd4a 10338
755eb2b4 10339(define_insn "align_8"
10340 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10341 "TARGET_EITHER"
755eb2b4 10342 "*
10343 assemble_align (64);
10344 return \"\";
10345 "
10346)
10347
cffb2a26 10348(define_insn "consttable_end"
e1159bbe 10349 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10350 "TARGET_EITHER"
f7fbdd4a 10351 "*
cffb2a26 10352 making_const_table = FALSE;
f7fbdd4a 10353 return \"\";
cffb2a26 10354 "
10355)
f7fbdd4a 10356
cffb2a26 10357(define_insn "consttable_1"
e1159bbe 10358 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10359 "TARGET_THUMB1"
f7fbdd4a 10360 "*
cffb2a26 10361 making_const_table = TRUE;
09d688ff 10362 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10363 assemble_zeros (3);
f7fbdd4a 10364 return \"\";
cffb2a26 10365 "
10366 [(set_attr "length" "4")]
10367)
f7fbdd4a 10368
cffb2a26 10369(define_insn "consttable_2"
e1159bbe 10370 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10371 "TARGET_THUMB1"
f7fbdd4a 10372 "*
cffb2a26 10373 making_const_table = TRUE;
9b8516be 10374 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10375 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10376 assemble_zeros (2);
f7fbdd4a 10377 return \"\";
cffb2a26 10378 "
10379 [(set_attr "length" "4")]
10380)
10381
10382(define_insn "consttable_4"
e1159bbe 10383 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10384 "TARGET_EITHER"
10385 "*
10386 {
9b8516be 10387 rtx x = operands[0];
cffb2a26 10388 making_const_table = TRUE;
9b8516be 10389 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10390 {
10391 case MODE_FLOAT:
9b8516be 10392 if (GET_MODE (x) == HFmode)
10393 arm_emit_fp16_const (x);
10394 else
10395 {
10396 REAL_VALUE_TYPE r;
10397 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10398 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10399 }
10400 break;
cffb2a26 10401 default:
7b04c5d5 10402 /* XXX: Sometimes gcc does something really dumb and ends up with
10403 a HIGH in a constant pool entry, usually because it's trying to
10404 load into a VFP register. We know this will always be used in
10405 combination with a LO_SUM which ignores the high bits, so just
10406 strip off the HIGH. */
10407 if (GET_CODE (x) == HIGH)
10408 x = XEXP (x, 0);
9b8516be 10409 assemble_integer (x, 4, BITS_PER_WORD, 1);
10410 mark_symbol_refs_as_used (x);
cffb2a26 10411 break;
10412 }
10413 return \"\";
10414 }"
10415 [(set_attr "length" "4")]
10416)
10417
10418(define_insn "consttable_8"
e1159bbe 10419 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10420 "TARGET_EITHER"
10421 "*
10422 {
10423 making_const_table = TRUE;
10424 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10425 {
10426 case MODE_FLOAT:
10427 {
badfe841 10428 REAL_VALUE_TYPE r;
10429 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10430 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10431 break;
10432 }
10433 default:
09d688ff 10434 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10435 break;
10436 }
10437 return \"\";
10438 }"
10439 [(set_attr "length" "8")]
10440)
10441
d98a3884 10442(define_insn "consttable_16"
10443 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10444 "TARGET_EITHER"
10445 "*
10446 {
10447 making_const_table = TRUE;
10448 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10449 {
10450 case MODE_FLOAT:
10451 {
10452 REAL_VALUE_TYPE r;
10453 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10454 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10455 break;
10456 }
10457 default:
10458 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10459 break;
10460 }
10461 return \"\";
10462 }"
10463 [(set_attr "length" "16")]
10464)
10465
cffb2a26 10466;; Miscellaneous Thumb patterns
10467
fd957ef3 10468(define_expand "tablejump"
7db9af5d 10469 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10470 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10471 "TARGET_THUMB1"
fd957ef3 10472 "
10473 if (flag_pic)
10474 {
10475 /* Hopefully, CSE will eliminate this copy. */
10476 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10477 rtx reg2 = gen_reg_rtx (SImode);
10478
10479 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10480 operands[0] = reg2;
10481 }
10482 "
10483)
10484
f1039640 10485;; NB never uses BX.
25f905c2 10486(define_insn "*thumb1_tablejump"
cffb2a26 10487 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10488 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10489 "TARGET_THUMB1"
fd957ef3 10490 "mov\\t%|pc, %0"
cffb2a26 10491 [(set_attr "length" "2")]
10492)
0d66636f 10493
331beb1a 10494;; V5 Instructions,
10495
8f4be2be 10496(define_insn "clzsi2"
10497 [(set (match_operand:SI 0 "s_register_operand" "=r")
10498 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10499 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10500 "clz%?\\t%0, %1"
bcaec148 10501 [(set_attr "predicable" "yes")
10502 (set_attr "insn" "clz")])
331beb1a 10503
099ad98b 10504(define_insn "rbitsi2"
10505 [(set (match_operand:SI 0 "s_register_operand" "=r")
10506 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10507 "TARGET_32BIT && arm_arch_thumb2"
10508 "rbit%?\\t%0, %1"
10509 [(set_attr "predicable" "yes")
10510 (set_attr "insn" "clz")])
10511
10512(define_expand "ctzsi2"
10513 [(set (match_operand:SI 0 "s_register_operand" "")
10514 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10515 "TARGET_32BIT && arm_arch_thumb2"
10516 "
30191172 10517 {
10518 rtx tmp = gen_reg_rtx (SImode);
10519 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10520 emit_insn (gen_clzsi2 (operands[0], tmp));
10521 }
099ad98b 10522 DONE;
10523 "
10524)
10525
e1159bbe 10526;; V5E instructions.
331beb1a 10527
10528(define_insn "prefetch"
f4e79814 10529 [(prefetch (match_operand:SI 0 "address_operand" "p")
10530 (match_operand:SI 1 "" "")
10531 (match_operand:SI 2 "" ""))]
25f905c2 10532 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10533 "pld\\t%a0")
331beb1a 10534
0d66636f 10535;; General predication pattern
10536
10537(define_cond_exec
10538 [(match_operator 0 "arm_comparison_operator"
10539 [(match_operand 1 "cc_register" "")
10540 (const_int 0)])]
25f905c2 10541 "TARGET_32BIT"
0d66636f 10542 ""
10543)
10544
063a05c7 10545(define_insn "prologue_use"
10546 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10547 ""
10548 "%@ %0 needed for prologue"
02cfc9c9 10549 [(set_attr "length" "0")]
063a05c7 10550)
7db9af5d 10551
4c44712e 10552
10553;; Patterns for exception handling
10554
10555(define_expand "eh_return"
10556 [(use (match_operand 0 "general_operand" ""))]
10557 "TARGET_EITHER"
10558 "
10559 {
25f905c2 10560 if (TARGET_32BIT)
4c44712e 10561 emit_insn (gen_arm_eh_return (operands[0]));
10562 else
10563 emit_insn (gen_thumb_eh_return (operands[0]));
10564 DONE;
10565 }"
10566)
10567
10568;; We can't expand this before we know where the link register is stored.
10569(define_insn_and_split "arm_eh_return"
10570 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10571 VUNSPEC_EH_RETURN)
10572 (clobber (match_scratch:SI 1 "=&r"))]
10573 "TARGET_ARM"
10574 "#"
10575 "&& reload_completed"
10576 [(const_int 0)]
10577 "
10578 {
10579 arm_set_return_address (operands[0], operands[1]);
10580 DONE;
10581 }"
10582)
10583
10584(define_insn_and_split "thumb_eh_return"
10585 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10586 VUNSPEC_EH_RETURN)
10587 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10588 "TARGET_THUMB1"
4c44712e 10589 "#"
10590 "&& reload_completed"
10591 [(const_int 0)]
10592 "
10593 {
10594 thumb_set_return_address (operands[0], operands[1]);
10595 DONE;
10596 }"
10597)
10598
f655717d 10599\f
10600;; TLS support
10601
10602(define_insn "load_tp_hard"
10603 [(set (match_operand:SI 0 "register_operand" "=r")
10604 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10605 "TARGET_HARD_TP"
10606 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10607 [(set_attr "predicable" "yes")]
10608)
10609
10610;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10611(define_insn "load_tp_soft"
10612 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10613 (clobber (reg:SI LR_REGNUM))
10614 (clobber (reg:SI IP_REGNUM))
10615 (clobber (reg:CC CC_REGNUM))]
10616 "TARGET_SOFT_TP"
10617 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10618 [(set_attr "conds" "clob")]
10619)
10620
aabe09ac 10621;; We only care about the lower 16 bits of the constant
10622;; being inserted into the upper 16 bits of the register.
eca5c984 10623(define_insn "*arm_movtas_ze"
10624 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10625 (const_int 16)
10626 (const_int 16))
10627 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10628 "arm_arch_thumb2"
aabe09ac 10629 "movt%?\t%0, %L1"
eca5c984 10630 [(set_attr "predicable" "yes")
10631 (set_attr "length" "4")]
10632)
10633
c0fc3696 10634(define_insn "*arm_rev"
ff82f757 10635 [(set (match_operand:SI 0 "s_register_operand" "=r")
10636 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 10637 "TARGET_32BIT && arm_arch6"
10638 "rev%?\t%0, %1"
10639 [(set_attr "predicable" "yes")
10640 (set_attr "length" "4")]
10641)
10642
10643(define_insn "*thumb1_rev"
10644 [(set (match_operand:SI 0 "s_register_operand" "=l")
10645 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10646 "TARGET_THUMB1 && arm_arch6"
10647 "rev\t%0, %1"
10648 [(set_attr "length" "2")]
ff82f757 10649)
10650
10651(define_expand "arm_legacy_rev"
10652 [(set (match_operand:SI 2 "s_register_operand" "")
10653 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10654 (const_int 16))
10655 (match_dup 1)))
10656 (set (match_dup 2)
10657 (lshiftrt:SI (match_dup 2)
10658 (const_int 8)))
10659 (set (match_operand:SI 3 "s_register_operand" "")
10660 (rotatert:SI (match_dup 1)
10661 (const_int 8)))
10662 (set (match_dup 2)
10663 (and:SI (match_dup 2)
10664 (const_int -65281)))
10665 (set (match_operand:SI 0 "s_register_operand" "")
10666 (xor:SI (match_dup 3)
10667 (match_dup 2)))]
10668 "TARGET_32BIT"
10669 ""
10670)
10671
10672;; Reuse temporaries to keep register pressure down.
10673(define_expand "thumb_legacy_rev"
10674 [(set (match_operand:SI 2 "s_register_operand" "")
10675 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10676 (const_int 24)))
10677 (set (match_operand:SI 3 "s_register_operand" "")
10678 (lshiftrt:SI (match_dup 1)
10679 (const_int 24)))
10680 (set (match_dup 3)
10681 (ior:SI (match_dup 3)
10682 (match_dup 2)))
10683 (set (match_operand:SI 4 "s_register_operand" "")
10684 (const_int 16))
10685 (set (match_operand:SI 5 "s_register_operand" "")
10686 (rotatert:SI (match_dup 1)
10687 (match_dup 4)))
10688 (set (match_dup 2)
10689 (ashift:SI (match_dup 5)
10690 (const_int 24)))
10691 (set (match_dup 5)
10692 (lshiftrt:SI (match_dup 5)
10693 (const_int 24)))
10694 (set (match_dup 5)
10695 (ior:SI (match_dup 5)
10696 (match_dup 2)))
10697 (set (match_dup 5)
10698 (rotatert:SI (match_dup 5)
10699 (match_dup 4)))
10700 (set (match_operand:SI 0 "s_register_operand" "")
10701 (ior:SI (match_dup 5)
10702 (match_dup 3)))]
10703 "TARGET_THUMB"
10704 ""
10705)
10706
10707(define_expand "bswapsi2"
10708 [(set (match_operand:SI 0 "s_register_operand" "=r")
10709 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10710"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10711"
8d1af482 10712 if (!arm_arch6)
10713 {
10714 rtx op2 = gen_reg_rtx (SImode);
10715 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10716
8d1af482 10717 if (TARGET_THUMB)
10718 {
10719 rtx op4 = gen_reg_rtx (SImode);
10720 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10721
8d1af482 10722 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10723 op2, op3, op4, op5));
10724 }
10725 else
10726 {
10727 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10728 op2, op3));
10729 }
ff82f757 10730
8d1af482 10731 DONE;
10732 }
ff82f757 10733 "
10734)
10735
320ea44d 10736;; Load the load/store multiple patterns
10737(include "ldmstm.md")
7db9af5d 10738;; Load the FPA co-processor patterns
10739(include "fpa.md")
10740;; Load the Maverick co-processor patterns
10741(include "cirrus.md")
d98a3884 10742;; Vector bits common to IWMMXT and Neon
10743(include "vec-common.md")
755eb2b4 10744;; Load the Intel Wireless Multimedia Extension patterns
10745(include "iwmmxt.md")
a2cd141b 10746;; Load the VFP co-processor patterns
10747(include "vfp.md")
25f905c2 10748;; Thumb-2 patterns
10749(include "thumb2.md")
d98a3884 10750;; Neon patterns
10751(include "neon.md")
06df6b17 10752;; Synchronization Primitives
10753(include "sync.md")