]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* config/arm/arm.c (arm_address_offset_is_imm): New.
[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.
d98a3884 54;; Unspec constants for Neon are defined in neon.md.
e1159bbe 55
56(define_constants
57 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
58 ; operand 0 is the result,
59 ; operand 1 the parameter.
60 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
61 ; operand 0 is the result,
62 ; operand 1 the parameter.
63 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
64 ; operand 0 is the first register,
65 ; subsequent registers are in parallel (use ...)
66 ; expressions.
67 (UNSPEC_PIC_SYM 3) ; 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.
c0c1fba5 70 (UNSPEC_PIC_BASE 4) ; 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.
2c96dc5a 73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
e1159bbe 74 ; being scheduled before the stack adjustment insn.
063a05c7 75 (UNSPEC_PROLOGUE_USE 6) ; 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".
68121397 80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
8d232dc7 81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
f655717d 93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
6cdcb15c 94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95 ; instruction stream.
2c2d2f40 96 (UNSPEC_STACK_ALIGN 22) ; Doubleword aligned stack pointer. Used to
25f905c2 97 ; generate correct unwind information.
2c2d2f40 98 (UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
bac7fc85 99 ; correctly for PIC usage.
c0c1fba5 100 (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
101 ; a given symbolic address.
e6ac8414 102 (UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
099ad98b 103 (UNSPEC_RBIT 26) ; rbit operation.
825ae2ed 104 (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
105 ; another symbolic address.
06df6b17 106 (UNSPEC_MEMORY_BARRIER 28) ; Represent a memory barrier.
e1159bbe 107 ]
108)
109
215b30b3 110;; UNSPEC_VOLATILE Usage:
e1159bbe 111
112(define_constants
113 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
114 ; insn in the code.
115 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
116 ; instruction epilogue sequence that isn't expanded
117 ; into normal RTL. Used for both normal and sibcall
118 ; epilogues.
119 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
120 ; for inlined constants.
121 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
122 ; table.
123 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
124 ; an 8-bit object.
125 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
126 ; a 16-bit object.
127 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
128 ; a 32-bit object.
129 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
130 ; a 64-bit object.
d98a3884 131 (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
132 ; a 128-bit object.
133 (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
134 (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
135 (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
136 (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
137 (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
138 (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 139 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 140 ; handling.
06df6b17 141 (VUNSPEC_SYNC_COMPARE_AND_SWAP 21) ; Represent an atomic compare swap.
142 (VUNSPEC_SYNC_LOCK 22) ; Represent a sync_lock_test_and_set.
143 (VUNSPEC_SYNC_OP 23) ; Represent a sync_<op>
144 (VUNSPEC_SYNC_NEW_OP 24) ; Represent a sync_new_<op>
145 (VUNSPEC_SYNC_OLD_OP 25) ; Represent a sync_old_<op>
e1159bbe 146 ]
147)
b11cae9e 148\f
e1159bbe 149;;---------------------------------------------------------------------------
9c08d1fa 150;; Attributes
151
215b30b3 152; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
153; generating ARM code. This is used to control the length of some insn
154; patterns that share the same RTL in both ARM and Thumb code.
1c494086 155(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 156
ef51b8e1 157; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
158(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
159
747b7458 160; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
161(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
162
331beb1a 163;; Operand number of an input operand that is shifted. Zero if the
164;; given instruction does not shift one of its input operands.
331beb1a 165(define_attr "shift" "" (const_int 0))
166
3d91c5d6 167; Floating Point Unit. If we only have floating point emulation, then there
168; is no point in scheduling the floating point insns. (Well, for best
169; performance we should try and group them together).
4fea7d65 170(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 171 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 172
06df6b17 173(define_attr "sync_result" "none,0,1,2,3,4,5" (const_string "none"))
174(define_attr "sync_memory" "none,0,1,2,3,4,5" (const_string "none"))
175(define_attr "sync_required_value" "none,0,1,2,3,4,5" (const_string "none"))
176(define_attr "sync_new_value" "none,0,1,2,3,4,5" (const_string "none"))
177(define_attr "sync_t1" "none,0,1,2,3,4,5" (const_string "none"))
178(define_attr "sync_t2" "none,0,1,2,3,4,5" (const_string "none"))
179(define_attr "sync_release_barrier" "yes,no" (const_string "yes"))
180(define_attr "sync_op" "none,add,sub,ior,xor,and,nand"
181 (const_string "none"))
182
094e994f 183; LENGTH of an instruction (in bytes)
06df6b17 184(define_attr "length" ""
185 (cond [(not (eq_attr "sync_memory" "none"))
186 (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
187 ] (const_int 4)))
9c08d1fa 188
d5d4dc8d 189; The architecture which supports the instruction (or alternative).
190; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
191; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
192; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
193; arm_arch6. This attribute is used to compute attribute "enabled",
194; use type "any" to enable an alternative in all cases.
195(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6"
196 (const_string "any"))
197
198(define_attr "arch_enabled" "no,yes"
199 (cond [(eq_attr "arch" "any")
200 (const_string "yes")
201
202 (and (eq_attr "arch" "a")
203 (ne (symbol_ref "TARGET_ARM") (const_int 0)))
204 (const_string "yes")
205
206 (and (eq_attr "arch" "t")
207 (ne (symbol_ref "TARGET_THUMB") (const_int 0)))
208 (const_string "yes")
209
210 (and (eq_attr "arch" "t1")
211 (ne (symbol_ref "TARGET_THUMB1") (const_int 0)))
212 (const_string "yes")
213
214 (and (eq_attr "arch" "t2")
215 (ne (symbol_ref "TARGET_THUMB2") (const_int 0)))
216 (const_string "yes")
217
218 (and (eq_attr "arch" "32")
219 (ne (symbol_ref "TARGET_32BIT") (const_int 0)))
220 (const_string "yes")
221
222 (and (eq_attr "arch" "v6")
223 (ne (symbol_ref "(TARGET_32BIT && arm_arch6)") (const_int 0)))
224 (const_string "yes")
225
226 (and (eq_attr "arch" "nov6")
227 (ne (symbol_ref "(TARGET_32BIT && !arm_arch6)") (const_int 0)))
228 (const_string "yes")]
229 (const_string "no")))
230
231; Allows an insn to disable certain alternatives for reasons other than
232; arch support.
233(define_attr "insn_enabled" "no,yes"
234 (const_string "yes"))
235
236; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 237 (define_attr "enabled" "no,yes"
238 (if_then_else (eq_attr "insn_enabled" "yes")
239 (if_then_else (eq_attr "arch_enabled" "yes")
240 (const_string "yes")
241 (const_string "no"))
242 (const_string "no")))
d5d4dc8d 243
56d27660 244; POOL_RANGE is how far away from a constant pool entry that this insn
245; can be placed. If the distance is zero, then this insn will never
246; reference the pool.
cffb2a26 247; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
248; before its address.
cde1623a 249(define_attr "arm_pool_range" "" (const_int 0))
250(define_attr "thumb2_pool_range" "" (const_int 0))
251(define_attr "arm_neg_pool_range" "" (const_int 0))
252(define_attr "thumb2_neg_pool_range" "" (const_int 0))
253
254(define_attr "pool_range" ""
255 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
256 (attr "arm_pool_range")))
257(define_attr "neg_pool_range" ""
258 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
259 (attr "arm_neg_pool_range")))
56d27660 260
215b30b3 261; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 262; If such an insn references the pool, then we have no way of knowing how,
263; so use the most conservative value for pool_range.
9c08d1fa 264(define_asm_attributes
4d7a8451 265 [(set_attr "conds" "clob")
266 (set_attr "length" "4")
267 (set_attr "pool_range" "250")])
9c08d1fa 268
a2cd141b 269;; The instruction used to implement a particular pattern. This
270;; information is used by pipeline descriptions to provide accurate
271;; scheduling information.
272
273(define_attr "insn"
934a1e72 274 "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 275 (const_string "other"))
276
9c08d1fa 277; TYPE attribute is used to detect floating point instructions which, if
278; running on a co-processor can run in parallel with other, basic instructions
279; If write-buffer scheduling is enabled then it can also be used in the
280; scheduling of writes.
281
282; Classification of each insn
607978a1 283; Note: vfp.md has different meanings for some of these, and some further
284; types as well. See that file for details.
a2cd141b 285; alu any alu instruction that doesn't hit memory or fp
286; regs or have a shifted source operand
287; alu_shift any data instruction that doesn't hit memory or fp
288; regs, but has a source operand shifted by a constant
289; alu_shift_reg any data instruction that doesn't hit memory or fp
290; regs, but has a source operand shifted by a register value
f7fbdd4a 291; mult a multiply instruction
9c08d1fa 292; block blockage insn, this blocks all functional units
293; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 294; fdivd DFmode floating point division
295; fdivs SFmode floating point division
296; fmul Floating point multiply
297; ffmul Fast floating point multiply
298; farith Floating point arithmetic (4 cycle)
299; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 300; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 301; even on a machine with an fpa.
9c08d1fa 302; f_load a floating point load from memory
303; f_store a floating point store to memory
9aff9709 304; f_load[sd] single/double load from memory
305; f_store[sd] single/double store to memory
c0e1af52 306; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 307; f_mem_r a transfer of a floating point register to a real reg via mem
308; r_mem_f the reverse of f_mem_r
309; f_2_r fast transfer float to arm (no memory needed)
310; r_2_f fast transfer arm to float
c0e1af52 311; f_cvt convert floating<->integral
a2cd141b 312; branch a branch
9c08d1fa 313; call a subroutine call
a2cd141b 314; load_byte load byte(s) from memory to arm registers
315; load1 load 1 word from memory to arm registers
316; load2 load 2 words from memory to arm registers
317; load3 load 3 words from memory to arm registers
318; load4 load 4 words from memory to arm registers
319; store store 1 word to memory from arm registers
9c08d1fa 320; store2 store 2 words
321; store3 store 3 words
a2cd141b 322; store4 store 4 (or more) words
2c6c7d8b 323; Additions for Cirrus Maverick co-processor:
324; mav_farith Floating point arithmetic (4 cycle)
325; mav_dmult Double multiplies (7 cycle)
9c08d1fa 326;
bcaec148 327
9c08d1fa 328(define_attr "type"
e3879fd0 329 "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_load,f_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 330 (if_then_else
331 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
332 (const_string "mult")
333 (const_string "alu")))
9c08d1fa 334
9888ad6d 335; Load scheduling, set from the arm_ld_sched variable
4c834714 336; initialized by arm_option_override()
9888ad6d 337(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 338
c52acdd2 339;; Classification of NEON instructions for scheduling purposes.
340;; Do not set this attribute and the "type" attribute together in
341;; any one instruction pattern.
342(define_attr "neon_type"
343 "neon_int_1,\
344 neon_int_2,\
345 neon_int_3,\
346 neon_int_4,\
347 neon_int_5,\
348 neon_vqneg_vqabs,\
349 neon_vmov,\
350 neon_vaba,\
351 neon_vsma,\
352 neon_vaba_qqq,\
353 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
354 neon_mul_qqq_8_16_32_ddd_32,\
355 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
356 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
357 neon_mla_qqq_8_16,\
358 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
359 neon_mla_qqq_32_qqd_32_scalar,\
360 neon_mul_ddd_16_scalar_32_16_long_scalar,\
361 neon_mul_qqd_32_scalar,\
362 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
363 neon_shift_1,\
364 neon_shift_2,\
365 neon_shift_3,\
366 neon_vshl_ddd,\
367 neon_vqshl_vrshl_vqrshl_qqq,\
368 neon_vsra_vrsra,\
369 neon_fp_vadd_ddd_vabs_dd,\
370 neon_fp_vadd_qqq_vabs_qq,\
371 neon_fp_vsum,\
372 neon_fp_vmul_ddd,\
373 neon_fp_vmul_qqd,\
374 neon_fp_vmla_ddd,\
375 neon_fp_vmla_qqq,\
376 neon_fp_vmla_ddd_scalar,\
377 neon_fp_vmla_qqq_scalar,\
378 neon_fp_vrecps_vrsqrts_ddd,\
379 neon_fp_vrecps_vrsqrts_qqq,\
380 neon_bp_simple,\
381 neon_bp_2cycle,\
382 neon_bp_3cycle,\
383 neon_ldr,\
384 neon_str,\
385 neon_vld1_1_2_regs,\
386 neon_vld1_3_4_regs,\
387 neon_vld2_2_regs_vld1_vld2_all_lanes,\
388 neon_vld2_4_regs,\
389 neon_vld3_vld4,\
390 neon_vst1_1_2_regs_vst2_2_regs,\
391 neon_vst1_3_4_regs,\
392 neon_vst2_4_regs_vst3_vst4,\
393 neon_vst3_vst4,\
394 neon_vld1_vld2_lane,\
395 neon_vld3_vld4_lane,\
396 neon_vst1_vst2_lane,\
397 neon_vst3_vst4_lane,\
398 neon_vld3_vld4_all_lanes,\
399 neon_mcr,\
400 neon_mcr_2_mcrr,\
401 neon_mrc,\
402 neon_mrrc,\
403 neon_ldm_2,\
404 neon_stm_2,\
405 none"
406 (const_string "none"))
407
f7fbdd4a 408; condition codes: this one is used by final_prescan_insn to speed up
409; conditionalizing instructions. It saves having to scan the rtl to see if
410; it uses or alters the condition codes.
215b30b3 411;
f7fbdd4a 412; USE means that the condition codes are used by the insn in the process of
215b30b3 413; outputting code, this means (at present) that we can't use the insn in
414; inlined branches
415;
f7fbdd4a 416; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 417; well defined manner.
418;
f7fbdd4a 419; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 420; they are altered at all
421;
ad6d3e2a 422; UNCONDITIONAL means the instruction can not be conditionally executed and
423; that the instruction does not use or alter the condition codes.
c52acdd2 424;
ad6d3e2a 425; NOCOND means that the instruction does not use or alter the condition
426; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 427
b0694be0 428(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 429 (if_then_else
430 (ior (eq_attr "is_thumb1" "yes")
431 (eq_attr "type" "call"))
c1a66faf 432 (const_string "clob")
c52acdd2 433 (if_then_else (eq_attr "neon_type" "none")
434 (const_string "nocond")
435 (const_string "unconditional"))))
f7fbdd4a 436
215b30b3 437; Predicable means that the insn can be conditionally executed based on
438; an automatically added predicate (additional patterns are generated by
439; gen...). We default to 'no' because no Thumb patterns match this rule
440; and not all ARM patterns do.
0d66636f 441(define_attr "predicable" "no,yes" (const_string "no"))
442
129a2fe4 443; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
444; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 445; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 446; affect the schedule).
74a71f7d 447(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 448
215b30b3 449; WRITE_CONFLICT implies that a read following an unrelated write is likely
450; to stall the processor. Used with model_wbuf above.
9c08d1fa 451(define_attr "write_conflict" "no,yes"
452 (if_then_else (eq_attr "type"
a2cd141b 453 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 454 (const_string "yes")
455 (const_string "no")))
456
215b30b3 457; Classify the insns into those that take one cycle and those that take more
458; than one on the main cpu execution unit.
f7fbdd4a 459(define_attr "core_cycles" "single,multi"
460 (if_then_else (eq_attr "type"
a2cd141b 461 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 462 (const_string "single")
463 (const_string "multi")))
464
cffb2a26 465;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 466;; distant label. Only applicable to Thumb code.
cffb2a26 467(define_attr "far_jump" "yes,no" (const_string "no"))
468
d51f92df 469
25f905c2 470;; The number of machine instructions this pattern expands to.
471;; Used for Thumb-2 conditional execution.
472(define_attr "ce_count" "" (const_int 1))
473
d51f92df 474;;---------------------------------------------------------------------------
fd781bb2 475;; Mode iterators
d51f92df 476
3de0dec6 477(include "iterators.md")
03770691 478
d51f92df 479;;---------------------------------------------------------------------------
480;; Predicates
481
9c9db025 482(include "predicates.md")
234f6557 483(include "constraints.md")
9c9db025 484
a2cd141b 485;;---------------------------------------------------------------------------
486;; Pipeline descriptions
215b30b3 487
06469f9e 488;; Processor type. This is created automatically from arm-cores.def.
489(include "arm-tune.md")
331beb1a 490
e3879fd0 491(define_attr "tune_cortexr4" "yes,no"
492 (const (if_then_else
493 (eq_attr "tune" "cortexr4,cortexr4f")
494 (const_string "yes")
495 (const_string "no"))))
496
a2cd141b 497;; True if the generic scheduling description should be used.
498
499(define_attr "generic_sched" "yes,no"
2546d93a 500 (const (if_then_else
501 (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexm4")
502 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 503 (const_string "no")
504 (const_string "yes"))))
505
c0e1af52 506(define_attr "generic_vfp" "yes,no"
507 (const (if_then_else
508 (and (eq_attr "fpu" "vfp")
2546d93a 509 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 510 (eq_attr "tune_cortexr4" "no"))
c0e1af52 511 (const_string "yes")
512 (const_string "no"))))
513
a2cd141b 514(include "arm-generic.md")
515(include "arm926ejs.md")
c0e1af52 516(include "arm1020e.md")
a2cd141b 517(include "arm1026ejs.md")
518(include "arm1136jfs.md")
3f1e069f 519(include "cortex-a5.md")
bcaec148 520(include "cortex-a8.md")
036068af 521(include "cortex-a9.md")
934a1e72 522(include "cortex-r4.md")
e3879fd0 523(include "cortex-r4f.md")
2546d93a 524(include "cortex-m4.md")
525(include "cortex-m4-fpu.md")
55e3ada8 526(include "vfp11.md")
3586df96 527
9c08d1fa 528\f
215b30b3 529;;---------------------------------------------------------------------------
e1159bbe 530;; Insn patterns
531;;
a0f94409 532;; Addition insns.
215b30b3 533
9c08d1fa 534;; Note: For DImode insns, there is normally no reason why operands should
535;; not be in the same register, what we don't want is for something being
536;; written to partially overlap something that is an input.
7d57ec45 537;; Cirrus 64bit additions should not be split because we have a native
538;; 64bit addition instructions.
9c08d1fa 539
cffb2a26 540(define_expand "adddi3"
541 [(parallel
215b30b3 542 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 543 (plus:DI (match_operand:DI 1 "s_register_operand" "")
544 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 545 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 546 "TARGET_EITHER"
547 "
a2cd141b 548 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 549 {
550 if (!cirrus_fp_register (operands[0], DImode))
551 operands[0] = force_reg (DImode, operands[0]);
552 if (!cirrus_fp_register (operands[1], DImode))
553 operands[1] = force_reg (DImode, operands[1]);
554 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
555 DONE;
556 }
557
25f905c2 558 if (TARGET_THUMB1)
cffb2a26 559 {
560 if (GET_CODE (operands[1]) != REG)
bc5a93af 561 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 562 if (GET_CODE (operands[2]) != REG)
bc5a93af 563 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 564 }
565 "
566)
567
25f905c2 568(define_insn "*thumb1_adddi3"
cffb2a26 569 [(set (match_operand:DI 0 "register_operand" "=l")
570 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 571 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 572 (clobber (reg:CC CC_REGNUM))
cffb2a26 573 ]
25f905c2 574 "TARGET_THUMB1"
cffb2a26 575 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
576 [(set_attr "length" "4")]
577)
578
a0f94409 579(define_insn_and_split "*arm_adddi3"
cffb2a26 580 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 581 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
582 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 583 (clobber (reg:CC CC_REGNUM))]
94829feb 584 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 585 "#"
94829feb 586 "TARGET_32BIT && reload_completed
587 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 588 [(parallel [(set (reg:CC_C CC_REGNUM)
589 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
590 (match_dup 1)))
591 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 592 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
593 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 594 "
595 {
596 operands[3] = gen_highpart (SImode, operands[0]);
597 operands[0] = gen_lowpart (SImode, operands[0]);
598 operands[4] = gen_highpart (SImode, operands[1]);
599 operands[1] = gen_lowpart (SImode, operands[1]);
600 operands[5] = gen_highpart (SImode, operands[2]);
601 operands[2] = gen_lowpart (SImode, operands[2]);
602 }"
cffb2a26 603 [(set_attr "conds" "clob")
604 (set_attr "length" "8")]
605)
9c08d1fa 606
a0f94409 607(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 608 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
609 (plus:DI (sign_extend:DI
97499065 610 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 611 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 612 (clobber (reg:CC CC_REGNUM))]
25f905c2 613 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 614 "#"
25f905c2 615 "TARGET_32BIT && reload_completed"
a0f94409 616 [(parallel [(set (reg:CC_C CC_REGNUM)
617 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
618 (match_dup 1)))
619 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 620 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 621 (const_int 31))
080c0b9a 622 (match_dup 4))
623 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 624 "
625 {
626 operands[3] = gen_highpart (SImode, operands[0]);
627 operands[0] = gen_lowpart (SImode, operands[0]);
628 operands[4] = gen_highpart (SImode, operands[1]);
629 operands[1] = gen_lowpart (SImode, operands[1]);
630 operands[2] = gen_lowpart (SImode, operands[2]);
631 }"
215b30b3 632 [(set_attr "conds" "clob")
633 (set_attr "length" "8")]
634)
9c08d1fa 635
a0f94409 636(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 637 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
638 (plus:DI (zero_extend:DI
97499065 639 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 640 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 641 (clobber (reg:CC CC_REGNUM))]
25f905c2 642 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 643 "#"
25f905c2 644 "TARGET_32BIT && reload_completed"
a0f94409 645 [(parallel [(set (reg:CC_C CC_REGNUM)
646 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
647 (match_dup 1)))
648 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 649 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
650 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 651 "
652 {
653 operands[3] = gen_highpart (SImode, operands[0]);
654 operands[0] = gen_lowpart (SImode, operands[0]);
655 operands[4] = gen_highpart (SImode, operands[1]);
656 operands[1] = gen_lowpart (SImode, operands[1]);
657 operands[2] = gen_lowpart (SImode, operands[2]);
658 }"
cffb2a26 659 [(set_attr "conds" "clob")
660 (set_attr "length" "8")]
661)
b11cae9e 662
87b22bf7 663(define_expand "addsi3"
cffb2a26 664 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 665 (plus:SI (match_operand:SI 1 "s_register_operand" "")
666 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 667 "TARGET_EITHER"
87b22bf7 668 "
25f905c2 669 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 670 {
96f57e36 671 arm_split_constant (PLUS, SImode, NULL_RTX,
672 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 673 optimize && can_create_pseudo_p ());
87b22bf7 674 DONE;
675 }
cffb2a26 676 "
677)
87b22bf7 678
5bd751ff 679; If there is a scratch available, this will be faster than synthesizing the
a0f94409 680; addition.
681(define_peephole2
682 [(match_scratch:SI 3 "r")
372575c7 683 (set (match_operand:SI 0 "arm_general_register_operand" "")
684 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 685 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 686 "TARGET_32BIT &&
a0f94409 687 !(const_ok_for_arm (INTVAL (operands[2]))
688 || const_ok_for_arm (-INTVAL (operands[2])))
689 && const_ok_for_arm (~INTVAL (operands[2]))"
690 [(set (match_dup 3) (match_dup 2))
691 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
692 ""
693)
87b22bf7 694
2f02c19f 695;; The r/r/k alternative is required when reloading the address
696;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
697;; put the duplicated register first, and not try the commutative version.
a0f94409 698(define_insn_and_split "*arm_addsi3"
bccb5444 699 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k,r")
700 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
701 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
25f905c2 702 "TARGET_32BIT"
5565501b 703 "@
704 add%?\\t%0, %1, %2
aaa37ad6 705 add%?\\t%0, %1, %2
2f02c19f 706 add%?\\t%0, %2, %1
aaa37ad6 707 sub%?\\t%0, %1, #%n2
87b22bf7 708 sub%?\\t%0, %1, #%n2
709 #"
a3ffc315 710 "TARGET_32BIT
711 && GET_CODE (operands[2]) == CONST_INT
a0f94409 712 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 713 || const_ok_for_arm (-INTVAL (operands[2])))
714 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 715 [(clobber (const_int 0))]
716 "
96f57e36 717 arm_split_constant (PLUS, SImode, curr_insn,
718 INTVAL (operands[2]), operands[0],
a0f94409 719 operands[1], 0);
720 DONE;
721 "
2f02c19f 722 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 723 (set_attr "predicable" "yes")]
cffb2a26 724)
725
0bdb6455 726(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 727 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
728 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
729 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 730 "TARGET_THUMB1"
cffb2a26 731 "*
0d66636f 732 static const char * const asms[] =
cffb2a26 733 {
734 \"add\\t%0, %0, %2\",
735 \"sub\\t%0, %0, #%n2\",
736 \"add\\t%0, %1, %2\",
737 \"add\\t%0, %0, %2\",
738 \"add\\t%0, %0, %2\",
739 \"add\\t%0, %1, %2\",
0bdb6455 740 \"add\\t%0, %1, %2\",
741 \"#\",
bf7bc2f6 742 \"#\",
0bdb6455 743 \"#\"
cffb2a26 744 };
745 if ((which_alternative == 2 || which_alternative == 6)
746 && GET_CODE (operands[2]) == CONST_INT
747 && INTVAL (operands[2]) < 0)
748 return \"sub\\t%0, %1, #%n2\";
749 return asms[which_alternative];
750 "
0bdb6455 751 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 752 && ((operands[1] != stack_pointer_rtx
753 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
754 || (operands[1] == stack_pointer_rtx
755 && INTVAL (operands[2]) > 1020))"
0bdb6455 756 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
757 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
758 {
759 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 760 if (operands[1] == stack_pointer_rtx)
761 offset -= 1020;
762 else
763 {
764 if (offset > 255)
765 offset = 255;
766 else if (offset < -255)
767 offset = -255;
768 }
0bdb6455 769 operands[3] = GEN_INT (offset);
770 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
771 }
bf7bc2f6 772 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 773)
774
775;; Reloading and elimination of the frame pointer can
776;; sometimes cause this optimization to be missed.
a0f94409 777(define_peephole2
372575c7 778 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 779 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 780 (set (match_dup 0)
372575c7 781 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 782 "TARGET_THUMB1
cffb2a26 783 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
784 && (INTVAL (operands[1]) & 3) == 0"
372575c7 785 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 786 ""
cffb2a26 787)
b11cae9e 788
f7fbdd4a 789(define_insn "*addsi3_compare0"
bd5b4116 790 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 791 (compare:CC_NOOV
215b30b3 792 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
793 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 794 (const_int 0)))
795 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 796 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 797 "TARGET_ARM"
5565501b 798 "@
25f905c2 799 add%.\\t%0, %1, %2
800 sub%.\\t%0, %1, #%n2"
cffb2a26 801 [(set_attr "conds" "set")]
802)
9c08d1fa 803
aea4c774 804(define_insn "*addsi3_compare0_scratch"
bd5b4116 805 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 806 (compare:CC_NOOV
215b30b3 807 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
808 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 809 (const_int 0)))]
ec792a7b 810 "TARGET_ARM"
cffb2a26 811 "@
812 cmn%?\\t%0, %1
813 cmp%?\\t%0, #%n1"
0d66636f 814 [(set_attr "conds" "set")]
815)
cffb2a26 816
aed179ae 817(define_insn "*compare_negsi_si"
818 [(set (reg:CC_Z CC_REGNUM)
819 (compare:CC_Z
820 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
821 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 822 "TARGET_32BIT"
aed179ae 823 "cmn%?\\t%1, %0"
0d66636f 824 [(set_attr "conds" "set")]
825)
aea4c774 826
203c488f 827;; This is the canonicalization of addsi3_compare0_for_combiner when the
828;; addend is a constant.
829(define_insn "*cmpsi2_addneg"
830 [(set (reg:CC CC_REGNUM)
831 (compare:CC
832 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 833 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 834 (set (match_operand:SI 0 "s_register_operand" "=r,r")
835 (plus:SI (match_dup 1)
2a977b78 836 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 837 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 838 "@
2a977b78 839 add%.\\t%0, %1, %3
840 sub%.\\t%0, %1, #%n3"
203c488f 841 [(set_attr "conds" "set")]
842)
843
844;; Convert the sequence
845;; sub rd, rn, #1
846;; cmn rd, #1 (equivalent to cmp rd, #-1)
847;; bne dest
848;; into
849;; subs rd, rn, #1
850;; bcs dest ((unsigned)rn >= 1)
851;; similarly for the beq variant using bcc.
852;; This is a common looping idiom (while (n--))
853(define_peephole2
372575c7 854 [(set (match_operand:SI 0 "arm_general_register_operand" "")
855 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 856 (const_int -1)))
857 (set (match_operand 2 "cc_register" "")
858 (compare (match_dup 0) (const_int -1)))
859 (set (pc)
860 (if_then_else (match_operator 3 "equality_operator"
861 [(match_dup 2) (const_int 0)])
862 (match_operand 4 "" "")
863 (match_operand 5 "" "")))]
25f905c2 864 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 865 [(parallel[
866 (set (match_dup 2)
867 (compare:CC
868 (match_dup 1) (const_int 1)))
869 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
870 (set (pc)
871 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
872 (match_dup 4)
873 (match_dup 5)))]
874 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
875 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
876 ? GEU : LTU),
877 VOIDmode,
878 operands[2], const0_rtx);"
879)
880
ebcc79bc 881;; The next four insns work because they compare the result with one of
882;; the operands, and we know that the use of the condition code is
883;; either GEU or LTU, so we can use the carry flag from the addition
884;; instead of doing the compare a second time.
885(define_insn "*addsi3_compare_op1"
bd5b4116 886 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 887 (compare:CC_C
888 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
889 (match_operand:SI 2 "arm_add_operand" "rI,L"))
890 (match_dup 1)))
891 (set (match_operand:SI 0 "s_register_operand" "=r,r")
892 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 893 "TARGET_32BIT"
ebcc79bc 894 "@
25f905c2 895 add%.\\t%0, %1, %2
896 sub%.\\t%0, %1, #%n2"
0d66636f 897 [(set_attr "conds" "set")]
898)
ebcc79bc 899
900(define_insn "*addsi3_compare_op2"
bd5b4116 901 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 902 (compare:CC_C
903 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
904 (match_operand:SI 2 "arm_add_operand" "rI,L"))
905 (match_dup 2)))
5565501b 906 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 907 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 908 "TARGET_32BIT"
5565501b 909 "@
25f905c2 910 add%.\\t%0, %1, %2
911 sub%.\\t%0, %1, #%n2"
0d66636f 912 [(set_attr "conds" "set")]
913)
9c08d1fa 914
ebcc79bc 915(define_insn "*compare_addsi2_op0"
bd5b4116 916 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 917 (compare:CC_C
918 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
919 (match_operand:SI 1 "arm_add_operand" "rI,L"))
920 (match_dup 0)))]
25f905c2 921 "TARGET_32BIT"
ebcc79bc 922 "@
923 cmn%?\\t%0, %1
924 cmp%?\\t%0, #%n1"
0d66636f 925 [(set_attr "conds" "set")]
926)
ebcc79bc 927
928(define_insn "*compare_addsi2_op1"
bd5b4116 929 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 930 (compare:CC_C
931 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
932 (match_operand:SI 1 "arm_add_operand" "rI,L"))
933 (match_dup 1)))]
25f905c2 934 "TARGET_32BIT"
ebcc79bc 935 "@
936 cmn%?\\t%0, %1
937 cmp%?\\t%0, #%n1"
0d66636f 938 [(set_attr "conds" "set")]
939)
ebcc79bc 940
080c0b9a 941(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 942 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 943 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 944 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 945 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 946 "TARGET_32BIT"
ebcc79bc 947 "adc%?\\t%0, %1, %2"
cffb2a26 948 [(set_attr "conds" "use")]
949)
ebcc79bc 950
080c0b9a 951(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 952 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 953 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
954 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 955 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 956 "TARGET_32BIT"
ebcc79bc 957 "adc%?\\t%0, %1, %2"
0d66636f 958 [(set_attr "conds" "use")]
959)
ebcc79bc 960
080c0b9a 961(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 962 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 963 (plus:SI (plus:SI
964 (match_operator:SI 2 "shift_operator"
965 [(match_operand:SI 3 "s_register_operand" "r")
966 (match_operand:SI 4 "reg_or_int_operand" "rM")])
967 (match_operand:SI 1 "s_register_operand" "r"))
968 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 969 "TARGET_32BIT"
080c0b9a 970 "adc%?\\t%0, %1, %3%S2"
971 [(set_attr "conds" "use")
972 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
973 (const_string "alu_shift")
974 (const_string "alu_shift_reg")))]
cffb2a26 975)
ebcc79bc 976
25f905c2 977(define_expand "incscc"
978 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
979 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
980 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
981 (match_operand:SI 1 "s_register_operand" "0,?r")))]
982 "TARGET_32BIT"
983 ""
984)
985
986(define_insn "*arm_incscc"
9c08d1fa 987 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 988 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 989 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 990 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 991 "TARGET_ARM"
5565501b 992 "@
993 add%d2\\t%0, %1, #1
994 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 995 [(set_attr "conds" "use")
215b30b3 996 (set_attr "length" "4,8")]
997)
9c08d1fa 998
d795fb69 999; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1000(define_split
1001 [(set (match_operand:SI 0 "s_register_operand" "")
1002 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1003 (match_operand:SI 2 "s_register_operand" ""))
1004 (const_int -1)))
1005 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1006 "TARGET_32BIT"
d795fb69 1007 [(set (match_dup 3) (match_dup 1))
1008 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1009 "
1010 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1011")
1012
604f3a0a 1013(define_expand "addsf3"
1014 [(set (match_operand:SF 0 "s_register_operand" "")
1015 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1016 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 1017 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1018 "
a2cd141b 1019 if (TARGET_MAVERICK
604f3a0a 1020 && !cirrus_fp_register (operands[2], SFmode))
1021 operands[2] = force_reg (SFmode, operands[2]);
1022")
1023
604f3a0a 1024(define_expand "adddf3"
1025 [(set (match_operand:DF 0 "s_register_operand" "")
1026 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1027 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1028 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1029 "
a2cd141b 1030 if (TARGET_MAVERICK
604f3a0a 1031 && !cirrus_fp_register (operands[2], DFmode))
1032 operands[2] = force_reg (DFmode, operands[2]);
1033")
1034
cffb2a26 1035(define_expand "subdi3"
1036 [(parallel
1037 [(set (match_operand:DI 0 "s_register_operand" "")
1038 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1039 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1040 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1041 "TARGET_EITHER"
1042 "
a2cd141b 1043 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1044 && TARGET_32BIT
7d57ec45 1045 && cirrus_fp_register (operands[0], DImode)
1046 && cirrus_fp_register (operands[1], DImode))
1047 {
1048 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1049 DONE;
1050 }
1051
25f905c2 1052 if (TARGET_THUMB1)
cffb2a26 1053 {
1054 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1055 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1056 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1057 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1058 }
1059 "
1060)
1061
1062(define_insn "*arm_subdi3"
1063 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1064 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1065 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1066 (clobber (reg:CC CC_REGNUM))]
94829feb 1067 "TARGET_32BIT && !TARGET_NEON"
97499065 1068 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1069 [(set_attr "conds" "clob")
1070 (set_attr "length" "8")]
1071)
1072
1073(define_insn "*thumb_subdi3"
1074 [(set (match_operand:DI 0 "register_operand" "=l")
1075 (minus:DI (match_operand:DI 1 "register_operand" "0")
1076 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1077 (clobber (reg:CC CC_REGNUM))]
25f905c2 1078 "TARGET_THUMB1"
cffb2a26 1079 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1080 [(set_attr "length" "4")]
1081)
9c08d1fa 1082
f7fbdd4a 1083(define_insn "*subdi_di_zesidi"
cffb2a26 1084 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1085 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1086 (zero_extend:DI
cffb2a26 1087 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1088 (clobber (reg:CC CC_REGNUM))]
25f905c2 1089 "TARGET_32BIT"
97499065 1090 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1091 [(set_attr "conds" "clob")
1092 (set_attr "length" "8")]
1093)
9c08d1fa 1094
f7fbdd4a 1095(define_insn "*subdi_di_sesidi"
cffb2a26 1096 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1097 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1098 (sign_extend:DI
cffb2a26 1099 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1100 (clobber (reg:CC CC_REGNUM))]
25f905c2 1101 "TARGET_32BIT"
97499065 1102 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1103 [(set_attr "conds" "clob")
1104 (set_attr "length" "8")]
1105)
9c08d1fa 1106
f7fbdd4a 1107(define_insn "*subdi_zesidi_di"
cffb2a26 1108 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1109 (minus:DI (zero_extend:DI
cffb2a26 1110 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1111 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1112 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1113 "TARGET_ARM"
97499065 1114 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1115 [(set_attr "conds" "clob")
1116 (set_attr "length" "8")]
1117)
9c08d1fa 1118
f7fbdd4a 1119(define_insn "*subdi_sesidi_di"
cffb2a26 1120 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1121 (minus:DI (sign_extend:DI
cffb2a26 1122 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1123 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1124 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1125 "TARGET_ARM"
97499065 1126 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1127 [(set_attr "conds" "clob")
1128 (set_attr "length" "8")]
1129)
9c08d1fa 1130
f7fbdd4a 1131(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1132 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1133 (minus:DI (zero_extend:DI
cffb2a26 1134 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1135 (zero_extend:DI
cffb2a26 1136 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1137 (clobber (reg:CC CC_REGNUM))]
25f905c2 1138 "TARGET_32BIT"
1139 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1140 [(set_attr "conds" "clob")
1141 (set_attr "length" "8")]
1142)
b11cae9e 1143
87b22bf7 1144(define_expand "subsi3"
cffb2a26 1145 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1146 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1147 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1148 "TARGET_EITHER"
87b22bf7 1149 "
1150 if (GET_CODE (operands[1]) == CONST_INT)
1151 {
25f905c2 1152 if (TARGET_32BIT)
cffb2a26 1153 {
96f57e36 1154 arm_split_constant (MINUS, SImode, NULL_RTX,
1155 INTVAL (operands[1]), operands[0],
e1ba4a27 1156 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1157 DONE;
1158 }
25f905c2 1159 else /* TARGET_THUMB1 */
cffb2a26 1160 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1161 }
cffb2a26 1162 "
1163)
87b22bf7 1164
747b7458 1165(define_insn "thumb1_subsi3_insn"
cffb2a26 1166 [(set (match_operand:SI 0 "register_operand" "=l")
1167 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1168 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1169 "TARGET_THUMB1"
cffb2a26 1170 "sub\\t%0, %1, %2"
747b7458 1171 [(set_attr "length" "2")
1172 (set_attr "conds" "set")])
cffb2a26 1173
25f905c2 1174; ??? Check Thumb-2 split length
a0f94409 1175(define_insn_and_split "*arm_subsi3_insn"
080c0b9a 1176 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
bccb5444 1177 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1178 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
25f905c2 1179 "TARGET_32BIT"
e2348bcb 1180 "@
87b22bf7 1181 rsb%?\\t%0, %2, %1
aaa37ad6 1182 sub%?\\t%0, %1, %2
080c0b9a 1183 sub%?\\t%0, %1, %2
1184 #
87b22bf7 1185 #"
080c0b9a 1186 "&& ((GET_CODE (operands[1]) == CONST_INT
1187 && !const_ok_for_arm (INTVAL (operands[1])))
1188 || (GET_CODE (operands[2]) == CONST_INT
1189 && !const_ok_for_arm (INTVAL (operands[2]))))"
87b22bf7 1190 [(clobber (const_int 0))]
1191 "
96f57e36 1192 arm_split_constant (MINUS, SImode, curr_insn,
1193 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1194 DONE;
cffb2a26 1195 "
080c0b9a 1196 [(set_attr "length" "4,4,4,16,16")
a0f94409 1197 (set_attr "predicable" "yes")]
1198)
1199
1200(define_peephole2
1201 [(match_scratch:SI 3 "r")
372575c7 1202 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1203 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1204 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1205 "TARGET_32BIT
a0f94409 1206 && !const_ok_for_arm (INTVAL (operands[1]))
1207 && const_ok_for_arm (~INTVAL (operands[1]))"
1208 [(set (match_dup 3) (match_dup 1))
1209 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1210 ""
cffb2a26 1211)
b11cae9e 1212
f7fbdd4a 1213(define_insn "*subsi3_compare0"
bd5b4116 1214 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1215 (compare:CC_NOOV
1216 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1217 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1218 (const_int 0)))
9c08d1fa 1219 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1220 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1221 "TARGET_32BIT"
e2348bcb 1222 "@
25f905c2 1223 sub%.\\t%0, %1, %2
1224 rsb%.\\t%0, %2, %1"
cffb2a26 1225 [(set_attr "conds" "set")]
1226)
9c08d1fa 1227
080c0b9a 1228(define_insn "*subsi3_compare"
1229 [(set (reg:CC CC_REGNUM)
1230 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1231 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1232 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1233 (minus:SI (match_dup 1) (match_dup 2)))]
1234 "TARGET_32BIT"
1235 "@
1236 sub%.\\t%0, %1, %2
1237 rsb%.\\t%0, %2, %1"
1238 [(set_attr "conds" "set")]
1239)
1240
25f905c2 1241(define_expand "decscc"
1242 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1243 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1244 (match_operator:SI 2 "arm_comparison_operator"
1245 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1246 "TARGET_32BIT"
1247 ""
1248)
1249
1250(define_insn "*arm_decscc"
cffb2a26 1251 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1252 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1253 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1254 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1255 "TARGET_ARM"
e2348bcb 1256 "@
215b30b3 1257 sub%d2\\t%0, %1, #1
1258 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1259 [(set_attr "conds" "use")
1260 (set_attr "length" "*,8")]
1261)
9c08d1fa 1262
604f3a0a 1263(define_expand "subsf3"
1264 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1265 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1266 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1267 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1268 "
a2cd141b 1269 if (TARGET_MAVERICK)
604f3a0a 1270 {
1271 if (!cirrus_fp_register (operands[1], SFmode))
1272 operands[1] = force_reg (SFmode, operands[1]);
1273 if (!cirrus_fp_register (operands[2], SFmode))
1274 operands[2] = force_reg (SFmode, operands[2]);
1275 }
1276")
1277
604f3a0a 1278(define_expand "subdf3"
1279 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1280 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1281 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1282 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1283 "
a2cd141b 1284 if (TARGET_MAVERICK)
604f3a0a 1285 {
1286 if (!cirrus_fp_register (operands[1], DFmode))
1287 operands[1] = force_reg (DFmode, operands[1]);
1288 if (!cirrus_fp_register (operands[2], DFmode))
1289 operands[2] = force_reg (DFmode, operands[2]);
1290 }
1291")
1292
b11cae9e 1293\f
1294;; Multiplication insns
1295
cffb2a26 1296(define_expand "mulsi3"
1297 [(set (match_operand:SI 0 "s_register_operand" "")
1298 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1299 (match_operand:SI 1 "s_register_operand" "")))]
1300 "TARGET_EITHER"
1301 ""
1302)
1303
9c08d1fa 1304;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1305(define_insn "*arm_mulsi3"
1306 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1307 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1308 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1309 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1310 "mul%?\\t%0, %2, %1"
a2cd141b 1311 [(set_attr "insn" "mul")
0d66636f 1312 (set_attr "predicable" "yes")]
cffb2a26 1313)
1314
58d7d654 1315(define_insn "*arm_mulsi3_v6"
1316 [(set (match_operand:SI 0 "s_register_operand" "=r")
1317 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1318 (match_operand:SI 2 "s_register_operand" "r")))]
1319 "TARGET_32BIT && arm_arch6"
1320 "mul%?\\t%0, %1, %2"
1321 [(set_attr "insn" "mul")
1322 (set_attr "predicable" "yes")]
1323)
1324
215b30b3 1325; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1326; 1 and 2; are the same, because reload will make operand 0 match
1327; operand 1 without realizing that this conflicts with operand 2. We fix
1328; this by adding another alternative to match this case, and then `reload'
1329; it ourselves. This alternative must come first.
cffb2a26 1330(define_insn "*thumb_mulsi3"
1331 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1332 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1333 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1334 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1335 "*
1336 if (which_alternative < 2)
20c4e896 1337 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1338 else
20c4e896 1339 return \"mul\\t%0, %2\";
cffb2a26 1340 "
1341 [(set_attr "length" "4,4,2")
a2cd141b 1342 (set_attr "insn" "mul")]
cffb2a26 1343)
b11cae9e 1344
58d7d654 1345(define_insn "*thumb_mulsi3_v6"
1346 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1347 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1348 (match_operand:SI 2 "register_operand" "l,0,0")))]
1349 "TARGET_THUMB1 && arm_arch6"
1350 "@
1490694c 1351 mul\\t%0, %2
1352 mul\\t%0, %1
58d7d654 1353 mul\\t%0, %1"
1354 [(set_attr "length" "2")
1355 (set_attr "insn" "mul")]
1356)
1357
f7fbdd4a 1358(define_insn "*mulsi3_compare0"
bd5b4116 1359 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1360 (compare:CC_NOOV (mult:SI
1361 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1362 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1363 (const_int 0)))
1364 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1365 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1366 "TARGET_ARM && !arm_arch6"
1367 "mul%.\\t%0, %2, %1"
1368 [(set_attr "conds" "set")
1369 (set_attr "insn" "muls")]
1370)
1371
1372(define_insn "*mulsi3_compare0_v6"
1373 [(set (reg:CC_NOOV CC_REGNUM)
1374 (compare:CC_NOOV (mult:SI
1375 (match_operand:SI 2 "s_register_operand" "r")
1376 (match_operand:SI 1 "s_register_operand" "r"))
1377 (const_int 0)))
1378 (set (match_operand:SI 0 "s_register_operand" "=r")
1379 (mult:SI (match_dup 2) (match_dup 1)))]
1380 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1381 "mul%.\\t%0, %2, %1"
cffb2a26 1382 [(set_attr "conds" "set")
a2cd141b 1383 (set_attr "insn" "muls")]
cffb2a26 1384)
9c08d1fa 1385
f7fbdd4a 1386(define_insn "*mulsi_compare0_scratch"
bd5b4116 1387 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1388 (compare:CC_NOOV (mult:SI
1389 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1390 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1391 (const_int 0)))
1392 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1393 "TARGET_ARM && !arm_arch6"
1394 "mul%.\\t%0, %2, %1"
1395 [(set_attr "conds" "set")
1396 (set_attr "insn" "muls")]
1397)
1398
1399(define_insn "*mulsi_compare0_scratch_v6"
1400 [(set (reg:CC_NOOV CC_REGNUM)
1401 (compare:CC_NOOV (mult:SI
1402 (match_operand:SI 2 "s_register_operand" "r")
1403 (match_operand:SI 1 "s_register_operand" "r"))
1404 (const_int 0)))
1405 (clobber (match_scratch:SI 0 "=r"))]
1406 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1407 "mul%.\\t%0, %2, %1"
cffb2a26 1408 [(set_attr "conds" "set")
a2cd141b 1409 (set_attr "insn" "muls")]
cffb2a26 1410)
9c08d1fa 1411
b11cae9e 1412;; Unnamed templates to match MLA instruction.
1413
f7fbdd4a 1414(define_insn "*mulsi3addsi"
9c08d1fa 1415 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1416 (plus:SI
9c08d1fa 1417 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1418 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1419 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1420 "TARGET_32BIT && !arm_arch6"
1421 "mla%?\\t%0, %2, %1, %3"
1422 [(set_attr "insn" "mla")
1423 (set_attr "predicable" "yes")]
1424)
1425
1426(define_insn "*mulsi3addsi_v6"
1427 [(set (match_operand:SI 0 "s_register_operand" "=r")
1428 (plus:SI
1429 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1430 (match_operand:SI 1 "s_register_operand" "r"))
1431 (match_operand:SI 3 "s_register_operand" "r")))]
1432 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1433 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1434 [(set_attr "insn" "mla")
0d66636f 1435 (set_attr "predicable" "yes")]
1436)
b11cae9e 1437
f7fbdd4a 1438(define_insn "*mulsi3addsi_compare0"
bd5b4116 1439 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1440 (compare:CC_NOOV
1441 (plus:SI (mult:SI
1442 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1443 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1444 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1445 (const_int 0)))
9c08d1fa 1446 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1447 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1448 (match_dup 3)))]
58d7d654 1449 "TARGET_ARM && arm_arch6"
1450 "mla%.\\t%0, %2, %1, %3"
1451 [(set_attr "conds" "set")
1452 (set_attr "insn" "mlas")]
1453)
1454
1455(define_insn "*mulsi3addsi_compare0_v6"
1456 [(set (reg:CC_NOOV CC_REGNUM)
1457 (compare:CC_NOOV
1458 (plus:SI (mult:SI
1459 (match_operand:SI 2 "s_register_operand" "r")
1460 (match_operand:SI 1 "s_register_operand" "r"))
1461 (match_operand:SI 3 "s_register_operand" "r"))
1462 (const_int 0)))
1463 (set (match_operand:SI 0 "s_register_operand" "=r")
1464 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1465 (match_dup 3)))]
1466 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1467 "mla%.\\t%0, %2, %1, %3"
0d66636f 1468 [(set_attr "conds" "set")
a2cd141b 1469 (set_attr "insn" "mlas")]
0d66636f 1470)
9c08d1fa 1471
f7fbdd4a 1472(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1473 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1474 (compare:CC_NOOV
1475 (plus:SI (mult:SI
1476 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1477 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1478 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1479 (const_int 0)))
9c08d1fa 1480 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1481 "TARGET_ARM && !arm_arch6"
1482 "mla%.\\t%0, %2, %1, %3"
1483 [(set_attr "conds" "set")
1484 (set_attr "insn" "mlas")]
1485)
1486
1487(define_insn "*mulsi3addsi_compare0_scratch_v6"
1488 [(set (reg:CC_NOOV CC_REGNUM)
1489 (compare:CC_NOOV
1490 (plus:SI (mult:SI
1491 (match_operand:SI 2 "s_register_operand" "r")
1492 (match_operand:SI 1 "s_register_operand" "r"))
1493 (match_operand:SI 3 "s_register_operand" "r"))
1494 (const_int 0)))
1495 (clobber (match_scratch:SI 0 "=r"))]
1496 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1497 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1498 [(set_attr "conds" "set")
a2cd141b 1499 (set_attr "insn" "mlas")]
cffb2a26 1500)
f7fbdd4a 1501
89545238 1502(define_insn "*mulsi3subsi"
1503 [(set (match_operand:SI 0 "s_register_operand" "=r")
1504 (minus:SI
1505 (match_operand:SI 3 "s_register_operand" "r")
1506 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1507 (match_operand:SI 1 "s_register_operand" "r"))))]
1508 "TARGET_32BIT && arm_arch_thumb2"
1509 "mls%?\\t%0, %2, %1, %3"
1510 [(set_attr "insn" "mla")
1511 (set_attr "predicable" "yes")]
1512)
1513
5cdca009 1514(define_expand "maddsidi4"
1515 [(set (match_operand:DI 0 "s_register_operand" "")
1516 (plus:DI
1517 (mult:DI
1518 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1519 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1520 (match_operand:DI 3 "s_register_operand" "")))]
1521 "TARGET_32BIT && arm_arch3m"
1522 "")
82b85d08 1523
1524(define_insn "*mulsidi3adddi"
fe8dbf85 1525 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1526 (plus:DI
215b30b3 1527 (mult:DI
fe8dbf85 1528 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1529 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1530 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1531 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1532 "smlal%?\\t%Q0, %R0, %3, %2"
1533 [(set_attr "insn" "smlal")
1534 (set_attr "predicable" "yes")]
1535)
1536
1537(define_insn "*mulsidi3adddi_v6"
1538 [(set (match_operand:DI 0 "s_register_operand" "=r")
1539 (plus:DI
1540 (mult:DI
1541 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1542 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1543 (match_operand:DI 1 "s_register_operand" "0")))]
1544 "TARGET_32BIT && arm_arch6"
fe8dbf85 1545 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1546 [(set_attr "insn" "smlal")
0d66636f 1547 (set_attr "predicable" "yes")]
1548)
82b85d08 1549
957788b0 1550;; 32x32->64 widening multiply.
1551;; As with mulsi3, the only difference between the v3-5 and v6+
1552;; versions of these patterns is the requirement that the output not
1553;; overlap the inputs, but that still means we have to have a named
1554;; expander and two different starred insns.
1555
1556(define_expand "mulsidi3"
1557 [(set (match_operand:DI 0 "s_register_operand" "")
1558 (mult:DI
1559 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1560 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1561 "TARGET_32BIT && arm_arch3m"
1562 ""
1563)
1564
1565(define_insn "*mulsidi3_nov6"
f7fbdd4a 1566 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1567 (mult:DI
1568 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1569 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1570 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1571 "smull%?\\t%Q0, %R0, %1, %2"
1572 [(set_attr "insn" "smull")
1573 (set_attr "predicable" "yes")]
1574)
1575
957788b0 1576(define_insn "*mulsidi3_v6"
58d7d654 1577 [(set (match_operand:DI 0 "s_register_operand" "=r")
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"))))]
1581 "TARGET_32BIT && arm_arch6"
97499065 1582 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1583 [(set_attr "insn" "smull")
0d66636f 1584 (set_attr "predicable" "yes")]
1585)
f7fbdd4a 1586
957788b0 1587(define_expand "umulsidi3"
1588 [(set (match_operand:DI 0 "s_register_operand" "")
1589 (mult:DI
1590 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1591 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1592 "TARGET_32BIT && arm_arch3m"
1593 ""
1594)
1595
1596(define_insn "*umulsidi3_nov6"
f7fbdd4a 1597 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1598 (mult:DI
1599 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1600 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1601 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1602 "umull%?\\t%Q0, %R0, %1, %2"
1603 [(set_attr "insn" "umull")
1604 (set_attr "predicable" "yes")]
1605)
1606
957788b0 1607(define_insn "*umulsidi3_v6"
58d7d654 1608 [(set (match_operand:DI 0 "s_register_operand" "=r")
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"))))]
1612 "TARGET_32BIT && arm_arch6"
97499065 1613 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1614 [(set_attr "insn" "umull")
0d66636f 1615 (set_attr "predicable" "yes")]
1616)
b11cae9e 1617
5cdca009 1618(define_expand "umaddsidi4"
1619 [(set (match_operand:DI 0 "s_register_operand" "")
1620 (plus:DI
1621 (mult:DI
1622 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1623 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1624 (match_operand:DI 3 "s_register_operand" "")))]
1625 "TARGET_32BIT && arm_arch3m"
1626 "")
82b85d08 1627
1628(define_insn "*umulsidi3adddi"
8ead09f9 1629 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1630 (plus:DI
215b30b3 1631 (mult:DI
fe8dbf85 1632 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1633 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1634 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1635 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1636 "umlal%?\\t%Q0, %R0, %3, %2"
1637 [(set_attr "insn" "umlal")
1638 (set_attr "predicable" "yes")]
1639)
1640
1641(define_insn "*umulsidi3adddi_v6"
1642 [(set (match_operand:DI 0 "s_register_operand" "=r")
1643 (plus:DI
1644 (mult:DI
1645 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1646 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1647 (match_operand:DI 1 "s_register_operand" "0")))]
1648 "TARGET_32BIT && arm_arch6"
fe8dbf85 1649 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1650 [(set_attr "insn" "umlal")
0d66636f 1651 (set_attr "predicable" "yes")]
1652)
82b85d08 1653
957788b0 1654(define_expand "smulsi3_highpart"
1655 [(parallel
1656 [(set (match_operand:SI 0 "s_register_operand" "")
1657 (truncate:SI
1658 (lshiftrt:DI
1659 (mult:DI
1660 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1661 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1662 (const_int 32))))
1663 (clobber (match_scratch:SI 3 ""))])]
1664 "TARGET_32BIT && arm_arch3m"
1665 ""
1666)
1667
1668(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1669 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1670 (truncate:SI
1671 (lshiftrt:DI
215b30b3 1672 (mult:DI
e5fea38e 1673 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1674 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1675 (const_int 32))))
1676 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1677 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1678 "smull%?\\t%3, %0, %2, %1"
1679 [(set_attr "insn" "smull")
1680 (set_attr "predicable" "yes")]
1681)
1682
957788b0 1683(define_insn "*smulsi3_highpart_v6"
58d7d654 1684 [(set (match_operand:SI 0 "s_register_operand" "=r")
1685 (truncate:SI
1686 (lshiftrt:DI
1687 (mult:DI
1688 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1689 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1690 (const_int 32))))
1691 (clobber (match_scratch:SI 3 "=r"))]
1692 "TARGET_32BIT && arm_arch6"
f082f1c4 1693 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1694 [(set_attr "insn" "smull")
0d66636f 1695 (set_attr "predicable" "yes")]
cffb2a26 1696)
f082f1c4 1697
957788b0 1698(define_expand "umulsi3_highpart"
1699 [(parallel
1700 [(set (match_operand:SI 0 "s_register_operand" "")
1701 (truncate:SI
1702 (lshiftrt:DI
1703 (mult:DI
1704 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1705 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1706 (const_int 32))))
1707 (clobber (match_scratch:SI 3 ""))])]
1708 "TARGET_32BIT && arm_arch3m"
1709 ""
1710)
1711
1712(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1713 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1714 (truncate:SI
1715 (lshiftrt:DI
215b30b3 1716 (mult:DI
e5fea38e 1717 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1718 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1719 (const_int 32))))
1720 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1721 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1722 "umull%?\\t%3, %0, %2, %1"
1723 [(set_attr "insn" "umull")
1724 (set_attr "predicable" "yes")]
1725)
1726
957788b0 1727(define_insn "*umulsi3_highpart_v6"
58d7d654 1728 [(set (match_operand:SI 0 "s_register_operand" "=r")
1729 (truncate:SI
1730 (lshiftrt:DI
1731 (mult:DI
1732 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1733 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1734 (const_int 32))))
1735 (clobber (match_scratch:SI 3 "=r"))]
1736 "TARGET_32BIT && arm_arch6"
f082f1c4 1737 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1738 [(set_attr "insn" "umull")
0d66636f 1739 (set_attr "predicable" "yes")]
cffb2a26 1740)
f082f1c4 1741
331beb1a 1742(define_insn "mulhisi3"
1743 [(set (match_operand:SI 0 "s_register_operand" "=r")
1744 (mult:SI (sign_extend:SI
1745 (match_operand:HI 1 "s_register_operand" "%r"))
1746 (sign_extend:SI
1747 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1748 "TARGET_DSP_MULTIPLY"
61a2d04c 1749 "smulbb%?\\t%0, %1, %2"
a2cd141b 1750 [(set_attr "insn" "smulxy")
fec538d9 1751 (set_attr "predicable" "yes")]
1752)
1753
1754(define_insn "*mulhisi3tb"
1755 [(set (match_operand:SI 0 "s_register_operand" "=r")
1756 (mult:SI (ashiftrt:SI
1757 (match_operand:SI 1 "s_register_operand" "r")
1758 (const_int 16))
1759 (sign_extend:SI
1760 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1761 "TARGET_DSP_MULTIPLY"
fec538d9 1762 "smultb%?\\t%0, %1, %2"
a2cd141b 1763 [(set_attr "insn" "smulxy")
fec538d9 1764 (set_attr "predicable" "yes")]
1765)
1766
1767(define_insn "*mulhisi3bt"
1768 [(set (match_operand:SI 0 "s_register_operand" "=r")
1769 (mult:SI (sign_extend:SI
1770 (match_operand:HI 1 "s_register_operand" "r"))
1771 (ashiftrt:SI
1772 (match_operand:SI 2 "s_register_operand" "r")
1773 (const_int 16))))]
25f905c2 1774 "TARGET_DSP_MULTIPLY"
fec538d9 1775 "smulbt%?\\t%0, %1, %2"
a2cd141b 1776 [(set_attr "insn" "smulxy")
fec538d9 1777 (set_attr "predicable" "yes")]
1778)
1779
1780(define_insn "*mulhisi3tt"
1781 [(set (match_operand:SI 0 "s_register_operand" "=r")
1782 (mult:SI (ashiftrt:SI
1783 (match_operand:SI 1 "s_register_operand" "r")
1784 (const_int 16))
1785 (ashiftrt:SI
1786 (match_operand:SI 2 "s_register_operand" "r")
1787 (const_int 16))))]
25f905c2 1788 "TARGET_DSP_MULTIPLY"
fec538d9 1789 "smultt%?\\t%0, %1, %2"
a2cd141b 1790 [(set_attr "insn" "smulxy")
fec538d9 1791 (set_attr "predicable" "yes")]
331beb1a 1792)
1793
5cdca009 1794(define_insn "maddhisi4"
331beb1a 1795 [(set (match_operand:SI 0 "s_register_operand" "=r")
5cdca009 1796 (plus:SI (match_operand:SI 3 "s_register_operand" "r")
331beb1a 1797 (mult:SI (sign_extend:SI
5cdca009 1798 (match_operand:HI 1 "s_register_operand" "%r"))
331beb1a 1799 (sign_extend:SI
5cdca009 1800 (match_operand:HI 2 "s_register_operand" "r")))))]
25f905c2 1801 "TARGET_DSP_MULTIPLY"
5cdca009 1802 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1803 [(set_attr "insn" "smlaxy")
fec538d9 1804 (set_attr "predicable" "yes")]
331beb1a 1805)
1806
5cdca009 1807(define_insn "*maddhidi4"
331beb1a 1808 [(set (match_operand:DI 0 "s_register_operand" "=r")
1809 (plus:DI
5cdca009 1810 (match_operand:DI 3 "s_register_operand" "0")
331beb1a 1811 (mult:DI (sign_extend:DI
5cdca009 1812 (match_operand:HI 1 "s_register_operand" "%r"))
331beb1a 1813 (sign_extend:DI
5cdca009 1814 (match_operand:HI 2 "s_register_operand" "r")))))]
25f905c2 1815 "TARGET_DSP_MULTIPLY"
5cdca009 1816 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1817 [(set_attr "insn" "smlalxy")
fec538d9 1818 (set_attr "predicable" "yes")])
331beb1a 1819
604f3a0a 1820(define_expand "mulsf3"
1821 [(set (match_operand:SF 0 "s_register_operand" "")
1822 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1823 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1824 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1825 "
a2cd141b 1826 if (TARGET_MAVERICK
604f3a0a 1827 && !cirrus_fp_register (operands[2], SFmode))
1828 operands[2] = force_reg (SFmode, operands[2]);
1829")
1830
604f3a0a 1831(define_expand "muldf3"
1832 [(set (match_operand:DF 0 "s_register_operand" "")
1833 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1834 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1835 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1836 "
a2cd141b 1837 if (TARGET_MAVERICK
604f3a0a 1838 && !cirrus_fp_register (operands[2], DFmode))
1839 operands[2] = force_reg (DFmode, operands[2]);
1840")
b11cae9e 1841\f
1842;; Division insns
1843
7db9af5d 1844(define_expand "divsf3"
1845 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1846 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1847 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1848 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1849 "")
9c08d1fa 1850
7db9af5d 1851(define_expand "divdf3"
1852 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1853 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1854 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1855 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1856 "")
b11cae9e 1857\f
1858;; Modulo insns
1859
7db9af5d 1860(define_expand "modsf3"
1861 [(set (match_operand:SF 0 "s_register_operand" "")
1862 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1863 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1864 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1865 "")
9c08d1fa 1866
7db9af5d 1867(define_expand "moddf3"
1868 [(set (match_operand:DF 0 "s_register_operand" "")
1869 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1870 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1871 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1872 "")
b11cae9e 1873\f
1874;; Boolean and,ior,xor insns
1875
f6ebffac 1876;; Split up double word logical operations
1877
1878;; Split up simple DImode logical operations. Simply perform the logical
1879;; operation on the upper and lower halves of the registers.
1880(define_split
1881 [(set (match_operand:DI 0 "s_register_operand" "")
1882 (match_operator:DI 6 "logical_binary_operator"
1883 [(match_operand:DI 1 "s_register_operand" "")
1884 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1885 "TARGET_32BIT && reload_completed
e2669ea7 1886 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1887 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1888 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1889 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1890 "
215b30b3 1891 {
1892 operands[3] = gen_highpart (SImode, operands[0]);
1893 operands[0] = gen_lowpart (SImode, operands[0]);
1894 operands[4] = gen_highpart (SImode, operands[1]);
1895 operands[1] = gen_lowpart (SImode, operands[1]);
1896 operands[5] = gen_highpart (SImode, operands[2]);
1897 operands[2] = gen_lowpart (SImode, operands[2]);
1898 }"
1899)
f6ebffac 1900
f6ebffac 1901(define_split
1902 [(set (match_operand:DI 0 "s_register_operand" "")
1903 (match_operator:DI 6 "logical_binary_operator"
1904 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1905 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1906 "TARGET_32BIT && reload_completed"
f6ebffac 1907 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1908 (set (match_dup 3) (match_op_dup:SI 6
1909 [(ashiftrt:SI (match_dup 2) (const_int 31))
1910 (match_dup 4)]))]
1911 "
215b30b3 1912 {
1913 operands[3] = gen_highpart (SImode, operands[0]);
1914 operands[0] = gen_lowpart (SImode, operands[0]);
1915 operands[4] = gen_highpart (SImode, operands[1]);
1916 operands[1] = gen_lowpart (SImode, operands[1]);
1917 operands[5] = gen_highpart (SImode, operands[2]);
1918 operands[2] = gen_lowpart (SImode, operands[2]);
1919 }"
1920)
f6ebffac 1921
f6ebffac 1922;; The zero extend of operand 2 means we can just copy the high part of
1923;; operand1 into operand0.
1924(define_split
1925 [(set (match_operand:DI 0 "s_register_operand" "")
1926 (ior:DI
1927 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1928 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1929 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1930 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1931 (set (match_dup 3) (match_dup 4))]
1932 "
215b30b3 1933 {
1934 operands[4] = gen_highpart (SImode, operands[1]);
1935 operands[3] = gen_highpart (SImode, operands[0]);
1936 operands[0] = gen_lowpart (SImode, operands[0]);
1937 operands[1] = gen_lowpart (SImode, operands[1]);
1938 }"
1939)
f6ebffac 1940
1941;; The zero extend of operand 2 means we can just copy the high part of
1942;; operand1 into operand0.
1943(define_split
1944 [(set (match_operand:DI 0 "s_register_operand" "")
1945 (xor:DI
1946 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1947 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1948 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1949 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1950 (set (match_dup 3) (match_dup 4))]
1951 "
215b30b3 1952 {
1953 operands[4] = gen_highpart (SImode, operands[1]);
1954 operands[3] = gen_highpart (SImode, operands[0]);
1955 operands[0] = gen_lowpart (SImode, operands[0]);
1956 operands[1] = gen_lowpart (SImode, operands[1]);
1957 }"
1958)
f6ebffac 1959
e2669ea7 1960(define_expand "anddi3"
1961 [(set (match_operand:DI 0 "s_register_operand" "")
1962 (and:DI (match_operand:DI 1 "s_register_operand" "")
1963 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1964 "TARGET_32BIT"
1965 ""
1966)
1967
1968(define_insn "*anddi3_insn"
cffb2a26 1969 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1970 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1971 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 1972 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 1973 "#"
215b30b3 1974 [(set_attr "length" "8")]
1975)
b11cae9e 1976
a0f94409 1977(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1978 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1979 (and:DI (zero_extend:DI
1980 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1981 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1982 "TARGET_32BIT"
f6ebffac 1983 "#"
25f905c2 1984 "TARGET_32BIT && reload_completed"
a0f94409 1985 ; The zero extend of operand 2 clears the high word of the output
1986 ; operand.
1987 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1988 (set (match_dup 3) (const_int 0))]
1989 "
1990 {
1991 operands[3] = gen_highpart (SImode, operands[0]);
1992 operands[0] = gen_lowpart (SImode, operands[0]);
1993 operands[1] = gen_lowpart (SImode, operands[1]);
1994 }"
215b30b3 1995 [(set_attr "length" "8")]
1996)
b11cae9e 1997
f7fbdd4a 1998(define_insn "*anddi_sesdi_di"
cffb2a26 1999 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2000 (and:DI (sign_extend:DI
2001 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2002 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2003 "TARGET_32BIT"
f6ebffac 2004 "#"
cffb2a26 2005 [(set_attr "length" "8")]
2006)
b11cae9e 2007
87b22bf7 2008(define_expand "andsi3"
cffb2a26 2009 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2010 (and:SI (match_operand:SI 1 "s_register_operand" "")
2011 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2012 "TARGET_EITHER"
87b22bf7 2013 "
25f905c2 2014 if (TARGET_32BIT)
87b22bf7 2015 {
cffb2a26 2016 if (GET_CODE (operands[2]) == CONST_INT)
2017 {
47b5b27b 2018 if (INTVAL (operands[2]) == 255 && arm_arch6)
2019 {
2020 operands[1] = convert_to_mode (QImode, operands[1], 1);
2021 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2022 operands[1]));
2023 }
2024 else
2025 arm_split_constant (AND, SImode, NULL_RTX,
2026 INTVAL (operands[2]), operands[0],
2027 operands[1],
2028 optimize && can_create_pseudo_p ());
615caa51 2029
cffb2a26 2030 DONE;
2031 }
87b22bf7 2032 }
25f905c2 2033 else /* TARGET_THUMB1 */
cffb2a26 2034 {
2035 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2036 {
2037 rtx tmp = force_reg (SImode, operands[2]);
2038 if (rtx_equal_p (operands[0], operands[1]))
2039 operands[2] = tmp;
2040 else
2041 {
2042 operands[2] = operands[1];
2043 operands[1] = tmp;
2044 }
2045 }
cffb2a26 2046 else
2047 {
2048 int i;
2049
215b30b3 2050 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2051 {
215b30b3 2052 operands[2] = force_reg (SImode,
2053 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2054
747b7458 2055 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2056
2057 DONE;
2058 }
87b22bf7 2059
cffb2a26 2060 for (i = 9; i <= 31; i++)
2061 {
2062 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2063 {
2064 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2065 const0_rtx));
2066 DONE;
2067 }
215b30b3 2068 else if ((((HOST_WIDE_INT) 1) << i) - 1
2069 == ~INTVAL (operands[2]))
cffb2a26 2070 {
2071 rtx shift = GEN_INT (i);
2072 rtx reg = gen_reg_rtx (SImode);
2073
2074 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2075 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2076
2077 DONE;
2078 }
2079 }
2080
2081 operands[2] = force_reg (SImode, operands[2]);
2082 }
215b30b3 2083 }
2084 "
cffb2a26 2085)
2086
25f905c2 2087; ??? Check split length for Thumb-2
a0f94409 2088(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2089 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2090 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2091 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2092 "TARGET_32BIT"
5565501b 2093 "@
2094 and%?\\t%0, %1, %2
87b22bf7 2095 bic%?\\t%0, %1, #%B2
2096 #"
25f905c2 2097 "TARGET_32BIT
a0f94409 2098 && GET_CODE (operands[2]) == CONST_INT
2099 && !(const_ok_for_arm (INTVAL (operands[2]))
2100 || const_ok_for_arm (~INTVAL (operands[2])))"
2101 [(clobber (const_int 0))]
2102 "
96f57e36 2103 arm_split_constant (AND, SImode, curr_insn,
2104 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2105 DONE;
2106 "
0d66636f 2107 [(set_attr "length" "4,4,16")
2108 (set_attr "predicable" "yes")]
cffb2a26 2109)
2110
25f905c2 2111(define_insn "*thumb1_andsi3_insn"
cffb2a26 2112 [(set (match_operand:SI 0 "register_operand" "=l")
2113 (and:SI (match_operand:SI 1 "register_operand" "%0")
2114 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2115 "TARGET_THUMB1"
747b7458 2116 "and\\t%0, %2"
2117 [(set_attr "length" "2")
2118 (set_attr "conds" "set")])
87b22bf7 2119
f7fbdd4a 2120(define_insn "*andsi3_compare0"
bd5b4116 2121 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2122 (compare:CC_NOOV
2123 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2124 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2125 (const_int 0)))
cffb2a26 2126 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2127 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2128 "TARGET_32BIT"
5565501b 2129 "@
25f905c2 2130 and%.\\t%0, %1, %2
2131 bic%.\\t%0, %1, #%B2"
cffb2a26 2132 [(set_attr "conds" "set")]
2133)
9c08d1fa 2134
f7fbdd4a 2135(define_insn "*andsi3_compare0_scratch"
bd5b4116 2136 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2137 (compare:CC_NOOV
2138 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2139 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2140 (const_int 0)))
dd193d7c 2141 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2142 "TARGET_32BIT"
5565501b 2143 "@
2144 tst%?\\t%0, %1
25f905c2 2145 bic%.\\t%2, %0, #%B1"
0d66636f 2146 [(set_attr "conds" "set")]
2147)
9c08d1fa 2148
f7fbdd4a 2149(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2150 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2151 (compare:CC_NOOV (zero_extract:SI
2152 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2153 (match_operand 1 "const_int_operand" "n")
2154 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2155 (const_int 0)))]
25f905c2 2156 "TARGET_32BIT
cffb2a26 2157 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2158 && INTVAL (operands[1]) > 0
2159 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2160 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2161 "*
5c49a439 2162 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2163 << INTVAL (operands[2]));
40dbec34 2164 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2165 return \"\";
0d66636f 2166 "
2167 [(set_attr "conds" "set")]
2168)
9c08d1fa 2169
f4462328 2170(define_insn_and_split "*ne_zeroextractsi"
c4034607 2171 [(set (match_operand:SI 0 "s_register_operand" "=r")
2172 (ne:SI (zero_extract:SI
2173 (match_operand:SI 1 "s_register_operand" "r")
2174 (match_operand:SI 2 "const_int_operand" "n")
2175 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2176 (const_int 0)))
2177 (clobber (reg:CC CC_REGNUM))]
25f905c2 2178 "TARGET_32BIT
cffb2a26 2179 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2180 && INTVAL (operands[2]) > 0
2181 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2182 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2183 "#"
25f905c2 2184 "TARGET_32BIT
f4462328 2185 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2186 && INTVAL (operands[2]) > 0
2187 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2188 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2189 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2190 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2191 (const_int 0)))
2192 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2193 (set (match_dup 0)
2194 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2195 (match_dup 0) (const_int 1)))]
2196 "
2197 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2198 << INTVAL (operands[3]));
2199 "
2200 [(set_attr "conds" "clob")
25f905c2 2201 (set (attr "length")
2202 (if_then_else (eq_attr "is_thumb" "yes")
2203 (const_int 12)
2204 (const_int 8)))]
f4462328 2205)
2206
2207(define_insn_and_split "*ne_zeroextractsi_shifted"
2208 [(set (match_operand:SI 0 "s_register_operand" "=r")
2209 (ne:SI (zero_extract:SI
2210 (match_operand:SI 1 "s_register_operand" "r")
2211 (match_operand:SI 2 "const_int_operand" "n")
2212 (const_int 0))
2213 (const_int 0)))
2214 (clobber (reg:CC CC_REGNUM))]
2215 "TARGET_ARM"
2216 "#"
2217 "TARGET_ARM"
2218 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2219 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2220 (const_int 0)))
2221 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2222 (set (match_dup 0)
2223 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2224 (match_dup 0) (const_int 1)))]
2225 "
2226 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2227 "
2228 [(set_attr "conds" "clob")
2229 (set_attr "length" "8")]
2230)
2231
2232(define_insn_and_split "*ite_ne_zeroextractsi"
2233 [(set (match_operand:SI 0 "s_register_operand" "=r")
2234 (if_then_else:SI (ne (zero_extract:SI
2235 (match_operand:SI 1 "s_register_operand" "r")
2236 (match_operand:SI 2 "const_int_operand" "n")
2237 (match_operand:SI 3 "const_int_operand" "n"))
2238 (const_int 0))
2239 (match_operand:SI 4 "arm_not_operand" "rIK")
2240 (const_int 0)))
2241 (clobber (reg:CC CC_REGNUM))]
2242 "TARGET_ARM
2243 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2244 && INTVAL (operands[2]) > 0
2245 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2246 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2247 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2248 "#"
2249 "TARGET_ARM
2250 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2251 && INTVAL (operands[2]) > 0
2252 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2253 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2254 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2255 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2256 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2257 (const_int 0)))
2258 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2259 (set (match_dup 0)
2260 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2261 (match_dup 0) (match_dup 4)))]
2262 "
c4034607 2263 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2264 << INTVAL (operands[3]));
2265 "
2266 [(set_attr "conds" "clob")
2267 (set_attr "length" "8")]
2268)
2269
2270(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2271 [(set (match_operand:SI 0 "s_register_operand" "=r")
2272 (if_then_else:SI (ne (zero_extract:SI
2273 (match_operand:SI 1 "s_register_operand" "r")
2274 (match_operand:SI 2 "const_int_operand" "n")
2275 (const_int 0))
2276 (const_int 0))
2277 (match_operand:SI 3 "arm_not_operand" "rIK")
2278 (const_int 0)))
2279 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2280 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2281 "#"
f8d7bf2f 2282 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2283 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2284 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2285 (const_int 0)))
2286 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2287 (set (match_dup 0)
2288 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2289 (match_dup 0) (match_dup 3)))]
2290 "
2291 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2292 "
2293 [(set_attr "conds" "clob")
215b30b3 2294 (set_attr "length" "8")]
2295)
9c08d1fa 2296
58d6528b 2297(define_split
2298 [(set (match_operand:SI 0 "s_register_operand" "")
2299 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2300 (match_operand:SI 2 "const_int_operand" "")
2301 (match_operand:SI 3 "const_int_operand" "")))
2302 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2303 "TARGET_THUMB1"
58d6528b 2304 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2305 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2306 "{
2307 HOST_WIDE_INT temp = INTVAL (operands[2]);
2308
2309 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2310 operands[3] = GEN_INT (32 - temp);
2311 }"
2312)
2313
25f905c2 2314;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2315(define_split
2316 [(set (match_operand:SI 0 "s_register_operand" "")
2317 (match_operator:SI 1 "shiftable_operator"
2318 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2319 (match_operand:SI 3 "const_int_operand" "")
2320 (match_operand:SI 4 "const_int_operand" ""))
2321 (match_operand:SI 5 "s_register_operand" "")]))
2322 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2323 "TARGET_ARM"
2324 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2325 (set (match_dup 0)
2326 (match_op_dup 1
2327 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2328 (match_dup 5)]))]
2329 "{
2330 HOST_WIDE_INT temp = INTVAL (operands[3]);
2331
2332 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2333 operands[4] = GEN_INT (32 - temp);
2334 }"
2335)
2336
58d6528b 2337(define_split
2338 [(set (match_operand:SI 0 "s_register_operand" "")
2339 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2340 (match_operand:SI 2 "const_int_operand" "")
2341 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2342 "TARGET_THUMB1"
58d6528b 2343 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2344 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2345 "{
2346 HOST_WIDE_INT temp = INTVAL (operands[2]);
2347
2348 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2349 operands[3] = GEN_INT (32 - temp);
2350 }"
2351)
2352
d7863cfe 2353(define_split
2354 [(set (match_operand:SI 0 "s_register_operand" "")
2355 (match_operator:SI 1 "shiftable_operator"
2356 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2357 (match_operand:SI 3 "const_int_operand" "")
2358 (match_operand:SI 4 "const_int_operand" ""))
2359 (match_operand:SI 5 "s_register_operand" "")]))
2360 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2361 "TARGET_ARM"
2362 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2363 (set (match_dup 0)
2364 (match_op_dup 1
2365 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2366 (match_dup 5)]))]
2367 "{
2368 HOST_WIDE_INT temp = INTVAL (operands[3]);
2369
2370 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2371 operands[4] = GEN_INT (32 - temp);
2372 }"
2373)
2374
a42059fd 2375;;; ??? This pattern is bogus. If operand3 has bits outside the range
2376;;; represented by the bitfield, then this will produce incorrect results.
2377;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2378;;; which have a real bit-field insert instruction, the truncation happens
2379;;; in the bit-field insert instruction itself. Since arm does not have a
2380;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2381;;; the value before we insert. This loses some of the advantage of having
2382;;; this insv pattern, so this pattern needs to be reevalutated.
2383
8a18b90c 2384(define_expand "insv"
2385 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2386 (match_operand:SI 1 "general_operand" "")
2387 (match_operand:SI 2 "general_operand" ""))
19335226 2388 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2389 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2390 "
215b30b3 2391 {
2392 int start_bit = INTVAL (operands[2]);
2393 int width = INTVAL (operands[1]);
2394 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2395 rtx target, subtarget;
2396
8b054d5a 2397 if (arm_arch_thumb2)
2398 {
2399 bool use_bfi = TRUE;
2400
2401 if (GET_CODE (operands[3]) == CONST_INT)
2402 {
2403 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2404
2405 if (val == 0)
2406 {
2407 emit_insn (gen_insv_zero (operands[0], operands[1],
2408 operands[2]));
2409 DONE;
2410 }
2411
2412 /* See if the set can be done with a single orr instruction. */
2413 if (val == mask && const_ok_for_arm (val << start_bit))
2414 use_bfi = FALSE;
2415 }
2416
2417 if (use_bfi)
2418 {
2419 if (GET_CODE (operands[3]) != REG)
2420 operands[3] = force_reg (SImode, operands[3]);
2421
2422 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2423 operands[3]));
2424 DONE;
2425 }
2426 }
2427
3f8fde42 2428 target = copy_rtx (operands[0]);
215b30b3 2429 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2430 subreg as the final target. */
2431 if (GET_CODE (target) == SUBREG)
2432 {
2433 subtarget = gen_reg_rtx (SImode);
2434 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2435 < GET_MODE_SIZE (SImode))
2436 target = SUBREG_REG (target);
2437 }
2438 else
2439 subtarget = target;
8a18b90c 2440
215b30b3 2441 if (GET_CODE (operands[3]) == CONST_INT)
2442 {
2443 /* Since we are inserting a known constant, we may be able to
2444 reduce the number of bits that we have to clear so that
2445 the mask becomes simple. */
2446 /* ??? This code does not check to see if the new mask is actually
2447 simpler. It may not be. */
2448 rtx op1 = gen_reg_rtx (SImode);
2449 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2450 start of this pattern. */
2451 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2452 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2453
c5b3a71b 2454 emit_insn (gen_andsi3 (op1, operands[0],
2455 gen_int_mode (~mask2, SImode)));
215b30b3 2456 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2457 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2458 }
2459 else if (start_bit == 0
2460 && !(const_ok_for_arm (mask)
2461 || const_ok_for_arm (~mask)))
2462 {
2463 /* A Trick, since we are setting the bottom bits in the word,
2464 we can shift operand[3] up, operand[0] down, OR them together
2465 and rotate the result back again. This takes 3 insns, and
5910bb95 2466 the third might be mergeable into another op. */
215b30b3 2467 /* The shift up copes with the possibility that operand[3] is
2468 wider than the bitfield. */
2469 rtx op0 = gen_reg_rtx (SImode);
2470 rtx op1 = gen_reg_rtx (SImode);
2471
2472 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2473 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2474 emit_insn (gen_iorsi3 (op1, op1, op0));
2475 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2476 }
2477 else if ((width + start_bit == 32)
2478 && !(const_ok_for_arm (mask)
2479 || const_ok_for_arm (~mask)))
2480 {
2481 /* Similar trick, but slightly less efficient. */
8a18b90c 2482
215b30b3 2483 rtx op0 = gen_reg_rtx (SImode);
2484 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2485
215b30b3 2486 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2487 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2488 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2489 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2490 }
2491 else
2492 {
c5b3a71b 2493 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2494 rtx op1 = gen_reg_rtx (SImode);
2495 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2496
215b30b3 2497 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2498 {
2499 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2500
215b30b3 2501 emit_insn (gen_movsi (tmp, op0));
2502 op0 = tmp;
2503 }
8a18b90c 2504
215b30b3 2505 /* Mask out any bits in operand[3] that are not needed. */
2506 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2507
215b30b3 2508 if (GET_CODE (op0) == CONST_INT
2509 && (const_ok_for_arm (mask << start_bit)
2510 || const_ok_for_arm (~(mask << start_bit))))
2511 {
c5b3a71b 2512 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2513 emit_insn (gen_andsi3 (op2, operands[0], op0));
2514 }
2515 else
2516 {
2517 if (GET_CODE (op0) == CONST_INT)
2518 {
2519 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2520
215b30b3 2521 emit_insn (gen_movsi (tmp, op0));
2522 op0 = tmp;
2523 }
2524
2525 if (start_bit != 0)
2526 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2527
215b30b3 2528 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2529 }
8a18b90c 2530
215b30b3 2531 if (start_bit != 0)
2532 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2533
215b30b3 2534 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2535 }
f082f1c4 2536
215b30b3 2537 if (subtarget != target)
2538 {
2539 /* If TARGET is still a SUBREG, then it must be wider than a word,
2540 so we must be careful only to set the subword we were asked to. */
2541 if (GET_CODE (target) == SUBREG)
2542 emit_move_insn (target, subtarget);
2543 else
2544 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2545 }
8a18b90c 2546
215b30b3 2547 DONE;
2548 }"
2549)
8a18b90c 2550
8b054d5a 2551(define_insn "insv_zero"
2552 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2553 (match_operand:SI 1 "const_int_operand" "M")
2554 (match_operand:SI 2 "const_int_operand" "M"))
2555 (const_int 0))]
2556 "arm_arch_thumb2"
2557 "bfc%?\t%0, %2, %1"
2558 [(set_attr "length" "4")
2559 (set_attr "predicable" "yes")]
2560)
2561
2562(define_insn "insv_t2"
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 (match_operand:SI 3 "s_register_operand" "r"))]
2567 "arm_arch_thumb2"
2568 "bfi%?\t%0, %3, %2, %1"
2569 [(set_attr "length" "4")
2570 (set_attr "predicable" "yes")]
2571)
2572
215b30b3 2573; constants for op 2 will never be given to these patterns.
a0f94409 2574(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2575 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2576 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2577 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2578 "TARGET_32BIT"
f6ebffac 2579 "#"
e2669ea7 2580 "TARGET_32BIT && reload_completed
2581 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2582 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2583 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2584 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2585 "
2586 {
2587 operands[3] = gen_highpart (SImode, operands[0]);
2588 operands[0] = gen_lowpart (SImode, operands[0]);
2589 operands[4] = gen_highpart (SImode, operands[1]);
2590 operands[1] = gen_lowpart (SImode, operands[1]);
2591 operands[5] = gen_highpart (SImode, operands[2]);
2592 operands[2] = gen_lowpart (SImode, operands[2]);
2593 }"
0d66636f 2594 [(set_attr "length" "8")
2595 (set_attr "predicable" "yes")]
2596)
9c08d1fa 2597
a0f94409 2598(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2599 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2600 (and:DI (not:DI (zero_extend:DI
2601 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2602 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2603 "TARGET_32BIT"
e2348bcb 2604 "@
97499065 2605 bic%?\\t%Q0, %Q1, %2
f6ebffac 2606 #"
a0f94409 2607 ; (not (zero_extend ...)) allows us to just copy the high word from
2608 ; operand1 to operand0.
25f905c2 2609 "TARGET_32BIT
a0f94409 2610 && reload_completed
2611 && operands[0] != operands[1]"
5a097f7d 2612 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2613 (set (match_dup 3) (match_dup 4))]
2614 "
2615 {
2616 operands[3] = gen_highpart (SImode, operands[0]);
2617 operands[0] = gen_lowpart (SImode, operands[0]);
2618 operands[4] = gen_highpart (SImode, operands[1]);
2619 operands[1] = gen_lowpart (SImode, operands[1]);
2620 }"
0d66636f 2621 [(set_attr "length" "4,8")
2622 (set_attr "predicable" "yes")]
2623)
9c08d1fa 2624
a0f94409 2625(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2626 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2627 (and:DI (not:DI (sign_extend:DI
2628 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2629 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2630 "TARGET_32BIT"
f6ebffac 2631 "#"
25f905c2 2632 "TARGET_32BIT && reload_completed"
5a097f7d 2633 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2634 (set (match_dup 3) (and:SI (not:SI
2635 (ashiftrt:SI (match_dup 2) (const_int 31)))
2636 (match_dup 4)))]
2637 "
2638 {
2639 operands[3] = gen_highpart (SImode, operands[0]);
2640 operands[0] = gen_lowpart (SImode, operands[0]);
2641 operands[4] = gen_highpart (SImode, operands[1]);
2642 operands[1] = gen_lowpart (SImode, operands[1]);
2643 }"
0d66636f 2644 [(set_attr "length" "8")
2645 (set_attr "predicable" "yes")]
2646)
9c08d1fa 2647
8a18b90c 2648(define_insn "andsi_notsi_si"
9c08d1fa 2649 [(set (match_operand:SI 0 "s_register_operand" "=r")
2650 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2651 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2652 "TARGET_32BIT"
0d66636f 2653 "bic%?\\t%0, %1, %2"
2654 [(set_attr "predicable" "yes")]
2655)
b11cae9e 2656
747b7458 2657(define_insn "thumb1_bicsi3"
cffb2a26 2658 [(set (match_operand:SI 0 "register_operand" "=l")
2659 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2660 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2661 "TARGET_THUMB1"
747b7458 2662 "bic\\t%0, %1"
2663 [(set_attr "length" "2")
2664 (set_attr "conds" "set")])
cffb2a26 2665
8a18b90c 2666(define_insn "andsi_not_shiftsi_si"
a2cd141b 2667 [(set (match_operand:SI 0 "s_register_operand" "=r")
2668 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2669 [(match_operand:SI 2 "s_register_operand" "r")
2670 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2671 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2672 "TARGET_ARM"
6c4c2133 2673 "bic%?\\t%0, %1, %2%S4"
344495ea 2674 [(set_attr "predicable" "yes")
331beb1a 2675 (set_attr "shift" "2")
a2cd141b 2676 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2677 (const_string "alu_shift")
2678 (const_string "alu_shift_reg")))]
6c4c2133 2679)
8a18b90c 2680
f7fbdd4a 2681(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2682 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2683 (compare:CC_NOOV
2684 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2685 (match_operand:SI 1 "s_register_operand" "r"))
2686 (const_int 0)))
9c08d1fa 2687 (set (match_operand:SI 0 "s_register_operand" "=r")
2688 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2689 "TARGET_32BIT"
2690 "bic%.\\t%0, %1, %2"
0d66636f 2691 [(set_attr "conds" "set")]
2692)
9c08d1fa 2693
f7fbdd4a 2694(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2695 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2696 (compare:CC_NOOV
2697 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2698 (match_operand:SI 1 "s_register_operand" "r"))
2699 (const_int 0)))
9c08d1fa 2700 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2701 "TARGET_32BIT"
2702 "bic%.\\t%0, %1, %2"
0d66636f 2703 [(set_attr "conds" "set")]
2704)
9c08d1fa 2705
e2669ea7 2706(define_expand "iordi3"
2707 [(set (match_operand:DI 0 "s_register_operand" "")
2708 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2709 (match_operand:DI 2 "neon_logic_op2" "")))]
2710 "TARGET_32BIT"
2711 ""
2712)
2713
2714(define_insn "*iordi3_insn"
cffb2a26 2715 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2716 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2717 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2718 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2719 "#"
0d66636f 2720 [(set_attr "length" "8")
2721 (set_attr "predicable" "yes")]
cffb2a26 2722)
9c08d1fa 2723
f7fbdd4a 2724(define_insn "*iordi_zesidi_di"
9c08d1fa 2725 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2726 (ior:DI (zero_extend:DI
2727 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2728 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2729 "TARGET_32BIT"
e2348bcb 2730 "@
97499065 2731 orr%?\\t%Q0, %Q1, %2
f6ebffac 2732 #"
0d66636f 2733 [(set_attr "length" "4,8")
2734 (set_attr "predicable" "yes")]
cffb2a26 2735)
9c08d1fa 2736
f7fbdd4a 2737(define_insn "*iordi_sesidi_di"
9c08d1fa 2738 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2739 (ior:DI (sign_extend:DI
2740 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2741 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2742 "TARGET_32BIT"
f6ebffac 2743 "#"
0d66636f 2744 [(set_attr "length" "8")
2745 (set_attr "predicable" "yes")]
cffb2a26 2746)
9c08d1fa 2747
87b22bf7 2748(define_expand "iorsi3"
cffb2a26 2749 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2750 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2751 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2752 "TARGET_EITHER"
87b22bf7 2753 "
2754 if (GET_CODE (operands[2]) == CONST_INT)
2755 {
25f905c2 2756 if (TARGET_32BIT)
cffb2a26 2757 {
96f57e36 2758 arm_split_constant (IOR, SImode, NULL_RTX,
2759 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2760 optimize && can_create_pseudo_p ());
cffb2a26 2761 DONE;
2762 }
25f905c2 2763 else /* TARGET_THUMB1 */
923ffadb 2764 {
2765 rtx tmp = force_reg (SImode, operands[2]);
2766 if (rtx_equal_p (operands[0], operands[1]))
2767 operands[2] = tmp;
2768 else
2769 {
2770 operands[2] = operands[1];
2771 operands[1] = tmp;
2772 }
2773 }
87b22bf7 2774 }
cffb2a26 2775 "
2776)
87b22bf7 2777
d5d4dc8d 2778(define_insn_and_split "*iorsi3_insn"
2779 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2780 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2781 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2782 "TARGET_32BIT"
87b22bf7 2783 "@
2784 orr%?\\t%0, %1, %2
d5d4dc8d 2785 orn%?\\t%0, %1, #%B2
87b22bf7 2786 #"
d5d4dc8d 2787 "TARGET_32BIT
a0f94409 2788 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2789 && !(const_ok_for_arm (INTVAL (operands[2]))
2790 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2791 [(clobber (const_int 0))]
d5d4dc8d 2792{
96f57e36 2793 arm_split_constant (IOR, SImode, curr_insn,
2794 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2795 DONE;
d5d4dc8d 2796}
2797 [(set_attr "length" "4,4,16")
2798 (set_attr "arch" "32,t2,32")
2799 (set_attr "predicable" "yes")])
cffb2a26 2800
747b7458 2801(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2802 [(set (match_operand:SI 0 "register_operand" "=l")
2803 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2804 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2805 "TARGET_THUMB1"
747b7458 2806 "orr\\t%0, %2"
2807 [(set_attr "length" "2")
2808 (set_attr "conds" "set")])
9c08d1fa 2809
a0f94409 2810(define_peephole2
2811 [(match_scratch:SI 3 "r")
372575c7 2812 (set (match_operand:SI 0 "arm_general_register_operand" "")
2813 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2814 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2815 "TARGET_ARM
a0f94409 2816 && !const_ok_for_arm (INTVAL (operands[2]))
2817 && const_ok_for_arm (~INTVAL (operands[2]))"
2818 [(set (match_dup 3) (match_dup 2))
2819 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2820 ""
215b30b3 2821)
a0f94409 2822
f7fbdd4a 2823(define_insn "*iorsi3_compare0"
bd5b4116 2824 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2825 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2826 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2827 (const_int 0)))
2828 (set (match_operand:SI 0 "s_register_operand" "=r")
2829 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2830 "TARGET_32BIT"
2831 "orr%.\\t%0, %1, %2"
cffb2a26 2832 [(set_attr "conds" "set")]
2833)
9c08d1fa 2834
f7fbdd4a 2835(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2836 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2837 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2838 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2839 (const_int 0)))
2840 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2841 "TARGET_32BIT"
2842 "orr%.\\t%0, %1, %2"
0d66636f 2843 [(set_attr "conds" "set")]
2844)
9c08d1fa 2845
e2669ea7 2846(define_expand "xordi3"
2847 [(set (match_operand:DI 0 "s_register_operand" "")
2848 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2849 (match_operand:DI 2 "s_register_operand" "")))]
2850 "TARGET_32BIT"
2851 ""
2852)
2853
2854(define_insn "*xordi3_insn"
cffb2a26 2855 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2856 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2857 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2858 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2859 "#"
0d66636f 2860 [(set_attr "length" "8")
2861 (set_attr "predicable" "yes")]
cffb2a26 2862)
9c08d1fa 2863
f7fbdd4a 2864(define_insn "*xordi_zesidi_di"
9c08d1fa 2865 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2866 (xor:DI (zero_extend:DI
2867 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2868 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2869 "TARGET_32BIT"
e2348bcb 2870 "@
97499065 2871 eor%?\\t%Q0, %Q1, %2
f6ebffac 2872 #"
0d66636f 2873 [(set_attr "length" "4,8")
2874 (set_attr "predicable" "yes")]
cffb2a26 2875)
9c08d1fa 2876
f7fbdd4a 2877(define_insn "*xordi_sesidi_di"
9c08d1fa 2878 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2879 (xor:DI (sign_extend:DI
2880 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2881 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2882 "TARGET_32BIT"
f6ebffac 2883 "#"
0d66636f 2884 [(set_attr "length" "8")
2885 (set_attr "predicable" "yes")]
cffb2a26 2886)
9c08d1fa 2887
cffb2a26 2888(define_expand "xorsi3"
2889 [(set (match_operand:SI 0 "s_register_operand" "")
2890 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2891 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2892 "TARGET_EITHER"
923ffadb 2893 "if (GET_CODE (operands[2]) == CONST_INT)
2894 {
2895 if (TARGET_32BIT)
2896 {
2897 arm_split_constant (XOR, SImode, NULL_RTX,
2898 INTVAL (operands[2]), operands[0], operands[1],
2899 optimize && can_create_pseudo_p ());
2900 DONE;
2901 }
2902 else /* TARGET_THUMB1 */
2903 {
2904 rtx tmp = force_reg (SImode, operands[2]);
2905 if (rtx_equal_p (operands[0], operands[1]))
2906 operands[2] = tmp;
2907 else
2908 {
2909 operands[2] = operands[1];
2910 operands[1] = tmp;
2911 }
2912 }
2913 }"
cffb2a26 2914)
2915
2916(define_insn "*arm_xorsi3"
2917 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2918 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2919 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2920 "TARGET_32BIT"
cffb2a26 2921 "eor%?\\t%0, %1, %2"
0d66636f 2922 [(set_attr "predicable" "yes")]
cffb2a26 2923)
2924
747b7458 2925(define_insn "*thumb1_xorsi3_insn"
cffb2a26 2926 [(set (match_operand:SI 0 "register_operand" "=l")
2927 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2928 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2929 "TARGET_THUMB1"
747b7458 2930 "eor\\t%0, %2"
2931 [(set_attr "length" "2")
2932 (set_attr "conds" "set")])
9c08d1fa 2933
f7fbdd4a 2934(define_insn "*xorsi3_compare0"
bd5b4116 2935 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2936 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2937 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2938 (const_int 0)))
2939 (set (match_operand:SI 0 "s_register_operand" "=r")
2940 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2941 "TARGET_32BIT"
2942 "eor%.\\t%0, %1, %2"
0d66636f 2943 [(set_attr "conds" "set")]
2944)
9c08d1fa 2945
f7fbdd4a 2946(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2947 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2948 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2949 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2950 (const_int 0)))]
25f905c2 2951 "TARGET_32BIT"
40dbec34 2952 "teq%?\\t%0, %1"
cffb2a26 2953 [(set_attr "conds" "set")]
2954)
9c08d1fa 2955
215b30b3 2956; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2957; (NOT D) we can sometimes merge the final NOT into one of the following
2958; insns.
9c08d1fa 2959
2960(define_split
a058e94a 2961 [(set (match_operand:SI 0 "s_register_operand" "")
2962 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2963 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2964 (match_operand:SI 3 "arm_rhs_operand" "")))
2965 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2966 "TARGET_32BIT"
9c08d1fa 2967 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2968 (not:SI (match_dup 3))))
2969 (set (match_dup 0) (not:SI (match_dup 4)))]
2970 ""
2971)
2972
f7fbdd4a 2973(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2974 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 2975 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 2976 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2977 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2978 "TARGET_32BIT"
40dbec34 2979 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2980 [(set_attr "length" "8")
25f905c2 2981 (set_attr "ce_count" "2")
0d66636f 2982 (set_attr "predicable" "yes")]
cffb2a26 2983)
9c08d1fa 2984
25f905c2 2985; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2986; insns are available?
d7863cfe 2987(define_split
2988 [(set (match_operand:SI 0 "s_register_operand" "")
2989 (match_operator:SI 1 "logical_binary_operator"
2990 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2991 (match_operand:SI 3 "const_int_operand" "")
2992 (match_operand:SI 4 "const_int_operand" ""))
2993 (match_operator:SI 9 "logical_binary_operator"
2994 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2995 (match_operand:SI 6 "const_int_operand" ""))
2996 (match_operand:SI 7 "s_register_operand" "")])]))
2997 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2998 "TARGET_32BIT
d7863cfe 2999 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3000 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3001 [(set (match_dup 8)
3002 (match_op_dup 1
3003 [(ashift:SI (match_dup 2) (match_dup 4))
3004 (match_dup 5)]))
3005 (set (match_dup 0)
3006 (match_op_dup 1
3007 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3008 (match_dup 7)]))]
3009 "
3010 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3011")
3012
3013(define_split
3014 [(set (match_operand:SI 0 "s_register_operand" "")
3015 (match_operator:SI 1 "logical_binary_operator"
3016 [(match_operator:SI 9 "logical_binary_operator"
3017 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3018 (match_operand:SI 6 "const_int_operand" ""))
3019 (match_operand:SI 7 "s_register_operand" "")])
3020 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3021 (match_operand:SI 3 "const_int_operand" "")
3022 (match_operand:SI 4 "const_int_operand" ""))]))
3023 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3024 "TARGET_32BIT
d7863cfe 3025 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3026 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3027 [(set (match_dup 8)
3028 (match_op_dup 1
3029 [(ashift:SI (match_dup 2) (match_dup 4))
3030 (match_dup 5)]))
3031 (set (match_dup 0)
3032 (match_op_dup 1
3033 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3034 (match_dup 7)]))]
3035 "
3036 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3037")
3038
3039(define_split
3040 [(set (match_operand:SI 0 "s_register_operand" "")
3041 (match_operator:SI 1 "logical_binary_operator"
3042 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3043 (match_operand:SI 3 "const_int_operand" "")
3044 (match_operand:SI 4 "const_int_operand" ""))
3045 (match_operator:SI 9 "logical_binary_operator"
3046 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3047 (match_operand:SI 6 "const_int_operand" ""))
3048 (match_operand:SI 7 "s_register_operand" "")])]))
3049 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3050 "TARGET_32BIT
d7863cfe 3051 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3052 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3053 [(set (match_dup 8)
3054 (match_op_dup 1
3055 [(ashift:SI (match_dup 2) (match_dup 4))
3056 (match_dup 5)]))
3057 (set (match_dup 0)
3058 (match_op_dup 1
3059 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3060 (match_dup 7)]))]
3061 "
3062 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3063")
3064
3065(define_split
3066 [(set (match_operand:SI 0 "s_register_operand" "")
3067 (match_operator:SI 1 "logical_binary_operator"
3068 [(match_operator:SI 9 "logical_binary_operator"
3069 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3070 (match_operand:SI 6 "const_int_operand" ""))
3071 (match_operand:SI 7 "s_register_operand" "")])
3072 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3073 (match_operand:SI 3 "const_int_operand" "")
3074 (match_operand:SI 4 "const_int_operand" ""))]))
3075 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3076 "TARGET_32BIT
d7863cfe 3077 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3078 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3079 [(set (match_dup 8)
3080 (match_op_dup 1
3081 [(ashift:SI (match_dup 2) (match_dup 4))
3082 (match_dup 5)]))
3083 (set (match_dup 0)
3084 (match_op_dup 1
3085 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3086 (match_dup 7)]))]
3087 "
3088 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3089")
9c08d1fa 3090\f
3091
3092;; Minimum and maximum insns
3093
8b9dc177 3094(define_expand "smaxsi3"
3095 [(parallel [
3096 (set (match_operand:SI 0 "s_register_operand" "")
3097 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3098 (match_operand:SI 2 "arm_rhs_operand" "")))
3099 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3100 "TARGET_32BIT"
8b9dc177 3101 "
8774928b 3102 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3103 {
3104 /* No need for a clobber of the condition code register here. */
3105 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3106 gen_rtx_SMAX (SImode, operands[1],
3107 operands[2])));
3108 DONE;
3109 }
3110")
3111
3112(define_insn "*smax_0"
3113 [(set (match_operand:SI 0 "s_register_operand" "=r")
3114 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3115 (const_int 0)))]
25f905c2 3116 "TARGET_32BIT"
8b9dc177 3117 "bic%?\\t%0, %1, %1, asr #31"
3118 [(set_attr "predicable" "yes")]
3119)
3120
8774928b 3121(define_insn "*smax_m1"
3122 [(set (match_operand:SI 0 "s_register_operand" "=r")
3123 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3124 (const_int -1)))]
25f905c2 3125 "TARGET_32BIT"
8774928b 3126 "orr%?\\t%0, %1, %1, asr #31"
3127 [(set_attr "predicable" "yes")]
3128)
3129
25f905c2 3130(define_insn "*arm_smax_insn"
8b9dc177 3131 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3132 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3133 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3134 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3135 "TARGET_ARM"
e2348bcb 3136 "@
3137 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3138 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3139 [(set_attr "conds" "clob")
8b9dc177 3140 (set_attr "length" "8,12")]
cffb2a26 3141)
9c08d1fa 3142
8b9dc177 3143(define_expand "sminsi3"
3144 [(parallel [
3145 (set (match_operand:SI 0 "s_register_operand" "")
3146 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3147 (match_operand:SI 2 "arm_rhs_operand" "")))
3148 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3149 "TARGET_32BIT"
8b9dc177 3150 "
3151 if (operands[2] == const0_rtx)
3152 {
3153 /* No need for a clobber of the condition code register here. */
3154 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3155 gen_rtx_SMIN (SImode, operands[1],
3156 operands[2])));
3157 DONE;
3158 }
3159")
3160
3161(define_insn "*smin_0"
3162 [(set (match_operand:SI 0 "s_register_operand" "=r")
3163 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3164 (const_int 0)))]
25f905c2 3165 "TARGET_32BIT"
8b9dc177 3166 "and%?\\t%0, %1, %1, asr #31"
3167 [(set_attr "predicable" "yes")]
3168)
3169
25f905c2 3170(define_insn "*arm_smin_insn"
8b9dc177 3171 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3172 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3173 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3174 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3175 "TARGET_ARM"
e2348bcb 3176 "@
3177 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3178 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3179 [(set_attr "conds" "clob")
8b9dc177 3180 (set_attr "length" "8,12")]
0d66636f 3181)
9c08d1fa 3182
25f905c2 3183(define_expand "umaxsi3"
3184 [(parallel [
3185 (set (match_operand:SI 0 "s_register_operand" "")
3186 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3187 (match_operand:SI 2 "arm_rhs_operand" "")))
3188 (clobber (reg:CC CC_REGNUM))])]
3189 "TARGET_32BIT"
3190 ""
3191)
3192
3193(define_insn "*arm_umaxsi3"
9c08d1fa 3194 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3195 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3196 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3197 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3198 "TARGET_ARM"
e2348bcb 3199 "@
3200 cmp\\t%1, %2\;movcc\\t%0, %2
3201 cmp\\t%1, %2\;movcs\\t%0, %1
3202 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3203 [(set_attr "conds" "clob")
3204 (set_attr "length" "8,8,12")]
3205)
9c08d1fa 3206
25f905c2 3207(define_expand "uminsi3"
3208 [(parallel [
3209 (set (match_operand:SI 0 "s_register_operand" "")
3210 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3211 (match_operand:SI 2 "arm_rhs_operand" "")))
3212 (clobber (reg:CC CC_REGNUM))])]
3213 "TARGET_32BIT"
3214 ""
3215)
3216
3217(define_insn "*arm_uminsi3"
9c08d1fa 3218 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3219 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3220 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3221 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3222 "TARGET_ARM"
e2348bcb 3223 "@
3224 cmp\\t%1, %2\;movcs\\t%0, %2
3225 cmp\\t%1, %2\;movcc\\t%0, %1
3226 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3227 [(set_attr "conds" "clob")
3228 (set_attr "length" "8,8,12")]
3229)
9c08d1fa 3230
8a18b90c 3231(define_insn "*store_minmaxsi"
9c08d1fa 3232 [(set (match_operand:SI 0 "memory_operand" "=m")
3233 (match_operator:SI 3 "minmax_operator"
3234 [(match_operand:SI 1 "s_register_operand" "r")
3235 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3236 (clobber (reg:CC CC_REGNUM))]
25f905c2 3237 "TARGET_32BIT"
9c08d1fa 3238 "*
dc55b8a9 3239 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3240 operands[1], operands[2]);
e2348bcb 3241 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3242 if (TARGET_THUMB2)
3243 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3244 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3245 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3246 return \"\";
0d66636f 3247 "
3248 [(set_attr "conds" "clob")
25f905c2 3249 (set (attr "length")
3250 (if_then_else (eq_attr "is_thumb" "yes")
3251 (const_int 14)
3252 (const_int 12)))
0d66636f 3253 (set_attr "type" "store1")]
3254)
9c08d1fa 3255
8a18b90c 3256; Reject the frame pointer in operand[1], since reloading this after
3257; it has been eliminated can cause carnage.
f7fbdd4a 3258(define_insn "*minmax_arithsi"
9c08d1fa 3259 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3260 (match_operator:SI 4 "shiftable_operator"
3261 [(match_operator:SI 5 "minmax_operator"
3262 [(match_operand:SI 2 "s_register_operand" "r,r")
3263 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3264 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3265 (clobber (reg:CC CC_REGNUM))]
25f905c2 3266 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3267 "*
0d66636f 3268 {
3269 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3270 bool need_else;
3271
3272 if (which_alternative != 0 || operands[3] != const0_rtx
3273 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3274 need_else = true;
3275 else
3276 need_else = false;
0d66636f 3277
dc55b8a9 3278 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3279 operands[2], operands[3]);
0d66636f 3280 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3281 if (TARGET_THUMB2)
3282 {
3283 if (need_else)
3284 output_asm_insn (\"ite\\t%d5\", operands);
3285 else
3286 output_asm_insn (\"it\\t%d5\", operands);
3287 }
0d66636f 3288 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3289 if (need_else)
0d66636f 3290 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3291 return \"\";
215b30b3 3292 }"
0d66636f 3293 [(set_attr "conds" "clob")
25f905c2 3294 (set (attr "length")
3295 (if_then_else (eq_attr "is_thumb" "yes")
3296 (const_int 14)
3297 (const_int 12)))]
0d66636f 3298)
9c08d1fa 3299
b11cae9e 3300\f
3301;; Shift and rotation insns
3302
a2cd141b 3303(define_expand "ashldi3"
3304 [(set (match_operand:DI 0 "s_register_operand" "")
3305 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3306 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3307 "TARGET_32BIT"
a2cd141b 3308 "
3309 if (GET_CODE (operands[2]) == CONST_INT)
3310 {
3311 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3312 {
3313 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3314 DONE;
3315 }
3316 /* Ideally we shouldn't fail here if we could know that operands[1]
3317 ends up already living in an iwmmxt register. Otherwise it's
3318 cheaper to have the alternate code being generated than moving
1d60d981 3319 values to iwmmxt regs and back. */
a2cd141b 3320 FAIL;
3321 }
3322 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3323 FAIL;
3324 "
3325)
3326
3327(define_insn "arm_ashldi3_1bit"
50ad1bf9 3328 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3329 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3330 (const_int 1)))
3331 (clobber (reg:CC CC_REGNUM))]
25f905c2 3332 "TARGET_32BIT"
a2cd141b 3333 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3334 [(set_attr "conds" "clob")
3335 (set_attr "length" "8")]
3336)
3337
87b22bf7 3338(define_expand "ashlsi3"
cffb2a26 3339 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3340 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3341 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3342 "TARGET_EITHER"
87b22bf7 3343 "
3344 if (GET_CODE (operands[2]) == CONST_INT
3345 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3346 {
3347 emit_insn (gen_movsi (operands[0], const0_rtx));
3348 DONE;
3349 }
cffb2a26 3350 "
3351)
3352
25f905c2 3353(define_insn "*thumb1_ashlsi3"
cffb2a26 3354 [(set (match_operand:SI 0 "register_operand" "=l,l")
3355 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3356 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3357 "TARGET_THUMB1"
cffb2a26 3358 "lsl\\t%0, %1, %2"
747b7458 3359 [(set_attr "length" "2")
3360 (set_attr "conds" "set")])
b11cae9e 3361
a2cd141b 3362(define_expand "ashrdi3"
3363 [(set (match_operand:DI 0 "s_register_operand" "")
3364 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3365 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3366 "TARGET_32BIT"
a2cd141b 3367 "
3368 if (GET_CODE (operands[2]) == CONST_INT)
3369 {
3370 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3371 {
3372 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3373 DONE;
3374 }
3375 /* Ideally we shouldn't fail here if we could know that operands[1]
3376 ends up already living in an iwmmxt register. Otherwise it's
3377 cheaper to have the alternate code being generated than moving
1d60d981 3378 values to iwmmxt regs and back. */
a2cd141b 3379 FAIL;
3380 }
3381 else if (!TARGET_REALLY_IWMMXT)
3382 FAIL;
3383 "
3384)
3385
3386(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3387 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3388 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3389 (const_int 1)))
3390 (clobber (reg:CC CC_REGNUM))]
25f905c2 3391 "TARGET_32BIT"
a2cd141b 3392 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3393 [(set_attr "conds" "clob")
d2a518d1 3394 (set_attr "insn" "mov")
a2cd141b 3395 (set_attr "length" "8")]
3396)
3397
87b22bf7 3398(define_expand "ashrsi3"
cffb2a26 3399 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3400 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3401 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3402 "TARGET_EITHER"
87b22bf7 3403 "
3404 if (GET_CODE (operands[2]) == CONST_INT
3405 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3406 operands[2] = GEN_INT (31);
cffb2a26 3407 "
3408)
3409
25f905c2 3410(define_insn "*thumb1_ashrsi3"
cffb2a26 3411 [(set (match_operand:SI 0 "register_operand" "=l,l")
3412 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3413 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3414 "TARGET_THUMB1"
cffb2a26 3415 "asr\\t%0, %1, %2"
747b7458 3416 [(set_attr "length" "2")
3417 (set_attr "conds" "set")])
b11cae9e 3418
a2cd141b 3419(define_expand "lshrdi3"
3420 [(set (match_operand:DI 0 "s_register_operand" "")
3421 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3422 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3423 "TARGET_32BIT"
a2cd141b 3424 "
3425 if (GET_CODE (operands[2]) == CONST_INT)
3426 {
3427 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3428 {
3429 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3430 DONE;
3431 }
3432 /* Ideally we shouldn't fail here if we could know that operands[1]
3433 ends up already living in an iwmmxt register. Otherwise it's
3434 cheaper to have the alternate code being generated than moving
1d60d981 3435 values to iwmmxt regs and back. */
a2cd141b 3436 FAIL;
3437 }
3438 else if (!TARGET_REALLY_IWMMXT)
3439 FAIL;
3440 "
3441)
3442
3443(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3444 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3445 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3446 (const_int 1)))
3447 (clobber (reg:CC CC_REGNUM))]
25f905c2 3448 "TARGET_32BIT"
a2cd141b 3449 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3450 [(set_attr "conds" "clob")
d2a518d1 3451 (set_attr "insn" "mov")
a2cd141b 3452 (set_attr "length" "8")]
3453)
3454
87b22bf7 3455(define_expand "lshrsi3"
cffb2a26 3456 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3457 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3458 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3459 "TARGET_EITHER"
87b22bf7 3460 "
3461 if (GET_CODE (operands[2]) == CONST_INT
3462 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3463 {
3464 emit_insn (gen_movsi (operands[0], const0_rtx));
3465 DONE;
3466 }
cffb2a26 3467 "
3468)
3469
25f905c2 3470(define_insn "*thumb1_lshrsi3"
cffb2a26 3471 [(set (match_operand:SI 0 "register_operand" "=l,l")
3472 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3473 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3474 "TARGET_THUMB1"
cffb2a26 3475 "lsr\\t%0, %1, %2"
747b7458 3476 [(set_attr "length" "2")
3477 (set_attr "conds" "set")])
b11cae9e 3478
87b22bf7 3479(define_expand "rotlsi3"
cffb2a26 3480 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3481 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3482 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3483 "TARGET_32BIT"
87b22bf7 3484 "
3485 if (GET_CODE (operands[2]) == CONST_INT)
3486 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3487 else
b11cae9e 3488 {
87b22bf7 3489 rtx reg = gen_reg_rtx (SImode);
3490 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3491 operands[2] = reg;
b11cae9e 3492 }
cffb2a26 3493 "
3494)
9c08d1fa 3495
87b22bf7 3496(define_expand "rotrsi3"
cffb2a26 3497 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3498 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3499 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3500 "TARGET_EITHER"
87b22bf7 3501 "
25f905c2 3502 if (TARGET_32BIT)
cffb2a26 3503 {
3504 if (GET_CODE (operands[2]) == CONST_INT
3505 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3506 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3507 }
25f905c2 3508 else /* TARGET_THUMB1 */
cffb2a26 3509 {
3510 if (GET_CODE (operands [2]) == CONST_INT)
3511 operands [2] = force_reg (SImode, operands[2]);
3512 }
3513 "
3514)
87b22bf7 3515
25f905c2 3516(define_insn "*thumb1_rotrsi3"
cffb2a26 3517 [(set (match_operand:SI 0 "register_operand" "=l")
3518 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3519 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3520 "TARGET_THUMB1"
cffb2a26 3521 "ror\\t%0, %0, %2"
3522 [(set_attr "length" "2")]
3523)
3524
3525(define_insn "*arm_shiftsi3"
3526 [(set (match_operand:SI 0 "s_register_operand" "=r")
3527 (match_operator:SI 3 "shift_operator"
3528 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3529 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3530 "TARGET_32BIT"
3531 "* return arm_output_shift(operands, 0);"
344495ea 3532 [(set_attr "predicable" "yes")
331beb1a 3533 (set_attr "shift" "1")
a2cd141b 3534 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3535 (const_string "alu_shift")
3536 (const_string "alu_shift_reg")))]
6c4c2133 3537)
87b22bf7 3538
f7fbdd4a 3539(define_insn "*shiftsi3_compare0"
bd5b4116 3540 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3541 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3542 [(match_operand:SI 1 "s_register_operand" "r")
3543 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3544 (const_int 0)))
3545 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3546 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3547 "TARGET_32BIT"
3548 "* return arm_output_shift(operands, 1);"
344495ea 3549 [(set_attr "conds" "set")
331beb1a 3550 (set_attr "shift" "1")
a2cd141b 3551 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3552 (const_string "alu_shift")
3553 (const_string "alu_shift_reg")))]
0d66636f 3554)
9c08d1fa 3555
f7fbdd4a 3556(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3557 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3558 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3559 [(match_operand:SI 1 "s_register_operand" "r")
3560 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3561 (const_int 0)))
3562 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3563 "TARGET_32BIT"
3564 "* return arm_output_shift(operands, 1);"
344495ea 3565 [(set_attr "conds" "set")
a2cd141b 3566 (set_attr "shift" "1")]
0d66636f 3567)
9c08d1fa 3568
d5d4dc8d 3569(define_insn "*not_shiftsi"
3570 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3571 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3572 [(match_operand:SI 1 "s_register_operand" "r,r")
3573 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3574 "TARGET_32BIT"
6c4c2133 3575 "mvn%?\\t%0, %1%S3"
344495ea 3576 [(set_attr "predicable" "yes")
331beb1a 3577 (set_attr "shift" "1")
d2a518d1 3578 (set_attr "insn" "mvn")
d5d4dc8d 3579 (set_attr "arch" "32,a")
3580 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3581
d5d4dc8d 3582(define_insn "*not_shiftsi_compare0"
bd5b4116 3583 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3584 (compare:CC_NOOV
3585 (not:SI (match_operator:SI 3 "shift_operator"
3586 [(match_operand:SI 1 "s_register_operand" "r,r")
3587 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3588 (const_int 0)))
3589 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3590 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3591 "TARGET_32BIT"
25f905c2 3592 "mvn%.\\t%0, %1%S3"
344495ea 3593 [(set_attr "conds" "set")
331beb1a 3594 (set_attr "shift" "1")
d2a518d1 3595 (set_attr "insn" "mvn")
d5d4dc8d 3596 (set_attr "arch" "32,a")
3597 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3598
d5d4dc8d 3599(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3600 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3601 (compare:CC_NOOV
3602 (not:SI (match_operator:SI 3 "shift_operator"
3603 [(match_operand:SI 1 "s_register_operand" "r,r")
3604 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3605 (const_int 0)))
3606 (clobber (match_scratch:SI 0 "=r,r"))]
3607 "TARGET_32BIT"
25f905c2 3608 "mvn%.\\t%0, %1%S3"
344495ea 3609 [(set_attr "conds" "set")
331beb1a 3610 (set_attr "shift" "1")
d2a518d1 3611 (set_attr "insn" "mvn")
d5d4dc8d 3612 (set_attr "arch" "32,a")
3613 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3614
cffb2a26 3615;; We don't really have extzv, but defining this using shifts helps
3616;; to reduce register pressure later on.
3617
3618(define_expand "extzv"
3619 [(set (match_dup 4)
3620 (ashift:SI (match_operand:SI 1 "register_operand" "")
3621 (match_operand:SI 2 "const_int_operand" "")))
3622 (set (match_operand:SI 0 "register_operand" "")
3623 (lshiftrt:SI (match_dup 4)
215b30b3 3624 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3625 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3626 "
3627 {
3628 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3629 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3630
8b054d5a 3631 if (arm_arch_thumb2)
3632 {
3633 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3634 operands[3]));
3635 DONE;
3636 }
3637
cffb2a26 3638 operands[3] = GEN_INT (rshift);
3639
3640 if (lshift == 0)
3641 {
3642 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3643 DONE;
3644 }
3645
3646 operands[2] = GEN_INT (lshift);
3647 operands[4] = gen_reg_rtx (SImode);
215b30b3 3648 }"
cffb2a26 3649)
3650
8b054d5a 3651(define_insn "extv"
3652 [(set (match_operand:SI 0 "s_register_operand" "=r")
3653 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3654 (match_operand:SI 2 "const_int_operand" "M")
3655 (match_operand:SI 3 "const_int_operand" "M")))]
3656 "arm_arch_thumb2"
3657 "sbfx%?\t%0, %1, %3, %2"
3658 [(set_attr "length" "4")
3659 (set_attr "predicable" "yes")]
3660)
3661
3662(define_insn "extzv_t2"
3663 [(set (match_operand:SI 0 "s_register_operand" "=r")
3664 (zero_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 "ubfx%?\t%0, %1, %3, %2"
3669 [(set_attr "length" "4")
3670 (set_attr "predicable" "yes")]
3671)
3672
b11cae9e 3673\f
3674;; Unary arithmetic insns
3675
cffb2a26 3676(define_expand "negdi2"
3677 [(parallel
8135a42b 3678 [(set (match_operand:DI 0 "s_register_operand" "")
3679 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3680 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3681 "TARGET_EITHER"
8135a42b 3682 ""
cffb2a26 3683)
3684
3685;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 3686;; The first alternative allows the common case of a *full* overlap.
cffb2a26 3687(define_insn "*arm_negdi2"
3688 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3689 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 3690 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3691 "TARGET_ARM"
97499065 3692 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3693 [(set_attr "conds" "clob")
3694 (set_attr "length" "8")]
3695)
b11cae9e 3696
25f905c2 3697(define_insn "*thumb1_negdi2"
8135a42b 3698 [(set (match_operand:DI 0 "register_operand" "=&l")
3699 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3700 (clobber (reg:CC CC_REGNUM))]
25f905c2 3701 "TARGET_THUMB1"
cffb2a26 3702 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3703 [(set_attr "length" "6")]
3704)
3705
3706(define_expand "negsi2"
3707 [(set (match_operand:SI 0 "s_register_operand" "")
3708 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3709 "TARGET_EITHER"
b11cae9e 3710 ""
cffb2a26 3711)
3712
3713(define_insn "*arm_negsi2"
3714 [(set (match_operand:SI 0 "s_register_operand" "=r")
3715 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3716 "TARGET_32BIT"
cffb2a26 3717 "rsb%?\\t%0, %1, #0"
0d66636f 3718 [(set_attr "predicable" "yes")]
cffb2a26 3719)
3720
25f905c2 3721(define_insn "*thumb1_negsi2"
cffb2a26 3722 [(set (match_operand:SI 0 "register_operand" "=l")
3723 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3724 "TARGET_THUMB1"
cffb2a26 3725 "neg\\t%0, %1"
3726 [(set_attr "length" "2")]
3727)
b11cae9e 3728
604f3a0a 3729(define_expand "negsf2"
3730 [(set (match_operand:SF 0 "s_register_operand" "")
3731 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3732 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3733 ""
3734)
3735
3736(define_expand "negdf2"
3737 [(set (match_operand:DF 0 "s_register_operand" "")
3738 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3739 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3740 "")
3741
9c08d1fa 3742;; abssi2 doesn't really clobber the condition codes if a different register
3743;; is being set. To keep things simple, assume during rtl manipulations that
3744;; it does, but tell the final scan operator the truth. Similarly for
3745;; (neg (abs...))
3746
604f3a0a 3747(define_expand "abssi2"
3748 [(parallel
3749 [(set (match_operand:SI 0 "s_register_operand" "")
3750 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3751 (clobber (match_dup 2))])]
3752 "TARGET_EITHER"
3753 "
25f905c2 3754 if (TARGET_THUMB1)
ba156559 3755 operands[2] = gen_rtx_SCRATCH (SImode);
3756 else
3757 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3758")
604f3a0a 3759
7d57ec45 3760(define_insn "*arm_abssi2"
ba156559 3761 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3762 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3763 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3764 "TARGET_ARM"
e2348bcb 3765 "@
3766 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3767 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3768 [(set_attr "conds" "clob,*")
331beb1a 3769 (set_attr "shift" "1")
0d66636f 3770 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3771 (set_attr "length" "8")]
3772)
9c08d1fa 3773
25f905c2 3774(define_insn_and_split "*thumb1_abssi2"
ba156559 3775 [(set (match_operand:SI 0 "s_register_operand" "=l")
3776 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3777 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3778 "TARGET_THUMB1"
ba156559 3779 "#"
25f905c2 3780 "TARGET_THUMB1 && reload_completed"
ba156559 3781 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3782 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3783 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3784 ""
3785 [(set_attr "length" "6")]
3786)
3787
3788(define_insn "*arm_neg_abssi2"
9c08d1fa 3789 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3790 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3791 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3792 "TARGET_ARM"
e2348bcb 3793 "@
3794 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3795 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3796 [(set_attr "conds" "clob,*")
331beb1a 3797 (set_attr "shift" "1")
0d66636f 3798 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3799 (set_attr "length" "8")]
3800)
b11cae9e 3801
25f905c2 3802(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3803 [(set (match_operand:SI 0 "s_register_operand" "=l")
3804 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3805 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3806 "TARGET_THUMB1"
ba156559 3807 "#"
25f905c2 3808 "TARGET_THUMB1 && reload_completed"
ba156559 3809 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3810 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3811 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3812 ""
3813 [(set_attr "length" "6")]
3814)
3815
604f3a0a 3816(define_expand "abssf2"
3817 [(set (match_operand:SF 0 "s_register_operand" "")
3818 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3819 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3820 "")
3821
604f3a0a 3822(define_expand "absdf2"
3823 [(set (match_operand:DF 0 "s_register_operand" "")
3824 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3825 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3826 "")
3827
7db9af5d 3828(define_expand "sqrtsf2"
3829 [(set (match_operand:SF 0 "s_register_operand" "")
3830 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3831 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3832 "")
9c08d1fa 3833
7db9af5d 3834(define_expand "sqrtdf2"
3835 [(set (match_operand:DF 0 "s_register_operand" "")
3836 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3837 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3838 "")
9c08d1fa 3839
a0f94409 3840(define_insn_and_split "one_cmpldi2"
9c08d1fa 3841 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3842 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3843 "TARGET_32BIT"
f6ebffac 3844 "#"
25f905c2 3845 "TARGET_32BIT && reload_completed"
a0f94409 3846 [(set (match_dup 0) (not:SI (match_dup 1)))
3847 (set (match_dup 2) (not:SI (match_dup 3)))]
3848 "
3849 {
3850 operands[2] = gen_highpart (SImode, operands[0]);
3851 operands[0] = gen_lowpart (SImode, operands[0]);
3852 operands[3] = gen_highpart (SImode, operands[1]);
3853 operands[1] = gen_lowpart (SImode, operands[1]);
3854 }"
0d66636f 3855 [(set_attr "length" "8")
3856 (set_attr "predicable" "yes")]
cffb2a26 3857)
b11cae9e 3858
cffb2a26 3859(define_expand "one_cmplsi2"
3860 [(set (match_operand:SI 0 "s_register_operand" "")
3861 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3862 "TARGET_EITHER"
b11cae9e 3863 ""
cffb2a26 3864)
3865
3866(define_insn "*arm_one_cmplsi2"
3867 [(set (match_operand:SI 0 "s_register_operand" "=r")
3868 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3869 "TARGET_32BIT"
cffb2a26 3870 "mvn%?\\t%0, %1"
d2a518d1 3871 [(set_attr "predicable" "yes")
3872 (set_attr "insn" "mvn")]
cffb2a26 3873)
3874
25f905c2 3875(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3876 [(set (match_operand:SI 0 "register_operand" "=l")
3877 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3878 "TARGET_THUMB1"
cffb2a26 3879 "mvn\\t%0, %1"
d2a518d1 3880 [(set_attr "length" "2")
3881 (set_attr "insn" "mvn")]
cffb2a26 3882)
9c08d1fa 3883
f7fbdd4a 3884(define_insn "*notsi_compare0"
bd5b4116 3885 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3886 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3887 (const_int 0)))
3888 (set (match_operand:SI 0 "s_register_operand" "=r")
3889 (not:SI (match_dup 1)))]
25f905c2 3890 "TARGET_32BIT"
3891 "mvn%.\\t%0, %1"
d2a518d1 3892 [(set_attr "conds" "set")
3893 (set_attr "insn" "mvn")]
cffb2a26 3894)
9c08d1fa 3895
f7fbdd4a 3896(define_insn "*notsi_compare0_scratch"
bd5b4116 3897 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3898 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3899 (const_int 0)))
3900 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3901 "TARGET_32BIT"
3902 "mvn%.\\t%0, %1"
d2a518d1 3903 [(set_attr "conds" "set")
3904 (set_attr "insn" "mvn")]
cffb2a26 3905)
b11cae9e 3906\f
3907;; Fixed <--> Floating conversion insns
3908
9b8516be 3909(define_expand "floatsihf2"
3910 [(set (match_operand:HF 0 "general_operand" "")
3911 (float:HF (match_operand:SI 1 "general_operand" "")))]
3912 "TARGET_EITHER"
3913 "
3914 {
3915 rtx op1 = gen_reg_rtx (SFmode);
3916 expand_float (op1, operands[1], 0);
3917 op1 = convert_to_mode (HFmode, op1, 0);
3918 emit_move_insn (operands[0], op1);
3919 DONE;
3920 }"
3921)
3922
3923(define_expand "floatdihf2"
3924 [(set (match_operand:HF 0 "general_operand" "")
3925 (float:HF (match_operand:DI 1 "general_operand" "")))]
3926 "TARGET_EITHER"
3927 "
3928 {
3929 rtx op1 = gen_reg_rtx (SFmode);
3930 expand_float (op1, operands[1], 0);
3931 op1 = convert_to_mode (HFmode, op1, 0);
3932 emit_move_insn (operands[0], op1);
3933 DONE;
3934 }"
3935)
3936
604f3a0a 3937(define_expand "floatsisf2"
3938 [(set (match_operand:SF 0 "s_register_operand" "")
3939 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3940 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3941 "
a2cd141b 3942 if (TARGET_MAVERICK)
604f3a0a 3943 {
3944 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3945 DONE;
3946 }
3947")
3948
604f3a0a 3949(define_expand "floatsidf2"
3950 [(set (match_operand:DF 0 "s_register_operand" "")
3951 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 3952 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3953 "
a2cd141b 3954 if (TARGET_MAVERICK)
604f3a0a 3955 {
3956 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3957 DONE;
3958 }
3959")
3960
9b8516be 3961(define_expand "fix_trunchfsi2"
3962 [(set (match_operand:SI 0 "general_operand" "")
3963 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3964 "TARGET_EITHER"
3965 "
3966 {
3967 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3968 expand_fix (operands[0], op1, 0);
3969 DONE;
3970 }"
3971)
3972
3973(define_expand "fix_trunchfdi2"
3974 [(set (match_operand:DI 0 "general_operand" "")
3975 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3976 "TARGET_EITHER"
3977 "
3978 {
3979 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3980 expand_fix (operands[0], op1, 0);
3981 DONE;
3982 }"
3983)
3984
604f3a0a 3985(define_expand "fix_truncsfsi2"
3986 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3987 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3988 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3989 "
a2cd141b 3990 if (TARGET_MAVERICK)
604f3a0a 3991 {
3992 if (!cirrus_fp_register (operands[0], SImode))
3993 operands[0] = force_reg (SImode, operands[0]);
3994 if (!cirrus_fp_register (operands[1], SFmode))
3995 operands[1] = force_reg (SFmode, operands[0]);
3996 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3997 DONE;
3998 }
3999")
4000
604f3a0a 4001(define_expand "fix_truncdfsi2"
4002 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4003 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4004 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4005 "
a2cd141b 4006 if (TARGET_MAVERICK)
604f3a0a 4007 {
4008 if (!cirrus_fp_register (operands[1], DFmode))
4009 operands[1] = force_reg (DFmode, operands[0]);
4010 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4011 DONE;
4012 }
4013")
4014
f544c6d2 4015;; Truncation insns
b11cae9e 4016
604f3a0a 4017(define_expand "truncdfsf2"
4018 [(set (match_operand:SF 0 "s_register_operand" "")
4019 (float_truncate:SF
4020 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4021 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4022 ""
4023)
9b8516be 4024
4025/* DFmode -> HFmode conversions have to go through SFmode. */
4026(define_expand "truncdfhf2"
4027 [(set (match_operand:HF 0 "general_operand" "")
4028 (float_truncate:HF
4029 (match_operand:DF 1 "general_operand" "")))]
4030 "TARGET_EITHER"
4031 "
4032 {
4033 rtx op1;
4034 op1 = convert_to_mode (SFmode, operands[1], 0);
4035 op1 = convert_to_mode (HFmode, op1, 0);
4036 emit_move_insn (operands[0], op1);
4037 DONE;
4038 }"
4039)
b11cae9e 4040\f
9c08d1fa 4041;; Zero and sign extension instructions.
b11cae9e 4042
848e66ac 4043(define_insn "zero_extend<mode>di2"
4044 [(set (match_operand:DI 0 "s_register_operand" "=r")
4045 (zero_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))]
4046 "TARGET_32BIT <qhs_zextenddi_cond>"
4047 "#"
4048 [(set_attr "length" "8")
4049 (set_attr "ce_count" "2")
4050 (set_attr "predicable" "yes")]
25f905c2 4051)
4052
848e66ac 4053(define_insn "extend<mode>di2"
9c08d1fa 4054 [(set (match_operand:DI 0 "s_register_operand" "=r")
848e66ac 4055 (sign_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))]
4056 "TARGET_32BIT <qhs_sextenddi_cond>"
4057 "#"
0d66636f 4058 [(set_attr "length" "8")
848e66ac 4059 (set_attr "ce_count" "2")
4060 (set_attr "shift" "1")
0d66636f 4061 (set_attr "predicable" "yes")]
4062)
9c08d1fa 4063
848e66ac 4064;; Splits for all extensions to DImode
4065(define_split
4066 [(set (match_operand:DI 0 "s_register_operand" "")
4067 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4068 "TARGET_32BIT"
848e66ac 4069 [(set (match_dup 0) (match_dup 1))]
4070{
848e66ac 4071 rtx lo_part = gen_lowpart (SImode, operands[0]);
4072 enum machine_mode src_mode = GET_MODE (operands[1]);
4073
4074 if (REG_P (operands[0])
4075 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4076 emit_clobber (operands[0]);
4077 if (!REG_P (lo_part) || src_mode != SImode
4078 || !rtx_equal_p (lo_part, operands[1]))
4079 {
4080 if (src_mode == SImode)
4081 emit_move_insn (lo_part, operands[1]);
4082 else
4083 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4084 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4085 operands[1] = lo_part;
4086 }
4087 operands[0] = gen_highpart (SImode, operands[0]);
4088 operands[1] = const0_rtx;
4089})
9c08d1fa 4090
848e66ac 4091(define_split
25f905c2 4092 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4093 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4094 "TARGET_32BIT"
848e66ac 4095 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4096{
4097 rtx lo_part = gen_lowpart (SImode, operands[0]);
4098 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4099
848e66ac 4100 if (REG_P (operands[0])
4101 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4102 emit_clobber (operands[0]);
4103
4104 if (!REG_P (lo_part) || src_mode != SImode
4105 || !rtx_equal_p (lo_part, operands[1]))
4106 {
4107 if (src_mode == SImode)
4108 emit_move_insn (lo_part, operands[1]);
4109 else
4110 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4111 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4112 operands[1] = lo_part;
4113 }
4114 operands[0] = gen_highpart (SImode, operands[0]);
4115})
9c08d1fa 4116
4117(define_expand "zero_extendhisi2"
ef51b8e1 4118 [(set (match_operand:SI 0 "s_register_operand" "")
4119 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4120 "TARGET_EITHER"
ef51b8e1 4121{
4122 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4123 {
ef51b8e1 4124 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4125 DONE;
25f7a26e 4126 }
ef51b8e1 4127 if (!arm_arch6 && !MEM_P (operands[1]))
4128 {
4129 rtx t = gen_lowpart (SImode, operands[1]);
4130 rtx tmp = gen_reg_rtx (SImode);
4131 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4132 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4133 DONE;
4134 }
4135})
9c08d1fa 4136
ef51b8e1 4137(define_split
4138 [(set (match_operand:SI 0 "register_operand" "")
747b7458 4139 (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
ef51b8e1 4140 "!TARGET_THUMB2 && !arm_arch6"
4141 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4142 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4143{
4144 operands[2] = gen_lowpart (SImode, operands[1]);
4145})
4146
4147(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4148 [(set (match_operand:SI 0 "register_operand" "=l,l")
4149 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4150 "TARGET_THUMB1"
848e66ac 4151{
a2cd141b 4152 rtx mem;
4153
ef51b8e1 4154 if (which_alternative == 0 && arm_arch6)
848e66ac 4155 return "uxth\t%0, %1";
ef51b8e1 4156 if (which_alternative == 0)
848e66ac 4157 return "#";
a2cd141b 4158
4159 mem = XEXP (operands[1], 0);
4160
4161 if (GET_CODE (mem) == CONST)
4162 mem = XEXP (mem, 0);
4163
a2cd141b 4164 if (GET_CODE (mem) == PLUS)
4165 {
4166 rtx a = XEXP (mem, 0);
a2cd141b 4167
4168 /* This can happen due to bugs in reload. */
4169 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4170 {
4171 rtx ops[2];
4172 ops[0] = operands[0];
4173 ops[1] = a;
4174
848e66ac 4175 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4176
4177 XEXP (mem, 0) = operands[0];
4178 }
a2cd141b 4179 }
4180
848e66ac 4181 return "ldrh\t%0, %1";
4182}
ef51b8e1 4183 [(set_attr_alternative "length"
4184 [(if_then_else (eq_attr "is_arch6" "yes")
4185 (const_int 2) (const_int 4))
4186 (const_int 4)])
848e66ac 4187 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4188)
4189
cffb2a26 4190(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4191 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4192 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4193 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4194 "@
4195 #
4196 ldr%(h%)\\t%0, %1"
4197 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4198 (set_attr "predicable" "yes")]
cffb2a26 4199)
f7fbdd4a 4200
a2cd141b 4201(define_insn "*arm_zero_extendhisi2_v6"
4202 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4203 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4204 "TARGET_ARM && arm_arch6"
4205 "@
4206 uxth%?\\t%0, %1
25f905c2 4207 ldr%(h%)\\t%0, %1"
a2cd141b 4208 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4209 (set_attr "predicable" "yes")]
a2cd141b 4210)
4211
4212(define_insn "*arm_zero_extendhisi2addsi"
4213 [(set (match_operand:SI 0 "s_register_operand" "=r")
4214 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4215 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4216 "TARGET_INT_SIMD"
a2cd141b 4217 "uxtah%?\\t%0, %2, %1"
4218 [(set_attr "type" "alu_shift")
4219 (set_attr "predicable" "yes")]
4220)
4221
87b22bf7 4222(define_expand "zero_extendqisi2"
cffb2a26 4223 [(set (match_operand:SI 0 "s_register_operand" "")
4224 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4225 "TARGET_EITHER"
ef51b8e1 4226{
4227 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4228 {
ef51b8e1 4229 emit_insn (gen_andsi3 (operands[0],
4230 gen_lowpart (SImode, operands[1]),
4231 GEN_INT (255)));
4232 DONE;
4233 }
4234 if (!arm_arch6 && !MEM_P (operands[1]))
4235 {
4236 rtx t = gen_lowpart (SImode, operands[1]);
4237 rtx tmp = gen_reg_rtx (SImode);
4238 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4239 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4240 DONE;
4241 }
4242})
cffb2a26 4243
ef51b8e1 4244(define_split
4245 [(set (match_operand:SI 0 "register_operand" "")
4246 (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4247 "!arm_arch6"
4248 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4249 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4250{
4251 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4252 if (TARGET_ARM)
4253 {
4254 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4255 DONE;
4256 }
ef51b8e1 4257})
9c08d1fa 4258
25f905c2 4259(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4260 [(set (match_operand:SI 0 "register_operand" "=l,l")
4261 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4262 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4263 "@
4264 #
4265 ldrb\\t%0, %1"
4266 [(set_attr "length" "4,2")
4267 (set_attr "type" "alu_shift,load_byte")
4268 (set_attr "pool_range" "*,32")]
cffb2a26 4269)
4270
25f905c2 4271(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4272 [(set (match_operand:SI 0 "register_operand" "=l,l")
4273 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4274 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4275 "@
4276 uxtb\\t%0, %1
4277 ldrb\\t%0, %1"
848e66ac 4278 [(set_attr "length" "2")
4279 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4280)
4281
cffb2a26 4282(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4283 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4284 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4285 "TARGET_ARM && !arm_arch6"
ef51b8e1 4286 "@
4287 #
4288 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4289 [(set_attr "length" "8,4")
4290 (set_attr "type" "alu_shift,load_byte")
848e66ac 4291 (set_attr "predicable" "yes")]
cffb2a26 4292)
87b22bf7 4293
a2cd141b 4294(define_insn "*arm_zero_extendqisi2_v6"
4295 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4296 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4297 "TARGET_ARM && arm_arch6"
4298 "@
25f905c2 4299 uxtb%(%)\\t%0, %1
4300 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4301 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4302 (set_attr "predicable" "yes")]
a2cd141b 4303)
4304
4305(define_insn "*arm_zero_extendqisi2addsi"
4306 [(set (match_operand:SI 0 "s_register_operand" "=r")
4307 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4308 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4309 "TARGET_INT_SIMD"
a2cd141b 4310 "uxtab%?\\t%0, %2, %1"
4311 [(set_attr "predicable" "yes")
bcaec148 4312 (set_attr "insn" "xtab")
a2cd141b 4313 (set_attr "type" "alu_shift")]
4314)
4315
87b22bf7 4316(define_split
4317 [(set (match_operand:SI 0 "s_register_operand" "")
4318 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4319 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4320 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4321 [(set (match_dup 2) (match_dup 1))
4322 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4323 ""
4324)
9c08d1fa 4325
8a4d25d6 4326(define_split
4327 [(set (match_operand:SI 0 "s_register_operand" "")
4328 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4329 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4330 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4331 [(set (match_dup 2) (match_dup 1))
4332 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4333 ""
4334)
4335
1c274529 4336
4337(define_split
4338 [(set (match_operand:SI 0 "s_register_operand" "")
4339 (ior_xor:SI (and:SI (ashift:SI
4340 (match_operand:SI 1 "s_register_operand" "")
4341 (match_operand:SI 2 "const_int_operand" ""))
4342 (match_operand:SI 3 "const_int_operand" ""))
4343 (zero_extend:SI
4344 (match_operator 5 "subreg_lowpart_operator"
4345 [(match_operand:SI 4 "s_register_operand" "")]))))]
4346 "TARGET_32BIT
63787642 4347 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4348 == (GET_MODE_MASK (GET_MODE (operands[5]))
4349 & (GET_MODE_MASK (GET_MODE (operands[5]))
4350 << (INTVAL (operands[2])))))"
4351 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4352 (match_dup 4)))
4353 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4354 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4355)
4356
f7fbdd4a 4357(define_insn "*compareqi_eq0"
bd5b4116 4358 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4359 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4360 (const_int 0)))]
25f905c2 4361 "TARGET_32BIT"
87b22bf7 4362 "tst\\t%0, #255"
cffb2a26 4363 [(set_attr "conds" "set")]
4364)
b11cae9e 4365
b11cae9e 4366(define_expand "extendhisi2"
ef51b8e1 4367 [(set (match_operand:SI 0 "s_register_operand" "")
4368 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4369 "TARGET_EITHER"
ef51b8e1 4370{
4371 if (TARGET_THUMB1)
4372 {
4373 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4374 DONE;
4375 }
4376 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4377 {
4378 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4379 DONE;
4380 }
ed29c566 4381
ef51b8e1 4382 if (!arm_arch6 && !MEM_P (operands[1]))
4383 {
4384 rtx t = gen_lowpart (SImode, operands[1]);
4385 rtx tmp = gen_reg_rtx (SImode);
4386 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4387 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4388 DONE;
4389 }
4390})
cffb2a26 4391
ef51b8e1 4392(define_split
4393 [(parallel
4394 [(set (match_operand:SI 0 "register_operand" "")
4395 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4396 (clobber (match_scratch:SI 2 ""))])]
4397 "!arm_arch6"
4398 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4399 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4400{
4401 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4402})
25f7a26e 4403
a2cd141b 4404;; We used to have an early-clobber on the scratch register here.
4405;; However, there's a bug somewhere in reload which means that this
4406;; can be partially ignored during spill allocation if the memory
ed29c566 4407;; address also needs reloading; this causes us to die later on when
a2cd141b 4408;; we try to verify the operands. Fortunately, we don't really need
4409;; the early-clobber: we can always use operand 0 if operand 2
4410;; overlaps the address.
ef51b8e1 4411(define_insn "thumb1_extendhisi2"
a2cd141b 4412 [(set (match_operand:SI 0 "register_operand" "=l,l")
4413 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4414 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4415 "TARGET_THUMB1"
a2cd141b 4416 "*
4417 {
4418 rtx ops[4];
4419 rtx mem;
4420
ef51b8e1 4421 if (which_alternative == 0 && !arm_arch6)
4422 return \"#\";
a2cd141b 4423 if (which_alternative == 0)
4424 return \"sxth\\t%0, %1\";
4425
4426 mem = XEXP (operands[1], 0);
4427
4428 /* This code used to try to use 'V', and fix the address only if it was
4429 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4430 range of QImode offsets, and offsettable_address_p does a QImode
4431 address check. */
4432
4433 if (GET_CODE (mem) == CONST)
4434 mem = XEXP (mem, 0);
4435
4436 if (GET_CODE (mem) == LABEL_REF)
4437 return \"ldr\\t%0, %1\";
4438
4439 if (GET_CODE (mem) == PLUS)
4440 {
4441 rtx a = XEXP (mem, 0);
4442 rtx b = XEXP (mem, 1);
4443
4444 if (GET_CODE (a) == LABEL_REF
4445 && GET_CODE (b) == CONST_INT)
4446 return \"ldr\\t%0, %1\";
4447
4448 if (GET_CODE (b) == REG)
4449 return \"ldrsh\\t%0, %1\";
4450
4451 ops[1] = a;
4452 ops[2] = b;
4453 }
4454 else
4455 {
4456 ops[1] = mem;
4457 ops[2] = const0_rtx;
4458 }
4459
ed29c566 4460 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4461
4462 ops[0] = operands[0];
4463 if (reg_mentioned_p (operands[2], ops[1]))
4464 ops[3] = ops[0];
4465 else
4466 ops[3] = operands[2];
4467 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4468 return \"\";
4469 }"
ef51b8e1 4470 [(set_attr_alternative "length"
4471 [(if_then_else (eq_attr "is_arch6" "yes")
4472 (const_int 2) (const_int 4))
4473 (const_int 4)])
a2cd141b 4474 (set_attr "type" "alu_shift,load_byte")
4475 (set_attr "pool_range" "*,1020")]
4476)
4477
25f905c2 4478;; This pattern will only be used when ldsh is not available
25f7a26e 4479(define_expand "extendhisi2_mem"
eab14235 4480 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4481 (set (match_dup 3)
eab14235 4482 (zero_extend:SI (match_dup 7)))
25f7a26e 4483 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4484 (set (match_operand:SI 0 "" "")
4485 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4486 "TARGET_ARM"
25f7a26e 4487 "
215b30b3 4488 {
4489 rtx mem1, mem2;
4490 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4491
788fcce0 4492 mem1 = change_address (operands[1], QImode, addr);
4493 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4494 operands[0] = gen_lowpart (SImode, operands[0]);
4495 operands[1] = mem1;
4496 operands[2] = gen_reg_rtx (SImode);
4497 operands[3] = gen_reg_rtx (SImode);
4498 operands[6] = gen_reg_rtx (SImode);
4499 operands[7] = mem2;
25f7a26e 4500
215b30b3 4501 if (BYTES_BIG_ENDIAN)
4502 {
4503 operands[4] = operands[2];
4504 operands[5] = operands[3];
4505 }
4506 else
4507 {
4508 operands[4] = operands[3];
4509 operands[5] = operands[2];
4510 }
4511 }"
4512)
b11cae9e 4513
ef51b8e1 4514(define_split
4515 [(set (match_operand:SI 0 "register_operand" "")
4516 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4517 "!arm_arch6"
4518 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4519 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4520{
4521 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4522})
4523
a2cd141b 4524(define_insn "*arm_extendhisi2"
ef51b8e1 4525 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4526 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4527 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4528 "@
4529 #
4530 ldr%(sh%)\\t%0, %1"
4531 [(set_attr "length" "8,4")
4532 (set_attr "type" "alu_shift,load_byte")
0d66636f 4533 (set_attr "predicable" "yes")
ef51b8e1 4534 (set_attr "pool_range" "*,256")
4535 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4536)
f7fbdd4a 4537
25f905c2 4538;; ??? Check Thumb-2 pool range
a2cd141b 4539(define_insn "*arm_extendhisi2_v6"
4540 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4541 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4542 "TARGET_32BIT && arm_arch6"
a2cd141b 4543 "@
4544 sxth%?\\t%0, %1
25f905c2 4545 ldr%(sh%)\\t%0, %1"
a2cd141b 4546 [(set_attr "type" "alu_shift,load_byte")
4547 (set_attr "predicable" "yes")
4548 (set_attr "pool_range" "*,256")
4549 (set_attr "neg_pool_range" "*,244")]
4550)
4551
4552(define_insn "*arm_extendhisi2addsi"
4553 [(set (match_operand:SI 0 "s_register_operand" "=r")
4554 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4555 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4556 "TARGET_INT_SIMD"
a2cd141b 4557 "sxtah%?\\t%0, %2, %1"
4558)
4559
c8f69309 4560(define_expand "extendqihi2"
4561 [(set (match_dup 2)
bed7d9a5 4562 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4563 (const_int 24)))
9c08d1fa 4564 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4565 (ashiftrt:SI (match_dup 2)
4566 (const_int 24)))]
cffb2a26 4567 "TARGET_ARM"
c8f69309 4568 "
215b30b3 4569 {
4570 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4571 {
4572 emit_insn (gen_rtx_SET (VOIDmode,
4573 operands[0],
4574 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4575 DONE;
4576 }
4577 if (!s_register_operand (operands[1], QImode))
4578 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4579 operands[0] = gen_lowpart (SImode, operands[0]);
4580 operands[1] = gen_lowpart (SImode, operands[1]);
4581 operands[2] = gen_reg_rtx (SImode);
4582 }"
4583)
f7fbdd4a 4584
25f905c2 4585(define_insn "*arm_extendqihi_insn"
b4e8a300 4586 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4587 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4588 "TARGET_ARM && arm_arch4"
25f905c2 4589 "ldr%(sb%)\\t%0, %1"
a2cd141b 4590 [(set_attr "type" "load_byte")
0d66636f 4591 (set_attr "predicable" "yes")
cffb2a26 4592 (set_attr "pool_range" "256")
4593 (set_attr "neg_pool_range" "244")]
4594)
3fc2009e 4595
b11cae9e 4596(define_expand "extendqisi2"
ef51b8e1 4597 [(set (match_operand:SI 0 "s_register_operand" "")
4598 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 4599 "TARGET_EITHER"
ef51b8e1 4600{
4601 if (!arm_arch4 && MEM_P (operands[1]))
4602 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4603
ef51b8e1 4604 if (!arm_arch6 && !MEM_P (operands[1]))
4605 {
4606 rtx t = gen_lowpart (SImode, operands[1]);
4607 rtx tmp = gen_reg_rtx (SImode);
4608 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4609 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4610 DONE;
4611 }
4612})
a2cd141b 4613
ef51b8e1 4614(define_split
4615 [(set (match_operand:SI 0 "register_operand" "")
4616 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4617 "!arm_arch6"
4618 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4619 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4620{
4621 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4622})
f7fbdd4a 4623
a2cd141b 4624(define_insn "*arm_extendqisi"
ef51b8e1 4625 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4626 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4627 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4628 "@
4629 #
4630 ldr%(sb%)\\t%0, %1"
4631 [(set_attr "length" "8,4")
4632 (set_attr "type" "alu_shift,load_byte")
0d66636f 4633 (set_attr "predicable" "yes")
ef51b8e1 4634 (set_attr "pool_range" "*,256")
4635 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4636)
3fc2009e 4637
a2cd141b 4638(define_insn "*arm_extendqisi_v6"
4639 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4640 (sign_extend:SI
4641 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4642 "TARGET_ARM && arm_arch6"
b4e8a300 4643 "@
4644 sxtb%?\\t%0, %1
25f905c2 4645 ldr%(sb%)\\t%0, %1"
a2cd141b 4646 [(set_attr "type" "alu_shift,load_byte")
4647 (set_attr "predicable" "yes")
a2cd141b 4648 (set_attr "pool_range" "*,256")
4649 (set_attr "neg_pool_range" "*,244")]
4650)
4651
4652(define_insn "*arm_extendqisi2addsi"
4653 [(set (match_operand:SI 0 "s_register_operand" "=r")
4654 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4655 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4656 "TARGET_INT_SIMD"
a2cd141b 4657 "sxtab%?\\t%0, %2, %1"
4658 [(set_attr "type" "alu_shift")
bcaec148 4659 (set_attr "insn" "xtab")
a2cd141b 4660 (set_attr "predicable" "yes")]
4661)
4662
ef51b8e1 4663(define_split
4664 [(set (match_operand:SI 0 "register_operand" "")
4665 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4666 "TARGET_THUMB1 && reload_completed"
4667 [(set (match_dup 0) (match_dup 2))
4668 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4669{
4670 rtx addr = XEXP (operands[1], 0);
cffb2a26 4671
ef51b8e1 4672 if (GET_CODE (addr) == CONST)
4673 addr = XEXP (addr, 0);
cffb2a26 4674
ef51b8e1 4675 if (GET_CODE (addr) == PLUS
4676 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4677 /* No split necessary. */
4678 FAIL;
4679
4680 if (GET_CODE (addr) == PLUS
4681 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4682 FAIL;
4683
4684 if (reg_overlap_mentioned_p (operands[0], addr))
4685 {
4686 rtx t = gen_lowpart (QImode, operands[0]);
4687 emit_move_insn (t, operands[1]);
4688 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4689 DONE;
4690 }
4691
4692 if (REG_P (addr))
4693 {
4694 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4695 operands[2] = const0_rtx;
4696 }
4697 else if (GET_CODE (addr) != PLUS)
4698 FAIL;
4699 else if (REG_P (XEXP (addr, 0)))
4700 {
4701 operands[2] = XEXP (addr, 1);
4702 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4703 }
4704 else
4705 {
4706 operands[2] = XEXP (addr, 0);
4707 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4708 }
cffb2a26 4709
ef51b8e1 4710 operands[3] = change_address (operands[1], QImode, addr);
4711})
4712
8a3b73a1 4713(define_peephole2
4714 [(set (match_operand:SI 0 "register_operand" "")
4715 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4716 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4717 (set (match_operand:SI 3 "register_operand" "")
4718 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4719 "TARGET_THUMB1
4720 && GET_CODE (XEXP (operands[4], 0)) == PLUS
4721 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4722 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4723 && (peep2_reg_dead_p (3, operands[0])
4724 || rtx_equal_p (operands[0], operands[3]))
4725 && (peep2_reg_dead_p (3, operands[2])
4726 || rtx_equal_p (operands[2], operands[3]))"
4727 [(set (match_dup 2) (match_dup 1))
4728 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4729{
4730 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4731 operands[4] = change_address (operands[4], QImode, addr);
4732})
4733
ef51b8e1 4734(define_insn "thumb1_extendqisi2"
a2cd141b 4735 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4736 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 4737 "TARGET_THUMB1"
4738{
4739 rtx addr;
a2cd141b 4740
ef51b8e1 4741 if (which_alternative == 0 && arm_arch6)
4742 return "sxtb\\t%0, %1";
4743 if (which_alternative == 0)
4744 return "#";
a2cd141b 4745
ef51b8e1 4746 addr = XEXP (operands[1], 0);
4747 if (GET_CODE (addr) == PLUS
4748 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4749 return "ldrsb\\t%0, %1";
a2cd141b 4750
ef51b8e1 4751 return "#";
4752}
4753 [(set_attr_alternative "length"
4754 [(if_then_else (eq_attr "is_arch6" "yes")
4755 (const_int 2) (const_int 4))
4756 (const_int 2)
4757 (if_then_else (eq_attr "is_arch6" "yes")
4758 (const_int 4) (const_int 6))])
4759 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 4760)
4761
caedf871 4762(define_expand "extendsfdf2"
4763 [(set (match_operand:DF 0 "s_register_operand" "")
4764 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4765 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4766 ""
4767)
9b8516be 4768
4769/* HFmode -> DFmode conversions have to go through SFmode. */
4770(define_expand "extendhfdf2"
4771 [(set (match_operand:DF 0 "general_operand" "")
4772 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4773 "TARGET_EITHER"
4774 "
4775 {
4776 rtx op1;
4777 op1 = convert_to_mode (SFmode, operands[1], 0);
4778 op1 = convert_to_mode (DFmode, op1, 0);
4779 emit_insn (gen_movdf (operands[0], op1));
4780 DONE;
4781 }"
4782)
b11cae9e 4783\f
4784;; Move insns (including loads and stores)
4785
4786;; XXX Just some ideas about movti.
9c08d1fa 4787;; I don't think these are a good idea on the arm, there just aren't enough
4788;; registers
b11cae9e 4789;;(define_expand "loadti"
9c08d1fa 4790;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4791;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4792;; "" "")
4793
4794;;(define_expand "storeti"
4795;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4796;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4797;; "" "")
4798
4799;;(define_expand "movti"
4800;; [(set (match_operand:TI 0 "general_operand" "")
4801;; (match_operand:TI 1 "general_operand" ""))]
4802;; ""
4803;; "
4804;;{
4805;; rtx insn;
4806;;
4807;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4808;; operands[1] = copy_to_reg (operands[1]);
4809;; if (GET_CODE (operands[0]) == MEM)
4810;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4811;; else if (GET_CODE (operands[1]) == MEM)
4812;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4813;; else
4814;; FAIL;
4815;;
4816;; emit_insn (insn);
4817;; DONE;
4818;;}")
4819
a2f10574 4820;; Recognize garbage generated above.
b11cae9e 4821
4822;;(define_insn ""
4823;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4824;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4825;; ""
4826;; "*
4827;; {
4828;; register mem = (which_alternative < 3);
0d66636f 4829;; register const char *template;
b11cae9e 4830;;
4831;; operands[mem] = XEXP (operands[mem], 0);
4832;; switch (which_alternative)
4833;; {
4834;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4835;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4836;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4837;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4838;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4839;; case 5: template = \"stmia\\t%0, %M1\"; break;
4840;; }
e2348bcb 4841;; output_asm_insn (template, operands);
4842;; return \"\";
b11cae9e 4843;; }")
4844
cffb2a26 4845(define_expand "movdi"
4846 [(set (match_operand:DI 0 "general_operand" "")
4847 (match_operand:DI 1 "general_operand" ""))]
4848 "TARGET_EITHER"
4849 "
e1ba4a27 4850 if (can_create_pseudo_p ())
cffb2a26 4851 {
b2778788 4852 if (GET_CODE (operands[0]) != REG)
4853 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4854 }
4855 "
4856)
b11cae9e 4857
cffb2a26 4858(define_insn "*arm_movdi"
d51f92df 4859 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4860 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 4861 "TARGET_32BIT
b2778788 4862 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4863 && !TARGET_IWMMXT
4864 && ( register_operand (operands[0], DImode)
4865 || register_operand (operands[1], DImode))"
b11cae9e 4866 "*
d51f92df 4867 switch (which_alternative)
4868 {
4869 case 0:
4870 case 1:
4871 case 2:
4872 return \"#\";
4873 default:
4874 return output_move_double (operands);
4875 }
cffb2a26 4876 "
359a6e9f 4877 [(set_attr "length" "8,12,16,8,8")
4878 (set_attr "type" "*,*,*,load2,store2")
cde1623a 4879 (set_attr "arm_pool_range" "*,*,*,1020,*")
4880 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
4881 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
4882 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 4883)
4884
d51f92df 4885(define_split
4886 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4887 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4888 "TARGET_32BIT
d51f92df 4889 && reload_completed
4890 && (arm_const_double_inline_cost (operands[1])
4891 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4892 [(const_int 0)]
4893 "
4894 arm_split_constant (SET, SImode, curr_insn,
4895 INTVAL (gen_lowpart (SImode, operands[1])),
4896 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4897 arm_split_constant (SET, SImode, curr_insn,
4898 INTVAL (gen_highpart_mode (SImode,
4899 GET_MODE (operands[0]),
4900 operands[1])),
4901 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4902 DONE;
4903 "
4904)
4905
e5ba9289 4906; If optimizing for size, or if we have load delay slots, then
4907; we want to split the constant into two separate operations.
4908; In both cases this may split a trivial part into a single data op
4909; leaving a single complex constant to load. We can also get longer
4910; offsets in a LDR which means we get better chances of sharing the pool
4911; entries. Finally, we can normally do a better job of scheduling
4912; LDR instructions than we can with LDM.
4913; This pattern will only match if the one above did not.
4914(define_split
4915 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4916 (match_operand:ANY64 1 "const_double_operand" ""))]
4917 "TARGET_ARM && reload_completed
4918 && arm_const_double_by_parts (operands[1])"
4919 [(set (match_dup 0) (match_dup 1))
4920 (set (match_dup 2) (match_dup 3))]
4921 "
4922 operands[2] = gen_highpart (SImode, operands[0]);
4923 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4924 operands[1]);
4925 operands[0] = gen_lowpart (SImode, operands[0]);
4926 operands[1] = gen_lowpart (SImode, operands[1]);
4927 "
4928)
4929
d51f92df 4930(define_split
4931 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4932 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4933 "TARGET_EITHER && reload_completed"
4934 [(set (match_dup 0) (match_dup 1))
4935 (set (match_dup 2) (match_dup 3))]
4936 "
4937 operands[2] = gen_highpart (SImode, operands[0]);
4938 operands[3] = gen_highpart (SImode, operands[1]);
4939 operands[0] = gen_lowpart (SImode, operands[0]);
4940 operands[1] = gen_lowpart (SImode, operands[1]);
4941
4942 /* Handle a partial overlap. */
4943 if (rtx_equal_p (operands[0], operands[3]))
4944 {
4945 rtx tmp0 = operands[0];
4946 rtx tmp1 = operands[1];
4947
4948 operands[0] = operands[2];
4949 operands[1] = operands[3];
4950 operands[2] = tmp0;
4951 operands[3] = tmp1;
4952 }
4953 "
4954)
4955
a8a3b539 4956;; We can't actually do base+index doubleword loads if the index and
4957;; destination overlap. Split here so that we at least have chance to
4958;; schedule.
4959(define_split
4960 [(set (match_operand:DI 0 "s_register_operand" "")
4961 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4962 (match_operand:SI 2 "s_register_operand" ""))))]
4963 "TARGET_LDRD
4964 && reg_overlap_mentioned_p (operands[0], operands[1])
4965 && reg_overlap_mentioned_p (operands[0], operands[2])"
4966 [(set (match_dup 4)
4967 (plus:SI (match_dup 1)
4968 (match_dup 2)))
4969 (set (match_dup 0)
4970 (mem:DI (match_dup 4)))]
4971 "
4972 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4973 "
4974)
4975
cffb2a26 4976;;; ??? This should have alternatives for constants.
4977;;; ??? This was originally identical to the movdf_insn pattern.
4978;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4979;;; thumb_reorg with a memory reference.
25f905c2 4980(define_insn "*thumb1_movdi_insn"
215b30b3 4981 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4982 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4983 "TARGET_THUMB1
a2cd141b 4984 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4985 && ( register_operand (operands[0], DImode)
4986 || register_operand (operands[1], DImode))"
4987 "*
4988 {
4989 switch (which_alternative)
4990 {
4991 default:
4992 case 0:
4993 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4994 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4995 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4996 case 1:
4997 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4998 case 2:
4999 operands[1] = GEN_INT (- INTVAL (operands[1]));
5000 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5001 case 3:
5002 return \"ldmia\\t%1, {%0, %H0}\";
5003 case 4:
5004 return \"stmia\\t%0, {%1, %H1}\";
5005 case 5:
5006 return thumb_load_double_from_address (operands);
5007 case 6:
1a83b3ff 5008 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5009 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5010 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5011 return \"\";
5012 case 7:
5013 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5014 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5015 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5016 }
5017 }"
5018 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5019 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5020 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5021 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5022)
b11cae9e 5023
9c08d1fa 5024(define_expand "movsi"
5025 [(set (match_operand:SI 0 "general_operand" "")
5026 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5027 "TARGET_EITHER"
9c08d1fa 5028 "
befb0bac 5029 {
e348ff3e 5030 rtx base, offset, tmp;
5031
25f905c2 5032 if (TARGET_32BIT)
9c08d1fa 5033 {
674a8f0b 5034 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5035 if (GET_CODE (operands[0]) == MEM)
5036 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5037 if (arm_general_register_operand (operands[0], SImode)
5038 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5039 && !(const_ok_for_arm (INTVAL (operands[1]))
5040 || const_ok_for_arm (~INTVAL (operands[1]))))
5041 {
96f57e36 5042 arm_split_constant (SET, SImode, NULL_RTX,
5043 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5044 optimize && can_create_pseudo_p ());
cffb2a26 5045 DONE;
5046 }
d0e6a121 5047
5048 if (TARGET_USE_MOVT && !target_word_relocations
5049 && GET_CODE (operands[1]) == SYMBOL_REF
5050 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5051 {
5052 arm_emit_movpair (operands[0], operands[1]);
5053 DONE;
5054 }
cffb2a26 5055 }
25f905c2 5056 else /* TARGET_THUMB1... */
cffb2a26 5057 {
e1ba4a27 5058 if (can_create_pseudo_p ())
cffb2a26 5059 {
5060 if (GET_CODE (operands[0]) != REG)
5061 operands[1] = force_reg (SImode, operands[1]);
5062 }
9c08d1fa 5063 }
f655717d 5064
e348ff3e 5065 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5066 {
5067 split_const (operands[1], &base, &offset);
5068 if (GET_CODE (base) == SYMBOL_REF
5069 && !offset_within_block_p (base, INTVAL (offset)))
5070 {
b308ddcf 5071 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5072 emit_move_insn (tmp, base);
5073 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5074 DONE;
5075 }
5076 }
5077
f655717d 5078 /* Recognize the case where operand[1] is a reference to thread-local
5079 data and load its address to a register. */
5080 if (arm_tls_referenced_p (operands[1]))
5081 {
5082 rtx tmp = operands[1];
5083 rtx addend = NULL;
5084
5085 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5086 {
5087 addend = XEXP (XEXP (tmp, 0), 1);
5088 tmp = XEXP (XEXP (tmp, 0), 0);
5089 }
5090
5091 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5092 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5093
e1ba4a27 5094 tmp = legitimize_tls_address (tmp,
5095 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5096 if (addend)
5097 {
5098 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5099 tmp = force_operand (tmp, operands[0]);
5100 }
5101 operands[1] = tmp;
5102 }
5103 else if (flag_pic
5104 && (CONSTANT_P (operands[1])
5105 || symbol_mentioned_p (operands[1])
5106 || label_mentioned_p (operands[1])))
5107 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5108 (!can_create_pseudo_p ()
5109 ? operands[0]
5110 : 0));
befb0bac 5111 }
215b30b3 5112 "
5113)
9c08d1fa 5114
d0e6a121 5115;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5116;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5117;; so this does not matter.
5118(define_insn "*arm_movt"
5119 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5120 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5121 (match_operand:SI 2 "general_operand" "i")))]
5122 "TARGET_32BIT"
5123 "movt%?\t%0, #:upper16:%c2"
5124 [(set_attr "predicable" "yes")
5125 (set_attr "length" "4")]
5126)
5127
cffb2a26 5128(define_insn "*arm_movsi_insn"
aaa37ad6 5129 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5130 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5131 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5132 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5133 && ( register_operand (operands[0], SImode)
5134 || register_operand (operands[1], SImode))"
f7fbdd4a 5135 "@
aaa37ad6 5136 mov%?\\t%0, %1
f7fbdd4a 5137 mov%?\\t%0, %1
5138 mvn%?\\t%0, #%B1
25f905c2 5139 movw%?\\t%0, %1
f7fbdd4a 5140 ldr%?\\t%0, %1
5141 str%?\\t%1, %0"
aaa37ad6 5142 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5143 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5144 (set_attr "predicable" "yes")
aaa37ad6 5145 (set_attr "pool_range" "*,*,*,*,4096,*")
5146 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5147)
87b22bf7 5148
5149(define_split
a2cd141b 5150 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5151 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5152 "TARGET_32BIT
215b30b3 5153 && (!(const_ok_for_arm (INTVAL (operands[1]))
5154 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5155 [(clobber (const_int 0))]
5156 "
96f57e36 5157 arm_split_constant (SET, SImode, NULL_RTX,
5158 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5159 DONE;
215b30b3 5160 "
5161)
9c08d1fa 5162
25f905c2 5163(define_insn "*thumb1_movsi_insn"
aaa37ad6 5164 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5165 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
25f905c2 5166 "TARGET_THUMB1
cffb2a26 5167 && ( register_operand (operands[0], SImode)
5168 || register_operand (operands[1], SImode))"
5169 "@
5170 mov %0, %1
5171 mov %0, %1
5172 #
5173 #
5174 ldmia\\t%1, {%0}
5175 stmia\\t%0, {%1}
5176 ldr\\t%0, %1
5177 str\\t%1, %0
5178 mov\\t%0, %1"
5179 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5180 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5181 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5182 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5183
5184(define_split
5185 [(set (match_operand:SI 0 "register_operand" "")
5186 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5187 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5188 [(set (match_dup 2) (match_dup 1))
5189 (set (match_dup 0) (neg:SI (match_dup 2)))]
5190 "
5191 {
5192 operands[1] = GEN_INT (- INTVAL (operands[1]));
5193 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5194 }"
cffb2a26 5195)
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_K (operands[1])"
1276f1b8 5201 [(set (match_dup 2) (match_dup 1))
5202 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5203 "
5204 {
e4aeee53 5205 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5206 unsigned HOST_WIDE_INT mask = 0xff;
5207 int i;
5208
5209 for (i = 0; i < 25; i++)
5210 if ((val & (mask << i)) == val)
5211 break;
5212
1276f1b8 5213 /* Don't split if the shift is zero. */
cffb2a26 5214 if (i == 0)
5215 FAIL;
5216
5217 operands[1] = GEN_INT (val >> i);
1276f1b8 5218 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5219 operands[3] = GEN_INT (i);
cffb2a26 5220 }"
5221)
5222
67336bcf 5223;; When generating pic, we need to load the symbol offset into a register.
5224;; So that the optimizer does not confuse this with a normal symbol load
5225;; we use an unspec. The offset will be loaded from a constant pool entry,
5226;; since that is the only type of relocation we can use.
5227
94f8caca 5228;; Wrap calculation of the whole PIC address in a single pattern for the
5229;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5230;; a PIC address involves two loads from memory, so we want to CSE it
5231;; as often as possible.
5232;; This pattern will be split into one of the pic_load_addr_* patterns
5233;; and a move after GCSE optimizations.
5234;;
5235;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5236(define_expand "calculate_pic_address"
5237 [(set (match_operand:SI 0 "register_operand" "")
5238 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5239 (unspec:SI [(match_operand:SI 2 "" "")]
5240 UNSPEC_PIC_SYM))))]
5241 "flag_pic"
5242)
5243
5244;; Split calculate_pic_address into pic_load_addr_* and a move.
5245(define_split
5246 [(set (match_operand:SI 0 "register_operand" "")
5247 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5248 (unspec:SI [(match_operand:SI 2 "" "")]
5249 UNSPEC_PIC_SYM))))]
5250 "flag_pic"
5251 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5252 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5253 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5254)
5255
67336bcf 5256;; The rather odd constraints on the following are to force reload to leave
5257;; the insn alone, and to force the minipool generation pass to then move
5258;; the GOT symbol to memory.
849170fd 5259
b3cd5f55 5260(define_insn "pic_load_addr_32bit"
849170fd 5261 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5262 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5263 "TARGET_32BIT && flag_pic"
67336bcf 5264 "ldr%?\\t%0, %1"
a2cd141b 5265 [(set_attr "type" "load1")
b3cd5f55 5266 (set_attr "pool_range" "4096")
5267 (set (attr "neg_pool_range")
5268 (if_then_else (eq_attr "is_thumb" "no")
5269 (const_int 4084)
5270 (const_int 0)))]
8c4d8060 5271)
5272
25f905c2 5273(define_insn "pic_load_addr_thumb1"
8c4d8060 5274 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5275 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5276 "TARGET_THUMB1 && flag_pic"
8c4d8060 5277 "ldr\\t%0, %1"
a2cd141b 5278 [(set_attr "type" "load1")
8c4d8060 5279 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5280)
849170fd 5281
cffb2a26 5282(define_insn "pic_add_dot_plus_four"
15d5d060 5283 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5284 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5285 (const_int 4)
beef0fb5 5286 (match_operand 2 "" "")]
5287 UNSPEC_PIC_BASE))]
b3cd5f55 5288 "TARGET_THUMB"
cffb2a26 5289 "*
6cdcb15c 5290 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5291 INTVAL (operands[2]));
cffb2a26 5292 return \"add\\t%0, %|pc\";
5293 "
5294 [(set_attr "length" "2")]
5295)
849170fd 5296
5297(define_insn "pic_add_dot_plus_eight"
15d5d060 5298 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5299 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5300 (const_int 8)
beef0fb5 5301 (match_operand 2 "" "")]
5302 UNSPEC_PIC_BASE))]
f655717d 5303 "TARGET_ARM"
c4034607 5304 "*
6cdcb15c 5305 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5306 INTVAL (operands[2]));
15d5d060 5307 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5308 "
0d66636f 5309 [(set_attr "predicable" "yes")]
cffb2a26 5310)
849170fd 5311
f655717d 5312(define_insn "tls_load_dot_plus_eight"
cc071db6 5313 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5314 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5315 (const_int 8)
beef0fb5 5316 (match_operand 2 "" "")]
5317 UNSPEC_PIC_BASE)))]
f655717d 5318 "TARGET_ARM"
5319 "*
6cdcb15c 5320 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5321 INTVAL (operands[2]));
f655717d 5322 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5323 "
5324 [(set_attr "predicable" "yes")]
5325)
5326
5327;; PIC references to local variables can generate pic_add_dot_plus_eight
5328;; followed by a load. These sequences can be crunched down to
5329;; tls_load_dot_plus_eight by a peephole.
5330
5331(define_peephole2
c0c1fba5 5332 [(set (match_operand:SI 0 "register_operand" "")
5333 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5334 (const_int 8)
5335 (match_operand 1 "" "")]
5336 UNSPEC_PIC_BASE))
f655717d 5337 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5338 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5339 [(set (match_dup 2)
5340 (mem:SI (unspec:SI [(match_dup 3)
5341 (const_int 8)
5342 (match_dup 1)]
5343 UNSPEC_PIC_BASE)))]
f655717d 5344 ""
5345)
5346
bac7fc85 5347(define_insn "pic_offset_arm"
5348 [(set (match_operand:SI 0 "register_operand" "=r")
5349 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5350 (unspec:SI [(match_operand:SI 2 "" "X")]
5351 UNSPEC_PIC_OFFSET))))]
5352 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5353 "ldr%?\\t%0, [%1,%2]"
5354 [(set_attr "type" "load1")]
5355)
5356
95373f08 5357(define_expand "builtin_setjmp_receiver"
5358 [(label_ref (match_operand 0 "" ""))]
5359 "flag_pic"
5360 "
5361{
b935b306 5362 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5363 register. */
2cb7d577 5364 if (arm_pic_register != INVALID_REGNUM)
5365 arm_load_pic_register (1UL << 3);
95373f08 5366 DONE;
5367}")
5368
9c08d1fa 5369;; If copying one reg to another we can set the condition codes according to
5370;; its value. Such a move is common after a return from subroutine and the
5371;; result is being tested against zero.
5372
f7fbdd4a 5373(define_insn "*movsi_compare0"
bd5b4116 5374 [(set (reg:CC CC_REGNUM)
cffb2a26 5375 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5376 (const_int 0)))
5377 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5378 (match_dup 1))]
25f905c2 5379 "TARGET_32BIT"
e2348bcb 5380 "@
40dbec34 5381 cmp%?\\t%0, #0
25f905c2 5382 sub%.\\t%0, %1, #0"
cffb2a26 5383 [(set_attr "conds" "set")]
5384)
b11cae9e 5385
b11cae9e 5386;; Subroutine to store a half word from a register into memory.
5387;; Operand 0 is the source register (HImode)
c8f69309 5388;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5389
9c08d1fa 5390;; In both this routine and the next, we must be careful not to spill
01cc3b75 5391;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5392;; can generate unrecognizable rtl.
5393
b11cae9e 5394(define_expand "storehi"
c8f69309 5395 [;; store the low byte
f082f1c4 5396 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5397 ;; extract the high byte
c8f69309 5398 (set (match_dup 2)
5399 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5400 ;; store the high byte
787f8210 5401 (set (match_dup 4) (match_dup 5))]
cffb2a26 5402 "TARGET_ARM"
b11cae9e 5403 "
215b30b3 5404 {
537ffcfc 5405 rtx op1 = operands[1];
5406 rtx addr = XEXP (op1, 0);
215b30b3 5407 enum rtx_code code = GET_CODE (addr);
5408
5409 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5410 || code == MINUS)
537ffcfc 5411 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5412
537ffcfc 5413 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5414 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5415 operands[3] = gen_lowpart (QImode, operands[0]);
5416 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5417 operands[2] = gen_reg_rtx (SImode);
5418 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5419 }"
5420)
b11cae9e 5421
c7597b5d 5422(define_expand "storehi_bigend"
f082f1c4 5423 [(set (match_dup 4) (match_dup 3))
c7597b5d 5424 (set (match_dup 2)
5425 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5426 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5427 "TARGET_ARM"
b11cae9e 5428 "
215b30b3 5429 {
537ffcfc 5430 rtx op1 = operands[1];
5431 rtx addr = XEXP (op1, 0);
215b30b3 5432 enum rtx_code code = GET_CODE (addr);
5433
5434 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5435 || code == MINUS)
537ffcfc 5436 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5437
537ffcfc 5438 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5439 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5440 operands[3] = gen_lowpart (QImode, operands[0]);
5441 operands[0] = gen_lowpart (SImode, operands[0]);
5442 operands[2] = gen_reg_rtx (SImode);
787f8210 5443 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5444 }"
5445)
c7597b5d 5446
5447;; Subroutine to store a half word integer constant into memory.
5448(define_expand "storeinthi"
f082f1c4 5449 [(set (match_operand 0 "" "")
787f8210 5450 (match_operand 1 "" ""))
9e8503e6 5451 (set (match_dup 3) (match_dup 2))]
cffb2a26 5452 "TARGET_ARM"
c7597b5d 5453 "
215b30b3 5454 {
5455 HOST_WIDE_INT value = INTVAL (operands[1]);
5456 rtx addr = XEXP (operands[0], 0);
537ffcfc 5457 rtx op0 = operands[0];
215b30b3 5458 enum rtx_code code = GET_CODE (addr);
c7597b5d 5459
215b30b3 5460 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5461 || code == MINUS)
537ffcfc 5462 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5463
215b30b3 5464 operands[1] = gen_reg_rtx (SImode);
5465 if (BYTES_BIG_ENDIAN)
5466 {
5467 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5468 if ((value & 255) == ((value >> 8) & 255))
5469 operands[2] = operands[1];
5470 else
5471 {
5472 operands[2] = gen_reg_rtx (SImode);
5473 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5474 }
5475 }
5476 else
5477 {
5478 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5479 if ((value & 255) == ((value >> 8) & 255))
5480 operands[2] = operands[1];
5481 else
5482 {
5483 operands[2] = gen_reg_rtx (SImode);
5484 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5485 }
5486 }
c7597b5d 5487
537ffcfc 5488 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5489 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5490 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5491 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5492 }"
5493)
b11cae9e 5494
f7fbdd4a 5495(define_expand "storehi_single_op"
5496 [(set (match_operand:HI 0 "memory_operand" "")
5497 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5498 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5499 "
215b30b3 5500 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5501 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5502 "
5503)
f7fbdd4a 5504
b11cae9e 5505(define_expand "movhi"
5506 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5507 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5508 "TARGET_EITHER"
b11cae9e 5509 "
cffb2a26 5510 if (TARGET_ARM)
b11cae9e 5511 {
e1ba4a27 5512 if (can_create_pseudo_p ())
cffb2a26 5513 {
5514 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5515 {
cffb2a26 5516 if (arm_arch4)
5517 {
5518 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5519 DONE;
5520 }
5521 if (GET_CODE (operands[1]) == CONST_INT)
5522 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5523 else
cffb2a26 5524 {
5525 if (GET_CODE (operands[1]) == MEM)
5526 operands[1] = force_reg (HImode, operands[1]);
5527 if (BYTES_BIG_ENDIAN)
5528 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5529 else
5530 emit_insn (gen_storehi (operands[1], operands[0]));
5531 }
5532 DONE;
b11cae9e 5533 }
cffb2a26 5534 /* Sign extend a constant, and keep it in an SImode reg. */
5535 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5536 {
cffb2a26 5537 rtx reg = gen_reg_rtx (SImode);
5538 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5539
5540 /* If the constant is already valid, leave it alone. */
215b30b3 5541 if (!const_ok_for_arm (val))
cffb2a26 5542 {
5543 /* If setting all the top bits will make the constant
5544 loadable in a single instruction, then set them.
5545 Otherwise, sign extend the number. */
5546
215b30b3 5547 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5548 val |= ~0xffff;
5549 else if (val & 0x8000)
5550 val |= ~0xffff;
5551 }
5552
5553 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5554 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5555 }
e1ba4a27 5556 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5557 && GET_CODE (operands[1]) == MEM)
5558 {
5559 rtx reg = gen_reg_rtx (SImode);
5560
5561 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5562 operands[1] = gen_lowpart (HImode, reg);
5563 }
215b30b3 5564 else if (!arm_arch4)
f7fbdd4a 5565 {
cffb2a26 5566 if (GET_CODE (operands[1]) == MEM)
5567 {
c1a66faf 5568 rtx base;
5569 rtx offset = const0_rtx;
5570 rtx reg = gen_reg_rtx (SImode);
5571
5572 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5573 || (GET_CODE (base) == PLUS
5574 && (GET_CODE (offset = XEXP (base, 1))
5575 == CONST_INT)
5576 && ((INTVAL(offset) & 1) != 1)
5577 && GET_CODE (base = XEXP (base, 0)) == REG))
5578 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5579 {
8deb3959 5580 rtx new_rtx;
c1a66faf 5581
8deb3959 5582 new_rtx = widen_memory_access (operands[1], SImode,
5583 ((INTVAL (offset) & ~3)
5584 - INTVAL (offset)));
5585 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5586 if (((INTVAL (offset) & 2) != 0)
5587 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5588 {
5589 rtx reg2 = gen_reg_rtx (SImode);
5590
5591 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5592 reg = reg2;
5593 }
206ee9a2 5594 }
c1a66faf 5595 else
5596 emit_insn (gen_movhi_bytes (reg, operands[1]));
5597
5598 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5599 }
5600 }
5601 }
674a8f0b 5602 /* Handle loading a large integer during reload. */
cffb2a26 5603 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5604 && !const_ok_for_arm (INTVAL (operands[1]))
5605 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5606 {
5607 /* Writing a constant to memory needs a scratch, which should
5608 be handled with SECONDARY_RELOADs. */
ed29c566 5609 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5610
5611 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5612 emit_insn (gen_movsi (operands[0], operands[1]));
5613 DONE;
5614 }
5615 }
25f905c2 5616 else if (TARGET_THUMB2)
5617 {
5618 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5619 if (can_create_pseudo_p ())
25f905c2 5620 {
5621 if (GET_CODE (operands[0]) != REG)
5622 operands[1] = force_reg (HImode, operands[1]);
5623 /* Zero extend a constant, and keep it in an SImode reg. */
5624 else if (GET_CODE (operands[1]) == CONST_INT)
5625 {
5626 rtx reg = gen_reg_rtx (SImode);
5627 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5628
5629 emit_insn (gen_movsi (reg, GEN_INT (val)));
5630 operands[1] = gen_lowpart (HImode, reg);
5631 }
5632 }
5633 }
5634 else /* TARGET_THUMB1 */
cffb2a26 5635 {
e1ba4a27 5636 if (can_create_pseudo_p ())
cffb2a26 5637 {
6cffc037 5638 if (GET_CODE (operands[1]) == CONST_INT)
5639 {
5640 rtx reg = gen_reg_rtx (SImode);
5641
5642 emit_insn (gen_movsi (reg, operands[1]));
5643 operands[1] = gen_lowpart (HImode, reg);
5644 }
cffb2a26 5645
5646 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5647 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5648 virtual register (also rejected as illegitimate for HImode/QImode)
5649 relative address. */
cffb2a26 5650 /* ??? This should perhaps be fixed elsewhere, for instance, in
5651 fixup_stack_1, by checking for other kinds of invalid addresses,
5652 e.g. a bare reference to a virtual register. This may confuse the
5653 alpha though, which must handle this case differently. */
5654 if (GET_CODE (operands[0]) == MEM
215b30b3 5655 && !memory_address_p (GET_MODE (operands[0]),
5656 XEXP (operands[0], 0)))
537ffcfc 5657 operands[0]
5658 = replace_equiv_address (operands[0],
5659 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5660
5661 if (GET_CODE (operands[1]) == MEM
215b30b3 5662 && !memory_address_p (GET_MODE (operands[1]),
5663 XEXP (operands[1], 0)))
537ffcfc 5664 operands[1]
5665 = replace_equiv_address (operands[1],
5666 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5667
5668 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5669 {
5670 rtx reg = gen_reg_rtx (SImode);
5671
5672 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5673 operands[1] = gen_lowpart (HImode, reg);
5674 }
5675
5676 if (GET_CODE (operands[0]) == MEM)
5677 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5678 }
cffb2a26 5679 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5680 && !satisfies_constraint_I (operands[1]))
cffb2a26 5681 {
6cffc037 5682 /* Handle loading a large integer during reload. */
5683
cffb2a26 5684 /* Writing a constant to memory needs a scratch, which should
5685 be handled with SECONDARY_RELOADs. */
ed29c566 5686 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5687
1a83b3ff 5688 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5689 emit_insn (gen_movsi (operands[0], operands[1]));
5690 DONE;
5691 }
b11cae9e 5692 }
cffb2a26 5693 "
5694)
5695
25f905c2 5696(define_insn "*thumb1_movhi_insn"
a941568e 5697 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5698 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5699 "TARGET_THUMB1
cffb2a26 5700 && ( register_operand (operands[0], HImode)
5701 || register_operand (operands[1], HImode))"
5702 "*
5703 switch (which_alternative)
d79300ac 5704 {
cffb2a26 5705 case 0: return \"add %0, %1, #0\";
5706 case 2: return \"strh %1, %0\";
5707 case 3: return \"mov %0, %1\";
5708 case 4: return \"mov %0, %1\";
5709 case 5: return \"mov %0, %1\";
ed29c566 5710 default: gcc_unreachable ();
cffb2a26 5711 case 1:
5712 /* The stack pointer can end up being taken as an index register.
5713 Catch this case here and deal with it. */
5714 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5715 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5716 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5717 {
5718 rtx ops[2];
5719 ops[0] = operands[0];
5720 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5721
5722 output_asm_insn (\"mov %0, %1\", ops);
5723
5724 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5725
5726 }
5727 return \"ldrh %0, %1\";
5728 }"
5729 [(set_attr "length" "2,4,2,2,2,2")
747b7458 5730 (set_attr "type" "*,load1,store1,*,*,*")
5731 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 5732
b11cae9e 5733
25f7a26e 5734(define_expand "movhi_bytes"
eab14235 5735 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5736 (set (match_dup 3)
eab14235 5737 (zero_extend:SI (match_dup 6)))
25f7a26e 5738 (set (match_operand:SI 0 "" "")
5739 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5740 "TARGET_ARM"
25f7a26e 5741 "
215b30b3 5742 {
5743 rtx mem1, mem2;
5744 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5745
788fcce0 5746 mem1 = change_address (operands[1], QImode, addr);
5747 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5748 operands[0] = gen_lowpart (SImode, operands[0]);
5749 operands[1] = mem1;
5750 operands[2] = gen_reg_rtx (SImode);
5751 operands[3] = gen_reg_rtx (SImode);
5752 operands[6] = mem2;
25f7a26e 5753
215b30b3 5754 if (BYTES_BIG_ENDIAN)
5755 {
5756 operands[4] = operands[2];
5757 operands[5] = operands[3];
5758 }
5759 else
5760 {
5761 operands[4] = operands[3];
5762 operands[5] = operands[2];
5763 }
5764 }"
5765)
25f7a26e 5766
c7597b5d 5767(define_expand "movhi_bigend"
5768 [(set (match_dup 2)
5769 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5770 (const_int 16)))
5771 (set (match_dup 3)
5772 (ashiftrt:SI (match_dup 2) (const_int 16)))
5773 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5774 (match_dup 4))]
cffb2a26 5775 "TARGET_ARM"
c7597b5d 5776 "
5777 operands[2] = gen_reg_rtx (SImode);
5778 operands[3] = gen_reg_rtx (SImode);
787f8210 5779 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5780 "
5781)
b11cae9e 5782
a2f10574 5783;; Pattern to recognize insn generated default case above
f7fbdd4a 5784(define_insn "*movhi_insn_arch4"
cde1623a 5785 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5786 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5787 "TARGET_ARM
5788 && arm_arch4
f7fbdd4a 5789 && (GET_CODE (operands[1]) != CONST_INT
5790 || const_ok_for_arm (INTVAL (operands[1]))
5791 || const_ok_for_arm (~INTVAL (operands[1])))"
5792 "@
5793 mov%?\\t%0, %1\\t%@ movhi
5794 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5795 str%(h%)\\t%1, %0\\t%@ movhi
5796 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5797 [(set_attr "type" "*,*,store1,load1")
0d66636f 5798 (set_attr "predicable" "yes")
d2a518d1 5799 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 5800 (set_attr "pool_range" "*,*,*,256")
5801 (set_attr "neg_pool_range" "*,*,*,244")]
5802)
f7fbdd4a 5803
f7fbdd4a 5804(define_insn "*movhi_bytes"
25f7a26e 5805 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5806 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5807 "TARGET_ARM"
25f7a26e 5808 "@
5809 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5810 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 5811 [(set_attr "predicable" "yes")
5812 (set_attr "insn" "mov,mvn")]
0d66636f 5813)
25f7a26e 5814
f90b51f1 5815(define_expand "thumb_movhi_clobber"
5816 [(set (match_operand:HI 0 "memory_operand" "")
5817 (match_operand:HI 1 "register_operand" ""))
5818 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5819 "TARGET_THUMB1"
f90b51f1 5820 "
5821 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5822 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5823 {
5824 emit_insn (gen_movhi (operands[0], operands[1]));
5825 DONE;
5826 }
5827 /* XXX Fixme, need to handle other cases here as well. */
5828 gcc_unreachable ();
5829 "
cffb2a26 5830)
5831
bc5c7e08 5832;; We use a DImode scratch because we may occasionally need an additional
5833;; temporary if the address isn't offsettable -- push_reload doesn't seem
5834;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5835(define_expand "reload_outhi"
cffb2a26 5836 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5837 (match_operand:HI 1 "s_register_operand" "r")
5838 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5839 "TARGET_EITHER"
5840 "if (TARGET_ARM)
5841 arm_reload_out_hi (operands);
5842 else
5843 thumb_reload_out_hi (operands);
d3373b54 5844 DONE;
cffb2a26 5845 "
5846)
d3373b54 5847
25f7a26e 5848(define_expand "reload_inhi"
5849 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5850 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5851 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5852 "TARGET_EITHER"
25f7a26e 5853 "
cffb2a26 5854 if (TARGET_ARM)
5855 arm_reload_in_hi (operands);
5856 else
5857 thumb_reload_out_hi (operands);
25f7a26e 5858 DONE;
5859")
5860
9c08d1fa 5861(define_expand "movqi"
5862 [(set (match_operand:QI 0 "general_operand" "")
5863 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5864 "TARGET_EITHER"
9c08d1fa 5865 "
6cffc037 5866 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5867
e1ba4a27 5868 if (can_create_pseudo_p ())
cffb2a26 5869 {
6cffc037 5870 if (GET_CODE (operands[1]) == CONST_INT)
5871 {
5872 rtx reg = gen_reg_rtx (SImode);
5873
03770691 5874 /* For thumb we want an unsigned immediate, then we are more likely
5875 to be able to use a movs insn. */
5876 if (TARGET_THUMB)
5877 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5878
6cffc037 5879 emit_insn (gen_movsi (reg, operands[1]));
5880 operands[1] = gen_lowpart (QImode, reg);
5881 }
cffb2a26 5882
6cffc037 5883 if (TARGET_THUMB)
5884 {
cffb2a26 5885 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5886 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5887 virtual register (also rejected as illegitimate for HImode/QImode)
5888 relative address. */
cffb2a26 5889 /* ??? This should perhaps be fixed elsewhere, for instance, in
5890 fixup_stack_1, by checking for other kinds of invalid addresses,
5891 e.g. a bare reference to a virtual register. This may confuse the
5892 alpha though, which must handle this case differently. */
5893 if (GET_CODE (operands[0]) == MEM
215b30b3 5894 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5895 XEXP (operands[0], 0)))
537ffcfc 5896 operands[0]
5897 = replace_equiv_address (operands[0],
5898 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5899 if (GET_CODE (operands[1]) == MEM
5900 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5901 XEXP (operands[1], 0)))
537ffcfc 5902 operands[1]
5903 = replace_equiv_address (operands[1],
5904 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5905 }
5906
5907 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5908 {
5909 rtx reg = gen_reg_rtx (SImode);
5910
5911 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5912 operands[1] = gen_lowpart (QImode, reg);
5913 }
5914
5915 if (GET_CODE (operands[0]) == MEM)
5916 operands[1] = force_reg (QImode, operands[1]);
5917 }
5918 else if (TARGET_THUMB
5919 && GET_CODE (operands[1]) == CONST_INT
234f6557 5920 && !satisfies_constraint_I (operands[1]))
6cffc037 5921 {
674a8f0b 5922 /* Handle loading a large integer during reload. */
cffb2a26 5923
6cffc037 5924 /* Writing a constant to memory needs a scratch, which should
5925 be handled with SECONDARY_RELOADs. */
5926 gcc_assert (GET_CODE (operands[0]) == REG);
5927
5928 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5929 emit_insn (gen_movsi (operands[0], operands[1]));
5930 DONE;
cffb2a26 5931 }
5932 "
5933)
b11cae9e 5934
9c08d1fa 5935
cffb2a26 5936(define_insn "*arm_movqi_insn"
5937 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5938 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5939 "TARGET_32BIT
cffb2a26 5940 && ( register_operand (operands[0], QImode)
5941 || register_operand (operands[1], QImode))"
5565501b 5942 "@
5943 mov%?\\t%0, %1
5944 mvn%?\\t%0, #%B1
25f905c2 5945 ldr%(b%)\\t%0, %1
5946 str%(b%)\\t%1, %0"
a2cd141b 5947 [(set_attr "type" "*,*,load1,store1")
d2a518d1 5948 (set_attr "insn" "mov,mvn,*,*")
0d66636f 5949 (set_attr "predicable" "yes")]
cffb2a26 5950)
5951
25f905c2 5952(define_insn "*thumb1_movqi_insn"
cffb2a26 5953 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5954 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5955 "TARGET_THUMB1
cffb2a26 5956 && ( register_operand (operands[0], QImode)
5957 || register_operand (operands[1], QImode))"
5958 "@
5959 add\\t%0, %1, #0
5960 ldrb\\t%0, %1
5961 strb\\t%1, %0
5962 mov\\t%0, %1
5963 mov\\t%0, %1
5964 mov\\t%0, %1"
5965 [(set_attr "length" "2")
a2cd141b 5966 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 5967 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 5968 (set_attr "pool_range" "*,32,*,*,*,*")
5969 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 5970
9b8516be 5971;; HFmode moves
5972(define_expand "movhf"
5973 [(set (match_operand:HF 0 "general_operand" "")
5974 (match_operand:HF 1 "general_operand" ""))]
5975 "TARGET_EITHER"
5976 "
5977 if (TARGET_32BIT)
5978 {
5979 if (GET_CODE (operands[0]) == MEM)
5980 operands[1] = force_reg (HFmode, operands[1]);
5981 }
5982 else /* TARGET_THUMB1 */
5983 {
5984 if (can_create_pseudo_p ())
5985 {
5986 if (GET_CODE (operands[0]) != REG)
5987 operands[1] = force_reg (HFmode, operands[1]);
5988 }
5989 }
5990 "
5991)
5992
5993(define_insn "*arm32_movhf"
5994 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5995 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 5996 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 5997 && ( s_register_operand (operands[0], HFmode)
5998 || s_register_operand (operands[1], HFmode))"
5999 "*
6000 switch (which_alternative)
6001 {
6002 case 0: /* ARM register from memory */
6003 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6004 case 1: /* memory from ARM register */
6005 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6006 case 2: /* ARM register from ARM register */
6007 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6008 case 3: /* ARM register from constant */
6009 {
6010 REAL_VALUE_TYPE r;
6011 long bits;
6012 rtx ops[4];
6013
6014 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6015 bits = real_to_target (NULL, &r, HFmode);
6016 ops[0] = operands[0];
6017 ops[1] = GEN_INT (bits);
6018 ops[2] = GEN_INT (bits & 0xff00);
6019 ops[3] = GEN_INT (bits & 0x00ff);
6020
6021 if (arm_arch_thumb2)
6022 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6023 else
6024 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6025 return \"\";
6026 }
6027 default:
6028 gcc_unreachable ();
6029 }
6030 "
6031 [(set_attr "conds" "unconditional")
6032 (set_attr "type" "load1,store1,*,*")
d2a518d1 6033 (set_attr "insn" "*,*,mov,mov")
9b8516be 6034 (set_attr "length" "4,4,4,8")
d2a518d1 6035 (set_attr "predicable" "yes")]
9b8516be 6036)
6037
6038(define_insn "*thumb1_movhf"
6039 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6040 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6041 "TARGET_THUMB1
6042 && ( s_register_operand (operands[0], HFmode)
6043 || s_register_operand (operands[1], HFmode))"
6044 "*
6045 switch (which_alternative)
6046 {
6047 case 1:
6048 {
6049 rtx addr;
6050 gcc_assert (GET_CODE(operands[1]) == MEM);
6051 addr = XEXP (operands[1], 0);
6052 if (GET_CODE (addr) == LABEL_REF
6053 || (GET_CODE (addr) == CONST
6054 && GET_CODE (XEXP (addr, 0)) == PLUS
6055 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6056 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6057 {
6058 /* Constant pool entry. */
6059 return \"ldr\\t%0, %1\";
6060 }
6061 return \"ldrh\\t%0, %1\";
6062 }
6063 case 2: return \"strh\\t%1, %0\";
6064 default: return \"mov\\t%0, %1\";
6065 }
6066 "
6067 [(set_attr "length" "2")
6068 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6069 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6070 (set_attr "pool_range" "*,1020,*,*,*")
6071 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6072
87b22bf7 6073(define_expand "movsf"
6074 [(set (match_operand:SF 0 "general_operand" "")
6075 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6076 "TARGET_EITHER"
87b22bf7 6077 "
25f905c2 6078 if (TARGET_32BIT)
cffb2a26 6079 {
6080 if (GET_CODE (operands[0]) == MEM)
6081 operands[1] = force_reg (SFmode, operands[1]);
6082 }
25f905c2 6083 else /* TARGET_THUMB1 */
cffb2a26 6084 {
e1ba4a27 6085 if (can_create_pseudo_p ())
cffb2a26 6086 {
6087 if (GET_CODE (operands[0]) != REG)
6088 operands[1] = force_reg (SFmode, operands[1]);
6089 }
6090 }
6091 "
6092)
6093
03d440a6 6094;; Transform a floating-point move of a constant into a core register into
6095;; an SImode operation.
cffb2a26 6096(define_split
03d440a6 6097 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6098 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6099 "TARGET_EITHER
cffb2a26 6100 && reload_completed
6101 && GET_CODE (operands[1]) == CONST_DOUBLE"
6102 [(set (match_dup 2) (match_dup 3))]
6103 "
6104 operands[2] = gen_lowpart (SImode, operands[0]);
6105 operands[3] = gen_lowpart (SImode, operands[1]);
6106 if (operands[2] == 0 || operands[3] == 0)
6107 FAIL;
215b30b3 6108 "
6109)
87b22bf7 6110
cffb2a26 6111(define_insn "*arm_movsf_soft_insn"
6112 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6113 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6114 "TARGET_32BIT
cffb2a26 6115 && TARGET_SOFT_FLOAT
215b30b3 6116 && (GET_CODE (operands[0]) != MEM
6117 || register_operand (operands[1], SFmode))"
9a1112d7 6118 "@
6119 mov%?\\t%0, %1
6120 ldr%?\\t%0, %1\\t%@ float
6121 str%?\\t%1, %0\\t%@ float"
cde1623a 6122 [(set_attr "predicable" "yes")
a2cd141b 6123 (set_attr "type" "*,load1,store1")
d2a518d1 6124 (set_attr "insn" "mov,*,*")
cffb2a26 6125 (set_attr "pool_range" "*,4096,*")
cde1623a 6126 (set_attr "arm_neg_pool_range" "*,4084,*")
6127 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6128)
6129
6130;;; ??? This should have alternatives for constants.
25f905c2 6131(define_insn "*thumb1_movsf_insn"
215b30b3 6132 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6133 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6134 "TARGET_THUMB1
cffb2a26 6135 && ( register_operand (operands[0], SFmode)
6136 || register_operand (operands[1], SFmode))"
6137 "@
6138 add\\t%0, %1, #0
6139 ldmia\\t%1, {%0}
6140 stmia\\t%0, {%1}
6141 ldr\\t%0, %1
6142 str\\t%1, %0
6143 mov\\t%0, %1
6144 mov\\t%0, %1"
6145 [(set_attr "length" "2")
a2cd141b 6146 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6147 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6148 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6149 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6150)
9a1112d7 6151
9c08d1fa 6152(define_expand "movdf"
87b22bf7 6153 [(set (match_operand:DF 0 "general_operand" "")
6154 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6155 "TARGET_EITHER"
9c08d1fa 6156 "
25f905c2 6157 if (TARGET_32BIT)
cffb2a26 6158 {
6159 if (GET_CODE (operands[0]) == MEM)
6160 operands[1] = force_reg (DFmode, operands[1]);
6161 }
6162 else /* TARGET_THUMB */
6163 {
e1ba4a27 6164 if (can_create_pseudo_p ())
cffb2a26 6165 {
6166 if (GET_CODE (operands[0]) != REG)
6167 operands[1] = force_reg (DFmode, operands[1]);
6168 }
6169 }
6170 "
6171)
b11cae9e 6172
9c08d1fa 6173;; Reloading a df mode value stored in integer regs to memory can require a
6174;; scratch reg.
6175(define_expand "reload_outdf"
cffb2a26 6176 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6177 (match_operand:DF 1 "s_register_operand" "r")
6178 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6179 "TARGET_32BIT"
87b22bf7 6180 "
215b30b3 6181 {
6182 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6183
215b30b3 6184 if (code == REG)
6185 operands[2] = XEXP (operands[0], 0);
6186 else if (code == POST_INC || code == PRE_DEC)
6187 {
6188 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6189 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6190 emit_insn (gen_movdi (operands[0], operands[1]));
6191 DONE;
6192 }
6193 else if (code == PRE_INC)
6194 {
6195 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6196
215b30b3 6197 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6198 operands[2] = reg;
6199 }
6200 else if (code == POST_DEC)
6201 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6202 else
6203 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6204 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6205
788fcce0 6206 emit_insn (gen_rtx_SET (VOIDmode,
6207 replace_equiv_address (operands[0], operands[2]),
215b30b3 6208 operands[1]));
f7fbdd4a 6209
215b30b3 6210 if (code == POST_DEC)
6211 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6212
6213 DONE;
6214 }"
6215)
9c08d1fa 6216
9a1112d7 6217(define_insn "*movdf_soft_insn"
359a6e9f 6218 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6219 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6220 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6221 && ( register_operand (operands[0], DFmode)
6222 || register_operand (operands[1], DFmode))"
d51f92df 6223 "*
6224 switch (which_alternative)
6225 {
6226 case 0:
6227 case 1:
6228 case 2:
6229 return \"#\";
6230 default:
6231 return output_move_double (operands);
6232 }
6233 "
359a6e9f 6234 [(set_attr "length" "8,12,16,8,8")
6235 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6236 (set_attr "pool_range" "*,*,*,1020,*")
6237 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6238 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6239)
6240
6241;;; ??? This should have alternatives for constants.
6242;;; ??? This was originally identical to the movdi_insn pattern.
6243;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6244;;; thumb_reorg with a memory reference.
6245(define_insn "*thumb_movdf_insn"
215b30b3 6246 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6247 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6248 "TARGET_THUMB1
cffb2a26 6249 && ( register_operand (operands[0], DFmode)
6250 || register_operand (operands[1], DFmode))"
6251 "*
6252 switch (which_alternative)
6253 {
6254 default:
6255 case 0:
6256 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6257 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6258 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6259 case 1:
6260 return \"ldmia\\t%1, {%0, %H0}\";
6261 case 2:
6262 return \"stmia\\t%0, {%1, %H1}\";
6263 case 3:
6264 return thumb_load_double_from_address (operands);
6265 case 4:
1a83b3ff 6266 operands[2] = gen_rtx_MEM (SImode,
6267 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6268 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6269 return \"\";
6270 case 5:
6271 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6272 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6273 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6274 }
6275 "
6276 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6277 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6278 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6279 (set_attr "pool_range" "*,*,*,1020,*,*")]
6280)
755eb2b4 6281
ccd90aaa 6282(define_expand "movxf"
6283 [(set (match_operand:XF 0 "general_operand" "")
6284 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6285 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6286 "
6287 if (GET_CODE (operands[0]) == MEM)
6288 operands[1] = force_reg (XFmode, operands[1]);
6289 "
6290)
6291
b11cae9e 6292\f
b11cae9e 6293
9c08d1fa 6294;; load- and store-multiple insns
6295;; The arm can load/store any set of registers, provided that they are in
320ea44d 6296;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6297
9c08d1fa 6298(define_expand "load_multiple"
6299 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6300 (match_operand:SI 1 "" ""))
6301 (use (match_operand:SI 2 "" ""))])]
25f905c2 6302 "TARGET_32BIT"
9580c25f 6303{
6304 HOST_WIDE_INT offset = 0;
6305
bd5b4116 6306 /* Support only fixed point registers. */
9c08d1fa 6307 if (GET_CODE (operands[2]) != CONST_INT
6308 || INTVAL (operands[2]) > 14
6309 || INTVAL (operands[2]) < 2
6310 || GET_CODE (operands[1]) != MEM
6311 || GET_CODE (operands[0]) != REG
bd5b4116 6312 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6313 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6314 FAIL;
6315
6316 operands[3]
320ea44d 6317 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6318 INTVAL (operands[2]),
f082f1c4 6319 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6320 FALSE, operands[1], &offset);
9580c25f 6321})
b11cae9e 6322
9c08d1fa 6323(define_expand "store_multiple"
6324 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6325 (match_operand:SI 1 "" ""))
6326 (use (match_operand:SI 2 "" ""))])]
25f905c2 6327 "TARGET_32BIT"
9580c25f 6328{
6329 HOST_WIDE_INT offset = 0;
6330
674a8f0b 6331 /* Support only fixed point registers. */
9c08d1fa 6332 if (GET_CODE (operands[2]) != CONST_INT
6333 || INTVAL (operands[2]) > 14
6334 || INTVAL (operands[2]) < 2
6335 || GET_CODE (operands[1]) != REG
6336 || GET_CODE (operands[0]) != MEM
bd5b4116 6337 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6338 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6339 FAIL;
6340
6341 operands[3]
320ea44d 6342 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6343 INTVAL (operands[2]),
f082f1c4 6344 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6345 FALSE, operands[0], &offset);
9580c25f 6346})
b11cae9e 6347
9c08d1fa 6348
6349;; Move a block of memory if it is word aligned and MORE than 2 words long.
6350;; We could let this apply for blocks of less than this, but it clobbers so
6351;; many registers that there is then probably a better way.
6352
008c057d 6353(define_expand "movmemqi"
34191dd1 6354 [(match_operand:BLK 0 "general_operand" "")
6355 (match_operand:BLK 1 "general_operand" "")
6356 (match_operand:SI 2 "const_int_operand" "")
6357 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6358 "TARGET_EITHER"
9c08d1fa 6359 "
25f905c2 6360 if (TARGET_32BIT)
cffb2a26 6361 {
008c057d 6362 if (arm_gen_movmemqi (operands))
cffb2a26 6363 DONE;
6364 FAIL;
6365 }
25f905c2 6366 else /* TARGET_THUMB1 */
cffb2a26 6367 {
6368 if ( INTVAL (operands[3]) != 4
6369 || INTVAL (operands[2]) > 48)
6370 FAIL;
6371
008c057d 6372 thumb_expand_movmemqi (operands);
cffb2a26 6373 DONE;
6374 }
6375 "
6376)
6377
2162064c 6378;; Thumb block-move insns
cffb2a26 6379
6380(define_insn "movmem12b"
960f3acf 6381 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6382 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6383 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6384 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6385 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6386 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6387 (set (match_operand:SI 0 "register_operand" "=l")
6388 (plus:SI (match_dup 2) (const_int 12)))
6389 (set (match_operand:SI 1 "register_operand" "=l")
6390 (plus:SI (match_dup 3) (const_int 12)))
6391 (clobber (match_scratch:SI 4 "=&l"))
6392 (clobber (match_scratch:SI 5 "=&l"))
6393 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6394 "TARGET_THUMB1"
cffb2a26 6395 "* return thumb_output_move_mem_multiple (3, operands);"
6396 [(set_attr "length" "4")
215b30b3 6397 ; This isn't entirely accurate... It loads as well, but in terms of
6398 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6399 (set_attr "type" "store3")]
6400)
6401
6402(define_insn "movmem8b"
960f3acf 6403 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6404 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6405 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6406 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6407 (set (match_operand:SI 0 "register_operand" "=l")
6408 (plus:SI (match_dup 2) (const_int 8)))
6409 (set (match_operand:SI 1 "register_operand" "=l")
6410 (plus:SI (match_dup 3) (const_int 8)))
6411 (clobber (match_scratch:SI 4 "=&l"))
6412 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6413 "TARGET_THUMB1"
cffb2a26 6414 "* return thumb_output_move_mem_multiple (2, operands);"
6415 [(set_attr "length" "4")
215b30b3 6416 ; This isn't entirely accurate... It loads as well, but in terms of
6417 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6418 (set_attr "type" "store2")]
6419)
6420
9c08d1fa 6421\f
b11cae9e 6422
341940e8 6423;; Compare & branch insns
8d232dc7 6424;; The range calculations are based as follows:
341940e8 6425;; For forward branches, the address calculation returns the address of
6426;; the next instruction. This is 2 beyond the branch instruction.
6427;; For backward branches, the address calculation returns the address of
6428;; the first instruction in this pattern (cmp). This is 2 before the branch
6429;; instruction for the shortest sequence, and 4 before the branch instruction
6430;; if we have to jump around an unconditional branch.
6431;; To the basic branch range the PC offset must be added (this is +4).
6432;; So for forward branches we have
6433;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6434;; And for backward branches we have
6435;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6436;;
6437;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6438;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6439
aeac46d4 6440(define_expand "cbranchsi4"
6441 [(set (pc) (if_then_else
6442 (match_operator 0 "arm_comparison_operator"
6443 [(match_operand:SI 1 "s_register_operand" "")
6444 (match_operand:SI 2 "nonmemory_operand" "")])
6445 (label_ref (match_operand 3 "" ""))
6446 (pc)))]
74f4459c 6447 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6448 "
74f4459c 6449 if (!TARGET_THUMB1)
6450 {
6451 if (!arm_add_operand (operands[2], SImode))
6452 operands[2] = force_reg (SImode, operands[2]);
6453 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6454 operands[3]));
6455 DONE;
6456 }
25f905c2 6457 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6458 {
6459 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6460 operands[3], operands[0]));
6461 DONE;
6462 }
25f905c2 6463 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6464 operands[2] = force_reg (SImode, operands[2]);
6465 ")
6466
a8e6c15d 6467;; A pattern to recognize a special situation and optimize for it.
6468;; On the thumb, zero-extension from memory is preferrable to sign-extension
6469;; due to the available addressing modes. Hence, convert a signed comparison
6470;; with zero into an unsigned comparison with 127 if possible.
6471(define_expand "cbranchqi4"
6472 [(set (pc) (if_then_else
6473 (match_operator 0 "lt_ge_comparison_operator"
6474 [(match_operand:QI 1 "memory_operand" "")
6475 (match_operand:QI 2 "const0_operand" "")])
6476 (label_ref (match_operand 3 "" ""))
6477 (pc)))]
6478 "TARGET_THUMB1"
6479{
d0f6c30d 6480 rtx xops[4];
a8e6c15d 6481 xops[1] = gen_reg_rtx (SImode);
6482 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6483 xops[2] = GEN_INT (127);
6484 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6485 VOIDmode, xops[1], xops[2]);
6486 xops[3] = operands[3];
6487 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6488 DONE;
6489})
6490
74f4459c 6491(define_expand "cbranchsf4"
6492 [(set (pc) (if_then_else
6493 (match_operator 0 "arm_comparison_operator"
6494 [(match_operand:SF 1 "s_register_operand" "")
6495 (match_operand:SF 2 "arm_float_compare_operand" "")])
6496 (label_ref (match_operand 3 "" ""))
6497 (pc)))]
6498 "TARGET_32BIT && TARGET_HARD_FLOAT"
6499 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6500 operands[3])); DONE;"
6501)
6502
6503(define_expand "cbranchdf4"
6504 [(set (pc) (if_then_else
6505 (match_operator 0 "arm_comparison_operator"
6506 [(match_operand:DF 1 "s_register_operand" "")
6507 (match_operand:DF 2 "arm_float_compare_operand" "")])
6508 (label_ref (match_operand 3 "" ""))
6509 (pc)))]
a50d7267 6510 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6511 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6512 operands[3])); DONE;"
6513)
6514
74f4459c 6515(define_expand "cbranchdi4"
6516 [(set (pc) (if_then_else
6517 (match_operator 0 "arm_comparison_operator"
a8045a4f 6518 [(match_operand:DI 1 "cmpdi_operand" "")
6519 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6520 (label_ref (match_operand 3 "" ""))
6521 (pc)))]
a8045a4f 6522 "TARGET_32BIT"
6523 "{
6524 rtx swap = NULL_RTX;
6525 enum rtx_code code = GET_CODE (operands[0]);
6526
6527 /* We should not have two constants. */
6528 gcc_assert (GET_MODE (operands[1]) == DImode
6529 || GET_MODE (operands[2]) == DImode);
6530
6531 /* Flip unimplemented DImode comparisons to a form that
6532 arm_gen_compare_reg can handle. */
6533 switch (code)
6534 {
6535 case GT:
6536 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6537 case LE:
6538 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6539 case GTU:
6540 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6541 case LEU:
6542 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6543 default:
6544 break;
6545 }
6546 if (swap)
6547 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6548 operands[3]));
6549 else
6550 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6551 operands[3]));
6552 DONE;
6553 }"
74f4459c 6554)
6555
d60047aa 6556(define_insn "cbranchsi4_insn"
aeac46d4 6557 [(set (pc) (if_then_else
6558 (match_operator 0 "arm_comparison_operator"
747b7458 6559 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 6560 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6561 (label_ref (match_operand 3 "" ""))
6562 (pc)))]
25f905c2 6563 "TARGET_THUMB1"
747b7458 6564{
6565 rtx t = cfun->machine->thumb1_cc_insn;
6566 if (t != NULL_RTX)
d60047aa 6567 {
747b7458 6568 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6569 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6570 t = NULL_RTX;
6571 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6572 {
6573 if (!noov_comparison_operator (operands[0], VOIDmode))
6574 t = NULL_RTX;
6575 }
6576 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 6577 t = NULL_RTX;
6578 }
d60047aa 6579 if (t == NULL_RTX)
747b7458 6580 {
6581 output_asm_insn ("cmp\t%1, %2", operands);
6582 cfun->machine->thumb1_cc_insn = insn;
6583 cfun->machine->thumb1_cc_op0 = operands[1];
6584 cfun->machine->thumb1_cc_op1 = operands[2];
6585 cfun->machine->thumb1_cc_mode = CCmode;
6586 }
6587 else
6588 /* Ensure we emit the right type of condition code on the jump. */
6589 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6590 CC_REGNUM);
aeac46d4 6591
cffb2a26 6592 switch (get_attr_length (insn))
6593 {
6594 case 4: return \"b%d0\\t%l3\";
6595 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6596 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6597 }
747b7458 6598}
cffb2a26 6599 [(set (attr "far_jump")
6600 (if_then_else
6601 (eq_attr "length" "8")
6602 (const_string "yes")
6603 (const_string "no")))
6604 (set (attr "length")
6605 (if_then_else
6606 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6607 (le (minus (match_dup 3) (pc)) (const_int 256)))
6608 (const_int 4)
6609 (if_then_else
6610 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6611 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6612 (const_int 6)
6613 (const_int 8))))]
6614)
6615
aeac46d4 6616(define_insn "cbranchsi4_scratch"
6617 [(set (pc) (if_then_else
6618 (match_operator 4 "arm_comparison_operator"
6619 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6620 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6621 (label_ref (match_operand 3 "" ""))
6622 (pc)))
6623 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6624 "TARGET_THUMB1"
aeac46d4 6625 "*
6626 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6627
6628 switch (get_attr_length (insn))
6629 {
6630 case 4: return \"b%d4\\t%l3\";
6631 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6632 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6633 }
6634 "
6635 [(set (attr "far_jump")
6636 (if_then_else
6637 (eq_attr "length" "8")
6638 (const_string "yes")
6639 (const_string "no")))
6640 (set (attr "length")
6641 (if_then_else
6642 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6643 (le (minus (match_dup 3) (pc)) (const_int 256)))
6644 (const_int 4)
6645 (if_then_else
6646 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6647 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6648 (const_int 6)
6649 (const_int 8))))]
6650)
446a1e96 6651
747b7458 6652;; Two peepholes to generate subtract of 0 instead of a move if the
6653;; condition codes will be useful.
446a1e96 6654(define_peephole2
6655 [(set (match_operand:SI 0 "low_register_operand" "")
6656 (match_operand:SI 1 "low_register_operand" ""))
6657 (set (pc)
6658 (if_then_else (match_operator 2 "arm_comparison_operator"
6659 [(match_dup 1) (const_int 0)])
6660 (label_ref (match_operand 3 "" ""))
6661 (pc)))]
6662 "TARGET_THUMB1"
747b7458 6663 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6664 (set (pc)
6665 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6666 (label_ref (match_dup 3))
747b7458 6667 (pc)))]
6668 "")
446a1e96 6669
6670;; Sigh! This variant shouldn't be needed, but combine often fails to
6671;; merge cases like this because the op1 is a hard register in
6672;; CLASS_LIKELY_SPILLED_P.
6673(define_peephole2
6674 [(set (match_operand:SI 0 "low_register_operand" "")
6675 (match_operand:SI 1 "low_register_operand" ""))
6676 (set (pc)
6677 (if_then_else (match_operator 2 "arm_comparison_operator"
6678 [(match_dup 0) (const_int 0)])
6679 (label_ref (match_operand 3 "" ""))
6680 (pc)))]
6681 "TARGET_THUMB1"
747b7458 6682 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6683 (set (pc)
6684 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6685 (label_ref (match_dup 3))
747b7458 6686 (pc)))]
6687 "")
446a1e96 6688
cffb2a26 6689(define_insn "*negated_cbranchsi4"
6690 [(set (pc)
6691 (if_then_else
aed179ae 6692 (match_operator 0 "equality_operator"
aeac46d4 6693 [(match_operand:SI 1 "s_register_operand" "l")
6694 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6695 (label_ref (match_operand 3 "" ""))
215b30b3 6696 (pc)))]
25f905c2 6697 "TARGET_THUMB1"
cffb2a26 6698 "*
6699 output_asm_insn (\"cmn\\t%1, %2\", operands);
6700 switch (get_attr_length (insn))
6701 {
6702 case 4: return \"b%d0\\t%l3\";
6703 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6704 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6705 }
6706 "
6707 [(set (attr "far_jump")
6708 (if_then_else
6709 (eq_attr "length" "8")
6710 (const_string "yes")
6711 (const_string "no")))
6712 (set (attr "length")
6713 (if_then_else
6714 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6715 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6716 (const_int 4)
6717 (if_then_else
341940e8 6718 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6719 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6720 (const_int 6)
6721 (const_int 8))))]
6722)
6723
58d6528b 6724(define_insn "*tbit_cbranch"
6725 [(set (pc)
6726 (if_then_else
6727 (match_operator 0 "equality_operator"
6728 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6729 (const_int 1)
6730 (match_operand:SI 2 "const_int_operand" "i"))
6731 (const_int 0)])
6732 (label_ref (match_operand 3 "" ""))
6733 (pc)))
6734 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6735 "TARGET_THUMB1"
58d6528b 6736 "*
6737 {
6738 rtx op[3];
6739 op[0] = operands[4];
6740 op[1] = operands[1];
6741 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6742
86efa74d 6743 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6744 switch (get_attr_length (insn))
6745 {
6746 case 4: return \"b%d0\\t%l3\";
6747 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6748 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6749 }
6750 }"
6751 [(set (attr "far_jump")
6752 (if_then_else
6753 (eq_attr "length" "8")
6754 (const_string "yes")
6755 (const_string "no")))
6756 (set (attr "length")
6757 (if_then_else
6758 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6759 (le (minus (match_dup 3) (pc)) (const_int 256)))
6760 (const_int 4)
6761 (if_then_else
6762 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6763 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6764 (const_int 6)
6765 (const_int 8))))]
6766)
6767
6768(define_insn "*tlobits_cbranch"
6769 [(set (pc)
6770 (if_then_else
6771 (match_operator 0 "equality_operator"
6772 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6773 (match_operand:SI 2 "const_int_operand" "i")
6774 (const_int 0))
6775 (const_int 0)])
6776 (label_ref (match_operand 3 "" ""))
6777 (pc)))
6778 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6779 "TARGET_THUMB1"
86efa74d 6780 "*
6781 {
6782 rtx op[3];
6783 op[0] = operands[4];
6784 op[1] = operands[1];
6785 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6786
58d6528b 6787 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6788 switch (get_attr_length (insn))
6789 {
6790 case 4: return \"b%d0\\t%l3\";
6791 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6792 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6793 }
6794 }"
6795 [(set (attr "far_jump")
6796 (if_then_else
6797 (eq_attr "length" "8")
6798 (const_string "yes")
6799 (const_string "no")))
6800 (set (attr "length")
6801 (if_then_else
6802 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6803 (le (minus (match_dup 3) (pc)) (const_int 256)))
6804 (const_int 4)
6805 (if_then_else
6806 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6807 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6808 (const_int 6)
6809 (const_int 8))))]
6810)
747b7458 6811
aeac46d4 6812(define_insn "*tstsi3_cbranch"
58d6528b 6813 [(set (pc)
6814 (if_then_else
aeac46d4 6815 (match_operator 3 "equality_operator"
6816 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6817 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6818 (const_int 0)])
aeac46d4 6819 (label_ref (match_operand 2 "" ""))
6820 (pc)))]
25f905c2 6821 "TARGET_THUMB1"
58d6528b 6822 "*
6823 {
aeac46d4 6824 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6825 switch (get_attr_length (insn))
6826 {
aeac46d4 6827 case 4: return \"b%d3\\t%l2\";
6828 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6829 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6830 }
6831 }"
6832 [(set (attr "far_jump")
6833 (if_then_else
6834 (eq_attr "length" "8")
6835 (const_string "yes")
6836 (const_string "no")))
6837 (set (attr "length")
6838 (if_then_else
aeac46d4 6839 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6840 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6841 (const_int 4)
6842 (if_then_else
aeac46d4 6843 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6844 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6845 (const_int 6)
6846 (const_int 8))))]
6847)
6848
203c488f 6849(define_insn "*cbranchne_decr1"
6850 [(set (pc)
6851 (if_then_else (match_operator 3 "equality_operator"
6852 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6853 (const_int 0)])
6854 (label_ref (match_operand 4 "" ""))
6855 (pc)))
aeac46d4 6856 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6857 (plus:SI (match_dup 2) (const_int -1)))
6858 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6859 "TARGET_THUMB1"
203c488f 6860 "*
6861 {
6862 rtx cond[2];
6863 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6864 ? GEU : LTU),
58d6528b 6865 VOIDmode, operands[2], const1_rtx);
203c488f 6866 cond[1] = operands[4];
6867
6868 if (which_alternative == 0)
6869 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6870 else if (which_alternative == 1)
6871 {
6872 /* We must provide an alternative for a hi reg because reload
6873 cannot handle output reloads on a jump instruction, but we
6874 can't subtract into that. Fortunately a mov from lo to hi
6875 does not clobber the condition codes. */
6876 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6877 output_asm_insn (\"mov\\t%0, %1\", operands);
6878 }
6879 else
6880 {
6881 /* Similarly, but the target is memory. */
6882 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6883 output_asm_insn (\"str\\t%1, %0\", operands);
6884 }
6885
6886 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6887 {
6888 case 4:
8aea555f 6889 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6890 return \"\";
6891 case 6:
8aea555f 6892 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6893 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6894 default:
8aea555f 6895 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6896 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6897 }
6898 }
6899 "
6900 [(set (attr "far_jump")
6901 (if_then_else
6902 (ior (and (eq (symbol_ref ("which_alternative"))
6903 (const_int 0))
6904 (eq_attr "length" "8"))
6905 (eq_attr "length" "10"))
6906 (const_string "yes")
6907 (const_string "no")))
6908 (set_attr_alternative "length"
6909 [
6910 ;; Alternative 0
6911 (if_then_else
6912 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6913 (le (minus (match_dup 4) (pc)) (const_int 256)))
6914 (const_int 4)
6915 (if_then_else
6916 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6917 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6918 (const_int 6)
6919 (const_int 8)))
6920 ;; Alternative 1
6921 (if_then_else
6922 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6923 (le (minus (match_dup 4) (pc)) (const_int 256)))
6924 (const_int 6)
6925 (if_then_else
6926 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6927 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6928 (const_int 8)
6929 (const_int 10)))
6930 ;; Alternative 2
6931 (if_then_else
6932 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6933 (le (minus (match_dup 4) (pc)) (const_int 256)))
6934 (const_int 6)
6935 (if_then_else
6936 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6937 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6938 (const_int 8)
6939 (const_int 10)))
6940 ;; Alternative 3
6941 (if_then_else
6942 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6943 (le (minus (match_dup 4) (pc)) (const_int 256)))
6944 (const_int 6)
6945 (if_then_else
6946 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6947 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6948 (const_int 8)
6949 (const_int 10)))])]
6950)
cffb2a26 6951
58d6528b 6952(define_insn "*addsi3_cbranch"
6953 [(set (pc)
6954 (if_then_else
b0694be0 6955 (match_operator 4 "arm_comparison_operator"
58d6528b 6956 [(plus:SI
e54011cb 6957 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
6958 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 6959 (const_int 0)])
6960 (label_ref (match_operand 5 "" ""))
6961 (pc)))
aeac46d4 6962 (set
6963 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6964 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 6965 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 6966 "TARGET_THUMB1
58d6528b 6967 && (GET_CODE (operands[4]) == EQ
6968 || GET_CODE (operands[4]) == NE
6969 || GET_CODE (operands[4]) == GE
6970 || GET_CODE (operands[4]) == LT)"
6971 "*
6972 {
6973 rtx cond[3];
6974
956a6170 6975 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 6976 cond[1] = operands[2];
6977 cond[2] = operands[3];
6978
6979 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6980 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6981 else
6982 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6983
956a6170 6984 if (which_alternative >= 2
58d6528b 6985 && which_alternative < 4)
6986 output_asm_insn (\"mov\\t%0, %1\", operands);
6987 else if (which_alternative >= 4)
6988 output_asm_insn (\"str\\t%1, %0\", operands);
6989
d0f6c30d 6990 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 6991 {
6992 case 4:
6993 return \"b%d4\\t%l5\";
6994 case 6:
6995 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6996 default:
6997 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6998 }
6999 }
7000 "
7001 [(set (attr "far_jump")
7002 (if_then_else
7003 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7004 (const_int 2))
58d6528b 7005 (eq_attr "length" "8"))
7006 (eq_attr "length" "10"))
7007 (const_string "yes")
7008 (const_string "no")))
7009 (set (attr "length")
7010 (if_then_else
7011 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7012 (const_int 2))
58d6528b 7013 (if_then_else
7014 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7015 (le (minus (match_dup 5) (pc)) (const_int 256)))
7016 (const_int 4)
7017 (if_then_else
7018 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7019 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7020 (const_int 6)
7021 (const_int 8)))
7022 (if_then_else
7023 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7024 (le (minus (match_dup 5) (pc)) (const_int 256)))
7025 (const_int 6)
7026 (if_then_else
7027 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7028 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7029 (const_int 8)
7030 (const_int 10)))))]
7031)
7032
7033(define_insn "*addsi3_cbranch_scratch"
7034 [(set (pc)
7035 (if_then_else
b0694be0 7036 (match_operator 3 "arm_comparison_operator"
58d6528b 7037 [(plus:SI
7038 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7039 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7040 (const_int 0)])
7041 (label_ref (match_operand 4 "" ""))
7042 (pc)))
7043 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7044 "TARGET_THUMB1
58d6528b 7045 && (GET_CODE (operands[3]) == EQ
7046 || GET_CODE (operands[3]) == NE
7047 || GET_CODE (operands[3]) == GE
7048 || GET_CODE (operands[3]) == LT)"
7049 "*
7050 {
7051 switch (which_alternative)
7052 {
7053 case 0:
7054 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7055 break;
7056 case 1:
7057 output_asm_insn (\"cmn\t%1, %2\", operands);
7058 break;
0f5e9701 7059 case 2:
3a445a04 7060 if (INTVAL (operands[2]) < 0)
7061 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7062 else
7063 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7064 break;
0f5e9701 7065 case 3:
3a445a04 7066 if (INTVAL (operands[2]) < 0)
7067 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7068 else
7069 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7070 break;
7071 }
7072
7073 switch (get_attr_length (insn))
7074 {
7075 case 4:
7076 return \"b%d3\\t%l4\";
7077 case 6:
7078 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7079 default:
7080 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7081 }
7082 }
7083 "
7084 [(set (attr "far_jump")
7085 (if_then_else
7086 (eq_attr "length" "8")
7087 (const_string "yes")
7088 (const_string "no")))
7089 (set (attr "length")
7090 (if_then_else
7091 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7092 (le (minus (match_dup 4) (pc)) (const_int 256)))
7093 (const_int 4)
7094 (if_then_else
7095 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7096 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7097 (const_int 6)
7098 (const_int 8))))]
7099)
7100
58d6528b 7101
9c08d1fa 7102;; Comparison and test insns
7103
cffb2a26 7104(define_insn "*arm_cmpsi_insn"
bd5b4116 7105 [(set (reg:CC CC_REGNUM)
aea4c774 7106 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7107 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7108 "TARGET_32BIT"
5565501b 7109 "@
aea4c774 7110 cmp%?\\t%0, %1
7111 cmn%?\\t%0, #%n1"
cffb2a26 7112 [(set_attr "conds" "set")]
7113)
b11cae9e 7114
d5d4dc8d 7115(define_insn "*cmpsi_shiftsi"
bd5b4116 7116 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7117 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7118 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7119 [(match_operand:SI 1 "s_register_operand" "r,r")
7120 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7121 "TARGET_32BIT"
aea4c774 7122 "cmp%?\\t%0, %1%S3"
344495ea 7123 [(set_attr "conds" "set")
331beb1a 7124 (set_attr "shift" "1")
d5d4dc8d 7125 (set_attr "arch" "32,a")
7126 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7127
d5d4dc8d 7128(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7129 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7130 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7131 [(match_operand:SI 1 "s_register_operand" "r,r")
7132 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7133 (match_operand:SI 0 "s_register_operand" "r,r")))]
7134 "TARGET_32BIT"
aea4c774 7135 "cmp%?\\t%0, %1%S3"
344495ea 7136 [(set_attr "conds" "set")
331beb1a 7137 (set_attr "shift" "1")
d5d4dc8d 7138 (set_attr "arch" "32,a")
7139 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7140
25f905c2 7141(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7142 [(set (reg:CC_Z CC_REGNUM)
7143 (compare:CC_Z
7144 (neg:SI (match_operator:SI 1 "shift_operator"
7145 [(match_operand:SI 2 "s_register_operand" "r")
7146 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7147 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7148 "TARGET_ARM"
aed179ae 7149 "cmn%?\\t%0, %2%S1"
344495ea 7150 [(set_attr "conds" "set")
aed179ae 7151 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7152 (const_string "alu_shift")
7153 (const_string "alu_shift_reg")))]
0d66636f 7154)
b11cae9e 7155
a8045a4f 7156;; DImode comparisons. The generic code generates branches that
7157;; if-conversion can not reduce to a conditional compare, so we do
7158;; that directly.
7159
7160(define_insn "*arm_cmpdi_insn"
7161 [(set (reg:CC_NCV CC_REGNUM)
7162 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7163 (match_operand:DI 1 "arm_di_operand" "rDi")))
7164 (clobber (match_scratch:SI 2 "=r"))]
7165 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7166 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7167 [(set_attr "conds" "set")
7168 (set_attr "length" "8")]
7169)
7170
7171(define_insn "*arm_cmpdi_unsigned"
7172 [(set (reg:CC_CZ CC_REGNUM)
7173 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7174 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7175 "TARGET_ARM"
7176 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7177 [(set_attr "conds" "set")
7178 (set_attr "length" "8")]
7179)
7180
7181(define_insn "*arm_cmpdi_zero"
7182 [(set (reg:CC_Z CC_REGNUM)
7183 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7184 (const_int 0)))
7185 (clobber (match_scratch:SI 1 "=r"))]
7186 "TARGET_32BIT"
7187 "orr%.\\t%1, %Q0, %R0"
7188 [(set_attr "conds" "set")]
7189)
7190
7191(define_insn "*thumb_cmpdi_zero"
7192 [(set (reg:CC_Z CC_REGNUM)
7193 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7194 (const_int 0)))
7195 (clobber (match_scratch:SI 1 "=l"))]
7196 "TARGET_THUMB1"
7197 "orr\\t%1, %Q0, %R0"
7198 [(set_attr "conds" "set")
7199 (set_attr "length" "2")]
7200)
7201
7d57ec45 7202;; Cirrus SF compare instruction
7203(define_insn "*cirrus_cmpsf"
7204 [(set (reg:CCFP CC_REGNUM)
7205 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7206 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7207 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7208 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7209 [(set_attr "type" "mav_farith")
7d57ec45 7210 (set_attr "cirrus" "compare")]
7211)
7212
7213;; Cirrus DF compare instruction
7214(define_insn "*cirrus_cmpdf"
7215 [(set (reg:CCFP CC_REGNUM)
7216 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7217 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7218 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7219 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7220 [(set_attr "type" "mav_farith")
7d57ec45 7221 (set_attr "cirrus" "compare")]
7222)
7223
7d57ec45 7224(define_insn "*cirrus_cmpdi"
7225 [(set (reg:CC CC_REGNUM)
7226 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7227 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7228 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7229 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7230 [(set_attr "type" "mav_farith")
7d57ec45 7231 (set_attr "cirrus" "compare")]
7232)
7233
9c08d1fa 7234; This insn allows redundant compares to be removed by cse, nothing should
7235; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7236; is deleted later on. The match_dup will match the mode here, so that
7237; mode changes of the condition codes aren't lost by this even though we don't
7238; specify what they are.
7239
8a18b90c 7240(define_insn "*deleted_compare"
9c08d1fa 7241 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7242 "TARGET_32BIT"
40dbec34 7243 "\\t%@ deleted compare"
cffb2a26 7244 [(set_attr "conds" "set")
7245 (set_attr "length" "0")]
7246)
9c08d1fa 7247
7248\f
7249;; Conditional branch insns
7250
74f4459c 7251(define_expand "cbranch_cc"
9c08d1fa 7252 [(set (pc)
74f4459c 7253 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7254 (match_operand 2 "" "")])
7255 (label_ref (match_operand 3 "" ""))
9c08d1fa 7256 (pc)))]
25f905c2 7257 "TARGET_32BIT"
74f4459c 7258 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7259 operands[1], operands[2]);
7260 operands[2] = const0_rtx;"
8fa3ba89 7261)
7262
7263;;
7264;; Patterns to match conditional branch insns.
7265;;
7266
cffb2a26 7267(define_insn "*arm_cond_branch"
9c08d1fa 7268 [(set (pc)
8fa3ba89 7269 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7270 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7271 (label_ref (match_operand 0 "" ""))
7272 (pc)))]
25f905c2 7273 "TARGET_32BIT"
d75350ce 7274 "*
9c08d1fa 7275 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7276 {
7277 arm_ccfsm_state += 2;
7278 return \"\";
7279 }
e2348bcb 7280 return \"b%d1\\t%l0\";
cffb2a26 7281 "
a2cd141b 7282 [(set_attr "conds" "use")
7283 (set_attr "type" "branch")]
cffb2a26 7284)
d75350ce 7285
cffb2a26 7286(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7287 [(set (pc)
8fa3ba89 7288 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7289 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7290 (pc)
7291 (label_ref (match_operand 0 "" ""))))]
25f905c2 7292 "TARGET_32BIT"
d75350ce 7293 "*
9c08d1fa 7294 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7295 {
7296 arm_ccfsm_state += 2;
7297 return \"\";
7298 }
e2348bcb 7299 return \"b%D1\\t%l0\";
cffb2a26 7300 "
a2cd141b 7301 [(set_attr "conds" "use")
7302 (set_attr "type" "branch")]
cffb2a26 7303)
7304
b11cae9e 7305\f
9c08d1fa 7306
7307; scc insns
7308
74f4459c 7309(define_expand "cstore_cc"
7db9af5d 7310 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7311 (match_operator:SI 1 "" [(match_operand 2 "" "")
7312 (match_operand 3 "" "")]))]
25f905c2 7313 "TARGET_32BIT"
74f4459c 7314 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7315 operands[2], operands[3]);
7316 operands[3] = const0_rtx;"
8fa3ba89 7317)
7318
f7fbdd4a 7319(define_insn "*mov_scc"
9c08d1fa 7320 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7321 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7322 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7323 "TARGET_ARM"
4d61e570 7324 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7325 [(set_attr "conds" "use")
d2a518d1 7326 (set_attr "insn" "mov")
cffb2a26 7327 (set_attr "length" "8")]
7328)
9c08d1fa 7329
f7fbdd4a 7330(define_insn "*mov_negscc"
9c08d1fa 7331 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7332 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7333 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7334 "TARGET_ARM"
4d61e570 7335 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7336 [(set_attr "conds" "use")
d2a518d1 7337 (set_attr "insn" "mov")
cffb2a26 7338 (set_attr "length" "8")]
7339)
9c08d1fa 7340
f7fbdd4a 7341(define_insn "*mov_notscc"
9c08d1fa 7342 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7343 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7344 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7345 "TARGET_ARM"
4d61e570 7346 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7347 [(set_attr "conds" "use")
d2a518d1 7348 (set_attr "insn" "mov")
cffb2a26 7349 (set_attr "length" "8")]
7350)
9c08d1fa 7351
595d88b5 7352(define_expand "cstoresi4"
7353 [(set (match_operand:SI 0 "s_register_operand" "")
7354 (match_operator:SI 1 "arm_comparison_operator"
7355 [(match_operand:SI 2 "s_register_operand" "")
7356 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7357 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7358 "{
7359 rtx op3, scratch, scratch2;
7360
74f4459c 7361 if (!TARGET_THUMB1)
7362 {
7363 if (!arm_add_operand (operands[3], SImode))
7364 operands[3] = force_reg (SImode, operands[3]);
7365 emit_insn (gen_cstore_cc (operands[0], operands[1],
7366 operands[2], operands[3]));
7367 DONE;
7368 }
7369
595d88b5 7370 if (operands[3] == const0_rtx)
7371 {
7372 switch (GET_CODE (operands[1]))
7373 {
7374 case EQ:
25f905c2 7375 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7376 break;
7377
7378 case NE:
25f905c2 7379 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7380 break;
7381
7382 case LE:
7383 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7384 NULL_RTX, 0, OPTAB_WIDEN);
7385 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7386 NULL_RTX, 0, OPTAB_WIDEN);
7387 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7388 operands[0], 1, OPTAB_WIDEN);
7389 break;
7390
7391 case GE:
7392 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7393 NULL_RTX, 1);
7394 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7395 NULL_RTX, 1, OPTAB_WIDEN);
7396 break;
7397
7398 case GT:
7399 scratch = expand_binop (SImode, ashr_optab, operands[2],
7400 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7401 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7402 NULL_RTX, 0, OPTAB_WIDEN);
7403 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7404 0, OPTAB_WIDEN);
7405 break;
7406
7407 /* LT is handled by generic code. No need for unsigned with 0. */
7408 default:
7409 FAIL;
7410 }
7411 DONE;
7412 }
7413
7414 switch (GET_CODE (operands[1]))
7415 {
7416 case EQ:
7417 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7418 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7419 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7420 break;
7421
7422 case NE:
7423 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7424 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7425 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7426 break;
7427
7428 case LE:
7429 op3 = force_reg (SImode, operands[3]);
7430
7431 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7432 NULL_RTX, 1, OPTAB_WIDEN);
7433 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7434 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7435 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7436 op3, operands[2]));
7437 break;
7438
7439 case GE:
7440 op3 = operands[3];
25f905c2 7441 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7442 op3 = force_reg (SImode, op3);
7443 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7444 NULL_RTX, 0, OPTAB_WIDEN);
7445 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7446 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7447 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7448 operands[2], op3));
7449 break;
7450
7451 case LEU:
7452 op3 = force_reg (SImode, operands[3]);
7453 scratch = force_reg (SImode, const0_rtx);
25f905c2 7454 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7455 op3, operands[2]));
7456 break;
7457
7458 case GEU:
7459 op3 = operands[3];
25f905c2 7460 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7461 op3 = force_reg (SImode, op3);
7462 scratch = force_reg (SImode, const0_rtx);
25f905c2 7463 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7464 operands[2], op3));
7465 break;
7466
7467 case LTU:
7468 op3 = operands[3];
25f905c2 7469 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7470 op3 = force_reg (SImode, op3);
7471 scratch = gen_reg_rtx (SImode);
408b7ae5 7472 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7473 break;
7474
7475 case GTU:
7476 op3 = force_reg (SImode, operands[3]);
7477 scratch = gen_reg_rtx (SImode);
408b7ae5 7478 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7479 break;
7480
7481 /* No good sequences for GT, LT. */
7482 default:
7483 FAIL;
7484 }
7485 DONE;
7486}")
7487
74f4459c 7488(define_expand "cstoresf4"
7489 [(set (match_operand:SI 0 "s_register_operand" "")
7490 (match_operator:SI 1 "arm_comparison_operator"
7491 [(match_operand:SF 2 "s_register_operand" "")
7492 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7493 "TARGET_32BIT && TARGET_HARD_FLOAT"
7494 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7495 operands[2], operands[3])); DONE;"
7496)
7497
7498(define_expand "cstoredf4"
7499 [(set (match_operand:SI 0 "s_register_operand" "")
7500 (match_operator:SI 1 "arm_comparison_operator"
7501 [(match_operand:DF 2 "s_register_operand" "")
7502 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7503 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7504 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7505 operands[2], operands[3])); DONE;"
7506)
7507
74f4459c 7508(define_expand "cstoredi4"
7509 [(set (match_operand:SI 0 "s_register_operand" "")
7510 (match_operator:SI 1 "arm_comparison_operator"
a8045a4f 7511 [(match_operand:DI 2 "cmpdi_operand" "")
7512 (match_operand:DI 3 "cmpdi_operand" "")]))]
7513 "TARGET_32BIT"
7514 "{
7515 rtx swap = NULL_RTX;
7516 enum rtx_code code = GET_CODE (operands[1]);
7517
7518 /* We should not have two constants. */
7519 gcc_assert (GET_MODE (operands[2]) == DImode
7520 || GET_MODE (operands[3]) == DImode);
7521
7522 /* Flip unimplemented DImode comparisons to a form that
7523 arm_gen_compare_reg can handle. */
7524 switch (code)
7525 {
7526 case GT:
7527 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7528 case LE:
7529 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7530 case GTU:
7531 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7532 case LEU:
7533 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7534 default:
7535 break;
7536 }
7537 if (swap)
7538 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7539 operands[2]));
7540 else
7541 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7542 operands[3]));
7543 DONE;
7544 }"
74f4459c 7545)
7546
25f905c2 7547(define_expand "cstoresi_eq0_thumb1"
595d88b5 7548 [(parallel
7549 [(set (match_operand:SI 0 "s_register_operand" "")
7550 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7551 (const_int 0)))
7552 (clobber (match_dup:SI 2))])]
25f905c2 7553 "TARGET_THUMB1"
595d88b5 7554 "operands[2] = gen_reg_rtx (SImode);"
7555)
7556
25f905c2 7557(define_expand "cstoresi_ne0_thumb1"
595d88b5 7558 [(parallel
7559 [(set (match_operand:SI 0 "s_register_operand" "")
7560 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7561 (const_int 0)))
7562 (clobber (match_dup:SI 2))])]
25f905c2 7563 "TARGET_THUMB1"
595d88b5 7564 "operands[2] = gen_reg_rtx (SImode);"
7565)
7566
25f905c2 7567(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7568 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7569 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7570 (const_int 0)))
7571 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7572 "TARGET_THUMB1"
595d88b5 7573 "@
7574 neg\\t%0, %1\;adc\\t%0, %0, %1
7575 neg\\t%2, %1\;adc\\t%0, %1, %2"
7576 [(set_attr "length" "4")]
7577)
7578
25f905c2 7579(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7580 [(set (match_operand:SI 0 "s_register_operand" "=l")
7581 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7582 (const_int 0)))
7583 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7584 "TARGET_THUMB1"
595d88b5 7585 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7586 [(set_attr "length" "4")]
7587)
7588
408b7ae5 7589;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 7590(define_insn "cstoresi_nltu_thumb1"
595d88b5 7591 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7592 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7593 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7594 "TARGET_THUMB1"
595d88b5 7595 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7596 [(set_attr "length" "4")]
7597)
7598
408b7ae5 7599(define_insn_and_split "cstoresi_ltu_thumb1"
7600 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7601 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7602 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7603 "TARGET_THUMB1"
7604 "#"
7605 "TARGET_THUMB1"
7606 [(set (match_dup 3)
7607 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7608 (set (match_dup 0) (neg:SI (match_dup 3)))]
7609 "operands[3] = gen_reg_rtx (SImode);"
7610 [(set_attr "length" "4")]
7611)
7612
595d88b5 7613;; Used as part of the expansion of thumb les sequence.
25f905c2 7614(define_insn "thumb1_addsi3_addgeu"
595d88b5 7615 [(set (match_operand:SI 0 "s_register_operand" "=l")
7616 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7617 (match_operand:SI 2 "s_register_operand" "l"))
7618 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 7619 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7620 "TARGET_THUMB1"
595d88b5 7621 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7622 [(set_attr "length" "4")]
7623)
7624
9c08d1fa 7625\f
39b5e676 7626;; Conditional move insns
7627
7628(define_expand "movsicc"
8a18b90c 7629 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7630 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7631 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7632 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7633 "TARGET_32BIT"
39b5e676 7634 "
215b30b3 7635 {
7636 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7637 rtx ccreg;
7638
7639 if (code == UNEQ || code == LTGT)
7640 FAIL;
39b5e676 7641
74f4459c 7642 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7643 XEXP (operands[1], 1));
29bb088d 7644 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7645 }"
7646)
39b5e676 7647
7648(define_expand "movsfcc"
8a18b90c 7649 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7650 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7651 (match_operand:SF 2 "s_register_operand" "")
7652 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 7653 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7654 "
215b30b3 7655 {
7656 enum rtx_code code = GET_CODE (operands[1]);
7657 rtx ccreg;
f082f1c4 7658
278b301d 7659 if (code == UNEQ || code == LTGT)
7660 FAIL;
7661
215b30b3 7662 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7663 Otherwise, ensure it is a valid FP add operand */
7664 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7665 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7666 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7667
74f4459c 7668 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7669 XEXP (operands[1], 1));
29bb088d 7670 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7671 }"
7672)
39b5e676 7673
7674(define_expand "movdfcc"
8a18b90c 7675 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7676 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7677 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7678 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 7679 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 7680 "
215b30b3 7681 {
7682 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7683 rtx ccreg;
39b5e676 7684
278b301d 7685 if (code == UNEQ || code == LTGT)
7686 FAIL;
7687
74f4459c 7688 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7689 XEXP (operands[1], 1));
29bb088d 7690 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7691 }"
7692)
39b5e676 7693
7694(define_insn "*movsicc_insn"
f082f1c4 7695 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7696 (if_then_else:SI
8fa3ba89 7697 (match_operator 3 "arm_comparison_operator"
8a18b90c 7698 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7699 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7700 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7701 "TARGET_ARM"
39b5e676 7702 "@
8a18b90c 7703 mov%D3\\t%0, %2
7704 mvn%D3\\t%0, #%B2
f082f1c4 7705 mov%d3\\t%0, %1
7706 mvn%d3\\t%0, #%B1
8a18b90c 7707 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7708 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7709 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7710 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7711 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7712 (set_attr "conds" "use")
7713 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 7714)
39b5e676 7715
39b5e676 7716(define_insn "*movsfcc_soft_insn"
f082f1c4 7717 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7718 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7719 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7720 (match_operand:SF 1 "s_register_operand" "0,r")
7721 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7722 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7723 "@
7724 mov%D3\\t%0, %2
7725 mov%d3\\t%0, %1"
d2a518d1 7726 [(set_attr "conds" "use")
7727 (set_attr "insn" "mov")]
8fa3ba89 7728)
39b5e676 7729
39b5e676 7730\f
9c08d1fa 7731;; Jump and linkage insns
7732
cffb2a26 7733(define_expand "jump"
9c08d1fa 7734 [(set (pc)
7735 (label_ref (match_operand 0 "" "")))]
cffb2a26 7736 "TARGET_EITHER"
9c08d1fa 7737 ""
cffb2a26 7738)
7739
7740(define_insn "*arm_jump"
7741 [(set (pc)
7742 (label_ref (match_operand 0 "" "")))]
25f905c2 7743 "TARGET_32BIT"
9c08d1fa 7744 "*
0d66636f 7745 {
7746 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7747 {
7748 arm_ccfsm_state += 2;
7749 return \"\";
7750 }
7751 return \"b%?\\t%l0\";
7752 }
7753 "
7754 [(set_attr "predicable" "yes")]
7755)
9c08d1fa 7756
cffb2a26 7757(define_insn "*thumb_jump"
7758 [(set (pc)
7759 (label_ref (match_operand 0 "" "")))]
25f905c2 7760 "TARGET_THUMB1"
cffb2a26 7761 "*
7762 if (get_attr_length (insn) == 2)
7763 return \"b\\t%l0\";
7764 return \"bl\\t%l0\\t%@ far jump\";
7765 "
7766 [(set (attr "far_jump")
7767 (if_then_else
7768 (eq_attr "length" "4")
7769 (const_string "yes")
7770 (const_string "no")))
7771 (set (attr "length")
7772 (if_then_else
911ed8af 7773 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7774 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7775 (const_int 2)
7776 (const_int 4)))]
7777)
7778
d3373b54 7779(define_expand "call"
7780 [(parallel [(call (match_operand 0 "memory_operand" "")
7781 (match_operand 1 "general_operand" ""))
cffb2a26 7782 (use (match_operand 2 "" ""))
bd5b4116 7783 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7784 "TARGET_EITHER"
6c4c2133 7785 "
7786 {
bac7fc85 7787 rtx callee, pat;
bbe777ea 7788
bbe777ea 7789 /* In an untyped call, we can get NULL for operand 2. */
7790 if (operands[2] == NULL_RTX)
7791 operands[2] = const0_rtx;
7792
de55252a 7793 /* Decide if we should generate indirect calls by loading the
85c36fd1 7794 32-bit address of the callee into a register before performing the
de55252a 7795 branch and link. */
7796 callee = XEXP (operands[0], 0);
7797 if (GET_CODE (callee) == SYMBOL_REF
7798 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7799 : !REG_P (callee))
bbe777ea 7800 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7801
7802 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7803 arm_emit_call_insn (pat, XEXP (operands[0], 0));
7804 DONE;
6c4c2133 7805 }"
7806)
d3373b54 7807
bac7fc85 7808(define_expand "call_internal"
7809 [(parallel [(call (match_operand 0 "memory_operand" "")
7810 (match_operand 1 "general_operand" ""))
7811 (use (match_operand 2 "" ""))
7812 (clobber (reg:SI LR_REGNUM))])])
7813
f1039640 7814(define_insn "*call_reg_armv5"
d3373b54 7815 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7816 (match_operand 1 "" ""))
7817 (use (match_operand 2 "" ""))
bd5b4116 7818 (clobber (reg:SI LR_REGNUM))]
f1039640 7819 "TARGET_ARM && arm_arch5"
7820 "blx%?\\t%0"
7821 [(set_attr "type" "call")]
7822)
7823
7824(define_insn "*call_reg_arm"
7825 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7826 (match_operand 1 "" ""))
7827 (use (match_operand 2 "" ""))
7828 (clobber (reg:SI LR_REGNUM))]
7829 "TARGET_ARM && !arm_arch5"
9c08d1fa 7830 "*
5565501b 7831 return output_call (operands);
cffb2a26 7832 "
7833 ;; length is worst case, normally it is only two
7834 [(set_attr "length" "12")
7835 (set_attr "type" "call")]
7836)
9c08d1fa 7837
89504fc1 7838
7839;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7840;; considered a function call by the branch predictor of some cores (PR40887).
7841;; Falls back to blx rN (*call_reg_armv5).
7842
f7fbdd4a 7843(define_insn "*call_mem"
a3c63a9d 7844 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7845 (match_operand 1 "" ""))
7846 (use (match_operand 2 "" ""))
bd5b4116 7847 (clobber (reg:SI LR_REGNUM))]
89504fc1 7848 "TARGET_ARM && !arm_arch5"
9c08d1fa 7849 "*
5565501b 7850 return output_call_mem (operands);
cffb2a26 7851 "
7852 [(set_attr "length" "12")
7853 (set_attr "type" "call")]
7854)
7855
25f905c2 7856(define_insn "*call_reg_thumb1_v5"
cffb2a26 7857 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7858 (match_operand 1 "" ""))
7859 (use (match_operand 2 "" ""))
bd5b4116 7860 (clobber (reg:SI LR_REGNUM))]
25f905c2 7861 "TARGET_THUMB1 && arm_arch5"
f1039640 7862 "blx\\t%0"
7863 [(set_attr "length" "2")
7864 (set_attr "type" "call")]
cffb2a26 7865)
7866
25f905c2 7867(define_insn "*call_reg_thumb1"
f1039640 7868 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7869 (match_operand 1 "" ""))
7870 (use (match_operand 2 "" ""))
bd5b4116 7871 (clobber (reg:SI LR_REGNUM))]
25f905c2 7872 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 7873 "*
7874 {
150502c9 7875 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7876 return thumb_call_via_reg (operands[0]);
150502c9 7877 else if (operands[1] == const0_rtx)
f1039640 7878 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7879 else if (frame_pointer_needed)
7880 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7881 else
150502c9 7882 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7883 }"
7884 [(set_attr "type" "call")]
7885)
9c08d1fa 7886
d3373b54 7887(define_expand "call_value"
e0698af7 7888 [(parallel [(set (match_operand 0 "" "")
7889 (call (match_operand 1 "memory_operand" "")
7890 (match_operand 2 "general_operand" "")))
cffb2a26 7891 (use (match_operand 3 "" ""))
bd5b4116 7892 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7893 "TARGET_EITHER"
6c4c2133 7894 "
7895 {
bac7fc85 7896 rtx pat, callee;
bbe777ea 7897
7898 /* In an untyped call, we can get NULL for operand 2. */
7899 if (operands[3] == 0)
7900 operands[3] = const0_rtx;
7901
de55252a 7902 /* Decide if we should generate indirect calls by loading the
7903 32-bit address of the callee into a register before performing the
7904 branch and link. */
7905 callee = XEXP (operands[1], 0);
7906 if (GET_CODE (callee) == SYMBOL_REF
7907 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7908 : !REG_P (callee))
78fe751b 7909 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7910
7911 pat = gen_call_value_internal (operands[0], operands[1],
7912 operands[2], operands[3]);
7913 arm_emit_call_insn (pat, XEXP (operands[1], 0));
7914 DONE;
6c4c2133 7915 }"
7916)
d3373b54 7917
bac7fc85 7918(define_expand "call_value_internal"
7919 [(parallel [(set (match_operand 0 "" "")
7920 (call (match_operand 1 "memory_operand" "")
7921 (match_operand 2 "general_operand" "")))
7922 (use (match_operand 3 "" ""))
7923 (clobber (reg:SI LR_REGNUM))])])
7924
f1039640 7925(define_insn "*call_value_reg_armv5"
27ed6835 7926 [(set (match_operand 0 "" "")
755eb2b4 7927 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7928 (match_operand 2 "" "")))
bbe777ea 7929 (use (match_operand 3 "" ""))
bd5b4116 7930 (clobber (reg:SI LR_REGNUM))]
f1039640 7931 "TARGET_ARM && arm_arch5"
7932 "blx%?\\t%1"
7933 [(set_attr "type" "call")]
7934)
7935
7936(define_insn "*call_value_reg_arm"
7937 [(set (match_operand 0 "" "")
7938 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7939 (match_operand 2 "" "")))
7940 (use (match_operand 3 "" ""))
7941 (clobber (reg:SI LR_REGNUM))]
7942 "TARGET_ARM && !arm_arch5"
9c08d1fa 7943 "*
215b30b3 7944 return output_call (&operands[1]);
cffb2a26 7945 "
7946 [(set_attr "length" "12")
7947 (set_attr "type" "call")]
7948)
9c08d1fa 7949
89504fc1 7950;; Note: see *call_mem
7951
f7fbdd4a 7952(define_insn "*call_value_mem"
27ed6835 7953 [(set (match_operand 0 "" "")
a3c63a9d 7954 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7955 (match_operand 2 "" "")))
bbe777ea 7956 (use (match_operand 3 "" ""))
bd5b4116 7957 (clobber (reg:SI LR_REGNUM))]
89504fc1 7958 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7959 "*
215b30b3 7960 return output_call_mem (&operands[1]);
cffb2a26 7961 "
7962 [(set_attr "length" "12")
7963 (set_attr "type" "call")]
7964)
9c08d1fa 7965
25f905c2 7966(define_insn "*call_value_reg_thumb1_v5"
f1039640 7967 [(set (match_operand 0 "" "")
7968 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7969 (match_operand 2 "" "")))
7970 (use (match_operand 3 "" ""))
7971 (clobber (reg:SI LR_REGNUM))]
25f905c2 7972 "TARGET_THUMB1 && arm_arch5"
f1039640 7973 "blx\\t%1"
7974 [(set_attr "length" "2")
7975 (set_attr "type" "call")]
7976)
7977
25f905c2 7978(define_insn "*call_value_reg_thumb1"
f1039640 7979 [(set (match_operand 0 "" "")
7980 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7981 (match_operand 2 "" "")))
7982 (use (match_operand 3 "" ""))
7983 (clobber (reg:SI LR_REGNUM))]
25f905c2 7984 "TARGET_THUMB1 && !arm_arch5"
f1039640 7985 "*
7986 {
150502c9 7987 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7988 return thumb_call_via_reg (operands[1]);
150502c9 7989 else if (operands[2] == const0_rtx)
f1039640 7990 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7991 else if (frame_pointer_needed)
7992 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7993 else
150502c9 7994 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 7995 }"
7996 [(set_attr "type" "call")]
7997)
7998
9c08d1fa 7999;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8000;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8001
f7fbdd4a 8002(define_insn "*call_symbol"
27ed6835 8003 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8004 (match_operand 1 "" ""))
bbe777ea 8005 (use (match_operand 2 "" ""))
bd5b4116 8006 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8007 "TARGET_32BIT
cffb2a26 8008 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8009 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8010 "*
8011 {
55c1e470 8012 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8013 }"
cffb2a26 8014 [(set_attr "type" "call")]
8015)
9c08d1fa 8016
f7fbdd4a 8017(define_insn "*call_value_symbol"
ccd90aaa 8018 [(set (match_operand 0 "" "")
27ed6835 8019 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8020 (match_operand:SI 2 "" "")))
bbe777ea 8021 (use (match_operand 3 "" ""))
bd5b4116 8022 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8023 "TARGET_32BIT
cffb2a26 8024 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8025 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8026 "*
8027 {
55c1e470 8028 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8029 }"
cffb2a26 8030 [(set_attr "type" "call")]
8031)
8032
8033(define_insn "*call_insn"
27ed6835 8034 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8035 (match_operand:SI 1 "" ""))
8036 (use (match_operand 2 "" ""))
bd5b4116 8037 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8038 "TARGET_THUMB1
1675c6e9 8039 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8040 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8041 "bl\\t%a0"
8042 [(set_attr "length" "4")
8043 (set_attr "type" "call")]
8044)
8045
8046(define_insn "*call_value_insn"
ccd90aaa 8047 [(set (match_operand 0 "" "")
27ed6835 8048 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8049 (match_operand 2 "" "")))
8050 (use (match_operand 3 "" ""))
bd5b4116 8051 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8052 "TARGET_THUMB1
1675c6e9 8053 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8054 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8055 "bl\\t%a1"
8056 [(set_attr "length" "4")
8057 (set_attr "type" "call")]
8058)
9c08d1fa 8059
1c494086 8060;; We may also be able to do sibcalls for Thumb, but it's much harder...
8061(define_expand "sibcall"
8062 [(parallel [(call (match_operand 0 "memory_operand" "")
8063 (match_operand 1 "general_operand" ""))
2ba80634 8064 (return)
8065 (use (match_operand 2 "" ""))])]
d68c2c10 8066 "TARGET_32BIT"
1c494086 8067 "
8068 {
8069 if (operands[2] == NULL_RTX)
8070 operands[2] = const0_rtx;
1c494086 8071 }"
8072)
8073
8074(define_expand "sibcall_value"
ccd90aaa 8075 [(parallel [(set (match_operand 0 "" "")
1c494086 8076 (call (match_operand 1 "memory_operand" "")
8077 (match_operand 2 "general_operand" "")))
2ba80634 8078 (return)
8079 (use (match_operand 3 "" ""))])]
d68c2c10 8080 "TARGET_32BIT"
1c494086 8081 "
8082 {
8083 if (operands[3] == NULL_RTX)
8084 operands[3] = const0_rtx;
1c494086 8085 }"
8086)
8087
8088(define_insn "*sibcall_insn"
8089 [(call (mem:SI (match_operand:SI 0 "" "X"))
8090 (match_operand 1 "" ""))
2ba80634 8091 (return)
8092 (use (match_operand 2 "" ""))]
d68c2c10 8093 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8094 "*
8095 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8096 "
8097 [(set_attr "type" "call")]
8098)
8099
8100(define_insn "*sibcall_value_insn"
ccd90aaa 8101 [(set (match_operand 0 "" "")
755eb2b4 8102 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8103 (match_operand 2 "" "")))
2ba80634 8104 (return)
8105 (use (match_operand 3 "" ""))]
d68c2c10 8106 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8107 "*
8108 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8109 "
8110 [(set_attr "type" "call")]
8111)
8112
d68c2c10 8113(define_expand "return"
8114 [(return)]
8115 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8116 "")
8117
9c08d1fa 8118;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8119(define_insn "*arm_return"
9c08d1fa 8120 [(return)]
cffb2a26 8121 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8122 "*
9c08d1fa 8123 {
cffb2a26 8124 if (arm_ccfsm_state == 2)
8125 {
8126 arm_ccfsm_state += 2;
8127 return \"\";
8128 }
5db468b7 8129 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8130 }"
a2cd141b 8131 [(set_attr "type" "load1")
755eb2b4 8132 (set_attr "length" "12")
0d66636f 8133 (set_attr "predicable" "yes")]
cffb2a26 8134)
9c08d1fa 8135
f7fbdd4a 8136(define_insn "*cond_return"
9c08d1fa 8137 [(set (pc)
8fa3ba89 8138 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8139 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8140 (return)
8141 (pc)))]
cffb2a26 8142 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8143 "*
8fa3ba89 8144 {
8145 if (arm_ccfsm_state == 2)
8146 {
8147 arm_ccfsm_state += 2;
8148 return \"\";
8149 }
8150 return output_return_instruction (operands[0], TRUE, FALSE);
8151 }"
8152 [(set_attr "conds" "use")
755eb2b4 8153 (set_attr "length" "12")
a2cd141b 8154 (set_attr "type" "load1")]
8fa3ba89 8155)
9c08d1fa 8156
f7fbdd4a 8157(define_insn "*cond_return_inverted"
9c08d1fa 8158 [(set (pc)
8fa3ba89 8159 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8160 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8161 (pc)
8162 (return)))]
cffb2a26 8163 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8164 "*
8fa3ba89 8165 {
8166 if (arm_ccfsm_state == 2)
8167 {
8168 arm_ccfsm_state += 2;
8169 return \"\";
8170 }
8171 return output_return_instruction (operands[0], TRUE, TRUE);
8172 }"
8173 [(set_attr "conds" "use")
37a1317b 8174 (set_attr "length" "12")
a2cd141b 8175 (set_attr "type" "load1")]
8fa3ba89 8176)
9c08d1fa 8177
68121397 8178;; Generate a sequence of instructions to determine if the processor is
8179;; in 26-bit or 32-bit mode, and return the appropriate return address
8180;; mask.
8181
8182(define_expand "return_addr_mask"
8183 [(set (match_dup 1)
8184 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8185 (const_int 0)))
8186 (set (match_operand:SI 0 "s_register_operand" "")
8187 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8188 (const_int -1)
8189 (const_int 67108860)))] ; 0x03fffffc
8190 "TARGET_ARM"
8191 "
62eddbd4 8192 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8193 ")
8194
8195(define_insn "*check_arch2"
8196 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8197 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8198 (const_int 0)))]
8199 "TARGET_ARM"
8200 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8201 [(set_attr "length" "8")
8202 (set_attr "conds" "set")]
8203)
8204
9c08d1fa 8205;; Call subroutine returning any type.
8206
8207(define_expand "untyped_call"
8208 [(parallel [(call (match_operand 0 "" "")
8209 (const_int 0))
8210 (match_operand 1 "" "")
8211 (match_operand 2 "" "")])]
ccd90aaa 8212 "TARGET_EITHER"
9c08d1fa 8213 "
215b30b3 8214 {
8215 int i;
ccd90aaa 8216 rtx par = gen_rtx_PARALLEL (VOIDmode,
8217 rtvec_alloc (XVECLEN (operands[2], 0)));
8218 rtx addr = gen_reg_rtx (Pmode);
8219 rtx mem;
8220 int size = 0;
9c08d1fa 8221
ccd90aaa 8222 emit_move_insn (addr, XEXP (operands[1], 0));
8223 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8224
215b30b3 8225 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8226 {
ccd90aaa 8227 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8228
ccd90aaa 8229 /* Default code only uses r0 as a return value, but we could
8230 be using anything up to 4 registers. */
8231 if (REGNO (src) == R0_REGNUM)
8232 src = gen_rtx_REG (TImode, R0_REGNUM);
8233
8234 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8235 GEN_INT (size));
8236 size += GET_MODE_SIZE (GET_MODE (src));
8237 }
8238
8239 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8240 const0_rtx));
8241
8242 size = 0;
8243
8244 for (i = 0; i < XVECLEN (par, 0); i++)
8245 {
8246 HOST_WIDE_INT offset = 0;
8247 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8248
8249 if (size != 0)
8250 emit_move_insn (addr, plus_constant (addr, size));
8251
8252 mem = change_address (mem, GET_MODE (reg), NULL);
8253 if (REGNO (reg) == R0_REGNUM)
8254 {
8255 /* On thumb we have to use a write-back instruction. */
320ea44d 8256 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8257 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8258 size = TARGET_ARM ? 16 : 0;
8259 }
8260 else
8261 {
8262 emit_move_insn (mem, reg);
8263 size = GET_MODE_SIZE (GET_MODE (reg));
8264 }
215b30b3 8265 }
9c08d1fa 8266
215b30b3 8267 /* The optimizer does not know that the call sets the function value
8268 registers we stored in the result block. We avoid problems by
8269 claiming that all hard registers are used and clobbered at this
8270 point. */
8271 emit_insn (gen_blockage ());
8272
8273 DONE;
8274 }"
8275)
9c08d1fa 8276
ccd90aaa 8277(define_expand "untyped_return"
8278 [(match_operand:BLK 0 "memory_operand" "")
8279 (match_operand 1 "" "")]
8280 "TARGET_EITHER"
8281 "
8282 {
8283 int i;
8284 rtx addr = gen_reg_rtx (Pmode);
8285 rtx mem;
8286 int size = 0;
8287
8288 emit_move_insn (addr, XEXP (operands[0], 0));
8289 mem = change_address (operands[0], BLKmode, addr);
8290
8291 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8292 {
8293 HOST_WIDE_INT offset = 0;
8294 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8295
8296 if (size != 0)
8297 emit_move_insn (addr, plus_constant (addr, size));
8298
8299 mem = change_address (mem, GET_MODE (reg), NULL);
8300 if (REGNO (reg) == R0_REGNUM)
8301 {
8302 /* On thumb we have to use a write-back instruction. */
320ea44d 8303 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8304 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8305 size = TARGET_ARM ? 16 : 0;
8306 }
8307 else
8308 {
8309 emit_move_insn (reg, mem);
8310 size = GET_MODE_SIZE (GET_MODE (reg));
8311 }
8312 }
8313
8314 /* Emit USE insns before the return. */
8315 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8316 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8317
8318 /* Construct the return. */
8319 expand_naked_return ();
8320
8321 DONE;
8322 }"
8323)
8324
9c08d1fa 8325;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8326;; all of memory. This blocks insns from being moved across this point.
8327
8328(define_insn "blockage"
e1159bbe 8329 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8330 "TARGET_EITHER"
9c08d1fa 8331 ""
cffb2a26 8332 [(set_attr "length" "0")
8333 (set_attr "type" "block")]
8334)
9c08d1fa 8335
f7fbdd4a 8336(define_expand "casesi"
8337 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8338 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8339 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8340 (match_operand:SI 3 "" "") ; table label
8341 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8342 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8343 "
215b30b3 8344 {
e6ac8414 8345 enum insn_code code;
215b30b3 8346 if (operands[1] != const0_rtx)
8347 {
e6ac8414 8348 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8349
215b30b3 8350 emit_insn (gen_addsi3 (reg, operands[0],
8351 GEN_INT (-INTVAL (operands[1]))));
8352 operands[0] = reg;
8353 }
9c08d1fa 8354
25f905c2 8355 if (TARGET_ARM)
e6ac8414 8356 code = CODE_FOR_arm_casesi_internal;
3db2019b 8357 else if (TARGET_THUMB1)
e6ac8414 8358 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8359 else if (flag_pic)
e6ac8414 8360 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8361 else
e6ac8414 8362 code = CODE_FOR_thumb2_casesi_internal;
8363
8364 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8365 operands[2] = force_reg (SImode, operands[2]);
8366
8367 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8368 operands[3], operands[4]));
215b30b3 8369 DONE;
8370 }"
8371)
f7fbdd4a 8372
f082f1c4 8373;; The USE in this pattern is needed to tell flow analysis that this is
8374;; a CASESI insn. It has no other purpose.
25f905c2 8375(define_insn "arm_casesi_internal"
f082f1c4 8376 [(parallel [(set (pc)
8377 (if_then_else
8378 (leu (match_operand:SI 0 "s_register_operand" "r")
8379 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8380 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8381 (label_ref (match_operand 2 "" ""))))
8382 (label_ref (match_operand 3 "" ""))))
bd5b4116 8383 (clobber (reg:CC CC_REGNUM))
f082f1c4 8384 (use (label_ref (match_dup 2)))])]
cffb2a26 8385 "TARGET_ARM"
f7fbdd4a 8386 "*
0d66636f 8387 if (flag_pic)
8388 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8389 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8390 "
8391 [(set_attr "conds" "clob")
8392 (set_attr "length" "12")]
8393)
9c08d1fa 8394
e6ac8414 8395(define_expand "thumb1_casesi_internal_pic"
8396 [(match_operand:SI 0 "s_register_operand" "")
8397 (match_operand:SI 1 "thumb1_cmp_operand" "")
8398 (match_operand 2 "" "")
8399 (match_operand 3 "" "")]
3db2019b 8400 "TARGET_THUMB1"
e6ac8414 8401 {
8402 rtx reg0;
8403 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8404 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8405 operands[3]));
8406 reg0 = gen_rtx_REG (SImode, 0);
8407 emit_move_insn (reg0, operands[0]);
8408 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8409 DONE;
8410 }
8411)
8412
8413(define_insn "thumb1_casesi_dispatch"
8414 [(parallel [(set (pc) (unspec [(reg:SI 0)
8415 (label_ref (match_operand 0 "" ""))
8416;; (label_ref (match_operand 1 "" ""))
8417]
8418 UNSPEC_THUMB1_CASESI))
8419 (clobber (reg:SI IP_REGNUM))
8420 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8421 "TARGET_THUMB1"
e6ac8414 8422 "* return thumb1_output_casesi(operands);"
8423 [(set_attr "length" "4")]
8424)
8425
cffb2a26 8426(define_expand "indirect_jump"
9c08d1fa 8427 [(set (pc)
cffb2a26 8428 (match_operand:SI 0 "s_register_operand" ""))]
8429 "TARGET_EITHER"
25f905c2 8430 "
8431 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8432 address and use bx. */
8433 if (TARGET_THUMB2)
8434 {
8435 rtx tmp;
8436 tmp = gen_reg_rtx (SImode);
8437 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8438 operands[0] = tmp;
8439 }
8440 "
cffb2a26 8441)
8442
f1039640 8443;; NB Never uses BX.
cffb2a26 8444(define_insn "*arm_indirect_jump"
8445 [(set (pc)
8446 (match_operand:SI 0 "s_register_operand" "r"))]
8447 "TARGET_ARM"
8448 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8449 [(set_attr "predicable" "yes")]
cffb2a26 8450)
9c08d1fa 8451
f7fbdd4a 8452(define_insn "*load_indirect_jump"
9c08d1fa 8453 [(set (pc)
8454 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8455 "TARGET_ARM"
8456 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8457 [(set_attr "type" "load1")
61a2d04c 8458 (set_attr "pool_range" "4096")
8459 (set_attr "neg_pool_range" "4084")
0d66636f 8460 (set_attr "predicable" "yes")]
cffb2a26 8461)
8462
f1039640 8463;; NB Never uses BX.
25f905c2 8464(define_insn "*thumb1_indirect_jump"
cffb2a26 8465 [(set (pc)
8466 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8467 "TARGET_THUMB1"
cffb2a26 8468 "mov\\tpc, %0"
8469 [(set_attr "conds" "clob")
8470 (set_attr "length" "2")]
8471)
8472
9c08d1fa 8473\f
8474;; Misc insns
8475
8476(define_insn "nop"
8477 [(const_int 0)]
cffb2a26 8478 "TARGET_EITHER"
8479 "*
25f905c2 8480 if (TARGET_UNIFIED_ASM)
8481 return \"nop\";
cffb2a26 8482 if (TARGET_ARM)
8483 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8484 return \"mov\\tr8, r8\";
8485 "
8486 [(set (attr "length")
8487 (if_then_else (eq_attr "is_thumb" "yes")
8488 (const_int 2)
8489 (const_int 4)))]
8490)
8491
9c08d1fa 8492\f
8493;; Patterns to allow combination of arithmetic, cond code and shifts
8494
f7fbdd4a 8495(define_insn "*arith_shiftsi"
d5d4dc8d 8496 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8497 (match_operator:SI 1 "shiftable_operator"
8498 [(match_operator:SI 3 "shift_operator"
d5d4dc8d 8499 [(match_operand:SI 4 "s_register_operand" "r,r")
8500 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8501 (match_operand:SI 2 "s_register_operand" "rk,rk")]))]
8502 "TARGET_32BIT"
6c4c2133 8503 "%i1%?\\t%0, %2, %4%S3"
344495ea 8504 [(set_attr "predicable" "yes")
331beb1a 8505 (set_attr "shift" "4")
d5d4dc8d 8506 (set_attr "arch" "32,a")
8507 ;; We have to make sure to disable the second alternative if
8508 ;; the shift_operator is MULT, since otherwise the insn will
8509 ;; also match a multiply_accumulate pattern and validate_change
8510 ;; will allow a replacement of the constant with a register
8511 ;; despite the checks done in shift_operator.
8512 (set_attr_alternative "insn_enabled"
8513 [(const_string "yes")
8514 (if_then_else
8515 (match_operand:SI 3 "mult_operator" "")
8516 (const_string "no") (const_string "yes"))])
8517 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8518
d7863cfe 8519(define_split
8520 [(set (match_operand:SI 0 "s_register_operand" "")
8521 (match_operator:SI 1 "shiftable_operator"
8522 [(match_operator:SI 2 "shiftable_operator"
8523 [(match_operator:SI 3 "shift_operator"
8524 [(match_operand:SI 4 "s_register_operand" "")
8525 (match_operand:SI 5 "reg_or_int_operand" "")])
8526 (match_operand:SI 6 "s_register_operand" "")])
8527 (match_operand:SI 7 "arm_rhs_operand" "")]))
8528 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8529 "TARGET_32BIT"
d7863cfe 8530 [(set (match_dup 8)
8531 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8532 (match_dup 6)]))
8533 (set (match_dup 0)
8534 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8535 "")
8536
f7fbdd4a 8537(define_insn "*arith_shiftsi_compare0"
bd5b4116 8538 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8539 (compare:CC_NOOV
8540 (match_operator:SI 1 "shiftable_operator"
8541 [(match_operator:SI 3 "shift_operator"
8542 [(match_operand:SI 4 "s_register_operand" "r,r")
8543 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8544 (match_operand:SI 2 "s_register_operand" "r,r")])
8545 (const_int 0)))
8546 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8547 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8548 (match_dup 2)]))]
d5d4dc8d 8549 "TARGET_32BIT"
25f905c2 8550 "%i1%.\\t%0, %2, %4%S3"
344495ea 8551 [(set_attr "conds" "set")
331beb1a 8552 (set_attr "shift" "4")
d5d4dc8d 8553 (set_attr "arch" "32,a")
8554 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8555
f7fbdd4a 8556(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8557 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8558 (compare:CC_NOOV
8559 (match_operator:SI 1 "shiftable_operator"
8560 [(match_operator:SI 3 "shift_operator"
8561 [(match_operand:SI 4 "s_register_operand" "r,r")
8562 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8563 (match_operand:SI 2 "s_register_operand" "r,r")])
8564 (const_int 0)))
8565 (clobber (match_scratch:SI 0 "=r,r"))]
8566 "TARGET_32BIT"
25f905c2 8567 "%i1%.\\t%0, %2, %4%S3"
344495ea 8568 [(set_attr "conds" "set")
331beb1a 8569 (set_attr "shift" "4")
d5d4dc8d 8570 (set_attr "arch" "32,a")
8571 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8572
f7fbdd4a 8573(define_insn "*sub_shiftsi"
d5d4dc8d 8574 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8575 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8576 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8577 [(match_operand:SI 3 "s_register_operand" "r,r")
8578 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8579 "TARGET_32BIT"
6c4c2133 8580 "sub%?\\t%0, %1, %3%S2"
344495ea 8581 [(set_attr "predicable" "yes")
331beb1a 8582 (set_attr "shift" "3")
d5d4dc8d 8583 (set_attr "arch" "32,a")
8584 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8585
f7fbdd4a 8586(define_insn "*sub_shiftsi_compare0"
bd5b4116 8587 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8588 (compare:CC_NOOV
d5d4dc8d 8589 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8590 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8591 [(match_operand:SI 3 "s_register_operand" "r,r")
8592 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8593 (const_int 0)))
d5d4dc8d 8594 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8595 (minus:SI (match_dup 1)
8596 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8597 "TARGET_32BIT"
25f905c2 8598 "sub%.\\t%0, %1, %3%S2"
344495ea 8599 [(set_attr "conds" "set")
a2cd141b 8600 (set_attr "shift" "3")
d5d4dc8d 8601 (set_attr "arch" "32,a")
8602 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8603
f7fbdd4a 8604(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8605 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8606 (compare:CC_NOOV
d5d4dc8d 8607 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8608 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8609 [(match_operand:SI 3 "s_register_operand" "r,r")
8610 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8611 (const_int 0)))
d5d4dc8d 8612 (clobber (match_scratch:SI 0 "=r,r"))]
8613 "TARGET_32BIT"
25f905c2 8614 "sub%.\\t%0, %1, %3%S2"
344495ea 8615 [(set_attr "conds" "set")
a2cd141b 8616 (set_attr "shift" "3")
d5d4dc8d 8617 (set_attr "arch" "32,a")
8618 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8619\f
8620
f7fbdd4a 8621(define_insn "*and_scc"
9c08d1fa 8622 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8623 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8624 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8625 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8626 "TARGET_ARM"
e2348bcb 8627 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8628 [(set_attr "conds" "use")
d2a518d1 8629 (set_attr "insn" "mov")
8fa3ba89 8630 (set_attr "length" "8")]
8631)
9c08d1fa 8632
f7fbdd4a 8633(define_insn "*ior_scc"
9c08d1fa 8634 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8635 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8636 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8637 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8638 "TARGET_ARM"
e2348bcb 8639 "@
899850b0 8640 orr%d2\\t%0, %1, #1
8641 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8642 [(set_attr "conds" "use")
8643 (set_attr "length" "4,8")]
8644)
9c08d1fa 8645
2df9477b 8646; A series of splitters for the compare_scc pattern below. Note that
8647; order is important.
8648(define_split
8649 [(set (match_operand:SI 0 "s_register_operand" "")
8650 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8651 (const_int 0)))
8652 (clobber (reg:CC CC_REGNUM))]
8653 "TARGET_32BIT && reload_completed"
8654 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8655
8656(define_split
8657 [(set (match_operand:SI 0 "s_register_operand" "")
8658 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8659 (const_int 0)))
8660 (clobber (reg:CC CC_REGNUM))]
8661 "TARGET_32BIT && reload_completed"
8662 [(set (match_dup 0) (not:SI (match_dup 1)))
8663 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8664
8665(define_split
8666 [(set (match_operand:SI 0 "s_register_operand" "")
8667 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8668 (const_int 0)))
8669 (clobber (reg:CC CC_REGNUM))]
8670 "TARGET_32BIT && reload_completed"
8671 [(parallel
080c0b9a 8672 [(set (reg:CC CC_REGNUM)
8673 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8674 (set (match_dup 0)
8675 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8676 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8677 (set (match_dup 0) (const_int 0)))])
8678
8679(define_split
8680 [(set (match_operand:SI 0 "s_register_operand" "")
8681 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8682 (match_operand:SI 2 "const_int_operand" "")))
8683 (clobber (reg:CC CC_REGNUM))]
8684 "TARGET_32BIT && reload_completed"
8685 [(parallel
8686 [(set (reg:CC CC_REGNUM)
8687 (compare:CC (match_dup 1) (match_dup 2)))
8688 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8689 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8690 (set (match_dup 0) (const_int 1)))]
8691{
8692 operands[3] = GEN_INT (-INTVAL (operands[2]));
8693})
8694
8695(define_split
8696 [(set (match_operand:SI 0 "s_register_operand" "")
8697 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8698 (match_operand:SI 2 "arm_add_operand" "")))
8699 (clobber (reg:CC CC_REGNUM))]
8700 "TARGET_32BIT && reload_completed"
8701 [(parallel
8702 [(set (reg:CC_NOOV CC_REGNUM)
8703 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8704 (const_int 0)))
8705 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8706 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8707 (set (match_dup 0) (const_int 1)))])
8708
8709(define_insn_and_split "*compare_scc"
5565501b 8710 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8711 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8712 [(match_operand:SI 2 "s_register_operand" "r,r")
8713 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8714 (clobber (reg:CC CC_REGNUM))]
2df9477b 8715 "TARGET_32BIT"
8716 "#"
8717 "&& reload_completed"
8718 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8719 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8720 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8721{
8722 rtx tmp1;
8723 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8724 operands[2], operands[3]);
8725 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8726
2df9477b 8727 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8728
2df9477b 8729 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8730 if (mode == CCFPmode || mode == CCFPEmode)
8731 rc = reverse_condition_maybe_unordered (rc);
8732 else
8733 rc = reverse_condition (rc);
8734 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8735})
9c08d1fa 8736
080c0b9a 8737;; Attempt to improve the sequence generated by the compare_scc splitters
8738;; not to use conditional execution.
8739(define_peephole2
8740 [(set (reg:CC CC_REGNUM)
8741 (compare:CC (match_operand:SI 1 "register_operand" "")
8742 (match_operand:SI 2 "arm_rhs_operand" "")))
8743 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8744 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8745 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8746 (set (match_dup 0) (const_int 1)))
8747 (match_scratch:SI 3 "r")]
8748 "TARGET_32BIT"
8749 [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
8750 (parallel
8751 [(set (reg:CC CC_REGNUM)
8752 (compare:CC (const_int 0) (match_dup 3)))
8753 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8754 (set (match_dup 0)
8755 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8756 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
8757
f7fbdd4a 8758(define_insn "*cond_move"
9c08d1fa 8759 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8760 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8761 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8762 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8763 (const_int 0)])
8764 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8765 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8766 "TARGET_ARM"
9c08d1fa 8767 "*
8fa3ba89 8768 if (GET_CODE (operands[3]) == NE)
8769 {
8770 if (which_alternative != 1)
8771 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8772 if (which_alternative != 0)
8773 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8774 return \"\";
8775 }
8776 if (which_alternative != 0)
8777 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8778 if (which_alternative != 1)
8779 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8780 return \"\";
8781 "
8782 [(set_attr "conds" "use")
d2a518d1 8783 (set_attr "insn" "mov")
8fa3ba89 8784 (set_attr "length" "4,4,8")]
8785)
9c08d1fa 8786
f7fbdd4a 8787(define_insn "*cond_arith"
9c08d1fa 8788 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8789 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8790 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8791 [(match_operand:SI 2 "s_register_operand" "r,r")
8792 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8793 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8794 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8795 "TARGET_ARM"
9c08d1fa 8796 "*
8fa3ba89 8797 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8798 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8799
8fa3ba89 8800 output_asm_insn (\"cmp\\t%2, %3\", operands);
8801 if (GET_CODE (operands[5]) == AND)
8802 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8803 else if (GET_CODE (operands[5]) == MINUS)
8804 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8805 else if (which_alternative != 0)
8806 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8807 return \"%i5%d4\\t%0, %1, #1\";
8808 "
8809 [(set_attr "conds" "clob")
8810 (set_attr "length" "12")]
8811)
9c08d1fa 8812
f7fbdd4a 8813(define_insn "*cond_sub"
9c08d1fa 8814 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8815 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8816 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8817 [(match_operand:SI 2 "s_register_operand" "r,r")
8818 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8819 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8820 "TARGET_ARM"
9c08d1fa 8821 "*
8fa3ba89 8822 output_asm_insn (\"cmp\\t%2, %3\", operands);
8823 if (which_alternative != 0)
8824 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8825 return \"sub%d4\\t%0, %1, #1\";
8826 "
8827 [(set_attr "conds" "clob")
8828 (set_attr "length" "8,12")]
8829)
9c08d1fa 8830
25f905c2 8831;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 8832(define_insn "*cmp_ite0"
cffb2a26 8833 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8834 (compare
8835 (if_then_else:SI
8fa3ba89 8836 (match_operator 4 "arm_comparison_operator"
aea4c774 8837 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8838 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8839 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8840 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8841 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8842 (const_int 0))
8843 (const_int 0)))]
cffb2a26 8844 "TARGET_ARM"
9c08d1fa 8845 "*
aea4c774 8846 {
8fa3ba89 8847 static const char * const opcodes[4][2] =
8848 {
8849 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8850 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8851 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8852 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8853 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8854 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8855 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8856 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8857 };
8858 int swap =
8859 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8860
8861 return opcodes[which_alternative][swap];
8862 }"
8863 [(set_attr "conds" "set")
8864 (set_attr "length" "8")]
8865)
9c08d1fa 8866
aea4c774 8867(define_insn "*cmp_ite1"
cffb2a26 8868 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8869 (compare
8870 (if_then_else:SI
8fa3ba89 8871 (match_operator 4 "arm_comparison_operator"
aea4c774 8872 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8873 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8874 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8875 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8876 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8877 (const_int 1))
8878 (const_int 0)))]
cffb2a26 8879 "TARGET_ARM"
9c08d1fa 8880 "*
9c08d1fa 8881 {
215b30b3 8882 static const char * const opcodes[4][2] =
8883 {
8884 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8885 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8886 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8887 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8888 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8889 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8890 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8891 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8892 };
8893 int swap =
8894 comparison_dominates_p (GET_CODE (operands[5]),
8895 reverse_condition (GET_CODE (operands[4])));
8896
8897 return opcodes[which_alternative][swap];
8898 }"
8fa3ba89 8899 [(set_attr "conds" "set")
8900 (set_attr "length" "8")]
8901)
9c08d1fa 8902
f6c53574 8903(define_insn "*cmp_and"
8904 [(set (match_operand 6 "dominant_cc_register" "")
8905 (compare
8906 (and:SI
8907 (match_operator 4 "arm_comparison_operator"
8908 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8909 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8910 (match_operator:SI 5 "arm_comparison_operator"
8911 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8912 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8913 (const_int 0)))]
8914 "TARGET_ARM"
8915 "*
8916 {
35823b64 8917 static const char *const opcodes[4][2] =
f6c53574 8918 {
8919 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8920 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8921 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8922 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8923 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8924 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8925 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8926 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8927 };
8928 int swap =
8929 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8930
8931 return opcodes[which_alternative][swap];
8932 }"
8933 [(set_attr "conds" "set")
8934 (set_attr "predicable" "no")
8935 (set_attr "length" "8")]
8936)
8937
8938(define_insn "*cmp_ior"
8939 [(set (match_operand 6 "dominant_cc_register" "")
8940 (compare
8941 (ior:SI
8942 (match_operator 4 "arm_comparison_operator"
8943 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8944 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8945 (match_operator:SI 5 "arm_comparison_operator"
8946 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8947 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8948 (const_int 0)))]
8949 "TARGET_ARM"
8950 "*
8951{
35823b64 8952 static const char *const opcodes[4][2] =
f6c53574 8953 {
8954 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8955 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8956 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8957 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8958 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8959 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8960 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8961 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8962 };
8963 int swap =
8964 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8965
8966 return opcodes[which_alternative][swap];
8967}
8968"
8969 [(set_attr "conds" "set")
8970 (set_attr "length" "8")]
8971)
8972
3c5afce6 8973(define_insn_and_split "*ior_scc_scc"
8974 [(set (match_operand:SI 0 "s_register_operand" "=r")
8975 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8976 [(match_operand:SI 1 "s_register_operand" "r")
8977 (match_operand:SI 2 "arm_add_operand" "rIL")])
8978 (match_operator:SI 6 "arm_comparison_operator"
8979 [(match_operand:SI 4 "s_register_operand" "r")
8980 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8981 (clobber (reg:CC CC_REGNUM))]
8982 "TARGET_ARM
8983 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8984 != CCmode)"
8985 "#"
8986 "TARGET_ARM && reload_completed"
8987 [(set (match_dup 7)
8988 (compare
8989 (ior:SI
8990 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8991 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8992 (const_int 0)))
8993 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8994 "operands[7]
8995 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8996 DOM_CC_X_OR_Y),
601f584c 8997 CC_REGNUM);"
8998 [(set_attr "conds" "clob")
8999 (set_attr "length" "16")])
9000
9001; If the above pattern is followed by a CMP insn, then the compare is
9002; redundant, since we can rework the conditional instruction that follows.
9003(define_insn_and_split "*ior_scc_scc_cmp"
9004 [(set (match_operand 0 "dominant_cc_register" "")
9005 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9006 [(match_operand:SI 1 "s_register_operand" "r")
9007 (match_operand:SI 2 "arm_add_operand" "rIL")])
9008 (match_operator:SI 6 "arm_comparison_operator"
9009 [(match_operand:SI 4 "s_register_operand" "r")
9010 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9011 (const_int 0)))
9012 (set (match_operand:SI 7 "s_register_operand" "=r")
9013 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9014 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9015 "TARGET_ARM"
9016 "#"
9017 "TARGET_ARM && reload_completed"
9018 [(set (match_dup 0)
9019 (compare
9020 (ior:SI
9021 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9022 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9023 (const_int 0)))
9024 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9025 ""
9026 [(set_attr "conds" "set")
9027 (set_attr "length" "16")])
3c5afce6 9028
9029(define_insn_and_split "*and_scc_scc"
9030 [(set (match_operand:SI 0 "s_register_operand" "=r")
9031 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9032 [(match_operand:SI 1 "s_register_operand" "r")
9033 (match_operand:SI 2 "arm_add_operand" "rIL")])
9034 (match_operator:SI 6 "arm_comparison_operator"
9035 [(match_operand:SI 4 "s_register_operand" "r")
9036 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9037 (clobber (reg:CC CC_REGNUM))]
9038 "TARGET_ARM
9039 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9040 != CCmode)"
9041 "#"
601f584c 9042 "TARGET_ARM && reload_completed
9043 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9044 != CCmode)"
3c5afce6 9045 [(set (match_dup 7)
9046 (compare
9047 (and:SI
9048 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9049 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9050 (const_int 0)))
9051 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9052 "operands[7]
9053 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9054 DOM_CC_X_AND_Y),
601f584c 9055 CC_REGNUM);"
9056 [(set_attr "conds" "clob")
9057 (set_attr "length" "16")])
9058
9059; If the above pattern is followed by a CMP insn, then the compare is
9060; redundant, since we can rework the conditional instruction that follows.
9061(define_insn_and_split "*and_scc_scc_cmp"
9062 [(set (match_operand 0 "dominant_cc_register" "")
9063 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9064 [(match_operand:SI 1 "s_register_operand" "r")
9065 (match_operand:SI 2 "arm_add_operand" "rIL")])
9066 (match_operator:SI 6 "arm_comparison_operator"
9067 [(match_operand:SI 4 "s_register_operand" "r")
9068 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9069 (const_int 0)))
9070 (set (match_operand:SI 7 "s_register_operand" "=r")
9071 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9072 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9073 "TARGET_ARM"
9074 "#"
9075 "TARGET_ARM && reload_completed"
9076 [(set (match_dup 0)
9077 (compare
9078 (and:SI
9079 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9080 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9081 (const_int 0)))
9082 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9083 ""
9084 [(set_attr "conds" "set")
9085 (set_attr "length" "16")])
9086
9087;; If there is no dominance in the comparison, then we can still save an
9088;; instruction in the AND case, since we can know that the second compare
9089;; need only zero the value if false (if true, then the value is already
9090;; correct).
9091(define_insn_and_split "*and_scc_scc_nodom"
9092 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9093 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9094 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9095 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9096 (match_operator:SI 6 "arm_comparison_operator"
9097 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9098 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9099 (clobber (reg:CC CC_REGNUM))]
9100 "TARGET_ARM
9101 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9102 == CCmode)"
9103 "#"
9104 "TARGET_ARM && reload_completed"
9105 [(parallel [(set (match_dup 0)
9106 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9107 (clobber (reg:CC CC_REGNUM))])
9108 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9109 (set (match_dup 0)
9110 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9111 (match_dup 0)
9112 (const_int 0)))]
9113 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9114 operands[4], operands[5]),
9115 CC_REGNUM);
9116 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9117 operands[5]);"
9118 [(set_attr "conds" "clob")
9119 (set_attr "length" "20")])
3c5afce6 9120
3a0bdee0 9121(define_split
9122 [(set (reg:CC_NOOV CC_REGNUM)
9123 (compare:CC_NOOV (ior:SI
9124 (and:SI (match_operand:SI 0 "s_register_operand" "")
9125 (const_int 1))
b0694be0 9126 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9127 [(match_operand:SI 2 "s_register_operand" "")
9128 (match_operand:SI 3 "arm_add_operand" "")]))
9129 (const_int 0)))
9130 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9131 "TARGET_ARM"
9132 [(set (match_dup 4)
9133 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9134 (match_dup 0)))
9135 (set (reg:CC_NOOV CC_REGNUM)
9136 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9137 (const_int 0)))]
9138 "")
9139
9140(define_split
9141 [(set (reg:CC_NOOV CC_REGNUM)
9142 (compare:CC_NOOV (ior:SI
b0694be0 9143 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9144 [(match_operand:SI 2 "s_register_operand" "")
9145 (match_operand:SI 3 "arm_add_operand" "")])
9146 (and:SI (match_operand:SI 0 "s_register_operand" "")
9147 (const_int 1)))
9148 (const_int 0)))
9149 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9150 "TARGET_ARM"
9151 [(set (match_dup 4)
9152 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9153 (match_dup 0)))
9154 (set (reg:CC_NOOV CC_REGNUM)
9155 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9156 (const_int 0)))]
9157 "")
25f905c2 9158;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9159
f7fbdd4a 9160(define_insn "*negscc"
9c08d1fa 9161 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9162 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9163 [(match_operand:SI 1 "s_register_operand" "r")
9164 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9165 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9166 "TARGET_ARM"
9c08d1fa 9167 "*
2ca2ec2e 9168 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9169 return \"mov\\t%0, %1, asr #31\";
9170
9c08d1fa 9171 if (GET_CODE (operands[3]) == NE)
e2348bcb 9172 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9173
e2348bcb 9174 output_asm_insn (\"cmp\\t%1, %2\", operands);
9175 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9176 return \"mvn%d3\\t%0, #0\";
215b30b3 9177 "
8fa3ba89 9178 [(set_attr "conds" "clob")
9179 (set_attr "length" "12")]
9180)
9c08d1fa 9181
9182(define_insn "movcond"
9183 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9184 (if_then_else:SI
8fa3ba89 9185 (match_operator 5 "arm_comparison_operator"
5565501b 9186 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9187 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9188 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9189 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9190 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9191 "TARGET_ARM"
9c08d1fa 9192 "*
9193 if (GET_CODE (operands[5]) == LT
9194 && (operands[4] == const0_rtx))
9195 {
5565501b 9196 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9197 {
9c08d1fa 9198 if (operands[2] == const0_rtx)
e2348bcb 9199 return \"and\\t%0, %1, %3, asr #31\";
9200 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9201 }
9202 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9203 {
9c08d1fa 9204 if (operands[1] == const0_rtx)
e2348bcb 9205 return \"bic\\t%0, %2, %3, asr #31\";
9206 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9207 }
9208 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9209 are constants. */
9c08d1fa 9210 }
e2348bcb 9211
9c08d1fa 9212 if (GET_CODE (operands[5]) == GE
9213 && (operands[4] == const0_rtx))
9214 {
9215 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9216 {
9c08d1fa 9217 if (operands[2] == const0_rtx)
e2348bcb 9218 return \"bic\\t%0, %1, %3, asr #31\";
9219 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9220 }
9221 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9222 {
9c08d1fa 9223 if (operands[1] == const0_rtx)
e2348bcb 9224 return \"and\\t%0, %2, %3, asr #31\";
9225 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9226 }
9227 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9228 are constants. */
9c08d1fa 9229 }
9230 if (GET_CODE (operands[4]) == CONST_INT
9231 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9232 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9233 else
e2348bcb 9234 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9235 if (which_alternative != 0)
e2348bcb 9236 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9237 if (which_alternative != 1)
e2348bcb 9238 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9239 return \"\";
215b30b3 9240 "
8fa3ba89 9241 [(set_attr "conds" "clob")
9242 (set_attr "length" "8,8,12")]
9243)
9c08d1fa 9244
25f905c2 9245;; ??? The patterns below need checking for Thumb-2 usefulness.
9246
8a18b90c 9247(define_insn "*ifcompare_plus_move"
9248 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9249 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9250 [(match_operand:SI 4 "s_register_operand" "r,r")
9251 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9252 (plus:SI
9253 (match_operand:SI 2 "s_register_operand" "r,r")
9254 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9255 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9256 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9257 "TARGET_ARM"
8a18b90c 9258 "#"
8fa3ba89 9259 [(set_attr "conds" "clob")
9260 (set_attr "length" "8,12")]
9261)
8a18b90c 9262
9263(define_insn "*if_plus_move"
129a2fe4 9264 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9265 (if_then_else:SI
8fa3ba89 9266 (match_operator 4 "arm_comparison_operator"
8a18b90c 9267 [(match_operand 5 "cc_register" "") (const_int 0)])
9268 (plus:SI
129a2fe4 9269 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9270 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9271 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9272 "TARGET_ARM"
8a18b90c 9273 "@
9274 add%d4\\t%0, %2, %3
9275 sub%d4\\t%0, %2, #%n3
9276 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9277 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9278 [(set_attr "conds" "use")
9279 (set_attr "length" "4,4,8,8")
9280 (set_attr "type" "*,*,*,*")]
9281)
8a18b90c 9282
9283(define_insn "*ifcompare_move_plus"
5565501b 9284 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9285 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9286 [(match_operand:SI 4 "s_register_operand" "r,r")
9287 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9288 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9289 (plus:SI
9290 (match_operand:SI 2 "s_register_operand" "r,r")
9291 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9292 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9293 "TARGET_ARM"
8a18b90c 9294 "#"
8fa3ba89 9295 [(set_attr "conds" "clob")
9296 (set_attr "length" "8,12")]
9297)
8a18b90c 9298
9299(define_insn "*if_move_plus"
129a2fe4 9300 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9301 (if_then_else:SI
8fa3ba89 9302 (match_operator 4 "arm_comparison_operator"
8a18b90c 9303 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9304 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9305 (plus:SI
129a2fe4 9306 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9307 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9308 "TARGET_ARM"
8a18b90c 9309 "@
9310 add%D4\\t%0, %2, %3
9311 sub%D4\\t%0, %2, #%n3
9312 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9313 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9314 [(set_attr "conds" "use")
9315 (set_attr "length" "4,4,8,8")
9316 (set_attr "type" "*,*,*,*")]
9317)
8a18b90c 9318
9319(define_insn "*ifcompare_arith_arith"
9320 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9321 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9322 [(match_operand:SI 5 "s_register_operand" "r")
9323 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9324 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9325 [(match_operand:SI 1 "s_register_operand" "r")
9326 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9327 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9328 [(match_operand:SI 3 "s_register_operand" "r")
9329 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9330 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9331 "TARGET_ARM"
8a18b90c 9332 "#"
8fa3ba89 9333 [(set_attr "conds" "clob")
9334 (set_attr "length" "12")]
9335)
9c08d1fa 9336
8a18b90c 9337(define_insn "*if_arith_arith"
9338 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9339 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9340 [(match_operand 8 "cc_register" "") (const_int 0)])
9341 (match_operator:SI 6 "shiftable_operator"
9342 [(match_operand:SI 1 "s_register_operand" "r")
9343 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9344 (match_operator:SI 7 "shiftable_operator"
9345 [(match_operand:SI 3 "s_register_operand" "r")
9346 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9347 "TARGET_ARM"
8a18b90c 9348 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9349 [(set_attr "conds" "use")
9350 (set_attr "length" "8")]
9351)
8a18b90c 9352
f7fbdd4a 9353(define_insn "*ifcompare_arith_move"
9c08d1fa 9354 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9355 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9356 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9357 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9358 (match_operator:SI 7 "shiftable_operator"
9359 [(match_operand:SI 4 "s_register_operand" "r,r")
9360 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9361 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9362 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9363 "TARGET_ARM"
9c08d1fa 9364 "*
9c08d1fa 9365 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9366 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9367 everything is in registers then we can do this in two instructions. */
9c08d1fa 9368 if (operands[3] == const0_rtx
9369 && GET_CODE (operands[7]) != AND
9370 && GET_CODE (operands[5]) == REG
9371 && GET_CODE (operands[1]) == REG
9372 && REGNO (operands[1]) == REGNO (operands[4])
9373 && REGNO (operands[4]) != REGNO (operands[0]))
9374 {
9375 if (GET_CODE (operands[6]) == LT)
40dbec34 9376 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9377 else if (GET_CODE (operands[6]) == GE)
40dbec34 9378 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9379 }
9380 if (GET_CODE (operands[3]) == CONST_INT
9381 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9382 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9383 else
e2348bcb 9384 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9385 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9386 if (which_alternative != 0)
129a2fe4 9387 return \"mov%D6\\t%0, %1\";
9c08d1fa 9388 return \"\";
215b30b3 9389 "
8fa3ba89 9390 [(set_attr "conds" "clob")
9391 (set_attr "length" "8,12")]
9392)
9c08d1fa 9393
8a18b90c 9394(define_insn "*if_arith_move"
129a2fe4 9395 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9396 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9397 [(match_operand 6 "cc_register" "") (const_int 0)])
9398 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9399 [(match_operand:SI 2 "s_register_operand" "r,r")
9400 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9401 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9402 "TARGET_ARM"
8a18b90c 9403 "@
9404 %I5%d4\\t%0, %2, %3
129a2fe4 9405 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9406 [(set_attr "conds" "use")
9407 (set_attr "length" "4,8")
9408 (set_attr "type" "*,*")]
9409)
8a18b90c 9410
f7fbdd4a 9411(define_insn "*ifcompare_move_arith"
9c08d1fa 9412 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9413 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9414 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9415 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9416 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9417 (match_operator:SI 7 "shiftable_operator"
9418 [(match_operand:SI 2 "s_register_operand" "r,r")
9419 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9420 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9421 "TARGET_ARM"
9c08d1fa 9422 "*
9c08d1fa 9423 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9424 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9425 everything is in registers then we can do this in two instructions */
9426 if (operands[5] == const0_rtx
9427 && GET_CODE (operands[7]) != AND
9428 && GET_CODE (operands[3]) == REG
9429 && GET_CODE (operands[1]) == REG
9430 && REGNO (operands[1]) == REGNO (operands[2])
9431 && REGNO (operands[2]) != REGNO (operands[0]))
9432 {
9433 if (GET_CODE (operands[6]) == GE)
40dbec34 9434 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9435 else if (GET_CODE (operands[6]) == LT)
40dbec34 9436 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9437 }
40dbec34 9438
9c08d1fa 9439 if (GET_CODE (operands[5]) == CONST_INT
9440 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9441 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9442 else
e2348bcb 9443 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9444
9c08d1fa 9445 if (which_alternative != 0)
129a2fe4 9446 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9447 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9448 "
8fa3ba89 9449 [(set_attr "conds" "clob")
9450 (set_attr "length" "8,12")]
9451)
9c08d1fa 9452
8a18b90c 9453(define_insn "*if_move_arith"
129a2fe4 9454 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9455 (if_then_else:SI
8fa3ba89 9456 (match_operator 4 "arm_comparison_operator"
8a18b90c 9457 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9458 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9459 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9460 [(match_operand:SI 2 "s_register_operand" "r,r")
9461 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9462 "TARGET_ARM"
8a18b90c 9463 "@
9464 %I5%D4\\t%0, %2, %3
129a2fe4 9465 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9466 [(set_attr "conds" "use")
9467 (set_attr "length" "4,8")
9468 (set_attr "type" "*,*")]
9469)
8a18b90c 9470
9471(define_insn "*ifcompare_move_not"
9c08d1fa 9472 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9473 (if_then_else:SI
8fa3ba89 9474 (match_operator 5 "arm_comparison_operator"
8a18b90c 9475 [(match_operand:SI 3 "s_register_operand" "r,r")
9476 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9477 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9478 (not:SI
9479 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9480 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9481 "TARGET_ARM"
8a18b90c 9482 "#"
8fa3ba89 9483 [(set_attr "conds" "clob")
9484 (set_attr "length" "8,12")]
9485)
9c08d1fa 9486
8a18b90c 9487(define_insn "*if_move_not"
9488 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9489 (if_then_else:SI
8fa3ba89 9490 (match_operator 4 "arm_comparison_operator"
8a18b90c 9491 [(match_operand 3 "cc_register" "") (const_int 0)])
9492 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9493 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9494 "TARGET_ARM"
8a18b90c 9495 "@
9496 mvn%D4\\t%0, %2
9497 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9498 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9499 [(set_attr "conds" "use")
d2a518d1 9500 (set_attr "insn" "mvn")
8fa3ba89 9501 (set_attr "length" "4,8,8")]
9502)
8a18b90c 9503
9504(define_insn "*ifcompare_not_move"
9c08d1fa 9505 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9506 (if_then_else:SI
8fa3ba89 9507 (match_operator 5 "arm_comparison_operator"
8a18b90c 9508 [(match_operand:SI 3 "s_register_operand" "r,r")
9509 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9510 (not:SI
9511 (match_operand:SI 2 "s_register_operand" "r,r"))
9512 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9513 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9514 "TARGET_ARM"
8a18b90c 9515 "#"
8fa3ba89 9516 [(set_attr "conds" "clob")
9517 (set_attr "length" "8,12")]
9518)
9c08d1fa 9519
8a18b90c 9520(define_insn "*if_not_move"
9521 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9522 (if_then_else:SI
8fa3ba89 9523 (match_operator 4 "arm_comparison_operator"
8a18b90c 9524 [(match_operand 3 "cc_register" "") (const_int 0)])
9525 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9526 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9527 "TARGET_ARM"
8a18b90c 9528 "@
9529 mvn%d4\\t%0, %2
9530 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9531 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9532 [(set_attr "conds" "use")
d2a518d1 9533 (set_attr "insn" "mvn")
8fa3ba89 9534 (set_attr "length" "4,8,8")]
9535)
8a18b90c 9536
9537(define_insn "*ifcompare_shift_move"
9c08d1fa 9538 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9539 (if_then_else:SI
8fa3ba89 9540 (match_operator 6 "arm_comparison_operator"
8a18b90c 9541 [(match_operand:SI 4 "s_register_operand" "r,r")
9542 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9543 (match_operator:SI 7 "shift_operator"
9544 [(match_operand:SI 2 "s_register_operand" "r,r")
9545 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9546 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9547 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9548 "TARGET_ARM"
9c08d1fa 9549 "#"
8fa3ba89 9550 [(set_attr "conds" "clob")
9551 (set_attr "length" "8,12")]
9552)
9c08d1fa 9553
8a18b90c 9554(define_insn "*if_shift_move"
9555 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9556 (if_then_else:SI
8fa3ba89 9557 (match_operator 5 "arm_comparison_operator"
8a18b90c 9558 [(match_operand 6 "cc_register" "") (const_int 0)])
9559 (match_operator:SI 4 "shift_operator"
9560 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9561 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9562 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9563 "TARGET_ARM"
5565501b 9564 "@
8a18b90c 9565 mov%d5\\t%0, %2%S4
9566 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9567 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9568 [(set_attr "conds" "use")
331beb1a 9569 (set_attr "shift" "2")
a2cd141b 9570 (set_attr "length" "4,8,8")
d2a518d1 9571 (set_attr "insn" "mov")
a2cd141b 9572 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9573 (const_string "alu_shift")
9574 (const_string "alu_shift_reg")))]
8fa3ba89 9575)
5565501b 9576
8a18b90c 9577(define_insn "*ifcompare_move_shift"
9578 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9579 (if_then_else:SI
8fa3ba89 9580 (match_operator 6 "arm_comparison_operator"
8a18b90c 9581 [(match_operand:SI 4 "s_register_operand" "r,r")
9582 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9583 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9584 (match_operator:SI 7 "shift_operator"
8a18b90c 9585 [(match_operand:SI 2 "s_register_operand" "r,r")
9586 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9587 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9588 "TARGET_ARM"
8a18b90c 9589 "#"
8fa3ba89 9590 [(set_attr "conds" "clob")
9591 (set_attr "length" "8,12")]
9592)
5565501b 9593
8a18b90c 9594(define_insn "*if_move_shift"
9595 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9596 (if_then_else:SI
8fa3ba89 9597 (match_operator 5 "arm_comparison_operator"
8a18b90c 9598 [(match_operand 6 "cc_register" "") (const_int 0)])
9599 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9600 (match_operator:SI 4 "shift_operator"
9601 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9602 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9603 "TARGET_ARM"
5565501b 9604 "@
8a18b90c 9605 mov%D5\\t%0, %2%S4
9606 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9607 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9608 [(set_attr "conds" "use")
331beb1a 9609 (set_attr "shift" "2")
a2cd141b 9610 (set_attr "length" "4,8,8")
d2a518d1 9611 (set_attr "insn" "mov")
a2cd141b 9612 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9613 (const_string "alu_shift")
9614 (const_string "alu_shift_reg")))]
8fa3ba89 9615)
9c08d1fa 9616
f7fbdd4a 9617(define_insn "*ifcompare_shift_shift"
8a18b90c 9618 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9619 (if_then_else:SI
8fa3ba89 9620 (match_operator 7 "arm_comparison_operator"
8a18b90c 9621 [(match_operand:SI 5 "s_register_operand" "r")
9622 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9623 (match_operator:SI 8 "shift_operator"
8a18b90c 9624 [(match_operand:SI 1 "s_register_operand" "r")
9625 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9626 (match_operator:SI 9 "shift_operator"
8a18b90c 9627 [(match_operand:SI 3 "s_register_operand" "r")
9628 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9629 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9630 "TARGET_ARM"
8a18b90c 9631 "#"
8fa3ba89 9632 [(set_attr "conds" "clob")
9633 (set_attr "length" "12")]
9634)
9c08d1fa 9635
8a18b90c 9636(define_insn "*if_shift_shift"
9637 [(set (match_operand:SI 0 "s_register_operand" "=r")
9638 (if_then_else:SI
8fa3ba89 9639 (match_operator 5 "arm_comparison_operator"
8a18b90c 9640 [(match_operand 8 "cc_register" "") (const_int 0)])
9641 (match_operator:SI 6 "shift_operator"
9642 [(match_operand:SI 1 "s_register_operand" "r")
9643 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9644 (match_operator:SI 7 "shift_operator"
9645 [(match_operand:SI 3 "s_register_operand" "r")
9646 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9647 "TARGET_ARM"
8a18b90c 9648 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9649 [(set_attr "conds" "use")
331beb1a 9650 (set_attr "shift" "1")
a2cd141b 9651 (set_attr "length" "8")
d2a518d1 9652 (set_attr "insn" "mov")
a2cd141b 9653 (set (attr "type") (if_then_else
9654 (and (match_operand 2 "const_int_operand" "")
9655 (match_operand 4 "const_int_operand" ""))
9656 (const_string "alu_shift")
9657 (const_string "alu_shift_reg")))]
8fa3ba89 9658)
8a18b90c 9659
f7fbdd4a 9660(define_insn "*ifcompare_not_arith"
8a18b90c 9661 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9662 (if_then_else:SI
8fa3ba89 9663 (match_operator 6 "arm_comparison_operator"
8a18b90c 9664 [(match_operand:SI 4 "s_register_operand" "r")
9665 (match_operand:SI 5 "arm_add_operand" "rIL")])
9666 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9667 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9668 [(match_operand:SI 2 "s_register_operand" "r")
9669 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9670 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9671 "TARGET_ARM"
8a18b90c 9672 "#"
8fa3ba89 9673 [(set_attr "conds" "clob")
9674 (set_attr "length" "12")]
9675)
9c08d1fa 9676
8a18b90c 9677(define_insn "*if_not_arith"
9678 [(set (match_operand:SI 0 "s_register_operand" "=r")
9679 (if_then_else:SI
8fa3ba89 9680 (match_operator 5 "arm_comparison_operator"
8a18b90c 9681 [(match_operand 4 "cc_register" "") (const_int 0)])
9682 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9683 (match_operator:SI 6 "shiftable_operator"
9684 [(match_operand:SI 2 "s_register_operand" "r")
9685 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9686 "TARGET_ARM"
8a18b90c 9687 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9688 [(set_attr "conds" "use")
d2a518d1 9689 (set_attr "insn" "mvn")
8fa3ba89 9690 (set_attr "length" "8")]
9691)
8a18b90c 9692
9693(define_insn "*ifcompare_arith_not"
9694 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9695 (if_then_else:SI
8fa3ba89 9696 (match_operator 6 "arm_comparison_operator"
8a18b90c 9697 [(match_operand:SI 4 "s_register_operand" "r")
9698 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9699 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9700 [(match_operand:SI 2 "s_register_operand" "r")
9701 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9702 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9703 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9704 "TARGET_ARM"
8a18b90c 9705 "#"
8fa3ba89 9706 [(set_attr "conds" "clob")
9707 (set_attr "length" "12")]
9708)
9c08d1fa 9709
8a18b90c 9710(define_insn "*if_arith_not"
9711 [(set (match_operand:SI 0 "s_register_operand" "=r")
9712 (if_then_else:SI
8fa3ba89 9713 (match_operator 5 "arm_comparison_operator"
8a18b90c 9714 [(match_operand 4 "cc_register" "") (const_int 0)])
9715 (match_operator:SI 6 "shiftable_operator"
9716 [(match_operand:SI 2 "s_register_operand" "r")
9717 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9718 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9719 "TARGET_ARM"
8a18b90c 9720 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9721 [(set_attr "conds" "use")
d2a518d1 9722 (set_attr "insn" "mvn")
8fa3ba89 9723 (set_attr "length" "8")]
9724)
8a18b90c 9725
f7fbdd4a 9726(define_insn "*ifcompare_neg_move"
8a18b90c 9727 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9728 (if_then_else:SI
8fa3ba89 9729 (match_operator 5 "arm_comparison_operator"
8a18b90c 9730 [(match_operand:SI 3 "s_register_operand" "r,r")
9731 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9732 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9733 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9734 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9735 "TARGET_ARM"
8a18b90c 9736 "#"
8fa3ba89 9737 [(set_attr "conds" "clob")
9738 (set_attr "length" "8,12")]
9739)
8a18b90c 9740
9741(define_insn "*if_neg_move"
9742 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9743 (if_then_else:SI
8fa3ba89 9744 (match_operator 4 "arm_comparison_operator"
8a18b90c 9745 [(match_operand 3 "cc_register" "") (const_int 0)])
9746 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9747 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9748 "TARGET_ARM"
8a18b90c 9749 "@
9750 rsb%d4\\t%0, %2, #0
9751 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9752 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9753 [(set_attr "conds" "use")
9754 (set_attr "length" "4,8,8")]
9755)
9c08d1fa 9756
f7fbdd4a 9757(define_insn "*ifcompare_move_neg"
8a18b90c 9758 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9759 (if_then_else:SI
8fa3ba89 9760 (match_operator 5 "arm_comparison_operator"
8a18b90c 9761 [(match_operand:SI 3 "s_register_operand" "r,r")
9762 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9763 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9764 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9765 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9766 "TARGET_ARM"
8a18b90c 9767 "#"
8fa3ba89 9768 [(set_attr "conds" "clob")
9769 (set_attr "length" "8,12")]
9770)
8a18b90c 9771
9772(define_insn "*if_move_neg"
9773 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9774 (if_then_else:SI
8fa3ba89 9775 (match_operator 4 "arm_comparison_operator"
8a18b90c 9776 [(match_operand 3 "cc_register" "") (const_int 0)])
9777 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9778 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9779 "TARGET_ARM"
8a18b90c 9780 "@
9781 rsb%D4\\t%0, %2, #0
9782 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9783 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9784 [(set_attr "conds" "use")
9785 (set_attr "length" "4,8,8")]
9786)
9c08d1fa 9787
f7fbdd4a 9788(define_insn "*arith_adjacentmem"
9c08d1fa 9789 [(set (match_operand:SI 0 "s_register_operand" "=r")
9790 (match_operator:SI 1 "shiftable_operator"
9791 [(match_operand:SI 2 "memory_operand" "m")
9792 (match_operand:SI 3 "memory_operand" "m")]))
9793 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9794 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9795 "*
215b30b3 9796 {
9797 rtx ldm[3];
9798 rtx arith[4];
94dee231 9799 rtx base_reg;
9800 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9801
215b30b3 9802 if (REGNO (operands[0]) > REGNO (operands[4]))
9803 {
9804 ldm[1] = operands[4];
9805 ldm[2] = operands[0];
9806 }
9807 else
9808 {
9809 ldm[1] = operands[0];
9810 ldm[2] = operands[4];
9811 }
94dee231 9812
9813 base_reg = XEXP (operands[2], 0);
9814
9815 if (!REG_P (base_reg))
9816 {
9817 val1 = INTVAL (XEXP (base_reg, 1));
9818 base_reg = XEXP (base_reg, 0);
9819 }
9820
9821 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9822 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9823
215b30b3 9824 arith[0] = operands[0];
9825 arith[3] = operands[1];
94dee231 9826
215b30b3 9827 if (val1 < val2)
9828 {
9829 arith[1] = ldm[1];
9830 arith[2] = ldm[2];
9831 }
9832 else
9833 {
9834 arith[1] = ldm[2];
9835 arith[2] = ldm[1];
9836 }
94dee231 9837
9838 ldm[0] = base_reg;
9839 if (val1 !=0 && val2 != 0)
215b30b3 9840 {
cdb1295a 9841 rtx ops[3];
9842
94dee231 9843 if (val1 == 4 || val2 == 4)
9844 /* Other val must be 8, since we know they are adjacent and neither
9845 is zero. */
25f905c2 9846 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 9847 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 9848 {
94dee231 9849 ldm[0] = ops[0] = operands[4];
9850 ops[1] = base_reg;
9851 ops[2] = GEN_INT (val1);
9852 output_add_immediate (ops);
9853 if (val1 < val2)
25f905c2 9854 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 9855 else
25f905c2 9856 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 9857 }
cdb1295a 9858 else
9859 {
9860 /* Offset is out of range for a single add, so use two ldr. */
9861 ops[0] = ldm[1];
9862 ops[1] = base_reg;
9863 ops[2] = GEN_INT (val1);
9864 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9865 ops[0] = ldm[2];
9866 ops[2] = GEN_INT (val2);
9867 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9868 }
215b30b3 9869 }
94dee231 9870 else if (val1 != 0)
215b30b3 9871 {
215b30b3 9872 if (val1 < val2)
25f905c2 9873 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9874 else
25f905c2 9875 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9876 }
9877 else
9878 {
215b30b3 9879 if (val1 < val2)
25f905c2 9880 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9881 else
25f905c2 9882 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9883 }
9884 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9885 return \"\";
9886 }"
9887 [(set_attr "length" "12")
9888 (set_attr "predicable" "yes")
a2cd141b 9889 (set_attr "type" "load1")]
215b30b3 9890)
9c08d1fa 9891
9c08d1fa 9892; This pattern is never tried by combine, so do it as a peephole
9893
a0f94409 9894(define_peephole2
372575c7 9895 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9896 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9897 (set (reg:CC CC_REGNUM)
aea4c774 9898 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9899 "TARGET_ARM"
a0f94409 9900 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9901 (set (match_dup 0) (match_dup 1))])]
9902 ""
0d66636f 9903)
9c08d1fa 9904
9c08d1fa 9905(define_split
9906 [(set (match_operand:SI 0 "s_register_operand" "")
9907 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9908 (const_int 0))
8fa3ba89 9909 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9910 [(match_operand:SI 3 "s_register_operand" "")
9911 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9912 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9913 "TARGET_ARM"
9c08d1fa 9914 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9915 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9916 (match_dup 5)))]
215b30b3 9917 ""
9918)
9c08d1fa 9919
aea4c774 9920;; This split can be used because CC_Z mode implies that the following
9921;; branch will be an equality, or an unsigned inequality, so the sign
9922;; extension is not needed.
9c08d1fa 9923
aea4c774 9924(define_split
bd5b4116 9925 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9926 (compare:CC_Z
9927 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9928 (const_int 24))
aea4c774 9929 (match_operand 1 "const_int_operand" "")))
9930 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9931 "TARGET_ARM
9932 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9933 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9934 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9935 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9936 "
9c08d1fa 9937 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9938 "
9939)
25f905c2 9940;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 9941
87b22bf7 9942(define_expand "prologue"
9943 [(clobber (const_int 0))]
cffb2a26 9944 "TARGET_EITHER"
25f905c2 9945 "if (TARGET_32BIT)
cffb2a26 9946 arm_expand_prologue ();
9947 else
25f905c2 9948 thumb1_expand_prologue ();
87b22bf7 9949 DONE;
cffb2a26 9950 "
9951)
87b22bf7 9952
56d27660 9953(define_expand "epilogue"
4c44712e 9954 [(clobber (const_int 0))]
cffb2a26 9955 "TARGET_EITHER"
56d27660 9956 "
18d50ae6 9957 if (crtl->calls_eh_return)
4c44712e 9958 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 9959 if (TARGET_THUMB1)
9960 thumb1_expand_epilogue ();
cffb2a26 9961 else if (USE_RETURN_INSN (FALSE))
56d27660 9962 {
9963 emit_jump_insn (gen_return ());
9964 DONE;
9965 }
cffb2a26 9966 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9967 gen_rtvec (1,
9968 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9969 VUNSPEC_EPILOGUE));
cffb2a26 9970 DONE;
9971 "
9972)
56d27660 9973
ef5651d0 9974;; Note - although unspec_volatile's USE all hard registers,
9975;; USEs are ignored after relaod has completed. Thus we need
9976;; to add an unspec of the link register to ensure that flow
9977;; does not think that it is unused by the sibcall branch that
9978;; will replace the standard function epilogue.
1c494086 9979(define_insn "sibcall_epilogue"
ef5651d0 9980 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9981 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 9982 "TARGET_32BIT"
1c494086 9983 "*
ffc9d00c 9984 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9985 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9986 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9987 "
9988;; Length is absolute worst case
9989 [(set_attr "length" "44")
defc47cf 9990 (set_attr "type" "block")
9991 ;; We don't clobber the conditions, but the potential length of this
9992 ;; operation is sufficient to make conditionalizing the sequence
9993 ;; unlikely to be profitable.
9994 (set_attr "conds" "clob")]
1c494086 9995)
9996
cffb2a26 9997(define_insn "*epilogue_insns"
e1159bbe 9998 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9999 "TARGET_EITHER"
56d27660 10000 "*
25f905c2 10001 if (TARGET_32BIT)
ffc9d00c 10002 return arm_output_epilogue (NULL);
25f905c2 10003 else /* TARGET_THUMB1 */
cffb2a26 10004 return thumb_unexpanded_epilogue ();
10005 "
215b30b3 10006 ; Length is absolute worst case
cffb2a26 10007 [(set_attr "length" "44")
defc47cf 10008 (set_attr "type" "block")
10009 ;; We don't clobber the conditions, but the potential length of this
10010 ;; operation is sufficient to make conditionalizing the sequence
10011 ;; unlikely to be profitable.
10012 (set_attr "conds" "clob")]
cffb2a26 10013)
10014
10015(define_expand "eh_epilogue"
7db9af5d 10016 [(use (match_operand:SI 0 "register_operand" ""))
10017 (use (match_operand:SI 1 "register_operand" ""))
10018 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10019 "TARGET_EITHER"
10020 "
215b30b3 10021 {
10022 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10023 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10024 {
10025 rtx ra = gen_rtx_REG (Pmode, 2);
10026
10027 emit_move_insn (ra, operands[2]);
10028 operands[2] = ra;
10029 }
5cf3595a 10030 /* This is a hack -- we may have crystalized the function type too
10031 early. */
10032 cfun->machine->func_type = 0;
215b30b3 10033 }"
10034)
56d27660 10035
9c08d1fa 10036;; This split is only used during output to reduce the number of patterns
10037;; that need assembler instructions adding to them. We allowed the setting
10038;; of the conditions to be implicit during rtl generation so that
10039;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10040;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10041;; up again here.
10042
25f905c2 10043;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10044;; conditional execution sufficient?
10045
9c08d1fa 10046(define_split
10047 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10048 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10049 [(match_operand 2 "" "") (match_operand 3 "" "")])
10050 (match_dup 0)
10051 (match_operand 4 "" "")))
bd5b4116 10052 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10053 "TARGET_ARM && reload_completed"
8fa3ba89 10054 [(set (match_dup 5) (match_dup 6))
10055 (cond_exec (match_dup 7)
10056 (set (match_dup 0) (match_dup 4)))]
10057 "
10058 {
10059 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10060 operands[2], operands[3]);
10061 enum rtx_code rc = GET_CODE (operands[1]);
10062
bd5b4116 10063 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10064 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10065 if (mode == CCFPmode || mode == CCFPEmode)
10066 rc = reverse_condition_maybe_unordered (rc);
10067 else
10068 rc = reverse_condition (rc);
10069
10070 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10071 }"
10072)
10073
10074(define_split
10075 [(set (match_operand:SI 0 "s_register_operand" "")
10076 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10077 [(match_operand 2 "" "") (match_operand 3 "" "")])
10078 (match_operand 4 "" "")
10079 (match_dup 0)))
bd5b4116 10080 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10081 "TARGET_ARM && reload_completed"
8fa3ba89 10082 [(set (match_dup 5) (match_dup 6))
10083 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10084 (set (match_dup 0) (match_dup 4)))]
10085 "
10086 {
10087 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10088 operands[2], operands[3]);
10089
bd5b4116 10090 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10091 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10092 }"
10093)
10094
10095(define_split
10096 [(set (match_operand:SI 0 "s_register_operand" "")
10097 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10098 [(match_operand 2 "" "") (match_operand 3 "" "")])
10099 (match_operand 4 "" "")
10100 (match_operand 5 "" "")))
bd5b4116 10101 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10102 "TARGET_ARM && reload_completed"
8fa3ba89 10103 [(set (match_dup 6) (match_dup 7))
10104 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10105 (set (match_dup 0) (match_dup 4)))
10106 (cond_exec (match_dup 8)
10107 (set (match_dup 0) (match_dup 5)))]
10108 "
10109 {
10110 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10111 operands[2], operands[3]);
10112 enum rtx_code rc = GET_CODE (operands[1]);
10113
bd5b4116 10114 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10115 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10116 if (mode == CCFPmode || mode == CCFPEmode)
10117 rc = reverse_condition_maybe_unordered (rc);
10118 else
10119 rc = reverse_condition (rc);
10120
10121 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10122 }"
10123)
10124
cffb2a26 10125(define_split
10126 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10127 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10128 [(match_operand:SI 2 "s_register_operand" "")
10129 (match_operand:SI 3 "arm_add_operand" "")])
10130 (match_operand:SI 4 "arm_rhs_operand" "")
10131 (not:SI
10132 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10133 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10134 "TARGET_ARM && reload_completed"
cffb2a26 10135 [(set (match_dup 6) (match_dup 7))
f6c53574 10136 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10137 (set (match_dup 0) (match_dup 4)))
10138 (cond_exec (match_dup 8)
10139 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10140 "
215b30b3 10141 {
10142 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10143 operands[2], operands[3]);
f6c53574 10144 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10145
bd5b4116 10146 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10147 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10148 if (mode == CCFPmode || mode == CCFPEmode)
10149 rc = reverse_condition_maybe_unordered (rc);
10150 else
10151 rc = reverse_condition (rc);
10152
10153 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10154 }"
10155)
cffb2a26 10156
10157(define_insn "*cond_move_not"
10158 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10159 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10160 [(match_operand 3 "cc_register" "") (const_int 0)])
10161 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10162 (not:SI
10163 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10164 "TARGET_ARM"
10165 "@
10166 mvn%D4\\t%0, %2
10167 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10168 [(set_attr "conds" "use")
d2a518d1 10169 (set_attr "insn" "mvn")
0d66636f 10170 (set_attr "length" "4,8")]
10171)
cffb2a26 10172
9c08d1fa 10173;; The next two patterns occur when an AND operation is followed by a
10174;; scc insn sequence
10175
f7fbdd4a 10176(define_insn "*sign_extract_onebit"
9c08d1fa 10177 [(set (match_operand:SI 0 "s_register_operand" "=r")
10178 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10179 (const_int 1)
ed750274 10180 (match_operand:SI 2 "const_int_operand" "n")))
10181 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10182 "TARGET_ARM"
9c08d1fa 10183 "*
0d66636f 10184 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10185 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10186 return \"mvnne\\t%0, #0\";
10187 "
10188 [(set_attr "conds" "clob")
10189 (set_attr "length" "8")]
10190)
9c08d1fa 10191
f7fbdd4a 10192(define_insn "*not_signextract_onebit"
9c08d1fa 10193 [(set (match_operand:SI 0 "s_register_operand" "=r")
10194 (not:SI
10195 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10196 (const_int 1)
ed750274 10197 (match_operand:SI 2 "const_int_operand" "n"))))
10198 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10199 "TARGET_ARM"
9c08d1fa 10200 "*
0d66636f 10201 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10202 output_asm_insn (\"tst\\t%1, %2\", operands);
10203 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10204 return \"movne\\t%0, #0\";
10205 "
10206 [(set_attr "conds" "clob")
10207 (set_attr "length" "12")]
10208)
25f905c2 10209;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10210
0d66636f 10211;; Push multiple registers to the stack. Registers are in parallel (use ...)
10212;; expressions. For simplicity, the first register is also in the unspec
10213;; part.
f7fbdd4a 10214(define_insn "*push_multi"
87b22bf7 10215 [(match_parallel 2 "multi_register_push"
10216 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10217 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10218 UNSPEC_PUSH_MULT))])]
25f905c2 10219 "TARGET_32BIT"
87b22bf7 10220 "*
215b30b3 10221 {
10222 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10223
215b30b3 10224 /* For the StrongARM at least it is faster to
25f905c2 10225 use STR to store only a single register.
542d5028 10226 In Thumb mode always use push, and the assembler will pick
10227 something appropriate. */
25f905c2 10228 if (num_saves == 1 && TARGET_ARM)
215b30b3 10229 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10230 else
10231 {
10232 int i;
10233 char pattern[100];
ed593f11 10234
25f905c2 10235 if (TARGET_ARM)
10236 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10237 else
10238 strcpy (pattern, \"push\\t{%1\");
215b30b3 10239
6079f055 10240 for (i = 1; i < num_saves; i++)
215b30b3 10241 {
10242 strcat (pattern, \", %|\");
10243 strcat (pattern,
10244 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10245 }
10246
10247 strcat (pattern, \"}\");
10248 output_asm_insn (pattern, operands);
10249 }
10250
10251 return \"\";
10252 }"
10253 [(set_attr "type" "store4")]
10254)
f7fbdd4a 10255
4c58c898 10256(define_insn "stack_tie"
10257 [(set (mem:BLK (scratch))
aaa37ad6 10258 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10259 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10260 UNSPEC_PRLG_STK))]
10261 ""
10262 ""
10263 [(set_attr "length" "0")]
10264)
10265
3398e91d 10266;; Similarly for the floating point registers
7b1d2fc4 10267(define_insn "*push_fp_multi"
10268 [(match_parallel 2 "multi_register_push"
10269 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10270 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10271 UNSPEC_PUSH_MULT))])]
25f905c2 10272 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10273 "*
215b30b3 10274 {
10275 char pattern[100];
7b1d2fc4 10276
215b30b3 10277 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10278 output_asm_insn (pattern, operands);
10279 return \"\";
10280 }"
10281 [(set_attr "type" "f_store")]
10282)
7b1d2fc4 10283
f7fbdd4a 10284;; Special patterns for dealing with the constant pool
10285
cffb2a26 10286(define_insn "align_4"
e1159bbe 10287 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10288 "TARGET_EITHER"
f7fbdd4a 10289 "*
cffb2a26 10290 assemble_align (32);
f7fbdd4a 10291 return \"\";
cffb2a26 10292 "
10293)
f7fbdd4a 10294
755eb2b4 10295(define_insn "align_8"
10296 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10297 "TARGET_EITHER"
755eb2b4 10298 "*
10299 assemble_align (64);
10300 return \"\";
10301 "
10302)
10303
cffb2a26 10304(define_insn "consttable_end"
e1159bbe 10305 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10306 "TARGET_EITHER"
f7fbdd4a 10307 "*
cffb2a26 10308 making_const_table = FALSE;
f7fbdd4a 10309 return \"\";
cffb2a26 10310 "
10311)
f7fbdd4a 10312
cffb2a26 10313(define_insn "consttable_1"
e1159bbe 10314 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10315 "TARGET_THUMB1"
f7fbdd4a 10316 "*
cffb2a26 10317 making_const_table = TRUE;
09d688ff 10318 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10319 assemble_zeros (3);
f7fbdd4a 10320 return \"\";
cffb2a26 10321 "
10322 [(set_attr "length" "4")]
10323)
f7fbdd4a 10324
cffb2a26 10325(define_insn "consttable_2"
e1159bbe 10326 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10327 "TARGET_THUMB1"
f7fbdd4a 10328 "*
cffb2a26 10329 making_const_table = TRUE;
9b8516be 10330 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10331 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10332 assemble_zeros (2);
f7fbdd4a 10333 return \"\";
cffb2a26 10334 "
10335 [(set_attr "length" "4")]
10336)
10337
10338(define_insn "consttable_4"
e1159bbe 10339 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10340 "TARGET_EITHER"
10341 "*
10342 {
9b8516be 10343 rtx x = operands[0];
cffb2a26 10344 making_const_table = TRUE;
9b8516be 10345 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10346 {
10347 case MODE_FLOAT:
9b8516be 10348 if (GET_MODE (x) == HFmode)
10349 arm_emit_fp16_const (x);
10350 else
10351 {
10352 REAL_VALUE_TYPE r;
10353 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10354 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10355 }
10356 break;
cffb2a26 10357 default:
7b04c5d5 10358 /* XXX: Sometimes gcc does something really dumb and ends up with
10359 a HIGH in a constant pool entry, usually because it's trying to
10360 load into a VFP register. We know this will always be used in
10361 combination with a LO_SUM which ignores the high bits, so just
10362 strip off the HIGH. */
10363 if (GET_CODE (x) == HIGH)
10364 x = XEXP (x, 0);
9b8516be 10365 assemble_integer (x, 4, BITS_PER_WORD, 1);
10366 mark_symbol_refs_as_used (x);
cffb2a26 10367 break;
10368 }
10369 return \"\";
10370 }"
10371 [(set_attr "length" "4")]
10372)
10373
10374(define_insn "consttable_8"
e1159bbe 10375 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10376 "TARGET_EITHER"
10377 "*
10378 {
10379 making_const_table = TRUE;
10380 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10381 {
10382 case MODE_FLOAT:
10383 {
badfe841 10384 REAL_VALUE_TYPE r;
10385 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10386 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10387 break;
10388 }
10389 default:
09d688ff 10390 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10391 break;
10392 }
10393 return \"\";
10394 }"
10395 [(set_attr "length" "8")]
10396)
10397
d98a3884 10398(define_insn "consttable_16"
10399 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10400 "TARGET_EITHER"
10401 "*
10402 {
10403 making_const_table = TRUE;
10404 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10405 {
10406 case MODE_FLOAT:
10407 {
10408 REAL_VALUE_TYPE r;
10409 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10410 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10411 break;
10412 }
10413 default:
10414 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10415 break;
10416 }
10417 return \"\";
10418 }"
10419 [(set_attr "length" "16")]
10420)
10421
cffb2a26 10422;; Miscellaneous Thumb patterns
10423
fd957ef3 10424(define_expand "tablejump"
7db9af5d 10425 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10426 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10427 "TARGET_THUMB1"
fd957ef3 10428 "
10429 if (flag_pic)
10430 {
10431 /* Hopefully, CSE will eliminate this copy. */
10432 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10433 rtx reg2 = gen_reg_rtx (SImode);
10434
10435 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10436 operands[0] = reg2;
10437 }
10438 "
10439)
10440
f1039640 10441;; NB never uses BX.
25f905c2 10442(define_insn "*thumb1_tablejump"
cffb2a26 10443 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10444 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10445 "TARGET_THUMB1"
fd957ef3 10446 "mov\\t%|pc, %0"
cffb2a26 10447 [(set_attr "length" "2")]
10448)
0d66636f 10449
331beb1a 10450;; V5 Instructions,
10451
8f4be2be 10452(define_insn "clzsi2"
10453 [(set (match_operand:SI 0 "s_register_operand" "=r")
10454 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10455 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10456 "clz%?\\t%0, %1"
bcaec148 10457 [(set_attr "predicable" "yes")
10458 (set_attr "insn" "clz")])
331beb1a 10459
099ad98b 10460(define_insn "rbitsi2"
10461 [(set (match_operand:SI 0 "s_register_operand" "=r")
10462 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10463 "TARGET_32BIT && arm_arch_thumb2"
10464 "rbit%?\\t%0, %1"
10465 [(set_attr "predicable" "yes")
10466 (set_attr "insn" "clz")])
10467
10468(define_expand "ctzsi2"
10469 [(set (match_operand:SI 0 "s_register_operand" "")
10470 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10471 "TARGET_32BIT && arm_arch_thumb2"
10472 "
30191172 10473 {
10474 rtx tmp = gen_reg_rtx (SImode);
10475 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10476 emit_insn (gen_clzsi2 (operands[0], tmp));
10477 }
099ad98b 10478 DONE;
10479 "
10480)
10481
e1159bbe 10482;; V5E instructions.
331beb1a 10483
10484(define_insn "prefetch"
f4e79814 10485 [(prefetch (match_operand:SI 0 "address_operand" "p")
10486 (match_operand:SI 1 "" "")
10487 (match_operand:SI 2 "" ""))]
25f905c2 10488 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10489 "pld\\t%a0")
331beb1a 10490
0d66636f 10491;; General predication pattern
10492
10493(define_cond_exec
10494 [(match_operator 0 "arm_comparison_operator"
10495 [(match_operand 1 "cc_register" "")
10496 (const_int 0)])]
25f905c2 10497 "TARGET_32BIT"
0d66636f 10498 ""
10499)
10500
063a05c7 10501(define_insn "prologue_use"
10502 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10503 ""
10504 "%@ %0 needed for prologue"
02cfc9c9 10505 [(set_attr "length" "0")]
063a05c7 10506)
7db9af5d 10507
4c44712e 10508
10509;; Patterns for exception handling
10510
10511(define_expand "eh_return"
10512 [(use (match_operand 0 "general_operand" ""))]
10513 "TARGET_EITHER"
10514 "
10515 {
25f905c2 10516 if (TARGET_32BIT)
4c44712e 10517 emit_insn (gen_arm_eh_return (operands[0]));
10518 else
10519 emit_insn (gen_thumb_eh_return (operands[0]));
10520 DONE;
10521 }"
10522)
10523
10524;; We can't expand this before we know where the link register is stored.
10525(define_insn_and_split "arm_eh_return"
10526 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10527 VUNSPEC_EH_RETURN)
10528 (clobber (match_scratch:SI 1 "=&r"))]
10529 "TARGET_ARM"
10530 "#"
10531 "&& reload_completed"
10532 [(const_int 0)]
10533 "
10534 {
10535 arm_set_return_address (operands[0], operands[1]);
10536 DONE;
10537 }"
10538)
10539
10540(define_insn_and_split "thumb_eh_return"
10541 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10542 VUNSPEC_EH_RETURN)
10543 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10544 "TARGET_THUMB1"
4c44712e 10545 "#"
10546 "&& reload_completed"
10547 [(const_int 0)]
10548 "
10549 {
10550 thumb_set_return_address (operands[0], operands[1]);
10551 DONE;
10552 }"
10553)
10554
f655717d 10555\f
10556;; TLS support
10557
10558(define_insn "load_tp_hard"
10559 [(set (match_operand:SI 0 "register_operand" "=r")
10560 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10561 "TARGET_HARD_TP"
10562 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10563 [(set_attr "predicable" "yes")]
10564)
10565
10566;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10567(define_insn "load_tp_soft"
10568 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10569 (clobber (reg:SI LR_REGNUM))
10570 (clobber (reg:SI IP_REGNUM))
10571 (clobber (reg:CC CC_REGNUM))]
10572 "TARGET_SOFT_TP"
10573 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10574 [(set_attr "conds" "clob")]
10575)
10576
eca5c984 10577(define_insn "*arm_movtas_ze"
10578 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10579 (const_int 16)
10580 (const_int 16))
10581 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10582 "arm_arch_thumb2"
eca5c984 10583 "movt%?\t%0, %c1"
10584 [(set_attr "predicable" "yes")
10585 (set_attr "length" "4")]
10586)
10587
c0fc3696 10588(define_insn "*arm_rev"
ff82f757 10589 [(set (match_operand:SI 0 "s_register_operand" "=r")
10590 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 10591 "TARGET_32BIT && arm_arch6"
10592 "rev%?\t%0, %1"
10593 [(set_attr "predicable" "yes")
10594 (set_attr "length" "4")]
10595)
10596
10597(define_insn "*thumb1_rev"
10598 [(set (match_operand:SI 0 "s_register_operand" "=l")
10599 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10600 "TARGET_THUMB1 && arm_arch6"
10601 "rev\t%0, %1"
10602 [(set_attr "length" "2")]
ff82f757 10603)
10604
10605(define_expand "arm_legacy_rev"
10606 [(set (match_operand:SI 2 "s_register_operand" "")
10607 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10608 (const_int 16))
10609 (match_dup 1)))
10610 (set (match_dup 2)
10611 (lshiftrt:SI (match_dup 2)
10612 (const_int 8)))
10613 (set (match_operand:SI 3 "s_register_operand" "")
10614 (rotatert:SI (match_dup 1)
10615 (const_int 8)))
10616 (set (match_dup 2)
10617 (and:SI (match_dup 2)
10618 (const_int -65281)))
10619 (set (match_operand:SI 0 "s_register_operand" "")
10620 (xor:SI (match_dup 3)
10621 (match_dup 2)))]
10622 "TARGET_32BIT"
10623 ""
10624)
10625
10626;; Reuse temporaries to keep register pressure down.
10627(define_expand "thumb_legacy_rev"
10628 [(set (match_operand:SI 2 "s_register_operand" "")
10629 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10630 (const_int 24)))
10631 (set (match_operand:SI 3 "s_register_operand" "")
10632 (lshiftrt:SI (match_dup 1)
10633 (const_int 24)))
10634 (set (match_dup 3)
10635 (ior:SI (match_dup 3)
10636 (match_dup 2)))
10637 (set (match_operand:SI 4 "s_register_operand" "")
10638 (const_int 16))
10639 (set (match_operand:SI 5 "s_register_operand" "")
10640 (rotatert:SI (match_dup 1)
10641 (match_dup 4)))
10642 (set (match_dup 2)
10643 (ashift:SI (match_dup 5)
10644 (const_int 24)))
10645 (set (match_dup 5)
10646 (lshiftrt:SI (match_dup 5)
10647 (const_int 24)))
10648 (set (match_dup 5)
10649 (ior:SI (match_dup 5)
10650 (match_dup 2)))
10651 (set (match_dup 5)
10652 (rotatert:SI (match_dup 5)
10653 (match_dup 4)))
10654 (set (match_operand:SI 0 "s_register_operand" "")
10655 (ior:SI (match_dup 5)
10656 (match_dup 3)))]
10657 "TARGET_THUMB"
10658 ""
10659)
10660
10661(define_expand "bswapsi2"
10662 [(set (match_operand:SI 0 "s_register_operand" "=r")
10663 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10664"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10665"
8d1af482 10666 if (!arm_arch6)
10667 {
10668 rtx op2 = gen_reg_rtx (SImode);
10669 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10670
8d1af482 10671 if (TARGET_THUMB)
10672 {
10673 rtx op4 = gen_reg_rtx (SImode);
10674 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10675
8d1af482 10676 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10677 op2, op3, op4, op5));
10678 }
10679 else
10680 {
10681 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10682 op2, op3));
10683 }
ff82f757 10684
8d1af482 10685 DONE;
10686 }
ff82f757 10687 "
10688)
10689
320ea44d 10690;; Load the load/store multiple patterns
10691(include "ldmstm.md")
7db9af5d 10692;; Load the FPA co-processor patterns
10693(include "fpa.md")
10694;; Load the Maverick co-processor patterns
10695(include "cirrus.md")
d98a3884 10696;; Vector bits common to IWMMXT and Neon
10697(include "vec-common.md")
755eb2b4 10698;; Load the Intel Wireless Multimedia Extension patterns
10699(include "iwmmxt.md")
a2cd141b 10700;; Load the VFP co-processor patterns
10701(include "vfp.md")
25f905c2 10702;; Thumb-2 patterns
10703(include "thumb2.md")
d98a3884 10704;; Neon patterns
10705(include "neon.md")
06df6b17 10706;; Synchronization Primitives
10707(include "sync.md")