]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
2010-09-16 Richard Guenther <rguenther@suse.de>
[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
457275b6 336; initialized by arm_override_options()
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"
4d5cb40d 500 (const (if_then_else
3f1e069f 501 (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9")
e3879fd0 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")
3f1e069f 509 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9")
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")
55e3ada8 524(include "vfp11.md")
3586df96 525
9c08d1fa 526\f
215b30b3 527;;---------------------------------------------------------------------------
e1159bbe 528;; Insn patterns
529;;
a0f94409 530;; Addition insns.
215b30b3 531
9c08d1fa 532;; Note: For DImode insns, there is normally no reason why operands should
533;; not be in the same register, what we don't want is for something being
534;; written to partially overlap something that is an input.
7d57ec45 535;; Cirrus 64bit additions should not be split because we have a native
536;; 64bit addition instructions.
9c08d1fa 537
cffb2a26 538(define_expand "adddi3"
539 [(parallel
215b30b3 540 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 541 (plus:DI (match_operand:DI 1 "s_register_operand" "")
542 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 543 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 544 "TARGET_EITHER"
545 "
a2cd141b 546 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 547 {
548 if (!cirrus_fp_register (operands[0], DImode))
549 operands[0] = force_reg (DImode, operands[0]);
550 if (!cirrus_fp_register (operands[1], DImode))
551 operands[1] = force_reg (DImode, operands[1]);
552 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
553 DONE;
554 }
555
25f905c2 556 if (TARGET_THUMB1)
cffb2a26 557 {
558 if (GET_CODE (operands[1]) != REG)
bc5a93af 559 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 560 if (GET_CODE (operands[2]) != REG)
bc5a93af 561 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 562 }
563 "
564)
565
25f905c2 566(define_insn "*thumb1_adddi3"
cffb2a26 567 [(set (match_operand:DI 0 "register_operand" "=l")
568 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 569 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 570 (clobber (reg:CC CC_REGNUM))
cffb2a26 571 ]
25f905c2 572 "TARGET_THUMB1"
cffb2a26 573 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
574 [(set_attr "length" "4")]
575)
576
a0f94409 577(define_insn_and_split "*arm_adddi3"
cffb2a26 578 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 579 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
580 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 581 (clobber (reg:CC CC_REGNUM))]
94829feb 582 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 583 "#"
94829feb 584 "TARGET_32BIT && reload_completed
585 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 586 [(parallel [(set (reg:CC_C CC_REGNUM)
587 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
588 (match_dup 1)))
589 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 590 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
591 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 592 "
593 {
594 operands[3] = gen_highpart (SImode, operands[0]);
595 operands[0] = gen_lowpart (SImode, operands[0]);
596 operands[4] = gen_highpart (SImode, operands[1]);
597 operands[1] = gen_lowpart (SImode, operands[1]);
598 operands[5] = gen_highpart (SImode, operands[2]);
599 operands[2] = gen_lowpart (SImode, operands[2]);
600 }"
cffb2a26 601 [(set_attr "conds" "clob")
602 (set_attr "length" "8")]
603)
9c08d1fa 604
a0f94409 605(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 606 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
607 (plus:DI (sign_extend:DI
97499065 608 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 609 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 610 (clobber (reg:CC CC_REGNUM))]
25f905c2 611 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 612 "#"
25f905c2 613 "TARGET_32BIT && reload_completed"
a0f94409 614 [(parallel [(set (reg:CC_C CC_REGNUM)
615 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
616 (match_dup 1)))
617 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 618 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 619 (const_int 31))
080c0b9a 620 (match_dup 4))
621 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 622 "
623 {
624 operands[3] = gen_highpart (SImode, operands[0]);
625 operands[0] = gen_lowpart (SImode, operands[0]);
626 operands[4] = gen_highpart (SImode, operands[1]);
627 operands[1] = gen_lowpart (SImode, operands[1]);
628 operands[2] = gen_lowpart (SImode, operands[2]);
629 }"
215b30b3 630 [(set_attr "conds" "clob")
631 (set_attr "length" "8")]
632)
9c08d1fa 633
a0f94409 634(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 635 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
636 (plus:DI (zero_extend:DI
97499065 637 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 638 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 639 (clobber (reg:CC CC_REGNUM))]
25f905c2 640 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 641 "#"
25f905c2 642 "TARGET_32BIT && reload_completed"
a0f94409 643 [(parallel [(set (reg:CC_C CC_REGNUM)
644 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
645 (match_dup 1)))
646 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 647 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
648 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 649 "
650 {
651 operands[3] = gen_highpart (SImode, operands[0]);
652 operands[0] = gen_lowpart (SImode, operands[0]);
653 operands[4] = gen_highpart (SImode, operands[1]);
654 operands[1] = gen_lowpart (SImode, operands[1]);
655 operands[2] = gen_lowpart (SImode, operands[2]);
656 }"
cffb2a26 657 [(set_attr "conds" "clob")
658 (set_attr "length" "8")]
659)
b11cae9e 660
87b22bf7 661(define_expand "addsi3"
cffb2a26 662 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 663 (plus:SI (match_operand:SI 1 "s_register_operand" "")
664 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 665 "TARGET_EITHER"
87b22bf7 666 "
25f905c2 667 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 668 {
96f57e36 669 arm_split_constant (PLUS, SImode, NULL_RTX,
670 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 671 optimize && can_create_pseudo_p ());
87b22bf7 672 DONE;
673 }
cffb2a26 674 "
675)
87b22bf7 676
5bd751ff 677; If there is a scratch available, this will be faster than synthesizing the
a0f94409 678; addition.
679(define_peephole2
680 [(match_scratch:SI 3 "r")
372575c7 681 (set (match_operand:SI 0 "arm_general_register_operand" "")
682 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 683 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 684 "TARGET_32BIT &&
a0f94409 685 !(const_ok_for_arm (INTVAL (operands[2]))
686 || const_ok_for_arm (-INTVAL (operands[2])))
687 && const_ok_for_arm (~INTVAL (operands[2]))"
688 [(set (match_dup 3) (match_dup 2))
689 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
690 ""
691)
87b22bf7 692
2f02c19f 693;; The r/r/k alternative is required when reloading the address
694;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
695;; put the duplicated register first, and not try the commutative version.
a0f94409 696(define_insn_and_split "*arm_addsi3"
bccb5444 697 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k,r")
698 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
699 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
25f905c2 700 "TARGET_32BIT"
5565501b 701 "@
702 add%?\\t%0, %1, %2
aaa37ad6 703 add%?\\t%0, %1, %2
2f02c19f 704 add%?\\t%0, %2, %1
aaa37ad6 705 sub%?\\t%0, %1, #%n2
87b22bf7 706 sub%?\\t%0, %1, #%n2
707 #"
a3ffc315 708 "TARGET_32BIT
709 && GET_CODE (operands[2]) == CONST_INT
a0f94409 710 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 711 || const_ok_for_arm (-INTVAL (operands[2])))
712 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 713 [(clobber (const_int 0))]
714 "
96f57e36 715 arm_split_constant (PLUS, SImode, curr_insn,
716 INTVAL (operands[2]), operands[0],
a0f94409 717 operands[1], 0);
718 DONE;
719 "
2f02c19f 720 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 721 (set_attr "predicable" "yes")]
cffb2a26 722)
723
0bdb6455 724(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 725 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
726 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
727 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 728 "TARGET_THUMB1"
cffb2a26 729 "*
0d66636f 730 static const char * const asms[] =
cffb2a26 731 {
732 \"add\\t%0, %0, %2\",
733 \"sub\\t%0, %0, #%n2\",
734 \"add\\t%0, %1, %2\",
735 \"add\\t%0, %0, %2\",
736 \"add\\t%0, %0, %2\",
737 \"add\\t%0, %1, %2\",
0bdb6455 738 \"add\\t%0, %1, %2\",
739 \"#\",
bf7bc2f6 740 \"#\",
0bdb6455 741 \"#\"
cffb2a26 742 };
743 if ((which_alternative == 2 || which_alternative == 6)
744 && GET_CODE (operands[2]) == CONST_INT
745 && INTVAL (operands[2]) < 0)
746 return \"sub\\t%0, %1, #%n2\";
747 return asms[which_alternative];
748 "
0bdb6455 749 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 750 && ((operands[1] != stack_pointer_rtx
751 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
752 || (operands[1] == stack_pointer_rtx
753 && INTVAL (operands[2]) > 1020))"
0bdb6455 754 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
755 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
756 {
757 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 758 if (operands[1] == stack_pointer_rtx)
759 offset -= 1020;
760 else
761 {
762 if (offset > 255)
763 offset = 255;
764 else if (offset < -255)
765 offset = -255;
766 }
0bdb6455 767 operands[3] = GEN_INT (offset);
768 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
769 }
bf7bc2f6 770 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 771)
772
773;; Reloading and elimination of the frame pointer can
774;; sometimes cause this optimization to be missed.
a0f94409 775(define_peephole2
372575c7 776 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 777 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 778 (set (match_dup 0)
372575c7 779 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 780 "TARGET_THUMB1
cffb2a26 781 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
782 && (INTVAL (operands[1]) & 3) == 0"
372575c7 783 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 784 ""
cffb2a26 785)
b11cae9e 786
f7fbdd4a 787(define_insn "*addsi3_compare0"
bd5b4116 788 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 789 (compare:CC_NOOV
215b30b3 790 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
791 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 792 (const_int 0)))
793 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 794 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 795 "TARGET_ARM"
5565501b 796 "@
25f905c2 797 add%.\\t%0, %1, %2
798 sub%.\\t%0, %1, #%n2"
cffb2a26 799 [(set_attr "conds" "set")]
800)
9c08d1fa 801
aea4c774 802(define_insn "*addsi3_compare0_scratch"
bd5b4116 803 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 804 (compare:CC_NOOV
215b30b3 805 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
806 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 807 (const_int 0)))]
ec792a7b 808 "TARGET_ARM"
cffb2a26 809 "@
810 cmn%?\\t%0, %1
811 cmp%?\\t%0, #%n1"
0d66636f 812 [(set_attr "conds" "set")]
813)
cffb2a26 814
aed179ae 815(define_insn "*compare_negsi_si"
816 [(set (reg:CC_Z CC_REGNUM)
817 (compare:CC_Z
818 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
819 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 820 "TARGET_32BIT"
aed179ae 821 "cmn%?\\t%1, %0"
0d66636f 822 [(set_attr "conds" "set")]
823)
aea4c774 824
203c488f 825;; This is the canonicalization of addsi3_compare0_for_combiner when the
826;; addend is a constant.
827(define_insn "*cmpsi2_addneg"
828 [(set (reg:CC CC_REGNUM)
829 (compare:CC
830 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 831 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 832 (set (match_operand:SI 0 "s_register_operand" "=r,r")
833 (plus:SI (match_dup 1)
2a977b78 834 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 835 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 836 "@
2a977b78 837 add%.\\t%0, %1, %3
838 sub%.\\t%0, %1, #%n3"
203c488f 839 [(set_attr "conds" "set")]
840)
841
842;; Convert the sequence
843;; sub rd, rn, #1
844;; cmn rd, #1 (equivalent to cmp rd, #-1)
845;; bne dest
846;; into
847;; subs rd, rn, #1
848;; bcs dest ((unsigned)rn >= 1)
849;; similarly for the beq variant using bcc.
850;; This is a common looping idiom (while (n--))
851(define_peephole2
372575c7 852 [(set (match_operand:SI 0 "arm_general_register_operand" "")
853 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 854 (const_int -1)))
855 (set (match_operand 2 "cc_register" "")
856 (compare (match_dup 0) (const_int -1)))
857 (set (pc)
858 (if_then_else (match_operator 3 "equality_operator"
859 [(match_dup 2) (const_int 0)])
860 (match_operand 4 "" "")
861 (match_operand 5 "" "")))]
25f905c2 862 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 863 [(parallel[
864 (set (match_dup 2)
865 (compare:CC
866 (match_dup 1) (const_int 1)))
867 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
868 (set (pc)
869 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
870 (match_dup 4)
871 (match_dup 5)))]
872 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
873 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
874 ? GEU : LTU),
875 VOIDmode,
876 operands[2], const0_rtx);"
877)
878
ebcc79bc 879;; The next four insns work because they compare the result with one of
880;; the operands, and we know that the use of the condition code is
881;; either GEU or LTU, so we can use the carry flag from the addition
882;; instead of doing the compare a second time.
883(define_insn "*addsi3_compare_op1"
bd5b4116 884 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 885 (compare:CC_C
886 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
887 (match_operand:SI 2 "arm_add_operand" "rI,L"))
888 (match_dup 1)))
889 (set (match_operand:SI 0 "s_register_operand" "=r,r")
890 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 891 "TARGET_32BIT"
ebcc79bc 892 "@
25f905c2 893 add%.\\t%0, %1, %2
894 sub%.\\t%0, %1, #%n2"
0d66636f 895 [(set_attr "conds" "set")]
896)
ebcc79bc 897
898(define_insn "*addsi3_compare_op2"
bd5b4116 899 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 900 (compare:CC_C
901 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
902 (match_operand:SI 2 "arm_add_operand" "rI,L"))
903 (match_dup 2)))
5565501b 904 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 905 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 906 "TARGET_32BIT"
5565501b 907 "@
25f905c2 908 add%.\\t%0, %1, %2
909 sub%.\\t%0, %1, #%n2"
0d66636f 910 [(set_attr "conds" "set")]
911)
9c08d1fa 912
ebcc79bc 913(define_insn "*compare_addsi2_op0"
bd5b4116 914 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 915 (compare:CC_C
916 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
917 (match_operand:SI 1 "arm_add_operand" "rI,L"))
918 (match_dup 0)))]
25f905c2 919 "TARGET_32BIT"
ebcc79bc 920 "@
921 cmn%?\\t%0, %1
922 cmp%?\\t%0, #%n1"
0d66636f 923 [(set_attr "conds" "set")]
924)
ebcc79bc 925
926(define_insn "*compare_addsi2_op1"
bd5b4116 927 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 928 (compare:CC_C
929 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
930 (match_operand:SI 1 "arm_add_operand" "rI,L"))
931 (match_dup 1)))]
25f905c2 932 "TARGET_32BIT"
ebcc79bc 933 "@
934 cmn%?\\t%0, %1
935 cmp%?\\t%0, #%n1"
0d66636f 936 [(set_attr "conds" "set")]
937)
ebcc79bc 938
080c0b9a 939(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 940 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 941 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 942 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 943 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 944 "TARGET_32BIT"
ebcc79bc 945 "adc%?\\t%0, %1, %2"
cffb2a26 946 [(set_attr "conds" "use")]
947)
ebcc79bc 948
080c0b9a 949(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 950 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 951 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
952 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 953 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 954 "TARGET_32BIT"
ebcc79bc 955 "adc%?\\t%0, %1, %2"
0d66636f 956 [(set_attr "conds" "use")]
957)
ebcc79bc 958
080c0b9a 959(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 960 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 961 (plus:SI (plus:SI
962 (match_operator:SI 2 "shift_operator"
963 [(match_operand:SI 3 "s_register_operand" "r")
964 (match_operand:SI 4 "reg_or_int_operand" "rM")])
965 (match_operand:SI 1 "s_register_operand" "r"))
966 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 967 "TARGET_32BIT"
080c0b9a 968 "adc%?\\t%0, %1, %3%S2"
969 [(set_attr "conds" "use")
970 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
971 (const_string "alu_shift")
972 (const_string "alu_shift_reg")))]
cffb2a26 973)
ebcc79bc 974
25f905c2 975(define_expand "incscc"
976 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
977 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
978 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
979 (match_operand:SI 1 "s_register_operand" "0,?r")))]
980 "TARGET_32BIT"
981 ""
982)
983
984(define_insn "*arm_incscc"
9c08d1fa 985 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 986 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 987 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 988 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 989 "TARGET_ARM"
5565501b 990 "@
991 add%d2\\t%0, %1, #1
992 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 993 [(set_attr "conds" "use")
215b30b3 994 (set_attr "length" "4,8")]
995)
9c08d1fa 996
d795fb69 997; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
998(define_split
999 [(set (match_operand:SI 0 "s_register_operand" "")
1000 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1001 (match_operand:SI 2 "s_register_operand" ""))
1002 (const_int -1)))
1003 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1004 "TARGET_32BIT"
d795fb69 1005 [(set (match_dup 3) (match_dup 1))
1006 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1007 "
1008 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1009")
1010
604f3a0a 1011(define_expand "addsf3"
1012 [(set (match_operand:SF 0 "s_register_operand" "")
1013 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1014 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 1015 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1016 "
a2cd141b 1017 if (TARGET_MAVERICK
604f3a0a 1018 && !cirrus_fp_register (operands[2], SFmode))
1019 operands[2] = force_reg (SFmode, operands[2]);
1020")
1021
604f3a0a 1022(define_expand "adddf3"
1023 [(set (match_operand:DF 0 "s_register_operand" "")
1024 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1025 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1026 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1027 "
a2cd141b 1028 if (TARGET_MAVERICK
604f3a0a 1029 && !cirrus_fp_register (operands[2], DFmode))
1030 operands[2] = force_reg (DFmode, operands[2]);
1031")
1032
cffb2a26 1033(define_expand "subdi3"
1034 [(parallel
1035 [(set (match_operand:DI 0 "s_register_operand" "")
1036 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1037 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1038 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1039 "TARGET_EITHER"
1040 "
a2cd141b 1041 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1042 && TARGET_32BIT
7d57ec45 1043 && cirrus_fp_register (operands[0], DImode)
1044 && cirrus_fp_register (operands[1], DImode))
1045 {
1046 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1047 DONE;
1048 }
1049
25f905c2 1050 if (TARGET_THUMB1)
cffb2a26 1051 {
1052 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1053 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1054 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1055 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1056 }
1057 "
1058)
1059
1060(define_insn "*arm_subdi3"
1061 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1062 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1063 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1064 (clobber (reg:CC CC_REGNUM))]
94829feb 1065 "TARGET_32BIT && !TARGET_NEON"
97499065 1066 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1067 [(set_attr "conds" "clob")
1068 (set_attr "length" "8")]
1069)
1070
1071(define_insn "*thumb_subdi3"
1072 [(set (match_operand:DI 0 "register_operand" "=l")
1073 (minus:DI (match_operand:DI 1 "register_operand" "0")
1074 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1075 (clobber (reg:CC CC_REGNUM))]
25f905c2 1076 "TARGET_THUMB1"
cffb2a26 1077 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1078 [(set_attr "length" "4")]
1079)
9c08d1fa 1080
f7fbdd4a 1081(define_insn "*subdi_di_zesidi"
cffb2a26 1082 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1083 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1084 (zero_extend:DI
cffb2a26 1085 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1086 (clobber (reg:CC CC_REGNUM))]
25f905c2 1087 "TARGET_32BIT"
97499065 1088 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1089 [(set_attr "conds" "clob")
1090 (set_attr "length" "8")]
1091)
9c08d1fa 1092
f7fbdd4a 1093(define_insn "*subdi_di_sesidi"
cffb2a26 1094 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1095 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1096 (sign_extend:DI
cffb2a26 1097 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1098 (clobber (reg:CC CC_REGNUM))]
25f905c2 1099 "TARGET_32BIT"
97499065 1100 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1101 [(set_attr "conds" "clob")
1102 (set_attr "length" "8")]
1103)
9c08d1fa 1104
f7fbdd4a 1105(define_insn "*subdi_zesidi_di"
cffb2a26 1106 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1107 (minus:DI (zero_extend:DI
cffb2a26 1108 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1109 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1110 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1111 "TARGET_ARM"
97499065 1112 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1113 [(set_attr "conds" "clob")
1114 (set_attr "length" "8")]
1115)
9c08d1fa 1116
f7fbdd4a 1117(define_insn "*subdi_sesidi_di"
cffb2a26 1118 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1119 (minus:DI (sign_extend:DI
cffb2a26 1120 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1121 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1122 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1123 "TARGET_ARM"
97499065 1124 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1125 [(set_attr "conds" "clob")
1126 (set_attr "length" "8")]
1127)
9c08d1fa 1128
f7fbdd4a 1129(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1130 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1131 (minus:DI (zero_extend:DI
cffb2a26 1132 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1133 (zero_extend:DI
cffb2a26 1134 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1135 (clobber (reg:CC CC_REGNUM))]
25f905c2 1136 "TARGET_32BIT"
1137 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1138 [(set_attr "conds" "clob")
1139 (set_attr "length" "8")]
1140)
b11cae9e 1141
87b22bf7 1142(define_expand "subsi3"
cffb2a26 1143 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1144 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1145 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1146 "TARGET_EITHER"
87b22bf7 1147 "
1148 if (GET_CODE (operands[1]) == CONST_INT)
1149 {
25f905c2 1150 if (TARGET_32BIT)
cffb2a26 1151 {
96f57e36 1152 arm_split_constant (MINUS, SImode, NULL_RTX,
1153 INTVAL (operands[1]), operands[0],
e1ba4a27 1154 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1155 DONE;
1156 }
25f905c2 1157 else /* TARGET_THUMB1 */
cffb2a26 1158 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1159 }
cffb2a26 1160 "
1161)
87b22bf7 1162
747b7458 1163(define_insn "thumb1_subsi3_insn"
cffb2a26 1164 [(set (match_operand:SI 0 "register_operand" "=l")
1165 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1166 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1167 "TARGET_THUMB1"
cffb2a26 1168 "sub\\t%0, %1, %2"
747b7458 1169 [(set_attr "length" "2")
1170 (set_attr "conds" "set")])
cffb2a26 1171
25f905c2 1172; ??? Check Thumb-2 split length
a0f94409 1173(define_insn_and_split "*arm_subsi3_insn"
080c0b9a 1174 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
bccb5444 1175 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1176 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
25f905c2 1177 "TARGET_32BIT"
e2348bcb 1178 "@
87b22bf7 1179 rsb%?\\t%0, %2, %1
aaa37ad6 1180 sub%?\\t%0, %1, %2
080c0b9a 1181 sub%?\\t%0, %1, %2
1182 #
87b22bf7 1183 #"
080c0b9a 1184 "&& ((GET_CODE (operands[1]) == CONST_INT
1185 && !const_ok_for_arm (INTVAL (operands[1])))
1186 || (GET_CODE (operands[2]) == CONST_INT
1187 && !const_ok_for_arm (INTVAL (operands[2]))))"
87b22bf7 1188 [(clobber (const_int 0))]
1189 "
96f57e36 1190 arm_split_constant (MINUS, SImode, curr_insn,
1191 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1192 DONE;
cffb2a26 1193 "
080c0b9a 1194 [(set_attr "length" "4,4,4,16,16")
a0f94409 1195 (set_attr "predicable" "yes")]
1196)
1197
1198(define_peephole2
1199 [(match_scratch:SI 3 "r")
372575c7 1200 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1201 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1202 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1203 "TARGET_32BIT
a0f94409 1204 && !const_ok_for_arm (INTVAL (operands[1]))
1205 && const_ok_for_arm (~INTVAL (operands[1]))"
1206 [(set (match_dup 3) (match_dup 1))
1207 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1208 ""
cffb2a26 1209)
b11cae9e 1210
f7fbdd4a 1211(define_insn "*subsi3_compare0"
bd5b4116 1212 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1213 (compare:CC_NOOV
1214 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1215 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1216 (const_int 0)))
9c08d1fa 1217 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1218 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1219 "TARGET_32BIT"
e2348bcb 1220 "@
25f905c2 1221 sub%.\\t%0, %1, %2
1222 rsb%.\\t%0, %2, %1"
cffb2a26 1223 [(set_attr "conds" "set")]
1224)
9c08d1fa 1225
080c0b9a 1226(define_insn "*subsi3_compare"
1227 [(set (reg:CC CC_REGNUM)
1228 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1229 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1230 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1231 (minus:SI (match_dup 1) (match_dup 2)))]
1232 "TARGET_32BIT"
1233 "@
1234 sub%.\\t%0, %1, %2
1235 rsb%.\\t%0, %2, %1"
1236 [(set_attr "conds" "set")]
1237)
1238
25f905c2 1239(define_expand "decscc"
1240 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1241 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1242 (match_operator:SI 2 "arm_comparison_operator"
1243 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1244 "TARGET_32BIT"
1245 ""
1246)
1247
1248(define_insn "*arm_decscc"
cffb2a26 1249 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1250 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1251 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1252 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1253 "TARGET_ARM"
e2348bcb 1254 "@
215b30b3 1255 sub%d2\\t%0, %1, #1
1256 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1257 [(set_attr "conds" "use")
1258 (set_attr "length" "*,8")]
1259)
9c08d1fa 1260
604f3a0a 1261(define_expand "subsf3"
1262 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1263 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1264 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1265 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1266 "
a2cd141b 1267 if (TARGET_MAVERICK)
604f3a0a 1268 {
1269 if (!cirrus_fp_register (operands[1], SFmode))
1270 operands[1] = force_reg (SFmode, operands[1]);
1271 if (!cirrus_fp_register (operands[2], SFmode))
1272 operands[2] = force_reg (SFmode, operands[2]);
1273 }
1274")
1275
604f3a0a 1276(define_expand "subdf3"
1277 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1278 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1279 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1280 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1281 "
a2cd141b 1282 if (TARGET_MAVERICK)
604f3a0a 1283 {
1284 if (!cirrus_fp_register (operands[1], DFmode))
1285 operands[1] = force_reg (DFmode, operands[1]);
1286 if (!cirrus_fp_register (operands[2], DFmode))
1287 operands[2] = force_reg (DFmode, operands[2]);
1288 }
1289")
1290
b11cae9e 1291\f
1292;; Multiplication insns
1293
cffb2a26 1294(define_expand "mulsi3"
1295 [(set (match_operand:SI 0 "s_register_operand" "")
1296 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1297 (match_operand:SI 1 "s_register_operand" "")))]
1298 "TARGET_EITHER"
1299 ""
1300)
1301
9c08d1fa 1302;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1303(define_insn "*arm_mulsi3"
1304 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1305 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1306 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1307 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1308 "mul%?\\t%0, %2, %1"
a2cd141b 1309 [(set_attr "insn" "mul")
0d66636f 1310 (set_attr "predicable" "yes")]
cffb2a26 1311)
1312
58d7d654 1313(define_insn "*arm_mulsi3_v6"
1314 [(set (match_operand:SI 0 "s_register_operand" "=r")
1315 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1316 (match_operand:SI 2 "s_register_operand" "r")))]
1317 "TARGET_32BIT && arm_arch6"
1318 "mul%?\\t%0, %1, %2"
1319 [(set_attr "insn" "mul")
1320 (set_attr "predicable" "yes")]
1321)
1322
215b30b3 1323; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1324; 1 and 2; are the same, because reload will make operand 0 match
1325; operand 1 without realizing that this conflicts with operand 2. We fix
1326; this by adding another alternative to match this case, and then `reload'
1327; it ourselves. This alternative must come first.
cffb2a26 1328(define_insn "*thumb_mulsi3"
1329 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1330 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1331 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1332 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1333 "*
1334 if (which_alternative < 2)
20c4e896 1335 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1336 else
20c4e896 1337 return \"mul\\t%0, %2\";
cffb2a26 1338 "
1339 [(set_attr "length" "4,4,2")
a2cd141b 1340 (set_attr "insn" "mul")]
cffb2a26 1341)
b11cae9e 1342
58d7d654 1343(define_insn "*thumb_mulsi3_v6"
1344 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1345 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1346 (match_operand:SI 2 "register_operand" "l,0,0")))]
1347 "TARGET_THUMB1 && arm_arch6"
1348 "@
1490694c 1349 mul\\t%0, %2
1350 mul\\t%0, %1
58d7d654 1351 mul\\t%0, %1"
1352 [(set_attr "length" "2")
1353 (set_attr "insn" "mul")]
1354)
1355
f7fbdd4a 1356(define_insn "*mulsi3_compare0"
bd5b4116 1357 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1358 (compare:CC_NOOV (mult:SI
1359 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1360 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1361 (const_int 0)))
1362 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1363 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1364 "TARGET_ARM && !arm_arch6"
1365 "mul%.\\t%0, %2, %1"
1366 [(set_attr "conds" "set")
1367 (set_attr "insn" "muls")]
1368)
1369
1370(define_insn "*mulsi3_compare0_v6"
1371 [(set (reg:CC_NOOV CC_REGNUM)
1372 (compare:CC_NOOV (mult:SI
1373 (match_operand:SI 2 "s_register_operand" "r")
1374 (match_operand:SI 1 "s_register_operand" "r"))
1375 (const_int 0)))
1376 (set (match_operand:SI 0 "s_register_operand" "=r")
1377 (mult:SI (match_dup 2) (match_dup 1)))]
1378 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1379 "mul%.\\t%0, %2, %1"
cffb2a26 1380 [(set_attr "conds" "set")
a2cd141b 1381 (set_attr "insn" "muls")]
cffb2a26 1382)
9c08d1fa 1383
f7fbdd4a 1384(define_insn "*mulsi_compare0_scratch"
bd5b4116 1385 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1386 (compare:CC_NOOV (mult:SI
1387 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1388 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1389 (const_int 0)))
1390 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1391 "TARGET_ARM && !arm_arch6"
1392 "mul%.\\t%0, %2, %1"
1393 [(set_attr "conds" "set")
1394 (set_attr "insn" "muls")]
1395)
1396
1397(define_insn "*mulsi_compare0_scratch_v6"
1398 [(set (reg:CC_NOOV CC_REGNUM)
1399 (compare:CC_NOOV (mult:SI
1400 (match_operand:SI 2 "s_register_operand" "r")
1401 (match_operand:SI 1 "s_register_operand" "r"))
1402 (const_int 0)))
1403 (clobber (match_scratch:SI 0 "=r"))]
1404 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1405 "mul%.\\t%0, %2, %1"
cffb2a26 1406 [(set_attr "conds" "set")
a2cd141b 1407 (set_attr "insn" "muls")]
cffb2a26 1408)
9c08d1fa 1409
b11cae9e 1410;; Unnamed templates to match MLA instruction.
1411
f7fbdd4a 1412(define_insn "*mulsi3addsi"
9c08d1fa 1413 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1414 (plus:SI
9c08d1fa 1415 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1416 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1417 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1418 "TARGET_32BIT && !arm_arch6"
1419 "mla%?\\t%0, %2, %1, %3"
1420 [(set_attr "insn" "mla")
1421 (set_attr "predicable" "yes")]
1422)
1423
1424(define_insn "*mulsi3addsi_v6"
1425 [(set (match_operand:SI 0 "s_register_operand" "=r")
1426 (plus:SI
1427 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1428 (match_operand:SI 1 "s_register_operand" "r"))
1429 (match_operand:SI 3 "s_register_operand" "r")))]
1430 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1431 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1432 [(set_attr "insn" "mla")
0d66636f 1433 (set_attr "predicable" "yes")]
1434)
b11cae9e 1435
f7fbdd4a 1436(define_insn "*mulsi3addsi_compare0"
bd5b4116 1437 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1438 (compare:CC_NOOV
1439 (plus:SI (mult:SI
1440 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1441 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1442 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1443 (const_int 0)))
9c08d1fa 1444 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1445 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1446 (match_dup 3)))]
58d7d654 1447 "TARGET_ARM && arm_arch6"
1448 "mla%.\\t%0, %2, %1, %3"
1449 [(set_attr "conds" "set")
1450 (set_attr "insn" "mlas")]
1451)
1452
1453(define_insn "*mulsi3addsi_compare0_v6"
1454 [(set (reg:CC_NOOV CC_REGNUM)
1455 (compare:CC_NOOV
1456 (plus:SI (mult:SI
1457 (match_operand:SI 2 "s_register_operand" "r")
1458 (match_operand:SI 1 "s_register_operand" "r"))
1459 (match_operand:SI 3 "s_register_operand" "r"))
1460 (const_int 0)))
1461 (set (match_operand:SI 0 "s_register_operand" "=r")
1462 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1463 (match_dup 3)))]
1464 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1465 "mla%.\\t%0, %2, %1, %3"
0d66636f 1466 [(set_attr "conds" "set")
a2cd141b 1467 (set_attr "insn" "mlas")]
0d66636f 1468)
9c08d1fa 1469
f7fbdd4a 1470(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1471 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1472 (compare:CC_NOOV
1473 (plus:SI (mult:SI
1474 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1475 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1476 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1477 (const_int 0)))
9c08d1fa 1478 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1479 "TARGET_ARM && !arm_arch6"
1480 "mla%.\\t%0, %2, %1, %3"
1481 [(set_attr "conds" "set")
1482 (set_attr "insn" "mlas")]
1483)
1484
1485(define_insn "*mulsi3addsi_compare0_scratch_v6"
1486 [(set (reg:CC_NOOV CC_REGNUM)
1487 (compare:CC_NOOV
1488 (plus:SI (mult:SI
1489 (match_operand:SI 2 "s_register_operand" "r")
1490 (match_operand:SI 1 "s_register_operand" "r"))
1491 (match_operand:SI 3 "s_register_operand" "r"))
1492 (const_int 0)))
1493 (clobber (match_scratch:SI 0 "=r"))]
1494 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1495 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1496 [(set_attr "conds" "set")
a2cd141b 1497 (set_attr "insn" "mlas")]
cffb2a26 1498)
f7fbdd4a 1499
89545238 1500(define_insn "*mulsi3subsi"
1501 [(set (match_operand:SI 0 "s_register_operand" "=r")
1502 (minus:SI
1503 (match_operand:SI 3 "s_register_operand" "r")
1504 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1505 (match_operand:SI 1 "s_register_operand" "r"))))]
1506 "TARGET_32BIT && arm_arch_thumb2"
1507 "mls%?\\t%0, %2, %1, %3"
1508 [(set_attr "insn" "mla")
1509 (set_attr "predicable" "yes")]
1510)
1511
5cdca009 1512(define_expand "maddsidi4"
1513 [(set (match_operand:DI 0 "s_register_operand" "")
1514 (plus:DI
1515 (mult:DI
1516 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1517 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1518 (match_operand:DI 3 "s_register_operand" "")))]
1519 "TARGET_32BIT && arm_arch3m"
1520 "")
82b85d08 1521
1522(define_insn "*mulsidi3adddi"
fe8dbf85 1523 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1524 (plus:DI
215b30b3 1525 (mult:DI
fe8dbf85 1526 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1527 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1528 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1529 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1530 "smlal%?\\t%Q0, %R0, %3, %2"
1531 [(set_attr "insn" "smlal")
1532 (set_attr "predicable" "yes")]
1533)
1534
1535(define_insn "*mulsidi3adddi_v6"
1536 [(set (match_operand:DI 0 "s_register_operand" "=r")
1537 (plus:DI
1538 (mult:DI
1539 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1540 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1541 (match_operand:DI 1 "s_register_operand" "0")))]
1542 "TARGET_32BIT && arm_arch6"
fe8dbf85 1543 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1544 [(set_attr "insn" "smlal")
0d66636f 1545 (set_attr "predicable" "yes")]
1546)
82b85d08 1547
957788b0 1548;; 32x32->64 widening multiply.
1549;; As with mulsi3, the only difference between the v3-5 and v6+
1550;; versions of these patterns is the requirement that the output not
1551;; overlap the inputs, but that still means we have to have a named
1552;; expander and two different starred insns.
1553
1554(define_expand "mulsidi3"
1555 [(set (match_operand:DI 0 "s_register_operand" "")
1556 (mult:DI
1557 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1558 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1559 "TARGET_32BIT && arm_arch3m"
1560 ""
1561)
1562
1563(define_insn "*mulsidi3_nov6"
f7fbdd4a 1564 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1565 (mult:DI
1566 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1567 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1568 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1569 "smull%?\\t%Q0, %R0, %1, %2"
1570 [(set_attr "insn" "smull")
1571 (set_attr "predicable" "yes")]
1572)
1573
957788b0 1574(define_insn "*mulsidi3_v6"
58d7d654 1575 [(set (match_operand:DI 0 "s_register_operand" "=r")
1576 (mult:DI
1577 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1578 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1579 "TARGET_32BIT && arm_arch6"
97499065 1580 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1581 [(set_attr "insn" "smull")
0d66636f 1582 (set_attr "predicable" "yes")]
1583)
f7fbdd4a 1584
957788b0 1585(define_expand "umulsidi3"
1586 [(set (match_operand:DI 0 "s_register_operand" "")
1587 (mult:DI
1588 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1589 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1590 "TARGET_32BIT && arm_arch3m"
1591 ""
1592)
1593
1594(define_insn "*umulsidi3_nov6"
f7fbdd4a 1595 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1596 (mult:DI
1597 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1598 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1599 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1600 "umull%?\\t%Q0, %R0, %1, %2"
1601 [(set_attr "insn" "umull")
1602 (set_attr "predicable" "yes")]
1603)
1604
957788b0 1605(define_insn "*umulsidi3_v6"
58d7d654 1606 [(set (match_operand:DI 0 "s_register_operand" "=r")
1607 (mult:DI
1608 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1609 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1610 "TARGET_32BIT && arm_arch6"
97499065 1611 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1612 [(set_attr "insn" "umull")
0d66636f 1613 (set_attr "predicable" "yes")]
1614)
b11cae9e 1615
5cdca009 1616(define_expand "umaddsidi4"
1617 [(set (match_operand:DI 0 "s_register_operand" "")
1618 (plus:DI
1619 (mult:DI
1620 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1621 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1622 (match_operand:DI 3 "s_register_operand" "")))]
1623 "TARGET_32BIT && arm_arch3m"
1624 "")
82b85d08 1625
1626(define_insn "*umulsidi3adddi"
8ead09f9 1627 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1628 (plus:DI
215b30b3 1629 (mult:DI
fe8dbf85 1630 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1631 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1632 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1633 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1634 "umlal%?\\t%Q0, %R0, %3, %2"
1635 [(set_attr "insn" "umlal")
1636 (set_attr "predicable" "yes")]
1637)
1638
1639(define_insn "*umulsidi3adddi_v6"
1640 [(set (match_operand:DI 0 "s_register_operand" "=r")
1641 (plus:DI
1642 (mult:DI
1643 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1644 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1645 (match_operand:DI 1 "s_register_operand" "0")))]
1646 "TARGET_32BIT && arm_arch6"
fe8dbf85 1647 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1648 [(set_attr "insn" "umlal")
0d66636f 1649 (set_attr "predicable" "yes")]
1650)
82b85d08 1651
957788b0 1652(define_expand "smulsi3_highpart"
1653 [(parallel
1654 [(set (match_operand:SI 0 "s_register_operand" "")
1655 (truncate:SI
1656 (lshiftrt:DI
1657 (mult:DI
1658 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1659 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1660 (const_int 32))))
1661 (clobber (match_scratch:SI 3 ""))])]
1662 "TARGET_32BIT && arm_arch3m"
1663 ""
1664)
1665
1666(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1667 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1668 (truncate:SI
1669 (lshiftrt:DI
215b30b3 1670 (mult:DI
e5fea38e 1671 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1672 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1673 (const_int 32))))
1674 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1675 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1676 "smull%?\\t%3, %0, %2, %1"
1677 [(set_attr "insn" "smull")
1678 (set_attr "predicable" "yes")]
1679)
1680
957788b0 1681(define_insn "*smulsi3_highpart_v6"
58d7d654 1682 [(set (match_operand:SI 0 "s_register_operand" "=r")
1683 (truncate:SI
1684 (lshiftrt:DI
1685 (mult:DI
1686 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1687 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1688 (const_int 32))))
1689 (clobber (match_scratch:SI 3 "=r"))]
1690 "TARGET_32BIT && arm_arch6"
f082f1c4 1691 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1692 [(set_attr "insn" "smull")
0d66636f 1693 (set_attr "predicable" "yes")]
cffb2a26 1694)
f082f1c4 1695
957788b0 1696(define_expand "umulsi3_highpart"
1697 [(parallel
1698 [(set (match_operand:SI 0 "s_register_operand" "")
1699 (truncate:SI
1700 (lshiftrt:DI
1701 (mult:DI
1702 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1703 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1704 (const_int 32))))
1705 (clobber (match_scratch:SI 3 ""))])]
1706 "TARGET_32BIT && arm_arch3m"
1707 ""
1708)
1709
1710(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1711 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1712 (truncate:SI
1713 (lshiftrt:DI
215b30b3 1714 (mult:DI
e5fea38e 1715 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1716 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1717 (const_int 32))))
1718 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1719 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1720 "umull%?\\t%3, %0, %2, %1"
1721 [(set_attr "insn" "umull")
1722 (set_attr "predicable" "yes")]
1723)
1724
957788b0 1725(define_insn "*umulsi3_highpart_v6"
58d7d654 1726 [(set (match_operand:SI 0 "s_register_operand" "=r")
1727 (truncate:SI
1728 (lshiftrt:DI
1729 (mult:DI
1730 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1731 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1732 (const_int 32))))
1733 (clobber (match_scratch:SI 3 "=r"))]
1734 "TARGET_32BIT && arm_arch6"
f082f1c4 1735 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1736 [(set_attr "insn" "umull")
0d66636f 1737 (set_attr "predicable" "yes")]
cffb2a26 1738)
f082f1c4 1739
331beb1a 1740(define_insn "mulhisi3"
1741 [(set (match_operand:SI 0 "s_register_operand" "=r")
1742 (mult:SI (sign_extend:SI
1743 (match_operand:HI 1 "s_register_operand" "%r"))
1744 (sign_extend:SI
1745 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1746 "TARGET_DSP_MULTIPLY"
61a2d04c 1747 "smulbb%?\\t%0, %1, %2"
a2cd141b 1748 [(set_attr "insn" "smulxy")
fec538d9 1749 (set_attr "predicable" "yes")]
1750)
1751
1752(define_insn "*mulhisi3tb"
1753 [(set (match_operand:SI 0 "s_register_operand" "=r")
1754 (mult:SI (ashiftrt:SI
1755 (match_operand:SI 1 "s_register_operand" "r")
1756 (const_int 16))
1757 (sign_extend:SI
1758 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1759 "TARGET_DSP_MULTIPLY"
fec538d9 1760 "smultb%?\\t%0, %1, %2"
a2cd141b 1761 [(set_attr "insn" "smulxy")
fec538d9 1762 (set_attr "predicable" "yes")]
1763)
1764
1765(define_insn "*mulhisi3bt"
1766 [(set (match_operand:SI 0 "s_register_operand" "=r")
1767 (mult:SI (sign_extend:SI
1768 (match_operand:HI 1 "s_register_operand" "r"))
1769 (ashiftrt:SI
1770 (match_operand:SI 2 "s_register_operand" "r")
1771 (const_int 16))))]
25f905c2 1772 "TARGET_DSP_MULTIPLY"
fec538d9 1773 "smulbt%?\\t%0, %1, %2"
a2cd141b 1774 [(set_attr "insn" "smulxy")
fec538d9 1775 (set_attr "predicable" "yes")]
1776)
1777
1778(define_insn "*mulhisi3tt"
1779 [(set (match_operand:SI 0 "s_register_operand" "=r")
1780 (mult:SI (ashiftrt:SI
1781 (match_operand:SI 1 "s_register_operand" "r")
1782 (const_int 16))
1783 (ashiftrt:SI
1784 (match_operand:SI 2 "s_register_operand" "r")
1785 (const_int 16))))]
25f905c2 1786 "TARGET_DSP_MULTIPLY"
fec538d9 1787 "smultt%?\\t%0, %1, %2"
a2cd141b 1788 [(set_attr "insn" "smulxy")
fec538d9 1789 (set_attr "predicable" "yes")]
331beb1a 1790)
1791
5cdca009 1792(define_insn "maddhisi4"
331beb1a 1793 [(set (match_operand:SI 0 "s_register_operand" "=r")
5cdca009 1794 (plus:SI (match_operand:SI 3 "s_register_operand" "r")
331beb1a 1795 (mult:SI (sign_extend:SI
5cdca009 1796 (match_operand:HI 1 "s_register_operand" "%r"))
331beb1a 1797 (sign_extend:SI
5cdca009 1798 (match_operand:HI 2 "s_register_operand" "r")))))]
25f905c2 1799 "TARGET_DSP_MULTIPLY"
5cdca009 1800 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1801 [(set_attr "insn" "smlaxy")
fec538d9 1802 (set_attr "predicable" "yes")]
331beb1a 1803)
1804
5cdca009 1805(define_insn "*maddhidi4"
331beb1a 1806 [(set (match_operand:DI 0 "s_register_operand" "=r")
1807 (plus:DI
5cdca009 1808 (match_operand:DI 3 "s_register_operand" "0")
331beb1a 1809 (mult:DI (sign_extend:DI
5cdca009 1810 (match_operand:HI 1 "s_register_operand" "%r"))
331beb1a 1811 (sign_extend:DI
5cdca009 1812 (match_operand:HI 2 "s_register_operand" "r")))))]
25f905c2 1813 "TARGET_DSP_MULTIPLY"
5cdca009 1814 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1815 [(set_attr "insn" "smlalxy")
fec538d9 1816 (set_attr "predicable" "yes")])
331beb1a 1817
604f3a0a 1818(define_expand "mulsf3"
1819 [(set (match_operand:SF 0 "s_register_operand" "")
1820 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1821 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1822 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1823 "
a2cd141b 1824 if (TARGET_MAVERICK
604f3a0a 1825 && !cirrus_fp_register (operands[2], SFmode))
1826 operands[2] = force_reg (SFmode, operands[2]);
1827")
1828
604f3a0a 1829(define_expand "muldf3"
1830 [(set (match_operand:DF 0 "s_register_operand" "")
1831 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1832 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1833 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1834 "
a2cd141b 1835 if (TARGET_MAVERICK
604f3a0a 1836 && !cirrus_fp_register (operands[2], DFmode))
1837 operands[2] = force_reg (DFmode, operands[2]);
1838")
b11cae9e 1839\f
1840;; Division insns
1841
7db9af5d 1842(define_expand "divsf3"
1843 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1844 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1845 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1846 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1847 "")
9c08d1fa 1848
7db9af5d 1849(define_expand "divdf3"
1850 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1851 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1852 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1853 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1854 "")
b11cae9e 1855\f
1856;; Modulo insns
1857
7db9af5d 1858(define_expand "modsf3"
1859 [(set (match_operand:SF 0 "s_register_operand" "")
1860 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1861 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1862 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1863 "")
9c08d1fa 1864
7db9af5d 1865(define_expand "moddf3"
1866 [(set (match_operand:DF 0 "s_register_operand" "")
1867 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1868 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1869 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1870 "")
b11cae9e 1871\f
1872;; Boolean and,ior,xor insns
1873
f6ebffac 1874;; Split up double word logical operations
1875
1876;; Split up simple DImode logical operations. Simply perform the logical
1877;; operation on the upper and lower halves of the registers.
1878(define_split
1879 [(set (match_operand:DI 0 "s_register_operand" "")
1880 (match_operator:DI 6 "logical_binary_operator"
1881 [(match_operand:DI 1 "s_register_operand" "")
1882 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1883 "TARGET_32BIT && reload_completed
e2669ea7 1884 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1885 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1886 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1887 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1888 "
215b30b3 1889 {
1890 operands[3] = gen_highpart (SImode, operands[0]);
1891 operands[0] = gen_lowpart (SImode, operands[0]);
1892 operands[4] = gen_highpart (SImode, operands[1]);
1893 operands[1] = gen_lowpart (SImode, operands[1]);
1894 operands[5] = gen_highpart (SImode, operands[2]);
1895 operands[2] = gen_lowpart (SImode, operands[2]);
1896 }"
1897)
f6ebffac 1898
f6ebffac 1899(define_split
1900 [(set (match_operand:DI 0 "s_register_operand" "")
1901 (match_operator:DI 6 "logical_binary_operator"
1902 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1903 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1904 "TARGET_32BIT && reload_completed"
f6ebffac 1905 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1906 (set (match_dup 3) (match_op_dup:SI 6
1907 [(ashiftrt:SI (match_dup 2) (const_int 31))
1908 (match_dup 4)]))]
1909 "
215b30b3 1910 {
1911 operands[3] = gen_highpart (SImode, operands[0]);
1912 operands[0] = gen_lowpart (SImode, operands[0]);
1913 operands[4] = gen_highpart (SImode, operands[1]);
1914 operands[1] = gen_lowpart (SImode, operands[1]);
1915 operands[5] = gen_highpart (SImode, operands[2]);
1916 operands[2] = gen_lowpart (SImode, operands[2]);
1917 }"
1918)
f6ebffac 1919
f6ebffac 1920;; The zero extend of operand 2 means we can just copy the high part of
1921;; operand1 into operand0.
1922(define_split
1923 [(set (match_operand:DI 0 "s_register_operand" "")
1924 (ior:DI
1925 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1926 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1927 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1928 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1929 (set (match_dup 3) (match_dup 4))]
1930 "
215b30b3 1931 {
1932 operands[4] = gen_highpart (SImode, operands[1]);
1933 operands[3] = gen_highpart (SImode, operands[0]);
1934 operands[0] = gen_lowpart (SImode, operands[0]);
1935 operands[1] = gen_lowpart (SImode, operands[1]);
1936 }"
1937)
f6ebffac 1938
1939;; The zero extend of operand 2 means we can just copy the high part of
1940;; operand1 into operand0.
1941(define_split
1942 [(set (match_operand:DI 0 "s_register_operand" "")
1943 (xor:DI
1944 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1945 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1946 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1947 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1948 (set (match_dup 3) (match_dup 4))]
1949 "
215b30b3 1950 {
1951 operands[4] = gen_highpart (SImode, operands[1]);
1952 operands[3] = gen_highpart (SImode, operands[0]);
1953 operands[0] = gen_lowpart (SImode, operands[0]);
1954 operands[1] = gen_lowpart (SImode, operands[1]);
1955 }"
1956)
f6ebffac 1957
e2669ea7 1958(define_expand "anddi3"
1959 [(set (match_operand:DI 0 "s_register_operand" "")
1960 (and:DI (match_operand:DI 1 "s_register_operand" "")
1961 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1962 "TARGET_32BIT"
1963 ""
1964)
1965
1966(define_insn "*anddi3_insn"
cffb2a26 1967 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1968 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1969 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 1970 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 1971 "#"
215b30b3 1972 [(set_attr "length" "8")]
1973)
b11cae9e 1974
a0f94409 1975(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1976 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1977 (and:DI (zero_extend:DI
1978 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1979 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1980 "TARGET_32BIT"
f6ebffac 1981 "#"
25f905c2 1982 "TARGET_32BIT && reload_completed"
a0f94409 1983 ; The zero extend of operand 2 clears the high word of the output
1984 ; operand.
1985 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1986 (set (match_dup 3) (const_int 0))]
1987 "
1988 {
1989 operands[3] = gen_highpart (SImode, operands[0]);
1990 operands[0] = gen_lowpart (SImode, operands[0]);
1991 operands[1] = gen_lowpart (SImode, operands[1]);
1992 }"
215b30b3 1993 [(set_attr "length" "8")]
1994)
b11cae9e 1995
f7fbdd4a 1996(define_insn "*anddi_sesdi_di"
cffb2a26 1997 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1998 (and:DI (sign_extend:DI
1999 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2000 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2001 "TARGET_32BIT"
f6ebffac 2002 "#"
cffb2a26 2003 [(set_attr "length" "8")]
2004)
b11cae9e 2005
87b22bf7 2006(define_expand "andsi3"
cffb2a26 2007 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2008 (and:SI (match_operand:SI 1 "s_register_operand" "")
2009 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2010 "TARGET_EITHER"
87b22bf7 2011 "
25f905c2 2012 if (TARGET_32BIT)
87b22bf7 2013 {
cffb2a26 2014 if (GET_CODE (operands[2]) == CONST_INT)
2015 {
47b5b27b 2016 if (INTVAL (operands[2]) == 255 && arm_arch6)
2017 {
2018 operands[1] = convert_to_mode (QImode, operands[1], 1);
2019 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2020 operands[1]));
2021 }
2022 else
2023 arm_split_constant (AND, SImode, NULL_RTX,
2024 INTVAL (operands[2]), operands[0],
2025 operands[1],
2026 optimize && can_create_pseudo_p ());
615caa51 2027
cffb2a26 2028 DONE;
2029 }
87b22bf7 2030 }
25f905c2 2031 else /* TARGET_THUMB1 */
cffb2a26 2032 {
2033 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2034 {
2035 rtx tmp = force_reg (SImode, operands[2]);
2036 if (rtx_equal_p (operands[0], operands[1]))
2037 operands[2] = tmp;
2038 else
2039 {
2040 operands[2] = operands[1];
2041 operands[1] = tmp;
2042 }
2043 }
cffb2a26 2044 else
2045 {
2046 int i;
2047
215b30b3 2048 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2049 {
215b30b3 2050 operands[2] = force_reg (SImode,
2051 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2052
747b7458 2053 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2054
2055 DONE;
2056 }
87b22bf7 2057
cffb2a26 2058 for (i = 9; i <= 31; i++)
2059 {
2060 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2061 {
2062 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2063 const0_rtx));
2064 DONE;
2065 }
215b30b3 2066 else if ((((HOST_WIDE_INT) 1) << i) - 1
2067 == ~INTVAL (operands[2]))
cffb2a26 2068 {
2069 rtx shift = GEN_INT (i);
2070 rtx reg = gen_reg_rtx (SImode);
2071
2072 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2073 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2074
2075 DONE;
2076 }
2077 }
2078
2079 operands[2] = force_reg (SImode, operands[2]);
2080 }
215b30b3 2081 }
2082 "
cffb2a26 2083)
2084
25f905c2 2085; ??? Check split length for Thumb-2
a0f94409 2086(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2087 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2088 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2089 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2090 "TARGET_32BIT"
5565501b 2091 "@
2092 and%?\\t%0, %1, %2
87b22bf7 2093 bic%?\\t%0, %1, #%B2
2094 #"
25f905c2 2095 "TARGET_32BIT
a0f94409 2096 && GET_CODE (operands[2]) == CONST_INT
2097 && !(const_ok_for_arm (INTVAL (operands[2]))
2098 || const_ok_for_arm (~INTVAL (operands[2])))"
2099 [(clobber (const_int 0))]
2100 "
96f57e36 2101 arm_split_constant (AND, SImode, curr_insn,
2102 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2103 DONE;
2104 "
0d66636f 2105 [(set_attr "length" "4,4,16")
2106 (set_attr "predicable" "yes")]
cffb2a26 2107)
2108
25f905c2 2109(define_insn "*thumb1_andsi3_insn"
cffb2a26 2110 [(set (match_operand:SI 0 "register_operand" "=l")
2111 (and:SI (match_operand:SI 1 "register_operand" "%0")
2112 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2113 "TARGET_THUMB1"
747b7458 2114 "and\\t%0, %2"
2115 [(set_attr "length" "2")
2116 (set_attr "conds" "set")])
87b22bf7 2117
f7fbdd4a 2118(define_insn "*andsi3_compare0"
bd5b4116 2119 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2120 (compare:CC_NOOV
2121 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2122 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2123 (const_int 0)))
cffb2a26 2124 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2125 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2126 "TARGET_32BIT"
5565501b 2127 "@
25f905c2 2128 and%.\\t%0, %1, %2
2129 bic%.\\t%0, %1, #%B2"
cffb2a26 2130 [(set_attr "conds" "set")]
2131)
9c08d1fa 2132
f7fbdd4a 2133(define_insn "*andsi3_compare0_scratch"
bd5b4116 2134 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2135 (compare:CC_NOOV
2136 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2137 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2138 (const_int 0)))
dd193d7c 2139 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2140 "TARGET_32BIT"
5565501b 2141 "@
2142 tst%?\\t%0, %1
25f905c2 2143 bic%.\\t%2, %0, #%B1"
0d66636f 2144 [(set_attr "conds" "set")]
2145)
9c08d1fa 2146
f7fbdd4a 2147(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2148 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2149 (compare:CC_NOOV (zero_extract:SI
2150 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2151 (match_operand 1 "const_int_operand" "n")
2152 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2153 (const_int 0)))]
25f905c2 2154 "TARGET_32BIT
cffb2a26 2155 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2156 && INTVAL (operands[1]) > 0
2157 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2158 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2159 "*
5c49a439 2160 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2161 << INTVAL (operands[2]));
40dbec34 2162 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2163 return \"\";
0d66636f 2164 "
2165 [(set_attr "conds" "set")]
2166)
9c08d1fa 2167
f4462328 2168(define_insn_and_split "*ne_zeroextractsi"
c4034607 2169 [(set (match_operand:SI 0 "s_register_operand" "=r")
2170 (ne:SI (zero_extract:SI
2171 (match_operand:SI 1 "s_register_operand" "r")
2172 (match_operand:SI 2 "const_int_operand" "n")
2173 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2174 (const_int 0)))
2175 (clobber (reg:CC CC_REGNUM))]
25f905c2 2176 "TARGET_32BIT
cffb2a26 2177 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2178 && INTVAL (operands[2]) > 0
2179 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2180 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2181 "#"
25f905c2 2182 "TARGET_32BIT
f4462328 2183 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2184 && INTVAL (operands[2]) > 0
2185 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2186 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2187 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2188 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2189 (const_int 0)))
2190 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2191 (set (match_dup 0)
2192 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2193 (match_dup 0) (const_int 1)))]
2194 "
2195 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2196 << INTVAL (operands[3]));
2197 "
2198 [(set_attr "conds" "clob")
25f905c2 2199 (set (attr "length")
2200 (if_then_else (eq_attr "is_thumb" "yes")
2201 (const_int 12)
2202 (const_int 8)))]
f4462328 2203)
2204
2205(define_insn_and_split "*ne_zeroextractsi_shifted"
2206 [(set (match_operand:SI 0 "s_register_operand" "=r")
2207 (ne:SI (zero_extract:SI
2208 (match_operand:SI 1 "s_register_operand" "r")
2209 (match_operand:SI 2 "const_int_operand" "n")
2210 (const_int 0))
2211 (const_int 0)))
2212 (clobber (reg:CC CC_REGNUM))]
2213 "TARGET_ARM"
2214 "#"
2215 "TARGET_ARM"
2216 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2217 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2218 (const_int 0)))
2219 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2220 (set (match_dup 0)
2221 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2222 (match_dup 0) (const_int 1)))]
2223 "
2224 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2225 "
2226 [(set_attr "conds" "clob")
2227 (set_attr "length" "8")]
2228)
2229
2230(define_insn_and_split "*ite_ne_zeroextractsi"
2231 [(set (match_operand:SI 0 "s_register_operand" "=r")
2232 (if_then_else:SI (ne (zero_extract:SI
2233 (match_operand:SI 1 "s_register_operand" "r")
2234 (match_operand:SI 2 "const_int_operand" "n")
2235 (match_operand:SI 3 "const_int_operand" "n"))
2236 (const_int 0))
2237 (match_operand:SI 4 "arm_not_operand" "rIK")
2238 (const_int 0)))
2239 (clobber (reg:CC CC_REGNUM))]
2240 "TARGET_ARM
2241 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2242 && INTVAL (operands[2]) > 0
2243 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2244 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2245 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2246 "#"
2247 "TARGET_ARM
2248 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2249 && INTVAL (operands[2]) > 0
2250 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2251 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2252 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2253 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2254 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2255 (const_int 0)))
2256 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2257 (set (match_dup 0)
2258 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2259 (match_dup 0) (match_dup 4)))]
2260 "
c4034607 2261 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2262 << INTVAL (operands[3]));
2263 "
2264 [(set_attr "conds" "clob")
2265 (set_attr "length" "8")]
2266)
2267
2268(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2269 [(set (match_operand:SI 0 "s_register_operand" "=r")
2270 (if_then_else:SI (ne (zero_extract:SI
2271 (match_operand:SI 1 "s_register_operand" "r")
2272 (match_operand:SI 2 "const_int_operand" "n")
2273 (const_int 0))
2274 (const_int 0))
2275 (match_operand:SI 3 "arm_not_operand" "rIK")
2276 (const_int 0)))
2277 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2278 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2279 "#"
f8d7bf2f 2280 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2281 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2282 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2283 (const_int 0)))
2284 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2285 (set (match_dup 0)
2286 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2287 (match_dup 0) (match_dup 3)))]
2288 "
2289 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2290 "
2291 [(set_attr "conds" "clob")
215b30b3 2292 (set_attr "length" "8")]
2293)
9c08d1fa 2294
58d6528b 2295(define_split
2296 [(set (match_operand:SI 0 "s_register_operand" "")
2297 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2298 (match_operand:SI 2 "const_int_operand" "")
2299 (match_operand:SI 3 "const_int_operand" "")))
2300 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2301 "TARGET_THUMB1"
58d6528b 2302 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2303 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2304 "{
2305 HOST_WIDE_INT temp = INTVAL (operands[2]);
2306
2307 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2308 operands[3] = GEN_INT (32 - temp);
2309 }"
2310)
2311
25f905c2 2312;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2313(define_split
2314 [(set (match_operand:SI 0 "s_register_operand" "")
2315 (match_operator:SI 1 "shiftable_operator"
2316 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2317 (match_operand:SI 3 "const_int_operand" "")
2318 (match_operand:SI 4 "const_int_operand" ""))
2319 (match_operand:SI 5 "s_register_operand" "")]))
2320 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2321 "TARGET_ARM"
2322 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2323 (set (match_dup 0)
2324 (match_op_dup 1
2325 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2326 (match_dup 5)]))]
2327 "{
2328 HOST_WIDE_INT temp = INTVAL (operands[3]);
2329
2330 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2331 operands[4] = GEN_INT (32 - temp);
2332 }"
2333)
2334
58d6528b 2335(define_split
2336 [(set (match_operand:SI 0 "s_register_operand" "")
2337 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2338 (match_operand:SI 2 "const_int_operand" "")
2339 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2340 "TARGET_THUMB1"
58d6528b 2341 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2342 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2343 "{
2344 HOST_WIDE_INT temp = INTVAL (operands[2]);
2345
2346 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2347 operands[3] = GEN_INT (32 - temp);
2348 }"
2349)
2350
d7863cfe 2351(define_split
2352 [(set (match_operand:SI 0 "s_register_operand" "")
2353 (match_operator:SI 1 "shiftable_operator"
2354 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2355 (match_operand:SI 3 "const_int_operand" "")
2356 (match_operand:SI 4 "const_int_operand" ""))
2357 (match_operand:SI 5 "s_register_operand" "")]))
2358 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2359 "TARGET_ARM"
2360 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2361 (set (match_dup 0)
2362 (match_op_dup 1
2363 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2364 (match_dup 5)]))]
2365 "{
2366 HOST_WIDE_INT temp = INTVAL (operands[3]);
2367
2368 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2369 operands[4] = GEN_INT (32 - temp);
2370 }"
2371)
2372
a42059fd 2373;;; ??? This pattern is bogus. If operand3 has bits outside the range
2374;;; represented by the bitfield, then this will produce incorrect results.
2375;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2376;;; which have a real bit-field insert instruction, the truncation happens
2377;;; in the bit-field insert instruction itself. Since arm does not have a
2378;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2379;;; the value before we insert. This loses some of the advantage of having
2380;;; this insv pattern, so this pattern needs to be reevalutated.
2381
8a18b90c 2382(define_expand "insv"
2383 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2384 (match_operand:SI 1 "general_operand" "")
2385 (match_operand:SI 2 "general_operand" ""))
19335226 2386 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2387 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2388 "
215b30b3 2389 {
2390 int start_bit = INTVAL (operands[2]);
2391 int width = INTVAL (operands[1]);
2392 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2393 rtx target, subtarget;
2394
8b054d5a 2395 if (arm_arch_thumb2)
2396 {
2397 bool use_bfi = TRUE;
2398
2399 if (GET_CODE (operands[3]) == CONST_INT)
2400 {
2401 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2402
2403 if (val == 0)
2404 {
2405 emit_insn (gen_insv_zero (operands[0], operands[1],
2406 operands[2]));
2407 DONE;
2408 }
2409
2410 /* See if the set can be done with a single orr instruction. */
2411 if (val == mask && const_ok_for_arm (val << start_bit))
2412 use_bfi = FALSE;
2413 }
2414
2415 if (use_bfi)
2416 {
2417 if (GET_CODE (operands[3]) != REG)
2418 operands[3] = force_reg (SImode, operands[3]);
2419
2420 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2421 operands[3]));
2422 DONE;
2423 }
2424 }
2425
3f8fde42 2426 target = copy_rtx (operands[0]);
215b30b3 2427 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2428 subreg as the final target. */
2429 if (GET_CODE (target) == SUBREG)
2430 {
2431 subtarget = gen_reg_rtx (SImode);
2432 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2433 < GET_MODE_SIZE (SImode))
2434 target = SUBREG_REG (target);
2435 }
2436 else
2437 subtarget = target;
8a18b90c 2438
215b30b3 2439 if (GET_CODE (operands[3]) == CONST_INT)
2440 {
2441 /* Since we are inserting a known constant, we may be able to
2442 reduce the number of bits that we have to clear so that
2443 the mask becomes simple. */
2444 /* ??? This code does not check to see if the new mask is actually
2445 simpler. It may not be. */
2446 rtx op1 = gen_reg_rtx (SImode);
2447 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2448 start of this pattern. */
2449 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2450 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2451
c5b3a71b 2452 emit_insn (gen_andsi3 (op1, operands[0],
2453 gen_int_mode (~mask2, SImode)));
215b30b3 2454 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2455 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2456 }
2457 else if (start_bit == 0
2458 && !(const_ok_for_arm (mask)
2459 || const_ok_for_arm (~mask)))
2460 {
2461 /* A Trick, since we are setting the bottom bits in the word,
2462 we can shift operand[3] up, operand[0] down, OR them together
2463 and rotate the result back again. This takes 3 insns, and
5910bb95 2464 the third might be mergeable into another op. */
215b30b3 2465 /* The shift up copes with the possibility that operand[3] is
2466 wider than the bitfield. */
2467 rtx op0 = gen_reg_rtx (SImode);
2468 rtx op1 = gen_reg_rtx (SImode);
2469
2470 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2471 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2472 emit_insn (gen_iorsi3 (op1, op1, op0));
2473 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2474 }
2475 else if ((width + start_bit == 32)
2476 && !(const_ok_for_arm (mask)
2477 || const_ok_for_arm (~mask)))
2478 {
2479 /* Similar trick, but slightly less efficient. */
8a18b90c 2480
215b30b3 2481 rtx op0 = gen_reg_rtx (SImode);
2482 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2483
215b30b3 2484 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2485 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2486 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2487 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2488 }
2489 else
2490 {
c5b3a71b 2491 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2492 rtx op1 = gen_reg_rtx (SImode);
2493 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2494
215b30b3 2495 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2496 {
2497 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2498
215b30b3 2499 emit_insn (gen_movsi (tmp, op0));
2500 op0 = tmp;
2501 }
8a18b90c 2502
215b30b3 2503 /* Mask out any bits in operand[3] that are not needed. */
2504 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2505
215b30b3 2506 if (GET_CODE (op0) == CONST_INT
2507 && (const_ok_for_arm (mask << start_bit)
2508 || const_ok_for_arm (~(mask << start_bit))))
2509 {
c5b3a71b 2510 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2511 emit_insn (gen_andsi3 (op2, operands[0], op0));
2512 }
2513 else
2514 {
2515 if (GET_CODE (op0) == CONST_INT)
2516 {
2517 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2518
215b30b3 2519 emit_insn (gen_movsi (tmp, op0));
2520 op0 = tmp;
2521 }
2522
2523 if (start_bit != 0)
2524 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2525
215b30b3 2526 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2527 }
8a18b90c 2528
215b30b3 2529 if (start_bit != 0)
2530 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2531
215b30b3 2532 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2533 }
f082f1c4 2534
215b30b3 2535 if (subtarget != target)
2536 {
2537 /* If TARGET is still a SUBREG, then it must be wider than a word,
2538 so we must be careful only to set the subword we were asked to. */
2539 if (GET_CODE (target) == SUBREG)
2540 emit_move_insn (target, subtarget);
2541 else
2542 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2543 }
8a18b90c 2544
215b30b3 2545 DONE;
2546 }"
2547)
8a18b90c 2548
8b054d5a 2549(define_insn "insv_zero"
2550 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2551 (match_operand:SI 1 "const_int_operand" "M")
2552 (match_operand:SI 2 "const_int_operand" "M"))
2553 (const_int 0))]
2554 "arm_arch_thumb2"
2555 "bfc%?\t%0, %2, %1"
2556 [(set_attr "length" "4")
2557 (set_attr "predicable" "yes")]
2558)
2559
2560(define_insn "insv_t2"
2561 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2562 (match_operand:SI 1 "const_int_operand" "M")
2563 (match_operand:SI 2 "const_int_operand" "M"))
2564 (match_operand:SI 3 "s_register_operand" "r"))]
2565 "arm_arch_thumb2"
2566 "bfi%?\t%0, %3, %2, %1"
2567 [(set_attr "length" "4")
2568 (set_attr "predicable" "yes")]
2569)
2570
215b30b3 2571; constants for op 2 will never be given to these patterns.
a0f94409 2572(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2573 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2574 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2575 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2576 "TARGET_32BIT"
f6ebffac 2577 "#"
e2669ea7 2578 "TARGET_32BIT && reload_completed
2579 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2580 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2581 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2582 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2583 "
2584 {
2585 operands[3] = gen_highpart (SImode, operands[0]);
2586 operands[0] = gen_lowpart (SImode, operands[0]);
2587 operands[4] = gen_highpart (SImode, operands[1]);
2588 operands[1] = gen_lowpart (SImode, operands[1]);
2589 operands[5] = gen_highpart (SImode, operands[2]);
2590 operands[2] = gen_lowpart (SImode, operands[2]);
2591 }"
0d66636f 2592 [(set_attr "length" "8")
2593 (set_attr "predicable" "yes")]
2594)
9c08d1fa 2595
a0f94409 2596(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2597 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2598 (and:DI (not:DI (zero_extend:DI
2599 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2600 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2601 "TARGET_32BIT"
e2348bcb 2602 "@
97499065 2603 bic%?\\t%Q0, %Q1, %2
f6ebffac 2604 #"
a0f94409 2605 ; (not (zero_extend ...)) allows us to just copy the high word from
2606 ; operand1 to operand0.
25f905c2 2607 "TARGET_32BIT
a0f94409 2608 && reload_completed
2609 && operands[0] != operands[1]"
5a097f7d 2610 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2611 (set (match_dup 3) (match_dup 4))]
2612 "
2613 {
2614 operands[3] = gen_highpart (SImode, operands[0]);
2615 operands[0] = gen_lowpart (SImode, operands[0]);
2616 operands[4] = gen_highpart (SImode, operands[1]);
2617 operands[1] = gen_lowpart (SImode, operands[1]);
2618 }"
0d66636f 2619 [(set_attr "length" "4,8")
2620 (set_attr "predicable" "yes")]
2621)
9c08d1fa 2622
a0f94409 2623(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2624 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2625 (and:DI (not:DI (sign_extend:DI
2626 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2627 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2628 "TARGET_32BIT"
f6ebffac 2629 "#"
25f905c2 2630 "TARGET_32BIT && reload_completed"
5a097f7d 2631 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2632 (set (match_dup 3) (and:SI (not:SI
2633 (ashiftrt:SI (match_dup 2) (const_int 31)))
2634 (match_dup 4)))]
2635 "
2636 {
2637 operands[3] = gen_highpart (SImode, operands[0]);
2638 operands[0] = gen_lowpart (SImode, operands[0]);
2639 operands[4] = gen_highpart (SImode, operands[1]);
2640 operands[1] = gen_lowpart (SImode, operands[1]);
2641 }"
0d66636f 2642 [(set_attr "length" "8")
2643 (set_attr "predicable" "yes")]
2644)
9c08d1fa 2645
8a18b90c 2646(define_insn "andsi_notsi_si"
9c08d1fa 2647 [(set (match_operand:SI 0 "s_register_operand" "=r")
2648 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2649 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2650 "TARGET_32BIT"
0d66636f 2651 "bic%?\\t%0, %1, %2"
2652 [(set_attr "predicable" "yes")]
2653)
b11cae9e 2654
747b7458 2655(define_insn "thumb1_bicsi3"
cffb2a26 2656 [(set (match_operand:SI 0 "register_operand" "=l")
2657 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2658 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2659 "TARGET_THUMB1"
747b7458 2660 "bic\\t%0, %1"
2661 [(set_attr "length" "2")
2662 (set_attr "conds" "set")])
cffb2a26 2663
8a18b90c 2664(define_insn "andsi_not_shiftsi_si"
a2cd141b 2665 [(set (match_operand:SI 0 "s_register_operand" "=r")
2666 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2667 [(match_operand:SI 2 "s_register_operand" "r")
2668 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2669 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2670 "TARGET_ARM"
6c4c2133 2671 "bic%?\\t%0, %1, %2%S4"
344495ea 2672 [(set_attr "predicable" "yes")
331beb1a 2673 (set_attr "shift" "2")
a2cd141b 2674 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2675 (const_string "alu_shift")
2676 (const_string "alu_shift_reg")))]
6c4c2133 2677)
8a18b90c 2678
f7fbdd4a 2679(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2680 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2681 (compare:CC_NOOV
2682 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2683 (match_operand:SI 1 "s_register_operand" "r"))
2684 (const_int 0)))
9c08d1fa 2685 (set (match_operand:SI 0 "s_register_operand" "=r")
2686 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2687 "TARGET_32BIT"
2688 "bic%.\\t%0, %1, %2"
0d66636f 2689 [(set_attr "conds" "set")]
2690)
9c08d1fa 2691
f7fbdd4a 2692(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2693 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2694 (compare:CC_NOOV
2695 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2696 (match_operand:SI 1 "s_register_operand" "r"))
2697 (const_int 0)))
9c08d1fa 2698 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2699 "TARGET_32BIT"
2700 "bic%.\\t%0, %1, %2"
0d66636f 2701 [(set_attr "conds" "set")]
2702)
9c08d1fa 2703
e2669ea7 2704(define_expand "iordi3"
2705 [(set (match_operand:DI 0 "s_register_operand" "")
2706 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2707 (match_operand:DI 2 "neon_logic_op2" "")))]
2708 "TARGET_32BIT"
2709 ""
2710)
2711
2712(define_insn "*iordi3_insn"
cffb2a26 2713 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2714 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2715 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2716 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2717 "#"
0d66636f 2718 [(set_attr "length" "8")
2719 (set_attr "predicable" "yes")]
cffb2a26 2720)
9c08d1fa 2721
f7fbdd4a 2722(define_insn "*iordi_zesidi_di"
9c08d1fa 2723 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2724 (ior:DI (zero_extend:DI
2725 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2726 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2727 "TARGET_32BIT"
e2348bcb 2728 "@
97499065 2729 orr%?\\t%Q0, %Q1, %2
f6ebffac 2730 #"
0d66636f 2731 [(set_attr "length" "4,8")
2732 (set_attr "predicable" "yes")]
cffb2a26 2733)
9c08d1fa 2734
f7fbdd4a 2735(define_insn "*iordi_sesidi_di"
9c08d1fa 2736 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2737 (ior:DI (sign_extend:DI
2738 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2739 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2740 "TARGET_32BIT"
f6ebffac 2741 "#"
0d66636f 2742 [(set_attr "length" "8")
2743 (set_attr "predicable" "yes")]
cffb2a26 2744)
9c08d1fa 2745
87b22bf7 2746(define_expand "iorsi3"
cffb2a26 2747 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2748 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2749 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2750 "TARGET_EITHER"
87b22bf7 2751 "
2752 if (GET_CODE (operands[2]) == CONST_INT)
2753 {
25f905c2 2754 if (TARGET_32BIT)
cffb2a26 2755 {
96f57e36 2756 arm_split_constant (IOR, SImode, NULL_RTX,
2757 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2758 optimize && can_create_pseudo_p ());
cffb2a26 2759 DONE;
2760 }
25f905c2 2761 else /* TARGET_THUMB1 */
923ffadb 2762 {
2763 rtx tmp = force_reg (SImode, operands[2]);
2764 if (rtx_equal_p (operands[0], operands[1]))
2765 operands[2] = tmp;
2766 else
2767 {
2768 operands[2] = operands[1];
2769 operands[1] = tmp;
2770 }
2771 }
87b22bf7 2772 }
cffb2a26 2773 "
2774)
87b22bf7 2775
d5d4dc8d 2776(define_insn_and_split "*iorsi3_insn"
2777 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2778 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2779 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2780 "TARGET_32BIT"
87b22bf7 2781 "@
2782 orr%?\\t%0, %1, %2
d5d4dc8d 2783 orn%?\\t%0, %1, #%B2
87b22bf7 2784 #"
d5d4dc8d 2785 "TARGET_32BIT
a0f94409 2786 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2787 && !(const_ok_for_arm (INTVAL (operands[2]))
2788 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2789 [(clobber (const_int 0))]
d5d4dc8d 2790{
96f57e36 2791 arm_split_constant (IOR, SImode, curr_insn,
2792 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2793 DONE;
d5d4dc8d 2794}
2795 [(set_attr "length" "4,4,16")
2796 (set_attr "arch" "32,t2,32")
2797 (set_attr "predicable" "yes")])
cffb2a26 2798
747b7458 2799(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2800 [(set (match_operand:SI 0 "register_operand" "=l")
2801 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2802 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2803 "TARGET_THUMB1"
747b7458 2804 "orr\\t%0, %2"
2805 [(set_attr "length" "2")
2806 (set_attr "conds" "set")])
9c08d1fa 2807
a0f94409 2808(define_peephole2
2809 [(match_scratch:SI 3 "r")
372575c7 2810 (set (match_operand:SI 0 "arm_general_register_operand" "")
2811 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2812 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2813 "TARGET_ARM
a0f94409 2814 && !const_ok_for_arm (INTVAL (operands[2]))
2815 && const_ok_for_arm (~INTVAL (operands[2]))"
2816 [(set (match_dup 3) (match_dup 2))
2817 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2818 ""
215b30b3 2819)
a0f94409 2820
f7fbdd4a 2821(define_insn "*iorsi3_compare0"
bd5b4116 2822 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2823 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2824 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2825 (const_int 0)))
2826 (set (match_operand:SI 0 "s_register_operand" "=r")
2827 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2828 "TARGET_32BIT"
2829 "orr%.\\t%0, %1, %2"
cffb2a26 2830 [(set_attr "conds" "set")]
2831)
9c08d1fa 2832
f7fbdd4a 2833(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2834 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2835 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2836 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2837 (const_int 0)))
2838 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2839 "TARGET_32BIT"
2840 "orr%.\\t%0, %1, %2"
0d66636f 2841 [(set_attr "conds" "set")]
2842)
9c08d1fa 2843
e2669ea7 2844(define_expand "xordi3"
2845 [(set (match_operand:DI 0 "s_register_operand" "")
2846 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2847 (match_operand:DI 2 "s_register_operand" "")))]
2848 "TARGET_32BIT"
2849 ""
2850)
2851
2852(define_insn "*xordi3_insn"
cffb2a26 2853 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2854 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2855 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2856 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2857 "#"
0d66636f 2858 [(set_attr "length" "8")
2859 (set_attr "predicable" "yes")]
cffb2a26 2860)
9c08d1fa 2861
f7fbdd4a 2862(define_insn "*xordi_zesidi_di"
9c08d1fa 2863 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2864 (xor:DI (zero_extend:DI
2865 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2866 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2867 "TARGET_32BIT"
e2348bcb 2868 "@
97499065 2869 eor%?\\t%Q0, %Q1, %2
f6ebffac 2870 #"
0d66636f 2871 [(set_attr "length" "4,8")
2872 (set_attr "predicable" "yes")]
cffb2a26 2873)
9c08d1fa 2874
f7fbdd4a 2875(define_insn "*xordi_sesidi_di"
9c08d1fa 2876 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2877 (xor:DI (sign_extend:DI
2878 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2879 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2880 "TARGET_32BIT"
f6ebffac 2881 "#"
0d66636f 2882 [(set_attr "length" "8")
2883 (set_attr "predicable" "yes")]
cffb2a26 2884)
9c08d1fa 2885
cffb2a26 2886(define_expand "xorsi3"
2887 [(set (match_operand:SI 0 "s_register_operand" "")
2888 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2889 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2890 "TARGET_EITHER"
923ffadb 2891 "if (GET_CODE (operands[2]) == CONST_INT)
2892 {
2893 if (TARGET_32BIT)
2894 {
2895 arm_split_constant (XOR, SImode, NULL_RTX,
2896 INTVAL (operands[2]), operands[0], operands[1],
2897 optimize && can_create_pseudo_p ());
2898 DONE;
2899 }
2900 else /* TARGET_THUMB1 */
2901 {
2902 rtx tmp = force_reg (SImode, operands[2]);
2903 if (rtx_equal_p (operands[0], operands[1]))
2904 operands[2] = tmp;
2905 else
2906 {
2907 operands[2] = operands[1];
2908 operands[1] = tmp;
2909 }
2910 }
2911 }"
cffb2a26 2912)
2913
2914(define_insn "*arm_xorsi3"
2915 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2916 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2917 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2918 "TARGET_32BIT"
cffb2a26 2919 "eor%?\\t%0, %1, %2"
0d66636f 2920 [(set_attr "predicable" "yes")]
cffb2a26 2921)
2922
747b7458 2923(define_insn "*thumb1_xorsi3_insn"
cffb2a26 2924 [(set (match_operand:SI 0 "register_operand" "=l")
2925 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2926 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2927 "TARGET_THUMB1"
747b7458 2928 "eor\\t%0, %2"
2929 [(set_attr "length" "2")
2930 (set_attr "conds" "set")])
9c08d1fa 2931
f7fbdd4a 2932(define_insn "*xorsi3_compare0"
bd5b4116 2933 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2934 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2935 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2936 (const_int 0)))
2937 (set (match_operand:SI 0 "s_register_operand" "=r")
2938 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2939 "TARGET_32BIT"
2940 "eor%.\\t%0, %1, %2"
0d66636f 2941 [(set_attr "conds" "set")]
2942)
9c08d1fa 2943
f7fbdd4a 2944(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2945 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2946 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2947 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2948 (const_int 0)))]
25f905c2 2949 "TARGET_32BIT"
40dbec34 2950 "teq%?\\t%0, %1"
cffb2a26 2951 [(set_attr "conds" "set")]
2952)
9c08d1fa 2953
215b30b3 2954; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2955; (NOT D) we can sometimes merge the final NOT into one of the following
2956; insns.
9c08d1fa 2957
2958(define_split
a058e94a 2959 [(set (match_operand:SI 0 "s_register_operand" "")
2960 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2961 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2962 (match_operand:SI 3 "arm_rhs_operand" "")))
2963 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2964 "TARGET_32BIT"
9c08d1fa 2965 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2966 (not:SI (match_dup 3))))
2967 (set (match_dup 0) (not:SI (match_dup 4)))]
2968 ""
2969)
2970
f7fbdd4a 2971(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2972 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 2973 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 2974 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2975 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2976 "TARGET_32BIT"
40dbec34 2977 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2978 [(set_attr "length" "8")
25f905c2 2979 (set_attr "ce_count" "2")
0d66636f 2980 (set_attr "predicable" "yes")]
cffb2a26 2981)
9c08d1fa 2982
25f905c2 2983; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2984; insns are available?
d7863cfe 2985(define_split
2986 [(set (match_operand:SI 0 "s_register_operand" "")
2987 (match_operator:SI 1 "logical_binary_operator"
2988 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2989 (match_operand:SI 3 "const_int_operand" "")
2990 (match_operand:SI 4 "const_int_operand" ""))
2991 (match_operator:SI 9 "logical_binary_operator"
2992 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2993 (match_operand:SI 6 "const_int_operand" ""))
2994 (match_operand:SI 7 "s_register_operand" "")])]))
2995 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2996 "TARGET_32BIT
d7863cfe 2997 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2998 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2999 [(set (match_dup 8)
3000 (match_op_dup 1
3001 [(ashift:SI (match_dup 2) (match_dup 4))
3002 (match_dup 5)]))
3003 (set (match_dup 0)
3004 (match_op_dup 1
3005 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3006 (match_dup 7)]))]
3007 "
3008 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3009")
3010
3011(define_split
3012 [(set (match_operand:SI 0 "s_register_operand" "")
3013 (match_operator:SI 1 "logical_binary_operator"
3014 [(match_operator:SI 9 "logical_binary_operator"
3015 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3016 (match_operand:SI 6 "const_int_operand" ""))
3017 (match_operand:SI 7 "s_register_operand" "")])
3018 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3019 (match_operand:SI 3 "const_int_operand" "")
3020 (match_operand:SI 4 "const_int_operand" ""))]))
3021 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3022 "TARGET_32BIT
d7863cfe 3023 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3024 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3025 [(set (match_dup 8)
3026 (match_op_dup 1
3027 [(ashift:SI (match_dup 2) (match_dup 4))
3028 (match_dup 5)]))
3029 (set (match_dup 0)
3030 (match_op_dup 1
3031 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3032 (match_dup 7)]))]
3033 "
3034 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3035")
3036
3037(define_split
3038 [(set (match_operand:SI 0 "s_register_operand" "")
3039 (match_operator:SI 1 "logical_binary_operator"
3040 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3041 (match_operand:SI 3 "const_int_operand" "")
3042 (match_operand:SI 4 "const_int_operand" ""))
3043 (match_operator:SI 9 "logical_binary_operator"
3044 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3045 (match_operand:SI 6 "const_int_operand" ""))
3046 (match_operand:SI 7 "s_register_operand" "")])]))
3047 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3048 "TARGET_32BIT
d7863cfe 3049 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3050 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3051 [(set (match_dup 8)
3052 (match_op_dup 1
3053 [(ashift:SI (match_dup 2) (match_dup 4))
3054 (match_dup 5)]))
3055 (set (match_dup 0)
3056 (match_op_dup 1
3057 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3058 (match_dup 7)]))]
3059 "
3060 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3061")
3062
3063(define_split
3064 [(set (match_operand:SI 0 "s_register_operand" "")
3065 (match_operator:SI 1 "logical_binary_operator"
3066 [(match_operator:SI 9 "logical_binary_operator"
3067 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3068 (match_operand:SI 6 "const_int_operand" ""))
3069 (match_operand:SI 7 "s_register_operand" "")])
3070 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3071 (match_operand:SI 3 "const_int_operand" "")
3072 (match_operand:SI 4 "const_int_operand" ""))]))
3073 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3074 "TARGET_32BIT
d7863cfe 3075 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3076 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3077 [(set (match_dup 8)
3078 (match_op_dup 1
3079 [(ashift:SI (match_dup 2) (match_dup 4))
3080 (match_dup 5)]))
3081 (set (match_dup 0)
3082 (match_op_dup 1
3083 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3084 (match_dup 7)]))]
3085 "
3086 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3087")
9c08d1fa 3088\f
3089
3090;; Minimum and maximum insns
3091
8b9dc177 3092(define_expand "smaxsi3"
3093 [(parallel [
3094 (set (match_operand:SI 0 "s_register_operand" "")
3095 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3096 (match_operand:SI 2 "arm_rhs_operand" "")))
3097 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3098 "TARGET_32BIT"
8b9dc177 3099 "
8774928b 3100 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3101 {
3102 /* No need for a clobber of the condition code register here. */
3103 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3104 gen_rtx_SMAX (SImode, operands[1],
3105 operands[2])));
3106 DONE;
3107 }
3108")
3109
3110(define_insn "*smax_0"
3111 [(set (match_operand:SI 0 "s_register_operand" "=r")
3112 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3113 (const_int 0)))]
25f905c2 3114 "TARGET_32BIT"
8b9dc177 3115 "bic%?\\t%0, %1, %1, asr #31"
3116 [(set_attr "predicable" "yes")]
3117)
3118
8774928b 3119(define_insn "*smax_m1"
3120 [(set (match_operand:SI 0 "s_register_operand" "=r")
3121 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3122 (const_int -1)))]
25f905c2 3123 "TARGET_32BIT"
8774928b 3124 "orr%?\\t%0, %1, %1, asr #31"
3125 [(set_attr "predicable" "yes")]
3126)
3127
25f905c2 3128(define_insn "*arm_smax_insn"
8b9dc177 3129 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3130 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3131 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3132 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3133 "TARGET_ARM"
e2348bcb 3134 "@
3135 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3136 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3137 [(set_attr "conds" "clob")
8b9dc177 3138 (set_attr "length" "8,12")]
cffb2a26 3139)
9c08d1fa 3140
8b9dc177 3141(define_expand "sminsi3"
3142 [(parallel [
3143 (set (match_operand:SI 0 "s_register_operand" "")
3144 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3145 (match_operand:SI 2 "arm_rhs_operand" "")))
3146 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3147 "TARGET_32BIT"
8b9dc177 3148 "
3149 if (operands[2] == const0_rtx)
3150 {
3151 /* No need for a clobber of the condition code register here. */
3152 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3153 gen_rtx_SMIN (SImode, operands[1],
3154 operands[2])));
3155 DONE;
3156 }
3157")
3158
3159(define_insn "*smin_0"
3160 [(set (match_operand:SI 0 "s_register_operand" "=r")
3161 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3162 (const_int 0)))]
25f905c2 3163 "TARGET_32BIT"
8b9dc177 3164 "and%?\\t%0, %1, %1, asr #31"
3165 [(set_attr "predicable" "yes")]
3166)
3167
25f905c2 3168(define_insn "*arm_smin_insn"
8b9dc177 3169 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3170 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3171 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3172 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3173 "TARGET_ARM"
e2348bcb 3174 "@
3175 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3176 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3177 [(set_attr "conds" "clob")
8b9dc177 3178 (set_attr "length" "8,12")]
0d66636f 3179)
9c08d1fa 3180
25f905c2 3181(define_expand "umaxsi3"
3182 [(parallel [
3183 (set (match_operand:SI 0 "s_register_operand" "")
3184 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3185 (match_operand:SI 2 "arm_rhs_operand" "")))
3186 (clobber (reg:CC CC_REGNUM))])]
3187 "TARGET_32BIT"
3188 ""
3189)
3190
3191(define_insn "*arm_umaxsi3"
9c08d1fa 3192 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3193 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3194 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3195 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3196 "TARGET_ARM"
e2348bcb 3197 "@
3198 cmp\\t%1, %2\;movcc\\t%0, %2
3199 cmp\\t%1, %2\;movcs\\t%0, %1
3200 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3201 [(set_attr "conds" "clob")
3202 (set_attr "length" "8,8,12")]
3203)
9c08d1fa 3204
25f905c2 3205(define_expand "uminsi3"
3206 [(parallel [
3207 (set (match_operand:SI 0 "s_register_operand" "")
3208 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3209 (match_operand:SI 2 "arm_rhs_operand" "")))
3210 (clobber (reg:CC CC_REGNUM))])]
3211 "TARGET_32BIT"
3212 ""
3213)
3214
3215(define_insn "*arm_uminsi3"
9c08d1fa 3216 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3217 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3218 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3219 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3220 "TARGET_ARM"
e2348bcb 3221 "@
3222 cmp\\t%1, %2\;movcs\\t%0, %2
3223 cmp\\t%1, %2\;movcc\\t%0, %1
3224 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3225 [(set_attr "conds" "clob")
3226 (set_attr "length" "8,8,12")]
3227)
9c08d1fa 3228
8a18b90c 3229(define_insn "*store_minmaxsi"
9c08d1fa 3230 [(set (match_operand:SI 0 "memory_operand" "=m")
3231 (match_operator:SI 3 "minmax_operator"
3232 [(match_operand:SI 1 "s_register_operand" "r")
3233 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3234 (clobber (reg:CC CC_REGNUM))]
25f905c2 3235 "TARGET_32BIT"
9c08d1fa 3236 "*
dc55b8a9 3237 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3238 operands[1], operands[2]);
e2348bcb 3239 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3240 if (TARGET_THUMB2)
3241 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3242 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3243 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3244 return \"\";
0d66636f 3245 "
3246 [(set_attr "conds" "clob")
25f905c2 3247 (set (attr "length")
3248 (if_then_else (eq_attr "is_thumb" "yes")
3249 (const_int 14)
3250 (const_int 12)))
0d66636f 3251 (set_attr "type" "store1")]
3252)
9c08d1fa 3253
8a18b90c 3254; Reject the frame pointer in operand[1], since reloading this after
3255; it has been eliminated can cause carnage.
f7fbdd4a 3256(define_insn "*minmax_arithsi"
9c08d1fa 3257 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3258 (match_operator:SI 4 "shiftable_operator"
3259 [(match_operator:SI 5 "minmax_operator"
3260 [(match_operand:SI 2 "s_register_operand" "r,r")
3261 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3262 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3263 (clobber (reg:CC CC_REGNUM))]
25f905c2 3264 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3265 "*
0d66636f 3266 {
3267 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3268 bool need_else;
3269
3270 if (which_alternative != 0 || operands[3] != const0_rtx
3271 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3272 need_else = true;
3273 else
3274 need_else = false;
0d66636f 3275
dc55b8a9 3276 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3277 operands[2], operands[3]);
0d66636f 3278 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3279 if (TARGET_THUMB2)
3280 {
3281 if (need_else)
3282 output_asm_insn (\"ite\\t%d5\", operands);
3283 else
3284 output_asm_insn (\"it\\t%d5\", operands);
3285 }
0d66636f 3286 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3287 if (need_else)
0d66636f 3288 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3289 return \"\";
215b30b3 3290 }"
0d66636f 3291 [(set_attr "conds" "clob")
25f905c2 3292 (set (attr "length")
3293 (if_then_else (eq_attr "is_thumb" "yes")
3294 (const_int 14)
3295 (const_int 12)))]
0d66636f 3296)
9c08d1fa 3297
b11cae9e 3298\f
3299;; Shift and rotation insns
3300
a2cd141b 3301(define_expand "ashldi3"
3302 [(set (match_operand:DI 0 "s_register_operand" "")
3303 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3304 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3305 "TARGET_32BIT"
a2cd141b 3306 "
3307 if (GET_CODE (operands[2]) == CONST_INT)
3308 {
3309 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3310 {
3311 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3312 DONE;
3313 }
3314 /* Ideally we shouldn't fail here if we could know that operands[1]
3315 ends up already living in an iwmmxt register. Otherwise it's
3316 cheaper to have the alternate code being generated than moving
1d60d981 3317 values to iwmmxt regs and back. */
a2cd141b 3318 FAIL;
3319 }
3320 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3321 FAIL;
3322 "
3323)
3324
3325(define_insn "arm_ashldi3_1bit"
50ad1bf9 3326 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3327 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3328 (const_int 1)))
3329 (clobber (reg:CC CC_REGNUM))]
25f905c2 3330 "TARGET_32BIT"
a2cd141b 3331 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3332 [(set_attr "conds" "clob")
3333 (set_attr "length" "8")]
3334)
3335
87b22bf7 3336(define_expand "ashlsi3"
cffb2a26 3337 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3338 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3339 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3340 "TARGET_EITHER"
87b22bf7 3341 "
3342 if (GET_CODE (operands[2]) == CONST_INT
3343 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3344 {
3345 emit_insn (gen_movsi (operands[0], const0_rtx));
3346 DONE;
3347 }
cffb2a26 3348 "
3349)
3350
25f905c2 3351(define_insn "*thumb1_ashlsi3"
cffb2a26 3352 [(set (match_operand:SI 0 "register_operand" "=l,l")
3353 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3354 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3355 "TARGET_THUMB1"
cffb2a26 3356 "lsl\\t%0, %1, %2"
747b7458 3357 [(set_attr "length" "2")
3358 (set_attr "conds" "set")])
b11cae9e 3359
a2cd141b 3360(define_expand "ashrdi3"
3361 [(set (match_operand:DI 0 "s_register_operand" "")
3362 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3363 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3364 "TARGET_32BIT"
a2cd141b 3365 "
3366 if (GET_CODE (operands[2]) == CONST_INT)
3367 {
3368 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3369 {
3370 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3371 DONE;
3372 }
3373 /* Ideally we shouldn't fail here if we could know that operands[1]
3374 ends up already living in an iwmmxt register. Otherwise it's
3375 cheaper to have the alternate code being generated than moving
1d60d981 3376 values to iwmmxt regs and back. */
a2cd141b 3377 FAIL;
3378 }
3379 else if (!TARGET_REALLY_IWMMXT)
3380 FAIL;
3381 "
3382)
3383
3384(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3385 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3386 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3387 (const_int 1)))
3388 (clobber (reg:CC CC_REGNUM))]
25f905c2 3389 "TARGET_32BIT"
a2cd141b 3390 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3391 [(set_attr "conds" "clob")
d2a518d1 3392 (set_attr "insn" "mov")
a2cd141b 3393 (set_attr "length" "8")]
3394)
3395
87b22bf7 3396(define_expand "ashrsi3"
cffb2a26 3397 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3398 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3399 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3400 "TARGET_EITHER"
87b22bf7 3401 "
3402 if (GET_CODE (operands[2]) == CONST_INT
3403 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3404 operands[2] = GEN_INT (31);
cffb2a26 3405 "
3406)
3407
25f905c2 3408(define_insn "*thumb1_ashrsi3"
cffb2a26 3409 [(set (match_operand:SI 0 "register_operand" "=l,l")
3410 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3411 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3412 "TARGET_THUMB1"
cffb2a26 3413 "asr\\t%0, %1, %2"
747b7458 3414 [(set_attr "length" "2")
3415 (set_attr "conds" "set")])
b11cae9e 3416
a2cd141b 3417(define_expand "lshrdi3"
3418 [(set (match_operand:DI 0 "s_register_operand" "")
3419 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3420 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3421 "TARGET_32BIT"
a2cd141b 3422 "
3423 if (GET_CODE (operands[2]) == CONST_INT)
3424 {
3425 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3426 {
3427 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3428 DONE;
3429 }
3430 /* Ideally we shouldn't fail here if we could know that operands[1]
3431 ends up already living in an iwmmxt register. Otherwise it's
3432 cheaper to have the alternate code being generated than moving
1d60d981 3433 values to iwmmxt regs and back. */
a2cd141b 3434 FAIL;
3435 }
3436 else if (!TARGET_REALLY_IWMMXT)
3437 FAIL;
3438 "
3439)
3440
3441(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3442 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3443 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3444 (const_int 1)))
3445 (clobber (reg:CC CC_REGNUM))]
25f905c2 3446 "TARGET_32BIT"
a2cd141b 3447 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3448 [(set_attr "conds" "clob")
d2a518d1 3449 (set_attr "insn" "mov")
a2cd141b 3450 (set_attr "length" "8")]
3451)
3452
87b22bf7 3453(define_expand "lshrsi3"
cffb2a26 3454 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3455 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3456 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3457 "TARGET_EITHER"
87b22bf7 3458 "
3459 if (GET_CODE (operands[2]) == CONST_INT
3460 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3461 {
3462 emit_insn (gen_movsi (operands[0], const0_rtx));
3463 DONE;
3464 }
cffb2a26 3465 "
3466)
3467
25f905c2 3468(define_insn "*thumb1_lshrsi3"
cffb2a26 3469 [(set (match_operand:SI 0 "register_operand" "=l,l")
3470 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3471 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3472 "TARGET_THUMB1"
cffb2a26 3473 "lsr\\t%0, %1, %2"
747b7458 3474 [(set_attr "length" "2")
3475 (set_attr "conds" "set")])
b11cae9e 3476
87b22bf7 3477(define_expand "rotlsi3"
cffb2a26 3478 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3479 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3480 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3481 "TARGET_32BIT"
87b22bf7 3482 "
3483 if (GET_CODE (operands[2]) == CONST_INT)
3484 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3485 else
b11cae9e 3486 {
87b22bf7 3487 rtx reg = gen_reg_rtx (SImode);
3488 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3489 operands[2] = reg;
b11cae9e 3490 }
cffb2a26 3491 "
3492)
9c08d1fa 3493
87b22bf7 3494(define_expand "rotrsi3"
cffb2a26 3495 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3496 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3497 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3498 "TARGET_EITHER"
87b22bf7 3499 "
25f905c2 3500 if (TARGET_32BIT)
cffb2a26 3501 {
3502 if (GET_CODE (operands[2]) == CONST_INT
3503 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3504 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3505 }
25f905c2 3506 else /* TARGET_THUMB1 */
cffb2a26 3507 {
3508 if (GET_CODE (operands [2]) == CONST_INT)
3509 operands [2] = force_reg (SImode, operands[2]);
3510 }
3511 "
3512)
87b22bf7 3513
25f905c2 3514(define_insn "*thumb1_rotrsi3"
cffb2a26 3515 [(set (match_operand:SI 0 "register_operand" "=l")
3516 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3517 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3518 "TARGET_THUMB1"
cffb2a26 3519 "ror\\t%0, %0, %2"
3520 [(set_attr "length" "2")]
3521)
3522
3523(define_insn "*arm_shiftsi3"
3524 [(set (match_operand:SI 0 "s_register_operand" "=r")
3525 (match_operator:SI 3 "shift_operator"
3526 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3527 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3528 "TARGET_32BIT"
3529 "* return arm_output_shift(operands, 0);"
344495ea 3530 [(set_attr "predicable" "yes")
331beb1a 3531 (set_attr "shift" "1")
a2cd141b 3532 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3533 (const_string "alu_shift")
3534 (const_string "alu_shift_reg")))]
6c4c2133 3535)
87b22bf7 3536
f7fbdd4a 3537(define_insn "*shiftsi3_compare0"
bd5b4116 3538 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3539 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3540 [(match_operand:SI 1 "s_register_operand" "r")
3541 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3542 (const_int 0)))
3543 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3544 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3545 "TARGET_32BIT"
3546 "* return arm_output_shift(operands, 1);"
344495ea 3547 [(set_attr "conds" "set")
331beb1a 3548 (set_attr "shift" "1")
a2cd141b 3549 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3550 (const_string "alu_shift")
3551 (const_string "alu_shift_reg")))]
0d66636f 3552)
9c08d1fa 3553
f7fbdd4a 3554(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3555 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3556 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3557 [(match_operand:SI 1 "s_register_operand" "r")
3558 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3559 (const_int 0)))
3560 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3561 "TARGET_32BIT"
3562 "* return arm_output_shift(operands, 1);"
344495ea 3563 [(set_attr "conds" "set")
a2cd141b 3564 (set_attr "shift" "1")]
0d66636f 3565)
9c08d1fa 3566
d5d4dc8d 3567(define_insn "*not_shiftsi"
3568 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3569 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3570 [(match_operand:SI 1 "s_register_operand" "r,r")
3571 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3572 "TARGET_32BIT"
6c4c2133 3573 "mvn%?\\t%0, %1%S3"
344495ea 3574 [(set_attr "predicable" "yes")
331beb1a 3575 (set_attr "shift" "1")
d2a518d1 3576 (set_attr "insn" "mvn")
d5d4dc8d 3577 (set_attr "arch" "32,a")
3578 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3579
d5d4dc8d 3580(define_insn "*not_shiftsi_compare0"
bd5b4116 3581 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3582 (compare:CC_NOOV
3583 (not:SI (match_operator:SI 3 "shift_operator"
3584 [(match_operand:SI 1 "s_register_operand" "r,r")
3585 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3586 (const_int 0)))
3587 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3588 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3589 "TARGET_32BIT"
25f905c2 3590 "mvn%.\\t%0, %1%S3"
344495ea 3591 [(set_attr "conds" "set")
331beb1a 3592 (set_attr "shift" "1")
d2a518d1 3593 (set_attr "insn" "mvn")
d5d4dc8d 3594 (set_attr "arch" "32,a")
3595 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3596
d5d4dc8d 3597(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3598 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3599 (compare:CC_NOOV
3600 (not:SI (match_operator:SI 3 "shift_operator"
3601 [(match_operand:SI 1 "s_register_operand" "r,r")
3602 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3603 (const_int 0)))
3604 (clobber (match_scratch:SI 0 "=r,r"))]
3605 "TARGET_32BIT"
25f905c2 3606 "mvn%.\\t%0, %1%S3"
344495ea 3607 [(set_attr "conds" "set")
331beb1a 3608 (set_attr "shift" "1")
d2a518d1 3609 (set_attr "insn" "mvn")
d5d4dc8d 3610 (set_attr "arch" "32,a")
3611 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3612
cffb2a26 3613;; We don't really have extzv, but defining this using shifts helps
3614;; to reduce register pressure later on.
3615
3616(define_expand "extzv"
3617 [(set (match_dup 4)
3618 (ashift:SI (match_operand:SI 1 "register_operand" "")
3619 (match_operand:SI 2 "const_int_operand" "")))
3620 (set (match_operand:SI 0 "register_operand" "")
3621 (lshiftrt:SI (match_dup 4)
215b30b3 3622 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3623 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3624 "
3625 {
3626 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3627 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3628
8b054d5a 3629 if (arm_arch_thumb2)
3630 {
3631 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3632 operands[3]));
3633 DONE;
3634 }
3635
cffb2a26 3636 operands[3] = GEN_INT (rshift);
3637
3638 if (lshift == 0)
3639 {
3640 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3641 DONE;
3642 }
3643
3644 operands[2] = GEN_INT (lshift);
3645 operands[4] = gen_reg_rtx (SImode);
215b30b3 3646 }"
cffb2a26 3647)
3648
8b054d5a 3649(define_insn "extv"
3650 [(set (match_operand:SI 0 "s_register_operand" "=r")
3651 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3652 (match_operand:SI 2 "const_int_operand" "M")
3653 (match_operand:SI 3 "const_int_operand" "M")))]
3654 "arm_arch_thumb2"
3655 "sbfx%?\t%0, %1, %3, %2"
3656 [(set_attr "length" "4")
3657 (set_attr "predicable" "yes")]
3658)
3659
3660(define_insn "extzv_t2"
3661 [(set (match_operand:SI 0 "s_register_operand" "=r")
3662 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3663 (match_operand:SI 2 "const_int_operand" "M")
3664 (match_operand:SI 3 "const_int_operand" "M")))]
3665 "arm_arch_thumb2"
3666 "ubfx%?\t%0, %1, %3, %2"
3667 [(set_attr "length" "4")
3668 (set_attr "predicable" "yes")]
3669)
3670
b11cae9e 3671\f
3672;; Unary arithmetic insns
3673
cffb2a26 3674(define_expand "negdi2"
3675 [(parallel
8135a42b 3676 [(set (match_operand:DI 0 "s_register_operand" "")
3677 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3678 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3679 "TARGET_EITHER"
8135a42b 3680 ""
cffb2a26 3681)
3682
3683;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 3684;; The first alternative allows the common case of a *full* overlap.
cffb2a26 3685(define_insn "*arm_negdi2"
3686 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3687 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 3688 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3689 "TARGET_ARM"
97499065 3690 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3691 [(set_attr "conds" "clob")
3692 (set_attr "length" "8")]
3693)
b11cae9e 3694
25f905c2 3695(define_insn "*thumb1_negdi2"
8135a42b 3696 [(set (match_operand:DI 0 "register_operand" "=&l")
3697 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3698 (clobber (reg:CC CC_REGNUM))]
25f905c2 3699 "TARGET_THUMB1"
cffb2a26 3700 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3701 [(set_attr "length" "6")]
3702)
3703
3704(define_expand "negsi2"
3705 [(set (match_operand:SI 0 "s_register_operand" "")
3706 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3707 "TARGET_EITHER"
b11cae9e 3708 ""
cffb2a26 3709)
3710
3711(define_insn "*arm_negsi2"
3712 [(set (match_operand:SI 0 "s_register_operand" "=r")
3713 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3714 "TARGET_32BIT"
cffb2a26 3715 "rsb%?\\t%0, %1, #0"
0d66636f 3716 [(set_attr "predicable" "yes")]
cffb2a26 3717)
3718
25f905c2 3719(define_insn "*thumb1_negsi2"
cffb2a26 3720 [(set (match_operand:SI 0 "register_operand" "=l")
3721 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3722 "TARGET_THUMB1"
cffb2a26 3723 "neg\\t%0, %1"
3724 [(set_attr "length" "2")]
3725)
b11cae9e 3726
604f3a0a 3727(define_expand "negsf2"
3728 [(set (match_operand:SF 0 "s_register_operand" "")
3729 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3730 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3731 ""
3732)
3733
3734(define_expand "negdf2"
3735 [(set (match_operand:DF 0 "s_register_operand" "")
3736 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3737 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3738 "")
3739
9c08d1fa 3740;; abssi2 doesn't really clobber the condition codes if a different register
3741;; is being set. To keep things simple, assume during rtl manipulations that
3742;; it does, but tell the final scan operator the truth. Similarly for
3743;; (neg (abs...))
3744
604f3a0a 3745(define_expand "abssi2"
3746 [(parallel
3747 [(set (match_operand:SI 0 "s_register_operand" "")
3748 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3749 (clobber (match_dup 2))])]
3750 "TARGET_EITHER"
3751 "
25f905c2 3752 if (TARGET_THUMB1)
ba156559 3753 operands[2] = gen_rtx_SCRATCH (SImode);
3754 else
3755 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3756")
604f3a0a 3757
7d57ec45 3758(define_insn "*arm_abssi2"
ba156559 3759 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3760 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3761 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3762 "TARGET_ARM"
e2348bcb 3763 "@
3764 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3765 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3766 [(set_attr "conds" "clob,*")
331beb1a 3767 (set_attr "shift" "1")
0d66636f 3768 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3769 (set_attr "length" "8")]
3770)
9c08d1fa 3771
25f905c2 3772(define_insn_and_split "*thumb1_abssi2"
ba156559 3773 [(set (match_operand:SI 0 "s_register_operand" "=l")
3774 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3775 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3776 "TARGET_THUMB1"
ba156559 3777 "#"
25f905c2 3778 "TARGET_THUMB1 && reload_completed"
ba156559 3779 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3780 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3781 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3782 ""
3783 [(set_attr "length" "6")]
3784)
3785
3786(define_insn "*arm_neg_abssi2"
9c08d1fa 3787 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3788 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3789 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3790 "TARGET_ARM"
e2348bcb 3791 "@
3792 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3793 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3794 [(set_attr "conds" "clob,*")
331beb1a 3795 (set_attr "shift" "1")
0d66636f 3796 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3797 (set_attr "length" "8")]
3798)
b11cae9e 3799
25f905c2 3800(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3801 [(set (match_operand:SI 0 "s_register_operand" "=l")
3802 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3803 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3804 "TARGET_THUMB1"
ba156559 3805 "#"
25f905c2 3806 "TARGET_THUMB1 && reload_completed"
ba156559 3807 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3808 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3809 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3810 ""
3811 [(set_attr "length" "6")]
3812)
3813
604f3a0a 3814(define_expand "abssf2"
3815 [(set (match_operand:SF 0 "s_register_operand" "")
3816 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3817 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3818 "")
3819
604f3a0a 3820(define_expand "absdf2"
3821 [(set (match_operand:DF 0 "s_register_operand" "")
3822 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3823 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3824 "")
3825
7db9af5d 3826(define_expand "sqrtsf2"
3827 [(set (match_operand:SF 0 "s_register_operand" "")
3828 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3829 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3830 "")
9c08d1fa 3831
7db9af5d 3832(define_expand "sqrtdf2"
3833 [(set (match_operand:DF 0 "s_register_operand" "")
3834 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3835 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3836 "")
9c08d1fa 3837
a0f94409 3838(define_insn_and_split "one_cmpldi2"
9c08d1fa 3839 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3840 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3841 "TARGET_32BIT"
f6ebffac 3842 "#"
25f905c2 3843 "TARGET_32BIT && reload_completed"
a0f94409 3844 [(set (match_dup 0) (not:SI (match_dup 1)))
3845 (set (match_dup 2) (not:SI (match_dup 3)))]
3846 "
3847 {
3848 operands[2] = gen_highpart (SImode, operands[0]);
3849 operands[0] = gen_lowpart (SImode, operands[0]);
3850 operands[3] = gen_highpart (SImode, operands[1]);
3851 operands[1] = gen_lowpart (SImode, operands[1]);
3852 }"
0d66636f 3853 [(set_attr "length" "8")
3854 (set_attr "predicable" "yes")]
cffb2a26 3855)
b11cae9e 3856
cffb2a26 3857(define_expand "one_cmplsi2"
3858 [(set (match_operand:SI 0 "s_register_operand" "")
3859 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3860 "TARGET_EITHER"
b11cae9e 3861 ""
cffb2a26 3862)
3863
3864(define_insn "*arm_one_cmplsi2"
3865 [(set (match_operand:SI 0 "s_register_operand" "=r")
3866 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3867 "TARGET_32BIT"
cffb2a26 3868 "mvn%?\\t%0, %1"
d2a518d1 3869 [(set_attr "predicable" "yes")
3870 (set_attr "insn" "mvn")]
cffb2a26 3871)
3872
25f905c2 3873(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3874 [(set (match_operand:SI 0 "register_operand" "=l")
3875 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3876 "TARGET_THUMB1"
cffb2a26 3877 "mvn\\t%0, %1"
d2a518d1 3878 [(set_attr "length" "2")
3879 (set_attr "insn" "mvn")]
cffb2a26 3880)
9c08d1fa 3881
f7fbdd4a 3882(define_insn "*notsi_compare0"
bd5b4116 3883 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3884 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3885 (const_int 0)))
3886 (set (match_operand:SI 0 "s_register_operand" "=r")
3887 (not:SI (match_dup 1)))]
25f905c2 3888 "TARGET_32BIT"
3889 "mvn%.\\t%0, %1"
d2a518d1 3890 [(set_attr "conds" "set")
3891 (set_attr "insn" "mvn")]
cffb2a26 3892)
9c08d1fa 3893
f7fbdd4a 3894(define_insn "*notsi_compare0_scratch"
bd5b4116 3895 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3896 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3897 (const_int 0)))
3898 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3899 "TARGET_32BIT"
3900 "mvn%.\\t%0, %1"
d2a518d1 3901 [(set_attr "conds" "set")
3902 (set_attr "insn" "mvn")]
cffb2a26 3903)
b11cae9e 3904\f
3905;; Fixed <--> Floating conversion insns
3906
9b8516be 3907(define_expand "floatsihf2"
3908 [(set (match_operand:HF 0 "general_operand" "")
3909 (float:HF (match_operand:SI 1 "general_operand" "")))]
3910 "TARGET_EITHER"
3911 "
3912 {
3913 rtx op1 = gen_reg_rtx (SFmode);
3914 expand_float (op1, operands[1], 0);
3915 op1 = convert_to_mode (HFmode, op1, 0);
3916 emit_move_insn (operands[0], op1);
3917 DONE;
3918 }"
3919)
3920
3921(define_expand "floatdihf2"
3922 [(set (match_operand:HF 0 "general_operand" "")
3923 (float:HF (match_operand:DI 1 "general_operand" "")))]
3924 "TARGET_EITHER"
3925 "
3926 {
3927 rtx op1 = gen_reg_rtx (SFmode);
3928 expand_float (op1, operands[1], 0);
3929 op1 = convert_to_mode (HFmode, op1, 0);
3930 emit_move_insn (operands[0], op1);
3931 DONE;
3932 }"
3933)
3934
604f3a0a 3935(define_expand "floatsisf2"
3936 [(set (match_operand:SF 0 "s_register_operand" "")
3937 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3938 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3939 "
a2cd141b 3940 if (TARGET_MAVERICK)
604f3a0a 3941 {
3942 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3943 DONE;
3944 }
3945")
3946
604f3a0a 3947(define_expand "floatsidf2"
3948 [(set (match_operand:DF 0 "s_register_operand" "")
3949 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 3950 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3951 "
a2cd141b 3952 if (TARGET_MAVERICK)
604f3a0a 3953 {
3954 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3955 DONE;
3956 }
3957")
3958
9b8516be 3959(define_expand "fix_trunchfsi2"
3960 [(set (match_operand:SI 0 "general_operand" "")
3961 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3962 "TARGET_EITHER"
3963 "
3964 {
3965 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3966 expand_fix (operands[0], op1, 0);
3967 DONE;
3968 }"
3969)
3970
3971(define_expand "fix_trunchfdi2"
3972 [(set (match_operand:DI 0 "general_operand" "")
3973 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3974 "TARGET_EITHER"
3975 "
3976 {
3977 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3978 expand_fix (operands[0], op1, 0);
3979 DONE;
3980 }"
3981)
3982
604f3a0a 3983(define_expand "fix_truncsfsi2"
3984 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3985 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3986 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3987 "
a2cd141b 3988 if (TARGET_MAVERICK)
604f3a0a 3989 {
3990 if (!cirrus_fp_register (operands[0], SImode))
3991 operands[0] = force_reg (SImode, operands[0]);
3992 if (!cirrus_fp_register (operands[1], SFmode))
3993 operands[1] = force_reg (SFmode, operands[0]);
3994 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3995 DONE;
3996 }
3997")
3998
604f3a0a 3999(define_expand "fix_truncdfsi2"
4000 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4001 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4002 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4003 "
a2cd141b 4004 if (TARGET_MAVERICK)
604f3a0a 4005 {
4006 if (!cirrus_fp_register (operands[1], DFmode))
4007 operands[1] = force_reg (DFmode, operands[0]);
4008 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4009 DONE;
4010 }
4011")
4012
f544c6d2 4013;; Truncation insns
b11cae9e 4014
604f3a0a 4015(define_expand "truncdfsf2"
4016 [(set (match_operand:SF 0 "s_register_operand" "")
4017 (float_truncate:SF
4018 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4019 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4020 ""
4021)
9b8516be 4022
4023/* DFmode -> HFmode conversions have to go through SFmode. */
4024(define_expand "truncdfhf2"
4025 [(set (match_operand:HF 0 "general_operand" "")
4026 (float_truncate:HF
4027 (match_operand:DF 1 "general_operand" "")))]
4028 "TARGET_EITHER"
4029 "
4030 {
4031 rtx op1;
4032 op1 = convert_to_mode (SFmode, operands[1], 0);
4033 op1 = convert_to_mode (HFmode, op1, 0);
4034 emit_move_insn (operands[0], op1);
4035 DONE;
4036 }"
4037)
b11cae9e 4038\f
9c08d1fa 4039;; Zero and sign extension instructions.
b11cae9e 4040
848e66ac 4041(define_insn "zero_extend<mode>di2"
4042 [(set (match_operand:DI 0 "s_register_operand" "=r")
4043 (zero_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))]
4044 "TARGET_32BIT <qhs_zextenddi_cond>"
4045 "#"
4046 [(set_attr "length" "8")
4047 (set_attr "ce_count" "2")
4048 (set_attr "predicable" "yes")]
25f905c2 4049)
4050
848e66ac 4051(define_insn "extend<mode>di2"
9c08d1fa 4052 [(set (match_operand:DI 0 "s_register_operand" "=r")
848e66ac 4053 (sign_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))]
4054 "TARGET_32BIT <qhs_sextenddi_cond>"
4055 "#"
0d66636f 4056 [(set_attr "length" "8")
848e66ac 4057 (set_attr "ce_count" "2")
4058 (set_attr "shift" "1")
0d66636f 4059 (set_attr "predicable" "yes")]
4060)
9c08d1fa 4061
848e66ac 4062;; Splits for all extensions to DImode
4063(define_split
4064 [(set (match_operand:DI 0 "s_register_operand" "")
4065 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4066 "TARGET_32BIT"
848e66ac 4067 [(set (match_dup 0) (match_dup 1))]
4068{
848e66ac 4069 rtx lo_part = gen_lowpart (SImode, operands[0]);
4070 enum machine_mode src_mode = GET_MODE (operands[1]);
4071
4072 if (REG_P (operands[0])
4073 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4074 emit_clobber (operands[0]);
4075 if (!REG_P (lo_part) || src_mode != SImode
4076 || !rtx_equal_p (lo_part, operands[1]))
4077 {
4078 if (src_mode == SImode)
4079 emit_move_insn (lo_part, operands[1]);
4080 else
4081 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4082 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4083 operands[1] = lo_part;
4084 }
4085 operands[0] = gen_highpart (SImode, operands[0]);
4086 operands[1] = const0_rtx;
4087})
9c08d1fa 4088
848e66ac 4089(define_split
25f905c2 4090 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4091 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4092 "TARGET_32BIT"
848e66ac 4093 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4094{
4095 rtx lo_part = gen_lowpart (SImode, operands[0]);
4096 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4097
848e66ac 4098 if (REG_P (operands[0])
4099 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4100 emit_clobber (operands[0]);
4101
4102 if (!REG_P (lo_part) || src_mode != SImode
4103 || !rtx_equal_p (lo_part, operands[1]))
4104 {
4105 if (src_mode == SImode)
4106 emit_move_insn (lo_part, operands[1]);
4107 else
4108 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4109 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4110 operands[1] = lo_part;
4111 }
4112 operands[0] = gen_highpart (SImode, operands[0]);
4113})
9c08d1fa 4114
4115(define_expand "zero_extendhisi2"
ef51b8e1 4116 [(set (match_operand:SI 0 "s_register_operand" "")
4117 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4118 "TARGET_EITHER"
ef51b8e1 4119{
4120 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4121 {
ef51b8e1 4122 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4123 DONE;
25f7a26e 4124 }
ef51b8e1 4125 if (!arm_arch6 && !MEM_P (operands[1]))
4126 {
4127 rtx t = gen_lowpart (SImode, operands[1]);
4128 rtx tmp = gen_reg_rtx (SImode);
4129 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4130 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4131 DONE;
4132 }
4133})
9c08d1fa 4134
ef51b8e1 4135(define_split
4136 [(set (match_operand:SI 0 "register_operand" "")
747b7458 4137 (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
ef51b8e1 4138 "!TARGET_THUMB2 && !arm_arch6"
4139 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4140 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4141{
4142 operands[2] = gen_lowpart (SImode, operands[1]);
4143})
4144
4145(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4146 [(set (match_operand:SI 0 "register_operand" "=l,l")
4147 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4148 "TARGET_THUMB1"
848e66ac 4149{
a2cd141b 4150 rtx mem;
4151
ef51b8e1 4152 if (which_alternative == 0 && arm_arch6)
848e66ac 4153 return "uxth\t%0, %1";
ef51b8e1 4154 if (which_alternative == 0)
848e66ac 4155 return "#";
a2cd141b 4156
4157 mem = XEXP (operands[1], 0);
4158
4159 if (GET_CODE (mem) == CONST)
4160 mem = XEXP (mem, 0);
4161
a2cd141b 4162 if (GET_CODE (mem) == PLUS)
4163 {
4164 rtx a = XEXP (mem, 0);
a2cd141b 4165
4166 /* This can happen due to bugs in reload. */
4167 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4168 {
4169 rtx ops[2];
4170 ops[0] = operands[0];
4171 ops[1] = a;
4172
848e66ac 4173 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4174
4175 XEXP (mem, 0) = operands[0];
4176 }
a2cd141b 4177 }
4178
848e66ac 4179 return "ldrh\t%0, %1";
4180}
ef51b8e1 4181 [(set_attr_alternative "length"
4182 [(if_then_else (eq_attr "is_arch6" "yes")
4183 (const_int 2) (const_int 4))
4184 (const_int 4)])
848e66ac 4185 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4186)
4187
cffb2a26 4188(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4189 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4190 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4191 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4192 "@
4193 #
4194 ldr%(h%)\\t%0, %1"
4195 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4196 (set_attr "predicable" "yes")]
cffb2a26 4197)
f7fbdd4a 4198
a2cd141b 4199(define_insn "*arm_zero_extendhisi2_v6"
4200 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4201 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4202 "TARGET_ARM && arm_arch6"
4203 "@
4204 uxth%?\\t%0, %1
25f905c2 4205 ldr%(h%)\\t%0, %1"
a2cd141b 4206 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4207 (set_attr "predicable" "yes")]
a2cd141b 4208)
4209
4210(define_insn "*arm_zero_extendhisi2addsi"
4211 [(set (match_operand:SI 0 "s_register_operand" "=r")
4212 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4213 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4214 "TARGET_INT_SIMD"
a2cd141b 4215 "uxtah%?\\t%0, %2, %1"
4216 [(set_attr "type" "alu_shift")
4217 (set_attr "predicable" "yes")]
4218)
4219
87b22bf7 4220(define_expand "zero_extendqisi2"
cffb2a26 4221 [(set (match_operand:SI 0 "s_register_operand" "")
4222 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4223 "TARGET_EITHER"
ef51b8e1 4224{
4225 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4226 {
ef51b8e1 4227 emit_insn (gen_andsi3 (operands[0],
4228 gen_lowpart (SImode, operands[1]),
4229 GEN_INT (255)));
4230 DONE;
4231 }
4232 if (!arm_arch6 && !MEM_P (operands[1]))
4233 {
4234 rtx t = gen_lowpart (SImode, operands[1]);
4235 rtx tmp = gen_reg_rtx (SImode);
4236 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4237 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4238 DONE;
4239 }
4240})
cffb2a26 4241
ef51b8e1 4242(define_split
4243 [(set (match_operand:SI 0 "register_operand" "")
4244 (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4245 "!arm_arch6"
4246 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4247 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4248{
4249 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4250 if (TARGET_ARM)
4251 {
4252 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4253 DONE;
4254 }
ef51b8e1 4255})
9c08d1fa 4256
25f905c2 4257(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4258 [(set (match_operand:SI 0 "register_operand" "=l,l")
4259 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4260 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4261 "@
4262 #
4263 ldrb\\t%0, %1"
4264 [(set_attr "length" "4,2")
4265 (set_attr "type" "alu_shift,load_byte")
4266 (set_attr "pool_range" "*,32")]
cffb2a26 4267)
4268
25f905c2 4269(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4270 [(set (match_operand:SI 0 "register_operand" "=l,l")
4271 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4272 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4273 "@
4274 uxtb\\t%0, %1
4275 ldrb\\t%0, %1"
848e66ac 4276 [(set_attr "length" "2")
4277 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4278)
4279
cffb2a26 4280(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4281 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4282 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4283 "TARGET_ARM && !arm_arch6"
ef51b8e1 4284 "@
4285 #
4286 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4287 [(set_attr "length" "8,4")
4288 (set_attr "type" "alu_shift,load_byte")
848e66ac 4289 (set_attr "predicable" "yes")]
cffb2a26 4290)
87b22bf7 4291
a2cd141b 4292(define_insn "*arm_zero_extendqisi2_v6"
4293 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4294 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4295 "TARGET_ARM && arm_arch6"
4296 "@
25f905c2 4297 uxtb%(%)\\t%0, %1
4298 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4299 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4300 (set_attr "predicable" "yes")]
a2cd141b 4301)
4302
4303(define_insn "*arm_zero_extendqisi2addsi"
4304 [(set (match_operand:SI 0 "s_register_operand" "=r")
4305 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4306 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4307 "TARGET_INT_SIMD"
a2cd141b 4308 "uxtab%?\\t%0, %2, %1"
4309 [(set_attr "predicable" "yes")
bcaec148 4310 (set_attr "insn" "xtab")
a2cd141b 4311 (set_attr "type" "alu_shift")]
4312)
4313
87b22bf7 4314(define_split
4315 [(set (match_operand:SI 0 "s_register_operand" "")
4316 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4317 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4318 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4319 [(set (match_dup 2) (match_dup 1))
4320 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4321 ""
4322)
9c08d1fa 4323
8a4d25d6 4324(define_split
4325 [(set (match_operand:SI 0 "s_register_operand" "")
4326 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4327 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4328 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4329 [(set (match_dup 2) (match_dup 1))
4330 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4331 ""
4332)
4333
1c274529 4334
4335(define_split
4336 [(set (match_operand:SI 0 "s_register_operand" "")
4337 (ior_xor:SI (and:SI (ashift:SI
4338 (match_operand:SI 1 "s_register_operand" "")
4339 (match_operand:SI 2 "const_int_operand" ""))
4340 (match_operand:SI 3 "const_int_operand" ""))
4341 (zero_extend:SI
4342 (match_operator 5 "subreg_lowpart_operator"
4343 [(match_operand:SI 4 "s_register_operand" "")]))))]
4344 "TARGET_32BIT
63787642 4345 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4346 == (GET_MODE_MASK (GET_MODE (operands[5]))
4347 & (GET_MODE_MASK (GET_MODE (operands[5]))
4348 << (INTVAL (operands[2])))))"
4349 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4350 (match_dup 4)))
4351 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4352 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4353)
4354
f7fbdd4a 4355(define_insn "*compareqi_eq0"
bd5b4116 4356 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4357 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4358 (const_int 0)))]
25f905c2 4359 "TARGET_32BIT"
87b22bf7 4360 "tst\\t%0, #255"
cffb2a26 4361 [(set_attr "conds" "set")]
4362)
b11cae9e 4363
b11cae9e 4364(define_expand "extendhisi2"
ef51b8e1 4365 [(set (match_operand:SI 0 "s_register_operand" "")
4366 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4367 "TARGET_EITHER"
ef51b8e1 4368{
4369 if (TARGET_THUMB1)
4370 {
4371 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4372 DONE;
4373 }
4374 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4375 {
4376 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4377 DONE;
4378 }
ed29c566 4379
ef51b8e1 4380 if (!arm_arch6 && !MEM_P (operands[1]))
4381 {
4382 rtx t = gen_lowpart (SImode, operands[1]);
4383 rtx tmp = gen_reg_rtx (SImode);
4384 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4385 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4386 DONE;
4387 }
4388})
cffb2a26 4389
ef51b8e1 4390(define_split
4391 [(parallel
4392 [(set (match_operand:SI 0 "register_operand" "")
4393 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4394 (clobber (match_scratch:SI 2 ""))])]
4395 "!arm_arch6"
4396 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4397 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4398{
4399 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4400})
25f7a26e 4401
a2cd141b 4402;; We used to have an early-clobber on the scratch register here.
4403;; However, there's a bug somewhere in reload which means that this
4404;; can be partially ignored during spill allocation if the memory
ed29c566 4405;; address also needs reloading; this causes us to die later on when
a2cd141b 4406;; we try to verify the operands. Fortunately, we don't really need
4407;; the early-clobber: we can always use operand 0 if operand 2
4408;; overlaps the address.
ef51b8e1 4409(define_insn "thumb1_extendhisi2"
a2cd141b 4410 [(set (match_operand:SI 0 "register_operand" "=l,l")
4411 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4412 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4413 "TARGET_THUMB1"
a2cd141b 4414 "*
4415 {
4416 rtx ops[4];
4417 rtx mem;
4418
ef51b8e1 4419 if (which_alternative == 0 && !arm_arch6)
4420 return \"#\";
a2cd141b 4421 if (which_alternative == 0)
4422 return \"sxth\\t%0, %1\";
4423
4424 mem = XEXP (operands[1], 0);
4425
4426 /* This code used to try to use 'V', and fix the address only if it was
4427 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4428 range of QImode offsets, and offsettable_address_p does a QImode
4429 address check. */
4430
4431 if (GET_CODE (mem) == CONST)
4432 mem = XEXP (mem, 0);
4433
4434 if (GET_CODE (mem) == LABEL_REF)
4435 return \"ldr\\t%0, %1\";
4436
4437 if (GET_CODE (mem) == PLUS)
4438 {
4439 rtx a = XEXP (mem, 0);
4440 rtx b = XEXP (mem, 1);
4441
4442 if (GET_CODE (a) == LABEL_REF
4443 && GET_CODE (b) == CONST_INT)
4444 return \"ldr\\t%0, %1\";
4445
4446 if (GET_CODE (b) == REG)
4447 return \"ldrsh\\t%0, %1\";
4448
4449 ops[1] = a;
4450 ops[2] = b;
4451 }
4452 else
4453 {
4454 ops[1] = mem;
4455 ops[2] = const0_rtx;
4456 }
4457
ed29c566 4458 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4459
4460 ops[0] = operands[0];
4461 if (reg_mentioned_p (operands[2], ops[1]))
4462 ops[3] = ops[0];
4463 else
4464 ops[3] = operands[2];
4465 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4466 return \"\";
4467 }"
ef51b8e1 4468 [(set_attr_alternative "length"
4469 [(if_then_else (eq_attr "is_arch6" "yes")
4470 (const_int 2) (const_int 4))
4471 (const_int 4)])
a2cd141b 4472 (set_attr "type" "alu_shift,load_byte")
4473 (set_attr "pool_range" "*,1020")]
4474)
4475
25f905c2 4476;; This pattern will only be used when ldsh is not available
25f7a26e 4477(define_expand "extendhisi2_mem"
eab14235 4478 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4479 (set (match_dup 3)
eab14235 4480 (zero_extend:SI (match_dup 7)))
25f7a26e 4481 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4482 (set (match_operand:SI 0 "" "")
4483 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4484 "TARGET_ARM"
25f7a26e 4485 "
215b30b3 4486 {
4487 rtx mem1, mem2;
4488 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4489
788fcce0 4490 mem1 = change_address (operands[1], QImode, addr);
4491 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4492 operands[0] = gen_lowpart (SImode, operands[0]);
4493 operands[1] = mem1;
4494 operands[2] = gen_reg_rtx (SImode);
4495 operands[3] = gen_reg_rtx (SImode);
4496 operands[6] = gen_reg_rtx (SImode);
4497 operands[7] = mem2;
25f7a26e 4498
215b30b3 4499 if (BYTES_BIG_ENDIAN)
4500 {
4501 operands[4] = operands[2];
4502 operands[5] = operands[3];
4503 }
4504 else
4505 {
4506 operands[4] = operands[3];
4507 operands[5] = operands[2];
4508 }
4509 }"
4510)
b11cae9e 4511
ef51b8e1 4512(define_split
4513 [(set (match_operand:SI 0 "register_operand" "")
4514 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4515 "!arm_arch6"
4516 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4517 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4518{
4519 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4520})
4521
a2cd141b 4522(define_insn "*arm_extendhisi2"
ef51b8e1 4523 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4524 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4525 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4526 "@
4527 #
4528 ldr%(sh%)\\t%0, %1"
4529 [(set_attr "length" "8,4")
4530 (set_attr "type" "alu_shift,load_byte")
0d66636f 4531 (set_attr "predicable" "yes")
ef51b8e1 4532 (set_attr "pool_range" "*,256")
4533 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4534)
f7fbdd4a 4535
25f905c2 4536;; ??? Check Thumb-2 pool range
a2cd141b 4537(define_insn "*arm_extendhisi2_v6"
4538 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4539 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4540 "TARGET_32BIT && arm_arch6"
a2cd141b 4541 "@
4542 sxth%?\\t%0, %1
25f905c2 4543 ldr%(sh%)\\t%0, %1"
a2cd141b 4544 [(set_attr "type" "alu_shift,load_byte")
4545 (set_attr "predicable" "yes")
4546 (set_attr "pool_range" "*,256")
4547 (set_attr "neg_pool_range" "*,244")]
4548)
4549
4550(define_insn "*arm_extendhisi2addsi"
4551 [(set (match_operand:SI 0 "s_register_operand" "=r")
4552 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4553 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4554 "TARGET_INT_SIMD"
a2cd141b 4555 "sxtah%?\\t%0, %2, %1"
4556)
4557
c8f69309 4558(define_expand "extendqihi2"
4559 [(set (match_dup 2)
bed7d9a5 4560 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4561 (const_int 24)))
9c08d1fa 4562 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4563 (ashiftrt:SI (match_dup 2)
4564 (const_int 24)))]
cffb2a26 4565 "TARGET_ARM"
c8f69309 4566 "
215b30b3 4567 {
4568 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4569 {
4570 emit_insn (gen_rtx_SET (VOIDmode,
4571 operands[0],
4572 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4573 DONE;
4574 }
4575 if (!s_register_operand (operands[1], QImode))
4576 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4577 operands[0] = gen_lowpart (SImode, operands[0]);
4578 operands[1] = gen_lowpart (SImode, operands[1]);
4579 operands[2] = gen_reg_rtx (SImode);
4580 }"
4581)
f7fbdd4a 4582
25f905c2 4583(define_insn "*arm_extendqihi_insn"
b4e8a300 4584 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4585 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4586 "TARGET_ARM && arm_arch4"
25f905c2 4587 "ldr%(sb%)\\t%0, %1"
a2cd141b 4588 [(set_attr "type" "load_byte")
0d66636f 4589 (set_attr "predicable" "yes")
cffb2a26 4590 (set_attr "pool_range" "256")
4591 (set_attr "neg_pool_range" "244")]
4592)
3fc2009e 4593
b11cae9e 4594(define_expand "extendqisi2"
ef51b8e1 4595 [(set (match_operand:SI 0 "s_register_operand" "")
4596 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 4597 "TARGET_EITHER"
ef51b8e1 4598{
4599 if (!arm_arch4 && MEM_P (operands[1]))
4600 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4601
ef51b8e1 4602 if (!arm_arch6 && !MEM_P (operands[1]))
4603 {
4604 rtx t = gen_lowpart (SImode, operands[1]);
4605 rtx tmp = gen_reg_rtx (SImode);
4606 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4607 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4608 DONE;
4609 }
4610})
a2cd141b 4611
ef51b8e1 4612(define_split
4613 [(set (match_operand:SI 0 "register_operand" "")
4614 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4615 "!arm_arch6"
4616 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4617 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4618{
4619 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4620})
f7fbdd4a 4621
a2cd141b 4622(define_insn "*arm_extendqisi"
ef51b8e1 4623 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4624 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4625 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4626 "@
4627 #
4628 ldr%(sb%)\\t%0, %1"
4629 [(set_attr "length" "8,4")
4630 (set_attr "type" "alu_shift,load_byte")
0d66636f 4631 (set_attr "predicable" "yes")
ef51b8e1 4632 (set_attr "pool_range" "*,256")
4633 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4634)
3fc2009e 4635
a2cd141b 4636(define_insn "*arm_extendqisi_v6"
4637 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4638 (sign_extend:SI
4639 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4640 "TARGET_ARM && arm_arch6"
b4e8a300 4641 "@
4642 sxtb%?\\t%0, %1
25f905c2 4643 ldr%(sb%)\\t%0, %1"
a2cd141b 4644 [(set_attr "type" "alu_shift,load_byte")
4645 (set_attr "predicable" "yes")
a2cd141b 4646 (set_attr "pool_range" "*,256")
4647 (set_attr "neg_pool_range" "*,244")]
4648)
4649
4650(define_insn "*arm_extendqisi2addsi"
4651 [(set (match_operand:SI 0 "s_register_operand" "=r")
4652 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4653 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4654 "TARGET_INT_SIMD"
a2cd141b 4655 "sxtab%?\\t%0, %2, %1"
4656 [(set_attr "type" "alu_shift")
bcaec148 4657 (set_attr "insn" "xtab")
a2cd141b 4658 (set_attr "predicable" "yes")]
4659)
4660
ef51b8e1 4661(define_split
4662 [(set (match_operand:SI 0 "register_operand" "")
4663 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4664 "TARGET_THUMB1 && reload_completed"
4665 [(set (match_dup 0) (match_dup 2))
4666 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4667{
4668 rtx addr = XEXP (operands[1], 0);
cffb2a26 4669
ef51b8e1 4670 if (GET_CODE (addr) == CONST)
4671 addr = XEXP (addr, 0);
cffb2a26 4672
ef51b8e1 4673 if (GET_CODE (addr) == PLUS
4674 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4675 /* No split necessary. */
4676 FAIL;
4677
4678 if (GET_CODE (addr) == PLUS
4679 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4680 FAIL;
4681
4682 if (reg_overlap_mentioned_p (operands[0], addr))
4683 {
4684 rtx t = gen_lowpart (QImode, operands[0]);
4685 emit_move_insn (t, operands[1]);
4686 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4687 DONE;
4688 }
4689
4690 if (REG_P (addr))
4691 {
4692 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4693 operands[2] = const0_rtx;
4694 }
4695 else if (GET_CODE (addr) != PLUS)
4696 FAIL;
4697 else if (REG_P (XEXP (addr, 0)))
4698 {
4699 operands[2] = XEXP (addr, 1);
4700 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4701 }
4702 else
4703 {
4704 operands[2] = XEXP (addr, 0);
4705 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4706 }
cffb2a26 4707
ef51b8e1 4708 operands[3] = change_address (operands[1], QImode, addr);
4709})
4710
8a3b73a1 4711(define_peephole2
4712 [(set (match_operand:SI 0 "register_operand" "")
4713 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4714 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4715 (set (match_operand:SI 3 "register_operand" "")
4716 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4717 "TARGET_THUMB1
4718 && GET_CODE (XEXP (operands[4], 0)) == PLUS
4719 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4720 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4721 && (peep2_reg_dead_p (3, operands[0])
4722 || rtx_equal_p (operands[0], operands[3]))
4723 && (peep2_reg_dead_p (3, operands[2])
4724 || rtx_equal_p (operands[2], operands[3]))"
4725 [(set (match_dup 2) (match_dup 1))
4726 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4727{
4728 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4729 operands[4] = change_address (operands[4], QImode, addr);
4730})
4731
ef51b8e1 4732(define_insn "thumb1_extendqisi2"
a2cd141b 4733 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4734 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 4735 "TARGET_THUMB1"
4736{
4737 rtx addr;
a2cd141b 4738
ef51b8e1 4739 if (which_alternative == 0 && arm_arch6)
4740 return "sxtb\\t%0, %1";
4741 if (which_alternative == 0)
4742 return "#";
a2cd141b 4743
ef51b8e1 4744 addr = XEXP (operands[1], 0);
4745 if (GET_CODE (addr) == PLUS
4746 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4747 return "ldrsb\\t%0, %1";
a2cd141b 4748
ef51b8e1 4749 return "#";
4750}
4751 [(set_attr_alternative "length"
4752 [(if_then_else (eq_attr "is_arch6" "yes")
4753 (const_int 2) (const_int 4))
4754 (const_int 2)
4755 (if_then_else (eq_attr "is_arch6" "yes")
4756 (const_int 4) (const_int 6))])
4757 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 4758)
4759
caedf871 4760(define_expand "extendsfdf2"
4761 [(set (match_operand:DF 0 "s_register_operand" "")
4762 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4763 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4764 ""
4765)
9b8516be 4766
4767/* HFmode -> DFmode conversions have to go through SFmode. */
4768(define_expand "extendhfdf2"
4769 [(set (match_operand:DF 0 "general_operand" "")
4770 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4771 "TARGET_EITHER"
4772 "
4773 {
4774 rtx op1;
4775 op1 = convert_to_mode (SFmode, operands[1], 0);
4776 op1 = convert_to_mode (DFmode, op1, 0);
4777 emit_insn (gen_movdf (operands[0], op1));
4778 DONE;
4779 }"
4780)
b11cae9e 4781\f
4782;; Move insns (including loads and stores)
4783
4784;; XXX Just some ideas about movti.
9c08d1fa 4785;; I don't think these are a good idea on the arm, there just aren't enough
4786;; registers
b11cae9e 4787;;(define_expand "loadti"
9c08d1fa 4788;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4789;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4790;; "" "")
4791
4792;;(define_expand "storeti"
4793;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4794;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4795;; "" "")
4796
4797;;(define_expand "movti"
4798;; [(set (match_operand:TI 0 "general_operand" "")
4799;; (match_operand:TI 1 "general_operand" ""))]
4800;; ""
4801;; "
4802;;{
4803;; rtx insn;
4804;;
4805;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4806;; operands[1] = copy_to_reg (operands[1]);
4807;; if (GET_CODE (operands[0]) == MEM)
4808;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4809;; else if (GET_CODE (operands[1]) == MEM)
4810;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4811;; else
4812;; FAIL;
4813;;
4814;; emit_insn (insn);
4815;; DONE;
4816;;}")
4817
a2f10574 4818;; Recognize garbage generated above.
b11cae9e 4819
4820;;(define_insn ""
4821;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4822;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4823;; ""
4824;; "*
4825;; {
4826;; register mem = (which_alternative < 3);
0d66636f 4827;; register const char *template;
b11cae9e 4828;;
4829;; operands[mem] = XEXP (operands[mem], 0);
4830;; switch (which_alternative)
4831;; {
4832;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4833;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4834;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4835;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4836;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4837;; case 5: template = \"stmia\\t%0, %M1\"; break;
4838;; }
e2348bcb 4839;; output_asm_insn (template, operands);
4840;; return \"\";
b11cae9e 4841;; }")
4842
cffb2a26 4843(define_expand "movdi"
4844 [(set (match_operand:DI 0 "general_operand" "")
4845 (match_operand:DI 1 "general_operand" ""))]
4846 "TARGET_EITHER"
4847 "
e1ba4a27 4848 if (can_create_pseudo_p ())
cffb2a26 4849 {
b2778788 4850 if (GET_CODE (operands[0]) != REG)
4851 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4852 }
4853 "
4854)
b11cae9e 4855
cffb2a26 4856(define_insn "*arm_movdi"
d51f92df 4857 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4858 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 4859 "TARGET_32BIT
b2778788 4860 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4861 && !TARGET_IWMMXT
4862 && ( register_operand (operands[0], DImode)
4863 || register_operand (operands[1], DImode))"
b11cae9e 4864 "*
d51f92df 4865 switch (which_alternative)
4866 {
4867 case 0:
4868 case 1:
4869 case 2:
4870 return \"#\";
4871 default:
4872 return output_move_double (operands);
4873 }
cffb2a26 4874 "
359a6e9f 4875 [(set_attr "length" "8,12,16,8,8")
4876 (set_attr "type" "*,*,*,load2,store2")
cde1623a 4877 (set_attr "arm_pool_range" "*,*,*,1020,*")
4878 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
4879 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
4880 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 4881)
4882
d51f92df 4883(define_split
4884 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4885 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4886 "TARGET_32BIT
d51f92df 4887 && reload_completed
4888 && (arm_const_double_inline_cost (operands[1])
4889 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4890 [(const_int 0)]
4891 "
4892 arm_split_constant (SET, SImode, curr_insn,
4893 INTVAL (gen_lowpart (SImode, operands[1])),
4894 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4895 arm_split_constant (SET, SImode, curr_insn,
4896 INTVAL (gen_highpart_mode (SImode,
4897 GET_MODE (operands[0]),
4898 operands[1])),
4899 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4900 DONE;
4901 "
4902)
4903
e5ba9289 4904; If optimizing for size, or if we have load delay slots, then
4905; we want to split the constant into two separate operations.
4906; In both cases this may split a trivial part into a single data op
4907; leaving a single complex constant to load. We can also get longer
4908; offsets in a LDR which means we get better chances of sharing the pool
4909; entries. Finally, we can normally do a better job of scheduling
4910; LDR instructions than we can with LDM.
4911; This pattern will only match if the one above did not.
4912(define_split
4913 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4914 (match_operand:ANY64 1 "const_double_operand" ""))]
4915 "TARGET_ARM && reload_completed
4916 && arm_const_double_by_parts (operands[1])"
4917 [(set (match_dup 0) (match_dup 1))
4918 (set (match_dup 2) (match_dup 3))]
4919 "
4920 operands[2] = gen_highpart (SImode, operands[0]);
4921 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4922 operands[1]);
4923 operands[0] = gen_lowpart (SImode, operands[0]);
4924 operands[1] = gen_lowpart (SImode, operands[1]);
4925 "
4926)
4927
d51f92df 4928(define_split
4929 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4930 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4931 "TARGET_EITHER && reload_completed"
4932 [(set (match_dup 0) (match_dup 1))
4933 (set (match_dup 2) (match_dup 3))]
4934 "
4935 operands[2] = gen_highpart (SImode, operands[0]);
4936 operands[3] = gen_highpart (SImode, operands[1]);
4937 operands[0] = gen_lowpart (SImode, operands[0]);
4938 operands[1] = gen_lowpart (SImode, operands[1]);
4939
4940 /* Handle a partial overlap. */
4941 if (rtx_equal_p (operands[0], operands[3]))
4942 {
4943 rtx tmp0 = operands[0];
4944 rtx tmp1 = operands[1];
4945
4946 operands[0] = operands[2];
4947 operands[1] = operands[3];
4948 operands[2] = tmp0;
4949 operands[3] = tmp1;
4950 }
4951 "
4952)
4953
a8a3b539 4954;; We can't actually do base+index doubleword loads if the index and
4955;; destination overlap. Split here so that we at least have chance to
4956;; schedule.
4957(define_split
4958 [(set (match_operand:DI 0 "s_register_operand" "")
4959 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4960 (match_operand:SI 2 "s_register_operand" ""))))]
4961 "TARGET_LDRD
4962 && reg_overlap_mentioned_p (operands[0], operands[1])
4963 && reg_overlap_mentioned_p (operands[0], operands[2])"
4964 [(set (match_dup 4)
4965 (plus:SI (match_dup 1)
4966 (match_dup 2)))
4967 (set (match_dup 0)
4968 (mem:DI (match_dup 4)))]
4969 "
4970 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4971 "
4972)
4973
cffb2a26 4974;;; ??? This should have alternatives for constants.
4975;;; ??? This was originally identical to the movdf_insn pattern.
4976;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4977;;; thumb_reorg with a memory reference.
25f905c2 4978(define_insn "*thumb1_movdi_insn"
215b30b3 4979 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4980 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4981 "TARGET_THUMB1
a2cd141b 4982 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4983 && ( register_operand (operands[0], DImode)
4984 || register_operand (operands[1], DImode))"
4985 "*
4986 {
4987 switch (which_alternative)
4988 {
4989 default:
4990 case 0:
4991 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4992 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4993 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4994 case 1:
4995 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4996 case 2:
4997 operands[1] = GEN_INT (- INTVAL (operands[1]));
4998 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4999 case 3:
5000 return \"ldmia\\t%1, {%0, %H0}\";
5001 case 4:
5002 return \"stmia\\t%0, {%1, %H1}\";
5003 case 5:
5004 return thumb_load_double_from_address (operands);
5005 case 6:
1a83b3ff 5006 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5007 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5008 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5009 return \"\";
5010 case 7:
5011 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5012 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5013 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5014 }
5015 }"
5016 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5017 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5018 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5019 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5020)
b11cae9e 5021
9c08d1fa 5022(define_expand "movsi"
5023 [(set (match_operand:SI 0 "general_operand" "")
5024 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5025 "TARGET_EITHER"
9c08d1fa 5026 "
befb0bac 5027 {
e348ff3e 5028 rtx base, offset, tmp;
5029
25f905c2 5030 if (TARGET_32BIT)
9c08d1fa 5031 {
674a8f0b 5032 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5033 if (GET_CODE (operands[0]) == MEM)
5034 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5035 if (arm_general_register_operand (operands[0], SImode)
5036 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5037 && !(const_ok_for_arm (INTVAL (operands[1]))
5038 || const_ok_for_arm (~INTVAL (operands[1]))))
5039 {
96f57e36 5040 arm_split_constant (SET, SImode, NULL_RTX,
5041 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5042 optimize && can_create_pseudo_p ());
cffb2a26 5043 DONE;
5044 }
d0e6a121 5045
5046 if (TARGET_USE_MOVT && !target_word_relocations
5047 && GET_CODE (operands[1]) == SYMBOL_REF
5048 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5049 {
5050 arm_emit_movpair (operands[0], operands[1]);
5051 DONE;
5052 }
cffb2a26 5053 }
25f905c2 5054 else /* TARGET_THUMB1... */
cffb2a26 5055 {
e1ba4a27 5056 if (can_create_pseudo_p ())
cffb2a26 5057 {
5058 if (GET_CODE (operands[0]) != REG)
5059 operands[1] = force_reg (SImode, operands[1]);
5060 }
9c08d1fa 5061 }
f655717d 5062
e348ff3e 5063 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5064 {
5065 split_const (operands[1], &base, &offset);
5066 if (GET_CODE (base) == SYMBOL_REF
5067 && !offset_within_block_p (base, INTVAL (offset)))
5068 {
b308ddcf 5069 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5070 emit_move_insn (tmp, base);
5071 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5072 DONE;
5073 }
5074 }
5075
f655717d 5076 /* Recognize the case where operand[1] is a reference to thread-local
5077 data and load its address to a register. */
5078 if (arm_tls_referenced_p (operands[1]))
5079 {
5080 rtx tmp = operands[1];
5081 rtx addend = NULL;
5082
5083 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5084 {
5085 addend = XEXP (XEXP (tmp, 0), 1);
5086 tmp = XEXP (XEXP (tmp, 0), 0);
5087 }
5088
5089 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5090 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5091
e1ba4a27 5092 tmp = legitimize_tls_address (tmp,
5093 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5094 if (addend)
5095 {
5096 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5097 tmp = force_operand (tmp, operands[0]);
5098 }
5099 operands[1] = tmp;
5100 }
5101 else if (flag_pic
5102 && (CONSTANT_P (operands[1])
5103 || symbol_mentioned_p (operands[1])
5104 || label_mentioned_p (operands[1])))
5105 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5106 (!can_create_pseudo_p ()
5107 ? operands[0]
5108 : 0));
befb0bac 5109 }
215b30b3 5110 "
5111)
9c08d1fa 5112
d0e6a121 5113;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5114;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5115;; so this does not matter.
5116(define_insn "*arm_movt"
5117 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5118 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5119 (match_operand:SI 2 "general_operand" "i")))]
5120 "TARGET_32BIT"
5121 "movt%?\t%0, #:upper16:%c2"
5122 [(set_attr "predicable" "yes")
5123 (set_attr "length" "4")]
5124)
5125
cffb2a26 5126(define_insn "*arm_movsi_insn"
aaa37ad6 5127 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5128 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5129 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5130 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5131 && ( register_operand (operands[0], SImode)
5132 || register_operand (operands[1], SImode))"
f7fbdd4a 5133 "@
aaa37ad6 5134 mov%?\\t%0, %1
f7fbdd4a 5135 mov%?\\t%0, %1
5136 mvn%?\\t%0, #%B1
25f905c2 5137 movw%?\\t%0, %1
f7fbdd4a 5138 ldr%?\\t%0, %1
5139 str%?\\t%1, %0"
aaa37ad6 5140 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5141 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5142 (set_attr "predicable" "yes")
aaa37ad6 5143 (set_attr "pool_range" "*,*,*,*,4096,*")
5144 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5145)
87b22bf7 5146
5147(define_split
a2cd141b 5148 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5149 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5150 "TARGET_32BIT
215b30b3 5151 && (!(const_ok_for_arm (INTVAL (operands[1]))
5152 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5153 [(clobber (const_int 0))]
5154 "
96f57e36 5155 arm_split_constant (SET, SImode, NULL_RTX,
5156 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5157 DONE;
215b30b3 5158 "
5159)
9c08d1fa 5160
25f905c2 5161(define_insn "*thumb1_movsi_insn"
aaa37ad6 5162 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5163 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
25f905c2 5164 "TARGET_THUMB1
cffb2a26 5165 && ( register_operand (operands[0], SImode)
5166 || register_operand (operands[1], SImode))"
5167 "@
5168 mov %0, %1
5169 mov %0, %1
5170 #
5171 #
5172 ldmia\\t%1, {%0}
5173 stmia\\t%0, {%1}
5174 ldr\\t%0, %1
5175 str\\t%1, %0
5176 mov\\t%0, %1"
5177 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5178 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5179 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5180 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5181
5182(define_split
5183 [(set (match_operand:SI 0 "register_operand" "")
5184 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5185 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5186 [(set (match_dup 2) (match_dup 1))
5187 (set (match_dup 0) (neg:SI (match_dup 2)))]
5188 "
5189 {
5190 operands[1] = GEN_INT (- INTVAL (operands[1]));
5191 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5192 }"
cffb2a26 5193)
5194
5195(define_split
5196 [(set (match_operand:SI 0 "register_operand" "")
5197 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5198 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5199 [(set (match_dup 2) (match_dup 1))
5200 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5201 "
5202 {
e4aeee53 5203 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5204 unsigned HOST_WIDE_INT mask = 0xff;
5205 int i;
5206
5207 for (i = 0; i < 25; i++)
5208 if ((val & (mask << i)) == val)
5209 break;
5210
1276f1b8 5211 /* Don't split if the shift is zero. */
cffb2a26 5212 if (i == 0)
5213 FAIL;
5214
5215 operands[1] = GEN_INT (val >> i);
1276f1b8 5216 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5217 operands[3] = GEN_INT (i);
cffb2a26 5218 }"
5219)
5220
67336bcf 5221;; When generating pic, we need to load the symbol offset into a register.
5222;; So that the optimizer does not confuse this with a normal symbol load
5223;; we use an unspec. The offset will be loaded from a constant pool entry,
5224;; since that is the only type of relocation we can use.
5225
94f8caca 5226;; Wrap calculation of the whole PIC address in a single pattern for the
5227;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5228;; a PIC address involves two loads from memory, so we want to CSE it
5229;; as often as possible.
5230;; This pattern will be split into one of the pic_load_addr_* patterns
5231;; and a move after GCSE optimizations.
5232;;
5233;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5234(define_expand "calculate_pic_address"
5235 [(set (match_operand:SI 0 "register_operand" "")
5236 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5237 (unspec:SI [(match_operand:SI 2 "" "")]
5238 UNSPEC_PIC_SYM))))]
5239 "flag_pic"
5240)
5241
5242;; Split calculate_pic_address into pic_load_addr_* and a move.
5243(define_split
5244 [(set (match_operand:SI 0 "register_operand" "")
5245 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5246 (unspec:SI [(match_operand:SI 2 "" "")]
5247 UNSPEC_PIC_SYM))))]
5248 "flag_pic"
5249 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5250 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5251 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5252)
5253
67336bcf 5254;; The rather odd constraints on the following are to force reload to leave
5255;; the insn alone, and to force the minipool generation pass to then move
5256;; the GOT symbol to memory.
849170fd 5257
b3cd5f55 5258(define_insn "pic_load_addr_32bit"
849170fd 5259 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5260 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5261 "TARGET_32BIT && flag_pic"
67336bcf 5262 "ldr%?\\t%0, %1"
a2cd141b 5263 [(set_attr "type" "load1")
b3cd5f55 5264 (set_attr "pool_range" "4096")
5265 (set (attr "neg_pool_range")
5266 (if_then_else (eq_attr "is_thumb" "no")
5267 (const_int 4084)
5268 (const_int 0)))]
8c4d8060 5269)
5270
25f905c2 5271(define_insn "pic_load_addr_thumb1"
8c4d8060 5272 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5273 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5274 "TARGET_THUMB1 && flag_pic"
8c4d8060 5275 "ldr\\t%0, %1"
a2cd141b 5276 [(set_attr "type" "load1")
8c4d8060 5277 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5278)
849170fd 5279
cffb2a26 5280(define_insn "pic_add_dot_plus_four"
15d5d060 5281 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5282 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5283 (const_int 4)
beef0fb5 5284 (match_operand 2 "" "")]
5285 UNSPEC_PIC_BASE))]
b3cd5f55 5286 "TARGET_THUMB"
cffb2a26 5287 "*
6cdcb15c 5288 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5289 INTVAL (operands[2]));
cffb2a26 5290 return \"add\\t%0, %|pc\";
5291 "
5292 [(set_attr "length" "2")]
5293)
849170fd 5294
5295(define_insn "pic_add_dot_plus_eight"
15d5d060 5296 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5297 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5298 (const_int 8)
beef0fb5 5299 (match_operand 2 "" "")]
5300 UNSPEC_PIC_BASE))]
f655717d 5301 "TARGET_ARM"
c4034607 5302 "*
6cdcb15c 5303 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5304 INTVAL (operands[2]));
15d5d060 5305 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5306 "
0d66636f 5307 [(set_attr "predicable" "yes")]
cffb2a26 5308)
849170fd 5309
f655717d 5310(define_insn "tls_load_dot_plus_eight"
cc071db6 5311 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5312 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5313 (const_int 8)
beef0fb5 5314 (match_operand 2 "" "")]
5315 UNSPEC_PIC_BASE)))]
f655717d 5316 "TARGET_ARM"
5317 "*
6cdcb15c 5318 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5319 INTVAL (operands[2]));
f655717d 5320 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5321 "
5322 [(set_attr "predicable" "yes")]
5323)
5324
5325;; PIC references to local variables can generate pic_add_dot_plus_eight
5326;; followed by a load. These sequences can be crunched down to
5327;; tls_load_dot_plus_eight by a peephole.
5328
5329(define_peephole2
c0c1fba5 5330 [(set (match_operand:SI 0 "register_operand" "")
5331 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5332 (const_int 8)
5333 (match_operand 1 "" "")]
5334 UNSPEC_PIC_BASE))
f655717d 5335 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5336 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5337 [(set (match_dup 2)
5338 (mem:SI (unspec:SI [(match_dup 3)
5339 (const_int 8)
5340 (match_dup 1)]
5341 UNSPEC_PIC_BASE)))]
f655717d 5342 ""
5343)
5344
bac7fc85 5345(define_insn "pic_offset_arm"
5346 [(set (match_operand:SI 0 "register_operand" "=r")
5347 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5348 (unspec:SI [(match_operand:SI 2 "" "X")]
5349 UNSPEC_PIC_OFFSET))))]
5350 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5351 "ldr%?\\t%0, [%1,%2]"
5352 [(set_attr "type" "load1")]
5353)
5354
95373f08 5355(define_expand "builtin_setjmp_receiver"
5356 [(label_ref (match_operand 0 "" ""))]
5357 "flag_pic"
5358 "
5359{
b935b306 5360 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5361 register. */
2cb7d577 5362 if (arm_pic_register != INVALID_REGNUM)
5363 arm_load_pic_register (1UL << 3);
95373f08 5364 DONE;
5365}")
5366
9c08d1fa 5367;; If copying one reg to another we can set the condition codes according to
5368;; its value. Such a move is common after a return from subroutine and the
5369;; result is being tested against zero.
5370
f7fbdd4a 5371(define_insn "*movsi_compare0"
bd5b4116 5372 [(set (reg:CC CC_REGNUM)
cffb2a26 5373 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5374 (const_int 0)))
5375 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5376 (match_dup 1))]
25f905c2 5377 "TARGET_32BIT"
e2348bcb 5378 "@
40dbec34 5379 cmp%?\\t%0, #0
25f905c2 5380 sub%.\\t%0, %1, #0"
cffb2a26 5381 [(set_attr "conds" "set")]
5382)
b11cae9e 5383
b11cae9e 5384;; Subroutine to store a half word from a register into memory.
5385;; Operand 0 is the source register (HImode)
c8f69309 5386;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5387
9c08d1fa 5388;; In both this routine and the next, we must be careful not to spill
01cc3b75 5389;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5390;; can generate unrecognizable rtl.
5391
b11cae9e 5392(define_expand "storehi"
c8f69309 5393 [;; store the low byte
f082f1c4 5394 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5395 ;; extract the high byte
c8f69309 5396 (set (match_dup 2)
5397 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5398 ;; store the high byte
787f8210 5399 (set (match_dup 4) (match_dup 5))]
cffb2a26 5400 "TARGET_ARM"
b11cae9e 5401 "
215b30b3 5402 {
537ffcfc 5403 rtx op1 = operands[1];
5404 rtx addr = XEXP (op1, 0);
215b30b3 5405 enum rtx_code code = GET_CODE (addr);
5406
5407 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5408 || code == MINUS)
537ffcfc 5409 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5410
537ffcfc 5411 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5412 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5413 operands[3] = gen_lowpart (QImode, operands[0]);
5414 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5415 operands[2] = gen_reg_rtx (SImode);
5416 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5417 }"
5418)
b11cae9e 5419
c7597b5d 5420(define_expand "storehi_bigend"
f082f1c4 5421 [(set (match_dup 4) (match_dup 3))
c7597b5d 5422 (set (match_dup 2)
5423 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5424 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5425 "TARGET_ARM"
b11cae9e 5426 "
215b30b3 5427 {
537ffcfc 5428 rtx op1 = operands[1];
5429 rtx addr = XEXP (op1, 0);
215b30b3 5430 enum rtx_code code = GET_CODE (addr);
5431
5432 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5433 || code == MINUS)
537ffcfc 5434 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5435
537ffcfc 5436 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5437 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5438 operands[3] = gen_lowpart (QImode, operands[0]);
5439 operands[0] = gen_lowpart (SImode, operands[0]);
5440 operands[2] = gen_reg_rtx (SImode);
787f8210 5441 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5442 }"
5443)
c7597b5d 5444
5445;; Subroutine to store a half word integer constant into memory.
5446(define_expand "storeinthi"
f082f1c4 5447 [(set (match_operand 0 "" "")
787f8210 5448 (match_operand 1 "" ""))
9e8503e6 5449 (set (match_dup 3) (match_dup 2))]
cffb2a26 5450 "TARGET_ARM"
c7597b5d 5451 "
215b30b3 5452 {
5453 HOST_WIDE_INT value = INTVAL (operands[1]);
5454 rtx addr = XEXP (operands[0], 0);
537ffcfc 5455 rtx op0 = operands[0];
215b30b3 5456 enum rtx_code code = GET_CODE (addr);
c7597b5d 5457
215b30b3 5458 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5459 || code == MINUS)
537ffcfc 5460 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5461
215b30b3 5462 operands[1] = gen_reg_rtx (SImode);
5463 if (BYTES_BIG_ENDIAN)
5464 {
5465 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5466 if ((value & 255) == ((value >> 8) & 255))
5467 operands[2] = operands[1];
5468 else
5469 {
5470 operands[2] = gen_reg_rtx (SImode);
5471 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5472 }
5473 }
5474 else
5475 {
5476 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5477 if ((value & 255) == ((value >> 8) & 255))
5478 operands[2] = operands[1];
5479 else
5480 {
5481 operands[2] = gen_reg_rtx (SImode);
5482 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5483 }
5484 }
c7597b5d 5485
537ffcfc 5486 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5487 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5488 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5489 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5490 }"
5491)
b11cae9e 5492
f7fbdd4a 5493(define_expand "storehi_single_op"
5494 [(set (match_operand:HI 0 "memory_operand" "")
5495 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5496 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5497 "
215b30b3 5498 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5499 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5500 "
5501)
f7fbdd4a 5502
b11cae9e 5503(define_expand "movhi"
5504 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5505 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5506 "TARGET_EITHER"
b11cae9e 5507 "
cffb2a26 5508 if (TARGET_ARM)
b11cae9e 5509 {
e1ba4a27 5510 if (can_create_pseudo_p ())
cffb2a26 5511 {
5512 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5513 {
cffb2a26 5514 if (arm_arch4)
5515 {
5516 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5517 DONE;
5518 }
5519 if (GET_CODE (operands[1]) == CONST_INT)
5520 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5521 else
cffb2a26 5522 {
5523 if (GET_CODE (operands[1]) == MEM)
5524 operands[1] = force_reg (HImode, operands[1]);
5525 if (BYTES_BIG_ENDIAN)
5526 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5527 else
5528 emit_insn (gen_storehi (operands[1], operands[0]));
5529 }
5530 DONE;
b11cae9e 5531 }
cffb2a26 5532 /* Sign extend a constant, and keep it in an SImode reg. */
5533 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5534 {
cffb2a26 5535 rtx reg = gen_reg_rtx (SImode);
5536 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5537
5538 /* If the constant is already valid, leave it alone. */
215b30b3 5539 if (!const_ok_for_arm (val))
cffb2a26 5540 {
5541 /* If setting all the top bits will make the constant
5542 loadable in a single instruction, then set them.
5543 Otherwise, sign extend the number. */
5544
215b30b3 5545 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5546 val |= ~0xffff;
5547 else if (val & 0x8000)
5548 val |= ~0xffff;
5549 }
5550
5551 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5552 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5553 }
e1ba4a27 5554 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5555 && GET_CODE (operands[1]) == MEM)
5556 {
5557 rtx reg = gen_reg_rtx (SImode);
5558
5559 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5560 operands[1] = gen_lowpart (HImode, reg);
5561 }
215b30b3 5562 else if (!arm_arch4)
f7fbdd4a 5563 {
cffb2a26 5564 if (GET_CODE (operands[1]) == MEM)
5565 {
c1a66faf 5566 rtx base;
5567 rtx offset = const0_rtx;
5568 rtx reg = gen_reg_rtx (SImode);
5569
5570 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5571 || (GET_CODE (base) == PLUS
5572 && (GET_CODE (offset = XEXP (base, 1))
5573 == CONST_INT)
5574 && ((INTVAL(offset) & 1) != 1)
5575 && GET_CODE (base = XEXP (base, 0)) == REG))
5576 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5577 {
8deb3959 5578 rtx new_rtx;
c1a66faf 5579
8deb3959 5580 new_rtx = widen_memory_access (operands[1], SImode,
5581 ((INTVAL (offset) & ~3)
5582 - INTVAL (offset)));
5583 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5584 if (((INTVAL (offset) & 2) != 0)
5585 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5586 {
5587 rtx reg2 = gen_reg_rtx (SImode);
5588
5589 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5590 reg = reg2;
5591 }
206ee9a2 5592 }
c1a66faf 5593 else
5594 emit_insn (gen_movhi_bytes (reg, operands[1]));
5595
5596 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5597 }
5598 }
5599 }
674a8f0b 5600 /* Handle loading a large integer during reload. */
cffb2a26 5601 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5602 && !const_ok_for_arm (INTVAL (operands[1]))
5603 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5604 {
5605 /* Writing a constant to memory needs a scratch, which should
5606 be handled with SECONDARY_RELOADs. */
ed29c566 5607 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5608
5609 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5610 emit_insn (gen_movsi (operands[0], operands[1]));
5611 DONE;
5612 }
5613 }
25f905c2 5614 else if (TARGET_THUMB2)
5615 {
5616 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5617 if (can_create_pseudo_p ())
25f905c2 5618 {
5619 if (GET_CODE (operands[0]) != REG)
5620 operands[1] = force_reg (HImode, operands[1]);
5621 /* Zero extend a constant, and keep it in an SImode reg. */
5622 else if (GET_CODE (operands[1]) == CONST_INT)
5623 {
5624 rtx reg = gen_reg_rtx (SImode);
5625 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5626
5627 emit_insn (gen_movsi (reg, GEN_INT (val)));
5628 operands[1] = gen_lowpart (HImode, reg);
5629 }
5630 }
5631 }
5632 else /* TARGET_THUMB1 */
cffb2a26 5633 {
e1ba4a27 5634 if (can_create_pseudo_p ())
cffb2a26 5635 {
6cffc037 5636 if (GET_CODE (operands[1]) == CONST_INT)
5637 {
5638 rtx reg = gen_reg_rtx (SImode);
5639
5640 emit_insn (gen_movsi (reg, operands[1]));
5641 operands[1] = gen_lowpart (HImode, reg);
5642 }
cffb2a26 5643
5644 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5645 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5646 virtual register (also rejected as illegitimate for HImode/QImode)
5647 relative address. */
cffb2a26 5648 /* ??? This should perhaps be fixed elsewhere, for instance, in
5649 fixup_stack_1, by checking for other kinds of invalid addresses,
5650 e.g. a bare reference to a virtual register. This may confuse the
5651 alpha though, which must handle this case differently. */
5652 if (GET_CODE (operands[0]) == MEM
215b30b3 5653 && !memory_address_p (GET_MODE (operands[0]),
5654 XEXP (operands[0], 0)))
537ffcfc 5655 operands[0]
5656 = replace_equiv_address (operands[0],
5657 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5658
5659 if (GET_CODE (operands[1]) == MEM
215b30b3 5660 && !memory_address_p (GET_MODE (operands[1]),
5661 XEXP (operands[1], 0)))
537ffcfc 5662 operands[1]
5663 = replace_equiv_address (operands[1],
5664 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5665
5666 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5667 {
5668 rtx reg = gen_reg_rtx (SImode);
5669
5670 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5671 operands[1] = gen_lowpart (HImode, reg);
5672 }
5673
5674 if (GET_CODE (operands[0]) == MEM)
5675 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5676 }
cffb2a26 5677 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5678 && !satisfies_constraint_I (operands[1]))
cffb2a26 5679 {
6cffc037 5680 /* Handle loading a large integer during reload. */
5681
cffb2a26 5682 /* Writing a constant to memory needs a scratch, which should
5683 be handled with SECONDARY_RELOADs. */
ed29c566 5684 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5685
1a83b3ff 5686 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5687 emit_insn (gen_movsi (operands[0], operands[1]));
5688 DONE;
5689 }
b11cae9e 5690 }
cffb2a26 5691 "
5692)
5693
25f905c2 5694(define_insn "*thumb1_movhi_insn"
a941568e 5695 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5696 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5697 "TARGET_THUMB1
cffb2a26 5698 && ( register_operand (operands[0], HImode)
5699 || register_operand (operands[1], HImode))"
5700 "*
5701 switch (which_alternative)
d79300ac 5702 {
cffb2a26 5703 case 0: return \"add %0, %1, #0\";
5704 case 2: return \"strh %1, %0\";
5705 case 3: return \"mov %0, %1\";
5706 case 4: return \"mov %0, %1\";
5707 case 5: return \"mov %0, %1\";
ed29c566 5708 default: gcc_unreachable ();
cffb2a26 5709 case 1:
5710 /* The stack pointer can end up being taken as an index register.
5711 Catch this case here and deal with it. */
5712 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5713 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5714 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5715 {
5716 rtx ops[2];
5717 ops[0] = operands[0];
5718 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5719
5720 output_asm_insn (\"mov %0, %1\", ops);
5721
5722 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5723
5724 }
5725 return \"ldrh %0, %1\";
5726 }"
5727 [(set_attr "length" "2,4,2,2,2,2")
747b7458 5728 (set_attr "type" "*,load1,store1,*,*,*")
5729 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 5730
b11cae9e 5731
25f7a26e 5732(define_expand "movhi_bytes"
eab14235 5733 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5734 (set (match_dup 3)
eab14235 5735 (zero_extend:SI (match_dup 6)))
25f7a26e 5736 (set (match_operand:SI 0 "" "")
5737 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5738 "TARGET_ARM"
25f7a26e 5739 "
215b30b3 5740 {
5741 rtx mem1, mem2;
5742 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5743
788fcce0 5744 mem1 = change_address (operands[1], QImode, addr);
5745 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5746 operands[0] = gen_lowpart (SImode, operands[0]);
5747 operands[1] = mem1;
5748 operands[2] = gen_reg_rtx (SImode);
5749 operands[3] = gen_reg_rtx (SImode);
5750 operands[6] = mem2;
25f7a26e 5751
215b30b3 5752 if (BYTES_BIG_ENDIAN)
5753 {
5754 operands[4] = operands[2];
5755 operands[5] = operands[3];
5756 }
5757 else
5758 {
5759 operands[4] = operands[3];
5760 operands[5] = operands[2];
5761 }
5762 }"
5763)
25f7a26e 5764
c7597b5d 5765(define_expand "movhi_bigend"
5766 [(set (match_dup 2)
5767 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5768 (const_int 16)))
5769 (set (match_dup 3)
5770 (ashiftrt:SI (match_dup 2) (const_int 16)))
5771 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5772 (match_dup 4))]
cffb2a26 5773 "TARGET_ARM"
c7597b5d 5774 "
5775 operands[2] = gen_reg_rtx (SImode);
5776 operands[3] = gen_reg_rtx (SImode);
787f8210 5777 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5778 "
5779)
b11cae9e 5780
a2f10574 5781;; Pattern to recognize insn generated default case above
f7fbdd4a 5782(define_insn "*movhi_insn_arch4"
cde1623a 5783 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5784 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5785 "TARGET_ARM
5786 && arm_arch4
f7fbdd4a 5787 && (GET_CODE (operands[1]) != CONST_INT
5788 || const_ok_for_arm (INTVAL (operands[1]))
5789 || const_ok_for_arm (~INTVAL (operands[1])))"
5790 "@
5791 mov%?\\t%0, %1\\t%@ movhi
5792 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5793 str%(h%)\\t%1, %0\\t%@ movhi
5794 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5795 [(set_attr "type" "*,*,store1,load1")
0d66636f 5796 (set_attr "predicable" "yes")
d2a518d1 5797 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 5798 (set_attr "pool_range" "*,*,*,256")
5799 (set_attr "neg_pool_range" "*,*,*,244")]
5800)
f7fbdd4a 5801
f7fbdd4a 5802(define_insn "*movhi_bytes"
25f7a26e 5803 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5804 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5805 "TARGET_ARM"
25f7a26e 5806 "@
5807 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5808 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 5809 [(set_attr "predicable" "yes")
5810 (set_attr "insn" "mov,mvn")]
0d66636f 5811)
25f7a26e 5812
f90b51f1 5813(define_expand "thumb_movhi_clobber"
5814 [(set (match_operand:HI 0 "memory_operand" "")
5815 (match_operand:HI 1 "register_operand" ""))
5816 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5817 "TARGET_THUMB1"
f90b51f1 5818 "
5819 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5820 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5821 {
5822 emit_insn (gen_movhi (operands[0], operands[1]));
5823 DONE;
5824 }
5825 /* XXX Fixme, need to handle other cases here as well. */
5826 gcc_unreachable ();
5827 "
cffb2a26 5828)
5829
bc5c7e08 5830;; We use a DImode scratch because we may occasionally need an additional
5831;; temporary if the address isn't offsettable -- push_reload doesn't seem
5832;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5833(define_expand "reload_outhi"
cffb2a26 5834 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5835 (match_operand:HI 1 "s_register_operand" "r")
5836 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5837 "TARGET_EITHER"
5838 "if (TARGET_ARM)
5839 arm_reload_out_hi (operands);
5840 else
5841 thumb_reload_out_hi (operands);
d3373b54 5842 DONE;
cffb2a26 5843 "
5844)
d3373b54 5845
25f7a26e 5846(define_expand "reload_inhi"
5847 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5848 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5849 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5850 "TARGET_EITHER"
25f7a26e 5851 "
cffb2a26 5852 if (TARGET_ARM)
5853 arm_reload_in_hi (operands);
5854 else
5855 thumb_reload_out_hi (operands);
25f7a26e 5856 DONE;
5857")
5858
9c08d1fa 5859(define_expand "movqi"
5860 [(set (match_operand:QI 0 "general_operand" "")
5861 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5862 "TARGET_EITHER"
9c08d1fa 5863 "
6cffc037 5864 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5865
e1ba4a27 5866 if (can_create_pseudo_p ())
cffb2a26 5867 {
6cffc037 5868 if (GET_CODE (operands[1]) == CONST_INT)
5869 {
5870 rtx reg = gen_reg_rtx (SImode);
5871
03770691 5872 /* For thumb we want an unsigned immediate, then we are more likely
5873 to be able to use a movs insn. */
5874 if (TARGET_THUMB)
5875 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5876
6cffc037 5877 emit_insn (gen_movsi (reg, operands[1]));
5878 operands[1] = gen_lowpart (QImode, reg);
5879 }
cffb2a26 5880
6cffc037 5881 if (TARGET_THUMB)
5882 {
cffb2a26 5883 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5884 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5885 virtual register (also rejected as illegitimate for HImode/QImode)
5886 relative address. */
cffb2a26 5887 /* ??? This should perhaps be fixed elsewhere, for instance, in
5888 fixup_stack_1, by checking for other kinds of invalid addresses,
5889 e.g. a bare reference to a virtual register. This may confuse the
5890 alpha though, which must handle this case differently. */
5891 if (GET_CODE (operands[0]) == MEM
215b30b3 5892 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5893 XEXP (operands[0], 0)))
537ffcfc 5894 operands[0]
5895 = replace_equiv_address (operands[0],
5896 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5897 if (GET_CODE (operands[1]) == MEM
5898 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5899 XEXP (operands[1], 0)))
537ffcfc 5900 operands[1]
5901 = replace_equiv_address (operands[1],
5902 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5903 }
5904
5905 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5906 {
5907 rtx reg = gen_reg_rtx (SImode);
5908
5909 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5910 operands[1] = gen_lowpart (QImode, reg);
5911 }
5912
5913 if (GET_CODE (operands[0]) == MEM)
5914 operands[1] = force_reg (QImode, operands[1]);
5915 }
5916 else if (TARGET_THUMB
5917 && GET_CODE (operands[1]) == CONST_INT
234f6557 5918 && !satisfies_constraint_I (operands[1]))
6cffc037 5919 {
674a8f0b 5920 /* Handle loading a large integer during reload. */
cffb2a26 5921
6cffc037 5922 /* Writing a constant to memory needs a scratch, which should
5923 be handled with SECONDARY_RELOADs. */
5924 gcc_assert (GET_CODE (operands[0]) == REG);
5925
5926 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5927 emit_insn (gen_movsi (operands[0], operands[1]));
5928 DONE;
cffb2a26 5929 }
5930 "
5931)
b11cae9e 5932
9c08d1fa 5933
cffb2a26 5934(define_insn "*arm_movqi_insn"
5935 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5936 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5937 "TARGET_32BIT
cffb2a26 5938 && ( register_operand (operands[0], QImode)
5939 || register_operand (operands[1], QImode))"
5565501b 5940 "@
5941 mov%?\\t%0, %1
5942 mvn%?\\t%0, #%B1
25f905c2 5943 ldr%(b%)\\t%0, %1
5944 str%(b%)\\t%1, %0"
a2cd141b 5945 [(set_attr "type" "*,*,load1,store1")
d2a518d1 5946 (set_attr "insn" "mov,mvn,*,*")
0d66636f 5947 (set_attr "predicable" "yes")]
cffb2a26 5948)
5949
25f905c2 5950(define_insn "*thumb1_movqi_insn"
cffb2a26 5951 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5952 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5953 "TARGET_THUMB1
cffb2a26 5954 && ( register_operand (operands[0], QImode)
5955 || register_operand (operands[1], QImode))"
5956 "@
5957 add\\t%0, %1, #0
5958 ldrb\\t%0, %1
5959 strb\\t%1, %0
5960 mov\\t%0, %1
5961 mov\\t%0, %1
5962 mov\\t%0, %1"
5963 [(set_attr "length" "2")
a2cd141b 5964 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 5965 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 5966 (set_attr "pool_range" "*,32,*,*,*,*")
5967 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 5968
9b8516be 5969;; HFmode moves
5970(define_expand "movhf"
5971 [(set (match_operand:HF 0 "general_operand" "")
5972 (match_operand:HF 1 "general_operand" ""))]
5973 "TARGET_EITHER"
5974 "
5975 if (TARGET_32BIT)
5976 {
5977 if (GET_CODE (operands[0]) == MEM)
5978 operands[1] = force_reg (HFmode, operands[1]);
5979 }
5980 else /* TARGET_THUMB1 */
5981 {
5982 if (can_create_pseudo_p ())
5983 {
5984 if (GET_CODE (operands[0]) != REG)
5985 operands[1] = force_reg (HFmode, operands[1]);
5986 }
5987 }
5988 "
5989)
5990
5991(define_insn "*arm32_movhf"
5992 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5993 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 5994 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 5995 && ( s_register_operand (operands[0], HFmode)
5996 || s_register_operand (operands[1], HFmode))"
5997 "*
5998 switch (which_alternative)
5999 {
6000 case 0: /* ARM register from memory */
6001 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6002 case 1: /* memory from ARM register */
6003 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6004 case 2: /* ARM register from ARM register */
6005 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6006 case 3: /* ARM register from constant */
6007 {
6008 REAL_VALUE_TYPE r;
6009 long bits;
6010 rtx ops[4];
6011
6012 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6013 bits = real_to_target (NULL, &r, HFmode);
6014 ops[0] = operands[0];
6015 ops[1] = GEN_INT (bits);
6016 ops[2] = GEN_INT (bits & 0xff00);
6017 ops[3] = GEN_INT (bits & 0x00ff);
6018
6019 if (arm_arch_thumb2)
6020 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6021 else
6022 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6023 return \"\";
6024 }
6025 default:
6026 gcc_unreachable ();
6027 }
6028 "
6029 [(set_attr "conds" "unconditional")
6030 (set_attr "type" "load1,store1,*,*")
d2a518d1 6031 (set_attr "insn" "*,*,mov,mov")
9b8516be 6032 (set_attr "length" "4,4,4,8")
d2a518d1 6033 (set_attr "predicable" "yes")]
9b8516be 6034)
6035
6036(define_insn "*thumb1_movhf"
6037 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6038 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6039 "TARGET_THUMB1
6040 && ( s_register_operand (operands[0], HFmode)
6041 || s_register_operand (operands[1], HFmode))"
6042 "*
6043 switch (which_alternative)
6044 {
6045 case 1:
6046 {
6047 rtx addr;
6048 gcc_assert (GET_CODE(operands[1]) == MEM);
6049 addr = XEXP (operands[1], 0);
6050 if (GET_CODE (addr) == LABEL_REF
6051 || (GET_CODE (addr) == CONST
6052 && GET_CODE (XEXP (addr, 0)) == PLUS
6053 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6054 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6055 {
6056 /* Constant pool entry. */
6057 return \"ldr\\t%0, %1\";
6058 }
6059 return \"ldrh\\t%0, %1\";
6060 }
6061 case 2: return \"strh\\t%1, %0\";
6062 default: return \"mov\\t%0, %1\";
6063 }
6064 "
6065 [(set_attr "length" "2")
6066 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6067 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6068 (set_attr "pool_range" "*,1020,*,*,*")
6069 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6070
87b22bf7 6071(define_expand "movsf"
6072 [(set (match_operand:SF 0 "general_operand" "")
6073 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6074 "TARGET_EITHER"
87b22bf7 6075 "
25f905c2 6076 if (TARGET_32BIT)
cffb2a26 6077 {
6078 if (GET_CODE (operands[0]) == MEM)
6079 operands[1] = force_reg (SFmode, operands[1]);
6080 }
25f905c2 6081 else /* TARGET_THUMB1 */
cffb2a26 6082 {
e1ba4a27 6083 if (can_create_pseudo_p ())
cffb2a26 6084 {
6085 if (GET_CODE (operands[0]) != REG)
6086 operands[1] = force_reg (SFmode, operands[1]);
6087 }
6088 }
6089 "
6090)
6091
03d440a6 6092;; Transform a floating-point move of a constant into a core register into
6093;; an SImode operation.
cffb2a26 6094(define_split
03d440a6 6095 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6096 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6097 "TARGET_EITHER
cffb2a26 6098 && reload_completed
6099 && GET_CODE (operands[1]) == CONST_DOUBLE"
6100 [(set (match_dup 2) (match_dup 3))]
6101 "
6102 operands[2] = gen_lowpart (SImode, operands[0]);
6103 operands[3] = gen_lowpart (SImode, operands[1]);
6104 if (operands[2] == 0 || operands[3] == 0)
6105 FAIL;
215b30b3 6106 "
6107)
87b22bf7 6108
cffb2a26 6109(define_insn "*arm_movsf_soft_insn"
6110 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6111 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6112 "TARGET_32BIT
cffb2a26 6113 && TARGET_SOFT_FLOAT
215b30b3 6114 && (GET_CODE (operands[0]) != MEM
6115 || register_operand (operands[1], SFmode))"
9a1112d7 6116 "@
6117 mov%?\\t%0, %1
6118 ldr%?\\t%0, %1\\t%@ float
6119 str%?\\t%1, %0\\t%@ float"
cde1623a 6120 [(set_attr "predicable" "yes")
a2cd141b 6121 (set_attr "type" "*,load1,store1")
d2a518d1 6122 (set_attr "insn" "mov,*,*")
cffb2a26 6123 (set_attr "pool_range" "*,4096,*")
cde1623a 6124 (set_attr "arm_neg_pool_range" "*,4084,*")
6125 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6126)
6127
6128;;; ??? This should have alternatives for constants.
25f905c2 6129(define_insn "*thumb1_movsf_insn"
215b30b3 6130 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6131 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6132 "TARGET_THUMB1
cffb2a26 6133 && ( register_operand (operands[0], SFmode)
6134 || register_operand (operands[1], SFmode))"
6135 "@
6136 add\\t%0, %1, #0
6137 ldmia\\t%1, {%0}
6138 stmia\\t%0, {%1}
6139 ldr\\t%0, %1
6140 str\\t%1, %0
6141 mov\\t%0, %1
6142 mov\\t%0, %1"
6143 [(set_attr "length" "2")
a2cd141b 6144 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6145 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6146 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6147 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6148)
9a1112d7 6149
9c08d1fa 6150(define_expand "movdf"
87b22bf7 6151 [(set (match_operand:DF 0 "general_operand" "")
6152 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6153 "TARGET_EITHER"
9c08d1fa 6154 "
25f905c2 6155 if (TARGET_32BIT)
cffb2a26 6156 {
6157 if (GET_CODE (operands[0]) == MEM)
6158 operands[1] = force_reg (DFmode, operands[1]);
6159 }
6160 else /* TARGET_THUMB */
6161 {
e1ba4a27 6162 if (can_create_pseudo_p ())
cffb2a26 6163 {
6164 if (GET_CODE (operands[0]) != REG)
6165 operands[1] = force_reg (DFmode, operands[1]);
6166 }
6167 }
6168 "
6169)
b11cae9e 6170
9c08d1fa 6171;; Reloading a df mode value stored in integer regs to memory can require a
6172;; scratch reg.
6173(define_expand "reload_outdf"
cffb2a26 6174 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6175 (match_operand:DF 1 "s_register_operand" "r")
6176 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6177 "TARGET_32BIT"
87b22bf7 6178 "
215b30b3 6179 {
6180 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6181
215b30b3 6182 if (code == REG)
6183 operands[2] = XEXP (operands[0], 0);
6184 else if (code == POST_INC || code == PRE_DEC)
6185 {
6186 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6187 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6188 emit_insn (gen_movdi (operands[0], operands[1]));
6189 DONE;
6190 }
6191 else if (code == PRE_INC)
6192 {
6193 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6194
215b30b3 6195 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6196 operands[2] = reg;
6197 }
6198 else if (code == POST_DEC)
6199 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6200 else
6201 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6202 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6203
788fcce0 6204 emit_insn (gen_rtx_SET (VOIDmode,
6205 replace_equiv_address (operands[0], operands[2]),
215b30b3 6206 operands[1]));
f7fbdd4a 6207
215b30b3 6208 if (code == POST_DEC)
6209 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6210
6211 DONE;
6212 }"
6213)
9c08d1fa 6214
9a1112d7 6215(define_insn "*movdf_soft_insn"
359a6e9f 6216 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6217 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6218 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6219 && ( register_operand (operands[0], DFmode)
6220 || register_operand (operands[1], DFmode))"
d51f92df 6221 "*
6222 switch (which_alternative)
6223 {
6224 case 0:
6225 case 1:
6226 case 2:
6227 return \"#\";
6228 default:
6229 return output_move_double (operands);
6230 }
6231 "
359a6e9f 6232 [(set_attr "length" "8,12,16,8,8")
6233 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6234 (set_attr "pool_range" "*,*,*,1020,*")
6235 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6236 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6237)
6238
6239;;; ??? This should have alternatives for constants.
6240;;; ??? This was originally identical to the movdi_insn pattern.
6241;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6242;;; thumb_reorg with a memory reference.
6243(define_insn "*thumb_movdf_insn"
215b30b3 6244 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6245 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6246 "TARGET_THUMB1
cffb2a26 6247 && ( register_operand (operands[0], DFmode)
6248 || register_operand (operands[1], DFmode))"
6249 "*
6250 switch (which_alternative)
6251 {
6252 default:
6253 case 0:
6254 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6255 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6256 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6257 case 1:
6258 return \"ldmia\\t%1, {%0, %H0}\";
6259 case 2:
6260 return \"stmia\\t%0, {%1, %H1}\";
6261 case 3:
6262 return thumb_load_double_from_address (operands);
6263 case 4:
1a83b3ff 6264 operands[2] = gen_rtx_MEM (SImode,
6265 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6266 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6267 return \"\";
6268 case 5:
6269 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6270 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6271 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6272 }
6273 "
6274 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6275 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6276 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6277 (set_attr "pool_range" "*,*,*,1020,*,*")]
6278)
755eb2b4 6279
ccd90aaa 6280(define_expand "movxf"
6281 [(set (match_operand:XF 0 "general_operand" "")
6282 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6283 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6284 "
6285 if (GET_CODE (operands[0]) == MEM)
6286 operands[1] = force_reg (XFmode, operands[1]);
6287 "
6288)
6289
b11cae9e 6290\f
b11cae9e 6291
9c08d1fa 6292;; load- and store-multiple insns
6293;; The arm can load/store any set of registers, provided that they are in
320ea44d 6294;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6295
9c08d1fa 6296(define_expand "load_multiple"
6297 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6298 (match_operand:SI 1 "" ""))
6299 (use (match_operand:SI 2 "" ""))])]
25f905c2 6300 "TARGET_32BIT"
9580c25f 6301{
6302 HOST_WIDE_INT offset = 0;
6303
bd5b4116 6304 /* Support only fixed point registers. */
9c08d1fa 6305 if (GET_CODE (operands[2]) != CONST_INT
6306 || INTVAL (operands[2]) > 14
6307 || INTVAL (operands[2]) < 2
6308 || GET_CODE (operands[1]) != MEM
6309 || GET_CODE (operands[0]) != REG
bd5b4116 6310 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6311 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6312 FAIL;
6313
6314 operands[3]
320ea44d 6315 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6316 INTVAL (operands[2]),
f082f1c4 6317 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6318 FALSE, operands[1], &offset);
9580c25f 6319})
b11cae9e 6320
9c08d1fa 6321(define_expand "store_multiple"
6322 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6323 (match_operand:SI 1 "" ""))
6324 (use (match_operand:SI 2 "" ""))])]
25f905c2 6325 "TARGET_32BIT"
9580c25f 6326{
6327 HOST_WIDE_INT offset = 0;
6328
674a8f0b 6329 /* Support only fixed point registers. */
9c08d1fa 6330 if (GET_CODE (operands[2]) != CONST_INT
6331 || INTVAL (operands[2]) > 14
6332 || INTVAL (operands[2]) < 2
6333 || GET_CODE (operands[1]) != REG
6334 || GET_CODE (operands[0]) != MEM
bd5b4116 6335 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6336 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6337 FAIL;
6338
6339 operands[3]
320ea44d 6340 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6341 INTVAL (operands[2]),
f082f1c4 6342 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6343 FALSE, operands[0], &offset);
9580c25f 6344})
b11cae9e 6345
9c08d1fa 6346
6347;; Move a block of memory if it is word aligned and MORE than 2 words long.
6348;; We could let this apply for blocks of less than this, but it clobbers so
6349;; many registers that there is then probably a better way.
6350
008c057d 6351(define_expand "movmemqi"
34191dd1 6352 [(match_operand:BLK 0 "general_operand" "")
6353 (match_operand:BLK 1 "general_operand" "")
6354 (match_operand:SI 2 "const_int_operand" "")
6355 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6356 "TARGET_EITHER"
9c08d1fa 6357 "
25f905c2 6358 if (TARGET_32BIT)
cffb2a26 6359 {
008c057d 6360 if (arm_gen_movmemqi (operands))
cffb2a26 6361 DONE;
6362 FAIL;
6363 }
25f905c2 6364 else /* TARGET_THUMB1 */
cffb2a26 6365 {
6366 if ( INTVAL (operands[3]) != 4
6367 || INTVAL (operands[2]) > 48)
6368 FAIL;
6369
008c057d 6370 thumb_expand_movmemqi (operands);
cffb2a26 6371 DONE;
6372 }
6373 "
6374)
6375
2162064c 6376;; Thumb block-move insns
cffb2a26 6377
6378(define_insn "movmem12b"
960f3acf 6379 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6380 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6381 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6382 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6383 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6384 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6385 (set (match_operand:SI 0 "register_operand" "=l")
6386 (plus:SI (match_dup 2) (const_int 12)))
6387 (set (match_operand:SI 1 "register_operand" "=l")
6388 (plus:SI (match_dup 3) (const_int 12)))
6389 (clobber (match_scratch:SI 4 "=&l"))
6390 (clobber (match_scratch:SI 5 "=&l"))
6391 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6392 "TARGET_THUMB1"
cffb2a26 6393 "* return thumb_output_move_mem_multiple (3, operands);"
6394 [(set_attr "length" "4")
215b30b3 6395 ; This isn't entirely accurate... It loads as well, but in terms of
6396 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6397 (set_attr "type" "store3")]
6398)
6399
6400(define_insn "movmem8b"
960f3acf 6401 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6402 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6403 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6404 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6405 (set (match_operand:SI 0 "register_operand" "=l")
6406 (plus:SI (match_dup 2) (const_int 8)))
6407 (set (match_operand:SI 1 "register_operand" "=l")
6408 (plus:SI (match_dup 3) (const_int 8)))
6409 (clobber (match_scratch:SI 4 "=&l"))
6410 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6411 "TARGET_THUMB1"
cffb2a26 6412 "* return thumb_output_move_mem_multiple (2, operands);"
6413 [(set_attr "length" "4")
215b30b3 6414 ; This isn't entirely accurate... It loads as well, but in terms of
6415 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6416 (set_attr "type" "store2")]
6417)
6418
9c08d1fa 6419\f
b11cae9e 6420
341940e8 6421;; Compare & branch insns
8d232dc7 6422;; The range calculations are based as follows:
341940e8 6423;; For forward branches, the address calculation returns the address of
6424;; the next instruction. This is 2 beyond the branch instruction.
6425;; For backward branches, the address calculation returns the address of
6426;; the first instruction in this pattern (cmp). This is 2 before the branch
6427;; instruction for the shortest sequence, and 4 before the branch instruction
6428;; if we have to jump around an unconditional branch.
6429;; To the basic branch range the PC offset must be added (this is +4).
6430;; So for forward branches we have
6431;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6432;; And for backward branches we have
6433;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6434;;
6435;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6436;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6437
aeac46d4 6438(define_expand "cbranchsi4"
6439 [(set (pc) (if_then_else
6440 (match_operator 0 "arm_comparison_operator"
6441 [(match_operand:SI 1 "s_register_operand" "")
6442 (match_operand:SI 2 "nonmemory_operand" "")])
6443 (label_ref (match_operand 3 "" ""))
6444 (pc)))]
74f4459c 6445 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6446 "
74f4459c 6447 if (!TARGET_THUMB1)
6448 {
6449 if (!arm_add_operand (operands[2], SImode))
6450 operands[2] = force_reg (SImode, operands[2]);
6451 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6452 operands[3]));
6453 DONE;
6454 }
25f905c2 6455 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6456 {
6457 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6458 operands[3], operands[0]));
6459 DONE;
6460 }
25f905c2 6461 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6462 operands[2] = force_reg (SImode, operands[2]);
6463 ")
6464
a8e6c15d 6465;; A pattern to recognize a special situation and optimize for it.
6466;; On the thumb, zero-extension from memory is preferrable to sign-extension
6467;; due to the available addressing modes. Hence, convert a signed comparison
6468;; with zero into an unsigned comparison with 127 if possible.
6469(define_expand "cbranchqi4"
6470 [(set (pc) (if_then_else
6471 (match_operator 0 "lt_ge_comparison_operator"
6472 [(match_operand:QI 1 "memory_operand" "")
6473 (match_operand:QI 2 "const0_operand" "")])
6474 (label_ref (match_operand 3 "" ""))
6475 (pc)))]
6476 "TARGET_THUMB1"
6477{
d0f6c30d 6478 rtx xops[4];
a8e6c15d 6479 xops[1] = gen_reg_rtx (SImode);
6480 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6481 xops[2] = GEN_INT (127);
6482 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6483 VOIDmode, xops[1], xops[2]);
6484 xops[3] = operands[3];
6485 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6486 DONE;
6487})
6488
74f4459c 6489(define_expand "cbranchsf4"
6490 [(set (pc) (if_then_else
6491 (match_operator 0 "arm_comparison_operator"
6492 [(match_operand:SF 1 "s_register_operand" "")
6493 (match_operand:SF 2 "arm_float_compare_operand" "")])
6494 (label_ref (match_operand 3 "" ""))
6495 (pc)))]
6496 "TARGET_32BIT && TARGET_HARD_FLOAT"
6497 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6498 operands[3])); DONE;"
6499)
6500
6501(define_expand "cbranchdf4"
6502 [(set (pc) (if_then_else
6503 (match_operator 0 "arm_comparison_operator"
6504 [(match_operand:DF 1 "s_register_operand" "")
6505 (match_operand:DF 2 "arm_float_compare_operand" "")])
6506 (label_ref (match_operand 3 "" ""))
6507 (pc)))]
a50d7267 6508 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6509 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6510 operands[3])); DONE;"
6511)
6512
74f4459c 6513(define_expand "cbranchdi4"
6514 [(set (pc) (if_then_else
6515 (match_operator 0 "arm_comparison_operator"
a8045a4f 6516 [(match_operand:DI 1 "cmpdi_operand" "")
6517 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6518 (label_ref (match_operand 3 "" ""))
6519 (pc)))]
a8045a4f 6520 "TARGET_32BIT"
6521 "{
6522 rtx swap = NULL_RTX;
6523 enum rtx_code code = GET_CODE (operands[0]);
6524
6525 /* We should not have two constants. */
6526 gcc_assert (GET_MODE (operands[1]) == DImode
6527 || GET_MODE (operands[2]) == DImode);
6528
6529 /* Flip unimplemented DImode comparisons to a form that
6530 arm_gen_compare_reg can handle. */
6531 switch (code)
6532 {
6533 case GT:
6534 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6535 case LE:
6536 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6537 case GTU:
6538 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6539 case LEU:
6540 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6541 default:
6542 break;
6543 }
6544 if (swap)
6545 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6546 operands[3]));
6547 else
6548 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6549 operands[3]));
6550 DONE;
6551 }"
74f4459c 6552)
6553
d60047aa 6554(define_insn "cbranchsi4_insn"
aeac46d4 6555 [(set (pc) (if_then_else
6556 (match_operator 0 "arm_comparison_operator"
747b7458 6557 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 6558 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6559 (label_ref (match_operand 3 "" ""))
6560 (pc)))]
25f905c2 6561 "TARGET_THUMB1"
747b7458 6562{
6563 rtx t = cfun->machine->thumb1_cc_insn;
6564 if (t != NULL_RTX)
d60047aa 6565 {
747b7458 6566 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6567 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6568 t = NULL_RTX;
6569 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6570 {
6571 if (!noov_comparison_operator (operands[0], VOIDmode))
6572 t = NULL_RTX;
6573 }
6574 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 6575 t = NULL_RTX;
6576 }
d60047aa 6577 if (t == NULL_RTX)
747b7458 6578 {
6579 output_asm_insn ("cmp\t%1, %2", operands);
6580 cfun->machine->thumb1_cc_insn = insn;
6581 cfun->machine->thumb1_cc_op0 = operands[1];
6582 cfun->machine->thumb1_cc_op1 = operands[2];
6583 cfun->machine->thumb1_cc_mode = CCmode;
6584 }
6585 else
6586 /* Ensure we emit the right type of condition code on the jump. */
6587 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6588 CC_REGNUM);
aeac46d4 6589
cffb2a26 6590 switch (get_attr_length (insn))
6591 {
6592 case 4: return \"b%d0\\t%l3\";
6593 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6594 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6595 }
747b7458 6596}
cffb2a26 6597 [(set (attr "far_jump")
6598 (if_then_else
6599 (eq_attr "length" "8")
6600 (const_string "yes")
6601 (const_string "no")))
6602 (set (attr "length")
6603 (if_then_else
6604 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6605 (le (minus (match_dup 3) (pc)) (const_int 256)))
6606 (const_int 4)
6607 (if_then_else
6608 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6609 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6610 (const_int 6)
6611 (const_int 8))))]
6612)
6613
aeac46d4 6614(define_insn "cbranchsi4_scratch"
6615 [(set (pc) (if_then_else
6616 (match_operator 4 "arm_comparison_operator"
6617 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6618 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6619 (label_ref (match_operand 3 "" ""))
6620 (pc)))
6621 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6622 "TARGET_THUMB1"
aeac46d4 6623 "*
6624 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6625
6626 switch (get_attr_length (insn))
6627 {
6628 case 4: return \"b%d4\\t%l3\";
6629 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6630 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6631 }
6632 "
6633 [(set (attr "far_jump")
6634 (if_then_else
6635 (eq_attr "length" "8")
6636 (const_string "yes")
6637 (const_string "no")))
6638 (set (attr "length")
6639 (if_then_else
6640 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6641 (le (minus (match_dup 3) (pc)) (const_int 256)))
6642 (const_int 4)
6643 (if_then_else
6644 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6645 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6646 (const_int 6)
6647 (const_int 8))))]
6648)
446a1e96 6649
747b7458 6650;; Two peepholes to generate subtract of 0 instead of a move if the
6651;; condition codes will be useful.
446a1e96 6652(define_peephole2
6653 [(set (match_operand:SI 0 "low_register_operand" "")
6654 (match_operand:SI 1 "low_register_operand" ""))
6655 (set (pc)
6656 (if_then_else (match_operator 2 "arm_comparison_operator"
6657 [(match_dup 1) (const_int 0)])
6658 (label_ref (match_operand 3 "" ""))
6659 (pc)))]
6660 "TARGET_THUMB1"
747b7458 6661 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6662 (set (pc)
6663 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6664 (label_ref (match_dup 3))
747b7458 6665 (pc)))]
6666 "")
446a1e96 6667
6668;; Sigh! This variant shouldn't be needed, but combine often fails to
6669;; merge cases like this because the op1 is a hard register in
6670;; CLASS_LIKELY_SPILLED_P.
6671(define_peephole2
6672 [(set (match_operand:SI 0 "low_register_operand" "")
6673 (match_operand:SI 1 "low_register_operand" ""))
6674 (set (pc)
6675 (if_then_else (match_operator 2 "arm_comparison_operator"
6676 [(match_dup 0) (const_int 0)])
6677 (label_ref (match_operand 3 "" ""))
6678 (pc)))]
6679 "TARGET_THUMB1"
747b7458 6680 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6681 (set (pc)
6682 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6683 (label_ref (match_dup 3))
747b7458 6684 (pc)))]
6685 "")
446a1e96 6686
cffb2a26 6687(define_insn "*negated_cbranchsi4"
6688 [(set (pc)
6689 (if_then_else
aed179ae 6690 (match_operator 0 "equality_operator"
aeac46d4 6691 [(match_operand:SI 1 "s_register_operand" "l")
6692 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6693 (label_ref (match_operand 3 "" ""))
215b30b3 6694 (pc)))]
25f905c2 6695 "TARGET_THUMB1"
cffb2a26 6696 "*
6697 output_asm_insn (\"cmn\\t%1, %2\", operands);
6698 switch (get_attr_length (insn))
6699 {
6700 case 4: return \"b%d0\\t%l3\";
6701 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6702 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6703 }
6704 "
6705 [(set (attr "far_jump")
6706 (if_then_else
6707 (eq_attr "length" "8")
6708 (const_string "yes")
6709 (const_string "no")))
6710 (set (attr "length")
6711 (if_then_else
6712 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6713 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6714 (const_int 4)
6715 (if_then_else
341940e8 6716 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6717 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6718 (const_int 6)
6719 (const_int 8))))]
6720)
6721
58d6528b 6722(define_insn "*tbit_cbranch"
6723 [(set (pc)
6724 (if_then_else
6725 (match_operator 0 "equality_operator"
6726 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6727 (const_int 1)
6728 (match_operand:SI 2 "const_int_operand" "i"))
6729 (const_int 0)])
6730 (label_ref (match_operand 3 "" ""))
6731 (pc)))
6732 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6733 "TARGET_THUMB1"
58d6528b 6734 "*
6735 {
6736 rtx op[3];
6737 op[0] = operands[4];
6738 op[1] = operands[1];
6739 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6740
86efa74d 6741 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6742 switch (get_attr_length (insn))
6743 {
6744 case 4: return \"b%d0\\t%l3\";
6745 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6746 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6747 }
6748 }"
6749 [(set (attr "far_jump")
6750 (if_then_else
6751 (eq_attr "length" "8")
6752 (const_string "yes")
6753 (const_string "no")))
6754 (set (attr "length")
6755 (if_then_else
6756 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6757 (le (minus (match_dup 3) (pc)) (const_int 256)))
6758 (const_int 4)
6759 (if_then_else
6760 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6761 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6762 (const_int 6)
6763 (const_int 8))))]
6764)
6765
6766(define_insn "*tlobits_cbranch"
6767 [(set (pc)
6768 (if_then_else
6769 (match_operator 0 "equality_operator"
6770 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6771 (match_operand:SI 2 "const_int_operand" "i")
6772 (const_int 0))
6773 (const_int 0)])
6774 (label_ref (match_operand 3 "" ""))
6775 (pc)))
6776 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6777 "TARGET_THUMB1"
86efa74d 6778 "*
6779 {
6780 rtx op[3];
6781 op[0] = operands[4];
6782 op[1] = operands[1];
6783 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6784
58d6528b 6785 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6786 switch (get_attr_length (insn))
6787 {
6788 case 4: return \"b%d0\\t%l3\";
6789 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6790 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6791 }
6792 }"
6793 [(set (attr "far_jump")
6794 (if_then_else
6795 (eq_attr "length" "8")
6796 (const_string "yes")
6797 (const_string "no")))
6798 (set (attr "length")
6799 (if_then_else
6800 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6801 (le (minus (match_dup 3) (pc)) (const_int 256)))
6802 (const_int 4)
6803 (if_then_else
6804 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6805 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6806 (const_int 6)
6807 (const_int 8))))]
6808)
747b7458 6809
aeac46d4 6810(define_insn "*tstsi3_cbranch"
58d6528b 6811 [(set (pc)
6812 (if_then_else
aeac46d4 6813 (match_operator 3 "equality_operator"
6814 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6815 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6816 (const_int 0)])
aeac46d4 6817 (label_ref (match_operand 2 "" ""))
6818 (pc)))]
25f905c2 6819 "TARGET_THUMB1"
58d6528b 6820 "*
6821 {
aeac46d4 6822 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6823 switch (get_attr_length (insn))
6824 {
aeac46d4 6825 case 4: return \"b%d3\\t%l2\";
6826 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6827 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6828 }
6829 }"
6830 [(set (attr "far_jump")
6831 (if_then_else
6832 (eq_attr "length" "8")
6833 (const_string "yes")
6834 (const_string "no")))
6835 (set (attr "length")
6836 (if_then_else
aeac46d4 6837 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6838 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6839 (const_int 4)
6840 (if_then_else
aeac46d4 6841 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6842 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6843 (const_int 6)
6844 (const_int 8))))]
6845)
6846
203c488f 6847(define_insn "*cbranchne_decr1"
6848 [(set (pc)
6849 (if_then_else (match_operator 3 "equality_operator"
6850 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6851 (const_int 0)])
6852 (label_ref (match_operand 4 "" ""))
6853 (pc)))
aeac46d4 6854 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6855 (plus:SI (match_dup 2) (const_int -1)))
6856 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6857 "TARGET_THUMB1"
203c488f 6858 "*
6859 {
6860 rtx cond[2];
6861 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6862 ? GEU : LTU),
58d6528b 6863 VOIDmode, operands[2], const1_rtx);
203c488f 6864 cond[1] = operands[4];
6865
6866 if (which_alternative == 0)
6867 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6868 else if (which_alternative == 1)
6869 {
6870 /* We must provide an alternative for a hi reg because reload
6871 cannot handle output reloads on a jump instruction, but we
6872 can't subtract into that. Fortunately a mov from lo to hi
6873 does not clobber the condition codes. */
6874 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6875 output_asm_insn (\"mov\\t%0, %1\", operands);
6876 }
6877 else
6878 {
6879 /* Similarly, but the target is memory. */
6880 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6881 output_asm_insn (\"str\\t%1, %0\", operands);
6882 }
6883
6884 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6885 {
6886 case 4:
8aea555f 6887 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6888 return \"\";
6889 case 6:
8aea555f 6890 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6891 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6892 default:
8aea555f 6893 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6894 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6895 }
6896 }
6897 "
6898 [(set (attr "far_jump")
6899 (if_then_else
6900 (ior (and (eq (symbol_ref ("which_alternative"))
6901 (const_int 0))
6902 (eq_attr "length" "8"))
6903 (eq_attr "length" "10"))
6904 (const_string "yes")
6905 (const_string "no")))
6906 (set_attr_alternative "length"
6907 [
6908 ;; Alternative 0
6909 (if_then_else
6910 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6911 (le (minus (match_dup 4) (pc)) (const_int 256)))
6912 (const_int 4)
6913 (if_then_else
6914 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6915 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6916 (const_int 6)
6917 (const_int 8)))
6918 ;; Alternative 1
6919 (if_then_else
6920 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6921 (le (minus (match_dup 4) (pc)) (const_int 256)))
6922 (const_int 6)
6923 (if_then_else
6924 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6925 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6926 (const_int 8)
6927 (const_int 10)))
6928 ;; Alternative 2
6929 (if_then_else
6930 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6931 (le (minus (match_dup 4) (pc)) (const_int 256)))
6932 (const_int 6)
6933 (if_then_else
6934 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6935 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6936 (const_int 8)
6937 (const_int 10)))
6938 ;; Alternative 3
6939 (if_then_else
6940 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6941 (le (minus (match_dup 4) (pc)) (const_int 256)))
6942 (const_int 6)
6943 (if_then_else
6944 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6945 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6946 (const_int 8)
6947 (const_int 10)))])]
6948)
cffb2a26 6949
58d6528b 6950(define_insn "*addsi3_cbranch"
6951 [(set (pc)
6952 (if_then_else
b0694be0 6953 (match_operator 4 "arm_comparison_operator"
58d6528b 6954 [(plus:SI
e54011cb 6955 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
6956 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 6957 (const_int 0)])
6958 (label_ref (match_operand 5 "" ""))
6959 (pc)))
aeac46d4 6960 (set
6961 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6962 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 6963 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 6964 "TARGET_THUMB1
58d6528b 6965 && (GET_CODE (operands[4]) == EQ
6966 || GET_CODE (operands[4]) == NE
6967 || GET_CODE (operands[4]) == GE
6968 || GET_CODE (operands[4]) == LT)"
6969 "*
6970 {
6971 rtx cond[3];
6972
956a6170 6973 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 6974 cond[1] = operands[2];
6975 cond[2] = operands[3];
6976
6977 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6978 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6979 else
6980 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6981
956a6170 6982 if (which_alternative >= 2
58d6528b 6983 && which_alternative < 4)
6984 output_asm_insn (\"mov\\t%0, %1\", operands);
6985 else if (which_alternative >= 4)
6986 output_asm_insn (\"str\\t%1, %0\", operands);
6987
d0f6c30d 6988 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 6989 {
6990 case 4:
6991 return \"b%d4\\t%l5\";
6992 case 6:
6993 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6994 default:
6995 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6996 }
6997 }
6998 "
6999 [(set (attr "far_jump")
7000 (if_then_else
7001 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7002 (const_int 2))
58d6528b 7003 (eq_attr "length" "8"))
7004 (eq_attr "length" "10"))
7005 (const_string "yes")
7006 (const_string "no")))
7007 (set (attr "length")
7008 (if_then_else
7009 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7010 (const_int 2))
58d6528b 7011 (if_then_else
7012 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7013 (le (minus (match_dup 5) (pc)) (const_int 256)))
7014 (const_int 4)
7015 (if_then_else
7016 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7017 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7018 (const_int 6)
7019 (const_int 8)))
7020 (if_then_else
7021 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7022 (le (minus (match_dup 5) (pc)) (const_int 256)))
7023 (const_int 6)
7024 (if_then_else
7025 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7026 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7027 (const_int 8)
7028 (const_int 10)))))]
7029)
7030
7031(define_insn "*addsi3_cbranch_scratch"
7032 [(set (pc)
7033 (if_then_else
b0694be0 7034 (match_operator 3 "arm_comparison_operator"
58d6528b 7035 [(plus:SI
7036 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7037 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7038 (const_int 0)])
7039 (label_ref (match_operand 4 "" ""))
7040 (pc)))
7041 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7042 "TARGET_THUMB1
58d6528b 7043 && (GET_CODE (operands[3]) == EQ
7044 || GET_CODE (operands[3]) == NE
7045 || GET_CODE (operands[3]) == GE
7046 || GET_CODE (operands[3]) == LT)"
7047 "*
7048 {
7049 switch (which_alternative)
7050 {
7051 case 0:
7052 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7053 break;
7054 case 1:
7055 output_asm_insn (\"cmn\t%1, %2\", operands);
7056 break;
0f5e9701 7057 case 2:
3a445a04 7058 if (INTVAL (operands[2]) < 0)
7059 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7060 else
7061 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7062 break;
0f5e9701 7063 case 3:
3a445a04 7064 if (INTVAL (operands[2]) < 0)
7065 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7066 else
7067 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7068 break;
7069 }
7070
7071 switch (get_attr_length (insn))
7072 {
7073 case 4:
7074 return \"b%d3\\t%l4\";
7075 case 6:
7076 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7077 default:
7078 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7079 }
7080 }
7081 "
7082 [(set (attr "far_jump")
7083 (if_then_else
7084 (eq_attr "length" "8")
7085 (const_string "yes")
7086 (const_string "no")))
7087 (set (attr "length")
7088 (if_then_else
7089 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7090 (le (minus (match_dup 4) (pc)) (const_int 256)))
7091 (const_int 4)
7092 (if_then_else
7093 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7094 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7095 (const_int 6)
7096 (const_int 8))))]
7097)
7098
58d6528b 7099
9c08d1fa 7100;; Comparison and test insns
7101
cffb2a26 7102(define_insn "*arm_cmpsi_insn"
bd5b4116 7103 [(set (reg:CC CC_REGNUM)
aea4c774 7104 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7105 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7106 "TARGET_32BIT"
5565501b 7107 "@
aea4c774 7108 cmp%?\\t%0, %1
7109 cmn%?\\t%0, #%n1"
cffb2a26 7110 [(set_attr "conds" "set")]
7111)
b11cae9e 7112
d5d4dc8d 7113(define_insn "*cmpsi_shiftsi"
bd5b4116 7114 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7115 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7116 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7117 [(match_operand:SI 1 "s_register_operand" "r,r")
7118 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7119 "TARGET_32BIT"
aea4c774 7120 "cmp%?\\t%0, %1%S3"
344495ea 7121 [(set_attr "conds" "set")
331beb1a 7122 (set_attr "shift" "1")
d5d4dc8d 7123 (set_attr "arch" "32,a")
7124 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7125
d5d4dc8d 7126(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7127 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7128 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7129 [(match_operand:SI 1 "s_register_operand" "r,r")
7130 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7131 (match_operand:SI 0 "s_register_operand" "r,r")))]
7132 "TARGET_32BIT"
aea4c774 7133 "cmp%?\\t%0, %1%S3"
344495ea 7134 [(set_attr "conds" "set")
331beb1a 7135 (set_attr "shift" "1")
d5d4dc8d 7136 (set_attr "arch" "32,a")
7137 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7138
25f905c2 7139(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7140 [(set (reg:CC_Z CC_REGNUM)
7141 (compare:CC_Z
7142 (neg:SI (match_operator:SI 1 "shift_operator"
7143 [(match_operand:SI 2 "s_register_operand" "r")
7144 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7145 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7146 "TARGET_ARM"
aed179ae 7147 "cmn%?\\t%0, %2%S1"
344495ea 7148 [(set_attr "conds" "set")
aed179ae 7149 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7150 (const_string "alu_shift")
7151 (const_string "alu_shift_reg")))]
0d66636f 7152)
b11cae9e 7153
a8045a4f 7154;; DImode comparisons. The generic code generates branches that
7155;; if-conversion can not reduce to a conditional compare, so we do
7156;; that directly.
7157
7158(define_insn "*arm_cmpdi_insn"
7159 [(set (reg:CC_NCV CC_REGNUM)
7160 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7161 (match_operand:DI 1 "arm_di_operand" "rDi")))
7162 (clobber (match_scratch:SI 2 "=r"))]
7163 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7164 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7165 [(set_attr "conds" "set")
7166 (set_attr "length" "8")]
7167)
7168
7169(define_insn "*arm_cmpdi_unsigned"
7170 [(set (reg:CC_CZ CC_REGNUM)
7171 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7172 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7173 "TARGET_ARM"
7174 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7175 [(set_attr "conds" "set")
7176 (set_attr "length" "8")]
7177)
7178
7179(define_insn "*arm_cmpdi_zero"
7180 [(set (reg:CC_Z CC_REGNUM)
7181 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7182 (const_int 0)))
7183 (clobber (match_scratch:SI 1 "=r"))]
7184 "TARGET_32BIT"
7185 "orr%.\\t%1, %Q0, %R0"
7186 [(set_attr "conds" "set")]
7187)
7188
7189(define_insn "*thumb_cmpdi_zero"
7190 [(set (reg:CC_Z CC_REGNUM)
7191 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7192 (const_int 0)))
7193 (clobber (match_scratch:SI 1 "=l"))]
7194 "TARGET_THUMB1"
7195 "orr\\t%1, %Q0, %R0"
7196 [(set_attr "conds" "set")
7197 (set_attr "length" "2")]
7198)
7199
7d57ec45 7200;; Cirrus SF compare instruction
7201(define_insn "*cirrus_cmpsf"
7202 [(set (reg:CCFP CC_REGNUM)
7203 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7204 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7205 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7206 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7207 [(set_attr "type" "mav_farith")
7d57ec45 7208 (set_attr "cirrus" "compare")]
7209)
7210
7211;; Cirrus DF compare instruction
7212(define_insn "*cirrus_cmpdf"
7213 [(set (reg:CCFP CC_REGNUM)
7214 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7215 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7216 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7217 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7218 [(set_attr "type" "mav_farith")
7d57ec45 7219 (set_attr "cirrus" "compare")]
7220)
7221
7d57ec45 7222(define_insn "*cirrus_cmpdi"
7223 [(set (reg:CC CC_REGNUM)
7224 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7225 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7226 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7227 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7228 [(set_attr "type" "mav_farith")
7d57ec45 7229 (set_attr "cirrus" "compare")]
7230)
7231
9c08d1fa 7232; This insn allows redundant compares to be removed by cse, nothing should
7233; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7234; is deleted later on. The match_dup will match the mode here, so that
7235; mode changes of the condition codes aren't lost by this even though we don't
7236; specify what they are.
7237
8a18b90c 7238(define_insn "*deleted_compare"
9c08d1fa 7239 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7240 "TARGET_32BIT"
40dbec34 7241 "\\t%@ deleted compare"
cffb2a26 7242 [(set_attr "conds" "set")
7243 (set_attr "length" "0")]
7244)
9c08d1fa 7245
7246\f
7247;; Conditional branch insns
7248
74f4459c 7249(define_expand "cbranch_cc"
9c08d1fa 7250 [(set (pc)
74f4459c 7251 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7252 (match_operand 2 "" "")])
7253 (label_ref (match_operand 3 "" ""))
9c08d1fa 7254 (pc)))]
25f905c2 7255 "TARGET_32BIT"
74f4459c 7256 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7257 operands[1], operands[2]);
7258 operands[2] = const0_rtx;"
8fa3ba89 7259)
7260
7261;;
7262;; Patterns to match conditional branch insns.
7263;;
7264
cffb2a26 7265(define_insn "*arm_cond_branch"
9c08d1fa 7266 [(set (pc)
8fa3ba89 7267 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7268 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7269 (label_ref (match_operand 0 "" ""))
7270 (pc)))]
25f905c2 7271 "TARGET_32BIT"
d75350ce 7272 "*
9c08d1fa 7273 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7274 {
7275 arm_ccfsm_state += 2;
7276 return \"\";
7277 }
e2348bcb 7278 return \"b%d1\\t%l0\";
cffb2a26 7279 "
a2cd141b 7280 [(set_attr "conds" "use")
7281 (set_attr "type" "branch")]
cffb2a26 7282)
d75350ce 7283
cffb2a26 7284(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7285 [(set (pc)
8fa3ba89 7286 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7287 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7288 (pc)
7289 (label_ref (match_operand 0 "" ""))))]
25f905c2 7290 "TARGET_32BIT"
d75350ce 7291 "*
9c08d1fa 7292 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7293 {
7294 arm_ccfsm_state += 2;
7295 return \"\";
7296 }
e2348bcb 7297 return \"b%D1\\t%l0\";
cffb2a26 7298 "
a2cd141b 7299 [(set_attr "conds" "use")
7300 (set_attr "type" "branch")]
cffb2a26 7301)
7302
b11cae9e 7303\f
9c08d1fa 7304
7305; scc insns
7306
74f4459c 7307(define_expand "cstore_cc"
7db9af5d 7308 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7309 (match_operator:SI 1 "" [(match_operand 2 "" "")
7310 (match_operand 3 "" "")]))]
25f905c2 7311 "TARGET_32BIT"
74f4459c 7312 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7313 operands[2], operands[3]);
7314 operands[3] = const0_rtx;"
8fa3ba89 7315)
7316
f7fbdd4a 7317(define_insn "*mov_scc"
9c08d1fa 7318 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7319 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7320 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7321 "TARGET_ARM"
4d61e570 7322 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7323 [(set_attr "conds" "use")
d2a518d1 7324 (set_attr "insn" "mov")
cffb2a26 7325 (set_attr "length" "8")]
7326)
9c08d1fa 7327
f7fbdd4a 7328(define_insn "*mov_negscc"
9c08d1fa 7329 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7330 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7331 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7332 "TARGET_ARM"
4d61e570 7333 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7334 [(set_attr "conds" "use")
d2a518d1 7335 (set_attr "insn" "mov")
cffb2a26 7336 (set_attr "length" "8")]
7337)
9c08d1fa 7338
f7fbdd4a 7339(define_insn "*mov_notscc"
9c08d1fa 7340 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7341 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7342 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7343 "TARGET_ARM"
4d61e570 7344 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7345 [(set_attr "conds" "use")
d2a518d1 7346 (set_attr "insn" "mov")
cffb2a26 7347 (set_attr "length" "8")]
7348)
9c08d1fa 7349
595d88b5 7350(define_expand "cstoresi4"
7351 [(set (match_operand:SI 0 "s_register_operand" "")
7352 (match_operator:SI 1 "arm_comparison_operator"
7353 [(match_operand:SI 2 "s_register_operand" "")
7354 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7355 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7356 "{
7357 rtx op3, scratch, scratch2;
7358
74f4459c 7359 if (!TARGET_THUMB1)
7360 {
7361 if (!arm_add_operand (operands[3], SImode))
7362 operands[3] = force_reg (SImode, operands[3]);
7363 emit_insn (gen_cstore_cc (operands[0], operands[1],
7364 operands[2], operands[3]));
7365 DONE;
7366 }
7367
595d88b5 7368 if (operands[3] == const0_rtx)
7369 {
7370 switch (GET_CODE (operands[1]))
7371 {
7372 case EQ:
25f905c2 7373 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7374 break;
7375
7376 case NE:
25f905c2 7377 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7378 break;
7379
7380 case LE:
7381 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7382 NULL_RTX, 0, OPTAB_WIDEN);
7383 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7384 NULL_RTX, 0, OPTAB_WIDEN);
7385 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7386 operands[0], 1, OPTAB_WIDEN);
7387 break;
7388
7389 case GE:
7390 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7391 NULL_RTX, 1);
7392 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7393 NULL_RTX, 1, OPTAB_WIDEN);
7394 break;
7395
7396 case GT:
7397 scratch = expand_binop (SImode, ashr_optab, operands[2],
7398 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7399 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7400 NULL_RTX, 0, OPTAB_WIDEN);
7401 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7402 0, OPTAB_WIDEN);
7403 break;
7404
7405 /* LT is handled by generic code. No need for unsigned with 0. */
7406 default:
7407 FAIL;
7408 }
7409 DONE;
7410 }
7411
7412 switch (GET_CODE (operands[1]))
7413 {
7414 case EQ:
7415 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7416 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7417 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7418 break;
7419
7420 case NE:
7421 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7422 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7423 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7424 break;
7425
7426 case LE:
7427 op3 = force_reg (SImode, operands[3]);
7428
7429 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7430 NULL_RTX, 1, OPTAB_WIDEN);
7431 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7432 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7433 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7434 op3, operands[2]));
7435 break;
7436
7437 case GE:
7438 op3 = operands[3];
25f905c2 7439 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7440 op3 = force_reg (SImode, op3);
7441 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7442 NULL_RTX, 0, OPTAB_WIDEN);
7443 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7444 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7445 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7446 operands[2], op3));
7447 break;
7448
7449 case LEU:
7450 op3 = force_reg (SImode, operands[3]);
7451 scratch = force_reg (SImode, const0_rtx);
25f905c2 7452 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7453 op3, operands[2]));
7454 break;
7455
7456 case GEU:
7457 op3 = operands[3];
25f905c2 7458 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7459 op3 = force_reg (SImode, op3);
7460 scratch = force_reg (SImode, const0_rtx);
25f905c2 7461 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7462 operands[2], op3));
7463 break;
7464
7465 case LTU:
7466 op3 = operands[3];
25f905c2 7467 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7468 op3 = force_reg (SImode, op3);
7469 scratch = gen_reg_rtx (SImode);
408b7ae5 7470 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7471 break;
7472
7473 case GTU:
7474 op3 = force_reg (SImode, operands[3]);
7475 scratch = gen_reg_rtx (SImode);
408b7ae5 7476 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7477 break;
7478
7479 /* No good sequences for GT, LT. */
7480 default:
7481 FAIL;
7482 }
7483 DONE;
7484}")
7485
74f4459c 7486(define_expand "cstoresf4"
7487 [(set (match_operand:SI 0 "s_register_operand" "")
7488 (match_operator:SI 1 "arm_comparison_operator"
7489 [(match_operand:SF 2 "s_register_operand" "")
7490 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7491 "TARGET_32BIT && TARGET_HARD_FLOAT"
7492 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7493 operands[2], operands[3])); DONE;"
7494)
7495
7496(define_expand "cstoredf4"
7497 [(set (match_operand:SI 0 "s_register_operand" "")
7498 (match_operator:SI 1 "arm_comparison_operator"
7499 [(match_operand:DF 2 "s_register_operand" "")
7500 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7501 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7502 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7503 operands[2], operands[3])); DONE;"
7504)
7505
74f4459c 7506(define_expand "cstoredi4"
7507 [(set (match_operand:SI 0 "s_register_operand" "")
7508 (match_operator:SI 1 "arm_comparison_operator"
a8045a4f 7509 [(match_operand:DI 2 "cmpdi_operand" "")
7510 (match_operand:DI 3 "cmpdi_operand" "")]))]
7511 "TARGET_32BIT"
7512 "{
7513 rtx swap = NULL_RTX;
7514 enum rtx_code code = GET_CODE (operands[1]);
7515
7516 /* We should not have two constants. */
7517 gcc_assert (GET_MODE (operands[2]) == DImode
7518 || GET_MODE (operands[3]) == DImode);
7519
7520 /* Flip unimplemented DImode comparisons to a form that
7521 arm_gen_compare_reg can handle. */
7522 switch (code)
7523 {
7524 case GT:
7525 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7526 case LE:
7527 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7528 case GTU:
7529 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7530 case LEU:
7531 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7532 default:
7533 break;
7534 }
7535 if (swap)
7536 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7537 operands[2]));
7538 else
7539 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7540 operands[3]));
7541 DONE;
7542 }"
74f4459c 7543)
7544
25f905c2 7545(define_expand "cstoresi_eq0_thumb1"
595d88b5 7546 [(parallel
7547 [(set (match_operand:SI 0 "s_register_operand" "")
7548 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7549 (const_int 0)))
7550 (clobber (match_dup:SI 2))])]
25f905c2 7551 "TARGET_THUMB1"
595d88b5 7552 "operands[2] = gen_reg_rtx (SImode);"
7553)
7554
25f905c2 7555(define_expand "cstoresi_ne0_thumb1"
595d88b5 7556 [(parallel
7557 [(set (match_operand:SI 0 "s_register_operand" "")
7558 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7559 (const_int 0)))
7560 (clobber (match_dup:SI 2))])]
25f905c2 7561 "TARGET_THUMB1"
595d88b5 7562 "operands[2] = gen_reg_rtx (SImode);"
7563)
7564
25f905c2 7565(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7566 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7567 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7568 (const_int 0)))
7569 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7570 "TARGET_THUMB1"
595d88b5 7571 "@
7572 neg\\t%0, %1\;adc\\t%0, %0, %1
7573 neg\\t%2, %1\;adc\\t%0, %1, %2"
7574 [(set_attr "length" "4")]
7575)
7576
25f905c2 7577(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7578 [(set (match_operand:SI 0 "s_register_operand" "=l")
7579 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7580 (const_int 0)))
7581 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7582 "TARGET_THUMB1"
595d88b5 7583 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7584 [(set_attr "length" "4")]
7585)
7586
408b7ae5 7587;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 7588(define_insn "cstoresi_nltu_thumb1"
595d88b5 7589 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7590 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7591 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7592 "TARGET_THUMB1"
595d88b5 7593 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7594 [(set_attr "length" "4")]
7595)
7596
408b7ae5 7597(define_insn_and_split "cstoresi_ltu_thumb1"
7598 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7599 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7600 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7601 "TARGET_THUMB1"
7602 "#"
7603 "TARGET_THUMB1"
7604 [(set (match_dup 3)
7605 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7606 (set (match_dup 0) (neg:SI (match_dup 3)))]
7607 "operands[3] = gen_reg_rtx (SImode);"
7608 [(set_attr "length" "4")]
7609)
7610
595d88b5 7611;; Used as part of the expansion of thumb les sequence.
25f905c2 7612(define_insn "thumb1_addsi3_addgeu"
595d88b5 7613 [(set (match_operand:SI 0 "s_register_operand" "=l")
7614 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7615 (match_operand:SI 2 "s_register_operand" "l"))
7616 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 7617 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7618 "TARGET_THUMB1"
595d88b5 7619 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7620 [(set_attr "length" "4")]
7621)
7622
9c08d1fa 7623\f
39b5e676 7624;; Conditional move insns
7625
7626(define_expand "movsicc"
8a18b90c 7627 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7628 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7629 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7630 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7631 "TARGET_32BIT"
39b5e676 7632 "
215b30b3 7633 {
7634 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7635 rtx ccreg;
7636
7637 if (code == UNEQ || code == LTGT)
7638 FAIL;
39b5e676 7639
74f4459c 7640 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7641 XEXP (operands[1], 1));
29bb088d 7642 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7643 }"
7644)
39b5e676 7645
7646(define_expand "movsfcc"
8a18b90c 7647 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7648 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7649 (match_operand:SF 2 "s_register_operand" "")
7650 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 7651 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7652 "
215b30b3 7653 {
7654 enum rtx_code code = GET_CODE (operands[1]);
7655 rtx ccreg;
f082f1c4 7656
278b301d 7657 if (code == UNEQ || code == LTGT)
7658 FAIL;
7659
215b30b3 7660 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7661 Otherwise, ensure it is a valid FP add operand */
7662 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7663 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7664 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7665
74f4459c 7666 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7667 XEXP (operands[1], 1));
29bb088d 7668 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7669 }"
7670)
39b5e676 7671
7672(define_expand "movdfcc"
8a18b90c 7673 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7674 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7675 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7676 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 7677 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 7678 "
215b30b3 7679 {
7680 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7681 rtx ccreg;
39b5e676 7682
278b301d 7683 if (code == UNEQ || code == LTGT)
7684 FAIL;
7685
74f4459c 7686 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7687 XEXP (operands[1], 1));
29bb088d 7688 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7689 }"
7690)
39b5e676 7691
7692(define_insn "*movsicc_insn"
f082f1c4 7693 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7694 (if_then_else:SI
8fa3ba89 7695 (match_operator 3 "arm_comparison_operator"
8a18b90c 7696 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7697 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7698 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7699 "TARGET_ARM"
39b5e676 7700 "@
8a18b90c 7701 mov%D3\\t%0, %2
7702 mvn%D3\\t%0, #%B2
f082f1c4 7703 mov%d3\\t%0, %1
7704 mvn%d3\\t%0, #%B1
8a18b90c 7705 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7706 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7707 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7708 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7709 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7710 (set_attr "conds" "use")
7711 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 7712)
39b5e676 7713
39b5e676 7714(define_insn "*movsfcc_soft_insn"
f082f1c4 7715 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7716 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7717 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7718 (match_operand:SF 1 "s_register_operand" "0,r")
7719 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7720 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7721 "@
7722 mov%D3\\t%0, %2
7723 mov%d3\\t%0, %1"
d2a518d1 7724 [(set_attr "conds" "use")
7725 (set_attr "insn" "mov")]
8fa3ba89 7726)
39b5e676 7727
39b5e676 7728\f
9c08d1fa 7729;; Jump and linkage insns
7730
cffb2a26 7731(define_expand "jump"
9c08d1fa 7732 [(set (pc)
7733 (label_ref (match_operand 0 "" "")))]
cffb2a26 7734 "TARGET_EITHER"
9c08d1fa 7735 ""
cffb2a26 7736)
7737
7738(define_insn "*arm_jump"
7739 [(set (pc)
7740 (label_ref (match_operand 0 "" "")))]
25f905c2 7741 "TARGET_32BIT"
9c08d1fa 7742 "*
0d66636f 7743 {
7744 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7745 {
7746 arm_ccfsm_state += 2;
7747 return \"\";
7748 }
7749 return \"b%?\\t%l0\";
7750 }
7751 "
7752 [(set_attr "predicable" "yes")]
7753)
9c08d1fa 7754
cffb2a26 7755(define_insn "*thumb_jump"
7756 [(set (pc)
7757 (label_ref (match_operand 0 "" "")))]
25f905c2 7758 "TARGET_THUMB1"
cffb2a26 7759 "*
7760 if (get_attr_length (insn) == 2)
7761 return \"b\\t%l0\";
7762 return \"bl\\t%l0\\t%@ far jump\";
7763 "
7764 [(set (attr "far_jump")
7765 (if_then_else
7766 (eq_attr "length" "4")
7767 (const_string "yes")
7768 (const_string "no")))
7769 (set (attr "length")
7770 (if_then_else
911ed8af 7771 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7772 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7773 (const_int 2)
7774 (const_int 4)))]
7775)
7776
d3373b54 7777(define_expand "call"
7778 [(parallel [(call (match_operand 0 "memory_operand" "")
7779 (match_operand 1 "general_operand" ""))
cffb2a26 7780 (use (match_operand 2 "" ""))
bd5b4116 7781 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7782 "TARGET_EITHER"
6c4c2133 7783 "
7784 {
bac7fc85 7785 rtx callee, pat;
bbe777ea 7786
bbe777ea 7787 /* In an untyped call, we can get NULL for operand 2. */
7788 if (operands[2] == NULL_RTX)
7789 operands[2] = const0_rtx;
7790
de55252a 7791 /* Decide if we should generate indirect calls by loading the
85c36fd1 7792 32-bit address of the callee into a register before performing the
de55252a 7793 branch and link. */
7794 callee = XEXP (operands[0], 0);
7795 if (GET_CODE (callee) == SYMBOL_REF
7796 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7797 : !REG_P (callee))
bbe777ea 7798 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7799
7800 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7801 arm_emit_call_insn (pat, XEXP (operands[0], 0));
7802 DONE;
6c4c2133 7803 }"
7804)
d3373b54 7805
bac7fc85 7806(define_expand "call_internal"
7807 [(parallel [(call (match_operand 0 "memory_operand" "")
7808 (match_operand 1 "general_operand" ""))
7809 (use (match_operand 2 "" ""))
7810 (clobber (reg:SI LR_REGNUM))])])
7811
f1039640 7812(define_insn "*call_reg_armv5"
d3373b54 7813 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7814 (match_operand 1 "" ""))
7815 (use (match_operand 2 "" ""))
bd5b4116 7816 (clobber (reg:SI LR_REGNUM))]
f1039640 7817 "TARGET_ARM && arm_arch5"
7818 "blx%?\\t%0"
7819 [(set_attr "type" "call")]
7820)
7821
7822(define_insn "*call_reg_arm"
7823 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7824 (match_operand 1 "" ""))
7825 (use (match_operand 2 "" ""))
7826 (clobber (reg:SI LR_REGNUM))]
7827 "TARGET_ARM && !arm_arch5"
9c08d1fa 7828 "*
5565501b 7829 return output_call (operands);
cffb2a26 7830 "
7831 ;; length is worst case, normally it is only two
7832 [(set_attr "length" "12")
7833 (set_attr "type" "call")]
7834)
9c08d1fa 7835
89504fc1 7836
7837;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7838;; considered a function call by the branch predictor of some cores (PR40887).
7839;; Falls back to blx rN (*call_reg_armv5).
7840
f7fbdd4a 7841(define_insn "*call_mem"
a3c63a9d 7842 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7843 (match_operand 1 "" ""))
7844 (use (match_operand 2 "" ""))
bd5b4116 7845 (clobber (reg:SI LR_REGNUM))]
89504fc1 7846 "TARGET_ARM && !arm_arch5"
9c08d1fa 7847 "*
5565501b 7848 return output_call_mem (operands);
cffb2a26 7849 "
7850 [(set_attr "length" "12")
7851 (set_attr "type" "call")]
7852)
7853
25f905c2 7854(define_insn "*call_reg_thumb1_v5"
cffb2a26 7855 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7856 (match_operand 1 "" ""))
7857 (use (match_operand 2 "" ""))
bd5b4116 7858 (clobber (reg:SI LR_REGNUM))]
25f905c2 7859 "TARGET_THUMB1 && arm_arch5"
f1039640 7860 "blx\\t%0"
7861 [(set_attr "length" "2")
7862 (set_attr "type" "call")]
cffb2a26 7863)
7864
25f905c2 7865(define_insn "*call_reg_thumb1"
f1039640 7866 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7867 (match_operand 1 "" ""))
7868 (use (match_operand 2 "" ""))
bd5b4116 7869 (clobber (reg:SI LR_REGNUM))]
25f905c2 7870 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 7871 "*
7872 {
150502c9 7873 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7874 return thumb_call_via_reg (operands[0]);
150502c9 7875 else if (operands[1] == const0_rtx)
f1039640 7876 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7877 else if (frame_pointer_needed)
7878 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7879 else
150502c9 7880 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7881 }"
7882 [(set_attr "type" "call")]
7883)
9c08d1fa 7884
d3373b54 7885(define_expand "call_value"
e0698af7 7886 [(parallel [(set (match_operand 0 "" "")
7887 (call (match_operand 1 "memory_operand" "")
7888 (match_operand 2 "general_operand" "")))
cffb2a26 7889 (use (match_operand 3 "" ""))
bd5b4116 7890 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7891 "TARGET_EITHER"
6c4c2133 7892 "
7893 {
bac7fc85 7894 rtx pat, callee;
bbe777ea 7895
7896 /* In an untyped call, we can get NULL for operand 2. */
7897 if (operands[3] == 0)
7898 operands[3] = const0_rtx;
7899
de55252a 7900 /* Decide if we should generate indirect calls by loading the
7901 32-bit address of the callee into a register before performing the
7902 branch and link. */
7903 callee = XEXP (operands[1], 0);
7904 if (GET_CODE (callee) == SYMBOL_REF
7905 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7906 : !REG_P (callee))
78fe751b 7907 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7908
7909 pat = gen_call_value_internal (operands[0], operands[1],
7910 operands[2], operands[3]);
7911 arm_emit_call_insn (pat, XEXP (operands[1], 0));
7912 DONE;
6c4c2133 7913 }"
7914)
d3373b54 7915
bac7fc85 7916(define_expand "call_value_internal"
7917 [(parallel [(set (match_operand 0 "" "")
7918 (call (match_operand 1 "memory_operand" "")
7919 (match_operand 2 "general_operand" "")))
7920 (use (match_operand 3 "" ""))
7921 (clobber (reg:SI LR_REGNUM))])])
7922
f1039640 7923(define_insn "*call_value_reg_armv5"
27ed6835 7924 [(set (match_operand 0 "" "")
755eb2b4 7925 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7926 (match_operand 2 "" "")))
bbe777ea 7927 (use (match_operand 3 "" ""))
bd5b4116 7928 (clobber (reg:SI LR_REGNUM))]
f1039640 7929 "TARGET_ARM && arm_arch5"
7930 "blx%?\\t%1"
7931 [(set_attr "type" "call")]
7932)
7933
7934(define_insn "*call_value_reg_arm"
7935 [(set (match_operand 0 "" "")
7936 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7937 (match_operand 2 "" "")))
7938 (use (match_operand 3 "" ""))
7939 (clobber (reg:SI LR_REGNUM))]
7940 "TARGET_ARM && !arm_arch5"
9c08d1fa 7941 "*
215b30b3 7942 return output_call (&operands[1]);
cffb2a26 7943 "
7944 [(set_attr "length" "12")
7945 (set_attr "type" "call")]
7946)
9c08d1fa 7947
89504fc1 7948;; Note: see *call_mem
7949
f7fbdd4a 7950(define_insn "*call_value_mem"
27ed6835 7951 [(set (match_operand 0 "" "")
a3c63a9d 7952 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7953 (match_operand 2 "" "")))
bbe777ea 7954 (use (match_operand 3 "" ""))
bd5b4116 7955 (clobber (reg:SI LR_REGNUM))]
89504fc1 7956 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7957 "*
215b30b3 7958 return output_call_mem (&operands[1]);
cffb2a26 7959 "
7960 [(set_attr "length" "12")
7961 (set_attr "type" "call")]
7962)
9c08d1fa 7963
25f905c2 7964(define_insn "*call_value_reg_thumb1_v5"
f1039640 7965 [(set (match_operand 0 "" "")
7966 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7967 (match_operand 2 "" "")))
7968 (use (match_operand 3 "" ""))
7969 (clobber (reg:SI LR_REGNUM))]
25f905c2 7970 "TARGET_THUMB1 && arm_arch5"
f1039640 7971 "blx\\t%1"
7972 [(set_attr "length" "2")
7973 (set_attr "type" "call")]
7974)
7975
25f905c2 7976(define_insn "*call_value_reg_thumb1"
f1039640 7977 [(set (match_operand 0 "" "")
7978 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7979 (match_operand 2 "" "")))
7980 (use (match_operand 3 "" ""))
7981 (clobber (reg:SI LR_REGNUM))]
25f905c2 7982 "TARGET_THUMB1 && !arm_arch5"
f1039640 7983 "*
7984 {
150502c9 7985 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7986 return thumb_call_via_reg (operands[1]);
150502c9 7987 else if (operands[2] == const0_rtx)
f1039640 7988 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7989 else if (frame_pointer_needed)
7990 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7991 else
150502c9 7992 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 7993 }"
7994 [(set_attr "type" "call")]
7995)
7996
9c08d1fa 7997;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7998;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7999
f7fbdd4a 8000(define_insn "*call_symbol"
27ed6835 8001 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8002 (match_operand 1 "" ""))
bbe777ea 8003 (use (match_operand 2 "" ""))
bd5b4116 8004 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8005 "TARGET_32BIT
cffb2a26 8006 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8007 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8008 "*
8009 {
55c1e470 8010 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8011 }"
cffb2a26 8012 [(set_attr "type" "call")]
8013)
9c08d1fa 8014
f7fbdd4a 8015(define_insn "*call_value_symbol"
ccd90aaa 8016 [(set (match_operand 0 "" "")
27ed6835 8017 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8018 (match_operand:SI 2 "" "")))
bbe777ea 8019 (use (match_operand 3 "" ""))
bd5b4116 8020 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8021 "TARGET_32BIT
cffb2a26 8022 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8023 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8024 "*
8025 {
55c1e470 8026 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8027 }"
cffb2a26 8028 [(set_attr "type" "call")]
8029)
8030
8031(define_insn "*call_insn"
27ed6835 8032 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8033 (match_operand:SI 1 "" ""))
8034 (use (match_operand 2 "" ""))
bd5b4116 8035 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8036 "TARGET_THUMB1
1675c6e9 8037 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8038 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8039 "bl\\t%a0"
8040 [(set_attr "length" "4")
8041 (set_attr "type" "call")]
8042)
8043
8044(define_insn "*call_value_insn"
ccd90aaa 8045 [(set (match_operand 0 "" "")
27ed6835 8046 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8047 (match_operand 2 "" "")))
8048 (use (match_operand 3 "" ""))
bd5b4116 8049 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8050 "TARGET_THUMB1
1675c6e9 8051 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8052 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8053 "bl\\t%a1"
8054 [(set_attr "length" "4")
8055 (set_attr "type" "call")]
8056)
9c08d1fa 8057
1c494086 8058;; We may also be able to do sibcalls for Thumb, but it's much harder...
8059(define_expand "sibcall"
8060 [(parallel [(call (match_operand 0 "memory_operand" "")
8061 (match_operand 1 "general_operand" ""))
2ba80634 8062 (return)
8063 (use (match_operand 2 "" ""))])]
d68c2c10 8064 "TARGET_32BIT"
1c494086 8065 "
8066 {
8067 if (operands[2] == NULL_RTX)
8068 operands[2] = const0_rtx;
1c494086 8069 }"
8070)
8071
8072(define_expand "sibcall_value"
ccd90aaa 8073 [(parallel [(set (match_operand 0 "" "")
1c494086 8074 (call (match_operand 1 "memory_operand" "")
8075 (match_operand 2 "general_operand" "")))
2ba80634 8076 (return)
8077 (use (match_operand 3 "" ""))])]
d68c2c10 8078 "TARGET_32BIT"
1c494086 8079 "
8080 {
8081 if (operands[3] == NULL_RTX)
8082 operands[3] = const0_rtx;
1c494086 8083 }"
8084)
8085
8086(define_insn "*sibcall_insn"
8087 [(call (mem:SI (match_operand:SI 0 "" "X"))
8088 (match_operand 1 "" ""))
2ba80634 8089 (return)
8090 (use (match_operand 2 "" ""))]
d68c2c10 8091 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8092 "*
8093 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8094 "
8095 [(set_attr "type" "call")]
8096)
8097
8098(define_insn "*sibcall_value_insn"
ccd90aaa 8099 [(set (match_operand 0 "" "")
755eb2b4 8100 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8101 (match_operand 2 "" "")))
2ba80634 8102 (return)
8103 (use (match_operand 3 "" ""))]
d68c2c10 8104 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8105 "*
8106 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8107 "
8108 [(set_attr "type" "call")]
8109)
8110
d68c2c10 8111(define_expand "return"
8112 [(return)]
8113 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8114 "")
8115
9c08d1fa 8116;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8117(define_insn "*arm_return"
9c08d1fa 8118 [(return)]
cffb2a26 8119 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8120 "*
9c08d1fa 8121 {
cffb2a26 8122 if (arm_ccfsm_state == 2)
8123 {
8124 arm_ccfsm_state += 2;
8125 return \"\";
8126 }
5db468b7 8127 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8128 }"
a2cd141b 8129 [(set_attr "type" "load1")
755eb2b4 8130 (set_attr "length" "12")
0d66636f 8131 (set_attr "predicable" "yes")]
cffb2a26 8132)
9c08d1fa 8133
f7fbdd4a 8134(define_insn "*cond_return"
9c08d1fa 8135 [(set (pc)
8fa3ba89 8136 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8137 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8138 (return)
8139 (pc)))]
cffb2a26 8140 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8141 "*
8fa3ba89 8142 {
8143 if (arm_ccfsm_state == 2)
8144 {
8145 arm_ccfsm_state += 2;
8146 return \"\";
8147 }
8148 return output_return_instruction (operands[0], TRUE, FALSE);
8149 }"
8150 [(set_attr "conds" "use")
755eb2b4 8151 (set_attr "length" "12")
a2cd141b 8152 (set_attr "type" "load1")]
8fa3ba89 8153)
9c08d1fa 8154
f7fbdd4a 8155(define_insn "*cond_return_inverted"
9c08d1fa 8156 [(set (pc)
8fa3ba89 8157 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8158 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8159 (pc)
8160 (return)))]
cffb2a26 8161 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8162 "*
8fa3ba89 8163 {
8164 if (arm_ccfsm_state == 2)
8165 {
8166 arm_ccfsm_state += 2;
8167 return \"\";
8168 }
8169 return output_return_instruction (operands[0], TRUE, TRUE);
8170 }"
8171 [(set_attr "conds" "use")
37a1317b 8172 (set_attr "length" "12")
a2cd141b 8173 (set_attr "type" "load1")]
8fa3ba89 8174)
9c08d1fa 8175
68121397 8176;; Generate a sequence of instructions to determine if the processor is
8177;; in 26-bit or 32-bit mode, and return the appropriate return address
8178;; mask.
8179
8180(define_expand "return_addr_mask"
8181 [(set (match_dup 1)
8182 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8183 (const_int 0)))
8184 (set (match_operand:SI 0 "s_register_operand" "")
8185 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8186 (const_int -1)
8187 (const_int 67108860)))] ; 0x03fffffc
8188 "TARGET_ARM"
8189 "
62eddbd4 8190 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8191 ")
8192
8193(define_insn "*check_arch2"
8194 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8195 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8196 (const_int 0)))]
8197 "TARGET_ARM"
8198 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8199 [(set_attr "length" "8")
8200 (set_attr "conds" "set")]
8201)
8202
9c08d1fa 8203;; Call subroutine returning any type.
8204
8205(define_expand "untyped_call"
8206 [(parallel [(call (match_operand 0 "" "")
8207 (const_int 0))
8208 (match_operand 1 "" "")
8209 (match_operand 2 "" "")])]
ccd90aaa 8210 "TARGET_EITHER"
9c08d1fa 8211 "
215b30b3 8212 {
8213 int i;
ccd90aaa 8214 rtx par = gen_rtx_PARALLEL (VOIDmode,
8215 rtvec_alloc (XVECLEN (operands[2], 0)));
8216 rtx addr = gen_reg_rtx (Pmode);
8217 rtx mem;
8218 int size = 0;
9c08d1fa 8219
ccd90aaa 8220 emit_move_insn (addr, XEXP (operands[1], 0));
8221 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8222
215b30b3 8223 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8224 {
ccd90aaa 8225 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8226
ccd90aaa 8227 /* Default code only uses r0 as a return value, but we could
8228 be using anything up to 4 registers. */
8229 if (REGNO (src) == R0_REGNUM)
8230 src = gen_rtx_REG (TImode, R0_REGNUM);
8231
8232 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8233 GEN_INT (size));
8234 size += GET_MODE_SIZE (GET_MODE (src));
8235 }
8236
8237 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8238 const0_rtx));
8239
8240 size = 0;
8241
8242 for (i = 0; i < XVECLEN (par, 0); i++)
8243 {
8244 HOST_WIDE_INT offset = 0;
8245 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8246
8247 if (size != 0)
8248 emit_move_insn (addr, plus_constant (addr, size));
8249
8250 mem = change_address (mem, GET_MODE (reg), NULL);
8251 if (REGNO (reg) == R0_REGNUM)
8252 {
8253 /* On thumb we have to use a write-back instruction. */
320ea44d 8254 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8255 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8256 size = TARGET_ARM ? 16 : 0;
8257 }
8258 else
8259 {
8260 emit_move_insn (mem, reg);
8261 size = GET_MODE_SIZE (GET_MODE (reg));
8262 }
215b30b3 8263 }
9c08d1fa 8264
215b30b3 8265 /* The optimizer does not know that the call sets the function value
8266 registers we stored in the result block. We avoid problems by
8267 claiming that all hard registers are used and clobbered at this
8268 point. */
8269 emit_insn (gen_blockage ());
8270
8271 DONE;
8272 }"
8273)
9c08d1fa 8274
ccd90aaa 8275(define_expand "untyped_return"
8276 [(match_operand:BLK 0 "memory_operand" "")
8277 (match_operand 1 "" "")]
8278 "TARGET_EITHER"
8279 "
8280 {
8281 int i;
8282 rtx addr = gen_reg_rtx (Pmode);
8283 rtx mem;
8284 int size = 0;
8285
8286 emit_move_insn (addr, XEXP (operands[0], 0));
8287 mem = change_address (operands[0], BLKmode, addr);
8288
8289 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8290 {
8291 HOST_WIDE_INT offset = 0;
8292 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8293
8294 if (size != 0)
8295 emit_move_insn (addr, plus_constant (addr, size));
8296
8297 mem = change_address (mem, GET_MODE (reg), NULL);
8298 if (REGNO (reg) == R0_REGNUM)
8299 {
8300 /* On thumb we have to use a write-back instruction. */
320ea44d 8301 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8302 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8303 size = TARGET_ARM ? 16 : 0;
8304 }
8305 else
8306 {
8307 emit_move_insn (reg, mem);
8308 size = GET_MODE_SIZE (GET_MODE (reg));
8309 }
8310 }
8311
8312 /* Emit USE insns before the return. */
8313 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8314 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8315
8316 /* Construct the return. */
8317 expand_naked_return ();
8318
8319 DONE;
8320 }"
8321)
8322
9c08d1fa 8323;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8324;; all of memory. This blocks insns from being moved across this point.
8325
8326(define_insn "blockage"
e1159bbe 8327 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8328 "TARGET_EITHER"
9c08d1fa 8329 ""
cffb2a26 8330 [(set_attr "length" "0")
8331 (set_attr "type" "block")]
8332)
9c08d1fa 8333
f7fbdd4a 8334(define_expand "casesi"
8335 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8336 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8337 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8338 (match_operand:SI 3 "" "") ; table label
8339 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8340 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8341 "
215b30b3 8342 {
e6ac8414 8343 enum insn_code code;
215b30b3 8344 if (operands[1] != const0_rtx)
8345 {
e6ac8414 8346 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8347
215b30b3 8348 emit_insn (gen_addsi3 (reg, operands[0],
8349 GEN_INT (-INTVAL (operands[1]))));
8350 operands[0] = reg;
8351 }
9c08d1fa 8352
25f905c2 8353 if (TARGET_ARM)
e6ac8414 8354 code = CODE_FOR_arm_casesi_internal;
3db2019b 8355 else if (TARGET_THUMB1)
e6ac8414 8356 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8357 else if (flag_pic)
e6ac8414 8358 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8359 else
e6ac8414 8360 code = CODE_FOR_thumb2_casesi_internal;
8361
8362 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8363 operands[2] = force_reg (SImode, operands[2]);
8364
8365 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8366 operands[3], operands[4]));
215b30b3 8367 DONE;
8368 }"
8369)
f7fbdd4a 8370
f082f1c4 8371;; The USE in this pattern is needed to tell flow analysis that this is
8372;; a CASESI insn. It has no other purpose.
25f905c2 8373(define_insn "arm_casesi_internal"
f082f1c4 8374 [(parallel [(set (pc)
8375 (if_then_else
8376 (leu (match_operand:SI 0 "s_register_operand" "r")
8377 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8378 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8379 (label_ref (match_operand 2 "" ""))))
8380 (label_ref (match_operand 3 "" ""))))
bd5b4116 8381 (clobber (reg:CC CC_REGNUM))
f082f1c4 8382 (use (label_ref (match_dup 2)))])]
cffb2a26 8383 "TARGET_ARM"
f7fbdd4a 8384 "*
0d66636f 8385 if (flag_pic)
8386 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8387 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8388 "
8389 [(set_attr "conds" "clob")
8390 (set_attr "length" "12")]
8391)
9c08d1fa 8392
e6ac8414 8393(define_expand "thumb1_casesi_internal_pic"
8394 [(match_operand:SI 0 "s_register_operand" "")
8395 (match_operand:SI 1 "thumb1_cmp_operand" "")
8396 (match_operand 2 "" "")
8397 (match_operand 3 "" "")]
3db2019b 8398 "TARGET_THUMB1"
e6ac8414 8399 {
8400 rtx reg0;
8401 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8402 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8403 operands[3]));
8404 reg0 = gen_rtx_REG (SImode, 0);
8405 emit_move_insn (reg0, operands[0]);
8406 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8407 DONE;
8408 }
8409)
8410
8411(define_insn "thumb1_casesi_dispatch"
8412 [(parallel [(set (pc) (unspec [(reg:SI 0)
8413 (label_ref (match_operand 0 "" ""))
8414;; (label_ref (match_operand 1 "" ""))
8415]
8416 UNSPEC_THUMB1_CASESI))
8417 (clobber (reg:SI IP_REGNUM))
8418 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8419 "TARGET_THUMB1"
e6ac8414 8420 "* return thumb1_output_casesi(operands);"
8421 [(set_attr "length" "4")]
8422)
8423
cffb2a26 8424(define_expand "indirect_jump"
9c08d1fa 8425 [(set (pc)
cffb2a26 8426 (match_operand:SI 0 "s_register_operand" ""))]
8427 "TARGET_EITHER"
25f905c2 8428 "
8429 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8430 address and use bx. */
8431 if (TARGET_THUMB2)
8432 {
8433 rtx tmp;
8434 tmp = gen_reg_rtx (SImode);
8435 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8436 operands[0] = tmp;
8437 }
8438 "
cffb2a26 8439)
8440
f1039640 8441;; NB Never uses BX.
cffb2a26 8442(define_insn "*arm_indirect_jump"
8443 [(set (pc)
8444 (match_operand:SI 0 "s_register_operand" "r"))]
8445 "TARGET_ARM"
8446 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8447 [(set_attr "predicable" "yes")]
cffb2a26 8448)
9c08d1fa 8449
f7fbdd4a 8450(define_insn "*load_indirect_jump"
9c08d1fa 8451 [(set (pc)
8452 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8453 "TARGET_ARM"
8454 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8455 [(set_attr "type" "load1")
61a2d04c 8456 (set_attr "pool_range" "4096")
8457 (set_attr "neg_pool_range" "4084")
0d66636f 8458 (set_attr "predicable" "yes")]
cffb2a26 8459)
8460
f1039640 8461;; NB Never uses BX.
25f905c2 8462(define_insn "*thumb1_indirect_jump"
cffb2a26 8463 [(set (pc)
8464 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8465 "TARGET_THUMB1"
cffb2a26 8466 "mov\\tpc, %0"
8467 [(set_attr "conds" "clob")
8468 (set_attr "length" "2")]
8469)
8470
9c08d1fa 8471\f
8472;; Misc insns
8473
8474(define_insn "nop"
8475 [(const_int 0)]
cffb2a26 8476 "TARGET_EITHER"
8477 "*
25f905c2 8478 if (TARGET_UNIFIED_ASM)
8479 return \"nop\";
cffb2a26 8480 if (TARGET_ARM)
8481 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8482 return \"mov\\tr8, r8\";
8483 "
8484 [(set (attr "length")
8485 (if_then_else (eq_attr "is_thumb" "yes")
8486 (const_int 2)
8487 (const_int 4)))]
8488)
8489
9c08d1fa 8490\f
8491;; Patterns to allow combination of arithmetic, cond code and shifts
8492
f7fbdd4a 8493(define_insn "*arith_shiftsi"
d5d4dc8d 8494 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8495 (match_operator:SI 1 "shiftable_operator"
8496 [(match_operator:SI 3 "shift_operator"
d5d4dc8d 8497 [(match_operand:SI 4 "s_register_operand" "r,r")
8498 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8499 (match_operand:SI 2 "s_register_operand" "rk,rk")]))]
8500 "TARGET_32BIT"
6c4c2133 8501 "%i1%?\\t%0, %2, %4%S3"
344495ea 8502 [(set_attr "predicable" "yes")
331beb1a 8503 (set_attr "shift" "4")
d5d4dc8d 8504 (set_attr "arch" "32,a")
8505 ;; We have to make sure to disable the second alternative if
8506 ;; the shift_operator is MULT, since otherwise the insn will
8507 ;; also match a multiply_accumulate pattern and validate_change
8508 ;; will allow a replacement of the constant with a register
8509 ;; despite the checks done in shift_operator.
8510 (set_attr_alternative "insn_enabled"
8511 [(const_string "yes")
8512 (if_then_else
8513 (match_operand:SI 3 "mult_operator" "")
8514 (const_string "no") (const_string "yes"))])
8515 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8516
d7863cfe 8517(define_split
8518 [(set (match_operand:SI 0 "s_register_operand" "")
8519 (match_operator:SI 1 "shiftable_operator"
8520 [(match_operator:SI 2 "shiftable_operator"
8521 [(match_operator:SI 3 "shift_operator"
8522 [(match_operand:SI 4 "s_register_operand" "")
8523 (match_operand:SI 5 "reg_or_int_operand" "")])
8524 (match_operand:SI 6 "s_register_operand" "")])
8525 (match_operand:SI 7 "arm_rhs_operand" "")]))
8526 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8527 "TARGET_32BIT"
d7863cfe 8528 [(set (match_dup 8)
8529 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8530 (match_dup 6)]))
8531 (set (match_dup 0)
8532 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8533 "")
8534
f7fbdd4a 8535(define_insn "*arith_shiftsi_compare0"
bd5b4116 8536 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8537 (compare:CC_NOOV
8538 (match_operator:SI 1 "shiftable_operator"
8539 [(match_operator:SI 3 "shift_operator"
8540 [(match_operand:SI 4 "s_register_operand" "r,r")
8541 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8542 (match_operand:SI 2 "s_register_operand" "r,r")])
8543 (const_int 0)))
8544 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8545 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8546 (match_dup 2)]))]
d5d4dc8d 8547 "TARGET_32BIT"
25f905c2 8548 "%i1%.\\t%0, %2, %4%S3"
344495ea 8549 [(set_attr "conds" "set")
331beb1a 8550 (set_attr "shift" "4")
d5d4dc8d 8551 (set_attr "arch" "32,a")
8552 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8553
f7fbdd4a 8554(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8555 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8556 (compare:CC_NOOV
8557 (match_operator:SI 1 "shiftable_operator"
8558 [(match_operator:SI 3 "shift_operator"
8559 [(match_operand:SI 4 "s_register_operand" "r,r")
8560 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8561 (match_operand:SI 2 "s_register_operand" "r,r")])
8562 (const_int 0)))
8563 (clobber (match_scratch:SI 0 "=r,r"))]
8564 "TARGET_32BIT"
25f905c2 8565 "%i1%.\\t%0, %2, %4%S3"
344495ea 8566 [(set_attr "conds" "set")
331beb1a 8567 (set_attr "shift" "4")
d5d4dc8d 8568 (set_attr "arch" "32,a")
8569 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8570
f7fbdd4a 8571(define_insn "*sub_shiftsi"
d5d4dc8d 8572 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8573 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8574 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8575 [(match_operand:SI 3 "s_register_operand" "r,r")
8576 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8577 "TARGET_32BIT"
6c4c2133 8578 "sub%?\\t%0, %1, %3%S2"
344495ea 8579 [(set_attr "predicable" "yes")
331beb1a 8580 (set_attr "shift" "3")
d5d4dc8d 8581 (set_attr "arch" "32,a")
8582 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8583
f7fbdd4a 8584(define_insn "*sub_shiftsi_compare0"
bd5b4116 8585 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8586 (compare:CC_NOOV
d5d4dc8d 8587 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8588 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8589 [(match_operand:SI 3 "s_register_operand" "r,r")
8590 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8591 (const_int 0)))
d5d4dc8d 8592 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8593 (minus:SI (match_dup 1)
8594 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8595 "TARGET_32BIT"
25f905c2 8596 "sub%.\\t%0, %1, %3%S2"
344495ea 8597 [(set_attr "conds" "set")
a2cd141b 8598 (set_attr "shift" "3")
d5d4dc8d 8599 (set_attr "arch" "32,a")
8600 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8601
f7fbdd4a 8602(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8603 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8604 (compare:CC_NOOV
d5d4dc8d 8605 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8606 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8607 [(match_operand:SI 3 "s_register_operand" "r,r")
8608 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8609 (const_int 0)))
d5d4dc8d 8610 (clobber (match_scratch:SI 0 "=r,r"))]
8611 "TARGET_32BIT"
25f905c2 8612 "sub%.\\t%0, %1, %3%S2"
344495ea 8613 [(set_attr "conds" "set")
a2cd141b 8614 (set_attr "shift" "3")
d5d4dc8d 8615 (set_attr "arch" "32,a")
8616 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8617\f
8618
f7fbdd4a 8619(define_insn "*and_scc"
9c08d1fa 8620 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8621 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8622 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8623 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8624 "TARGET_ARM"
e2348bcb 8625 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8626 [(set_attr "conds" "use")
d2a518d1 8627 (set_attr "insn" "mov")
8fa3ba89 8628 (set_attr "length" "8")]
8629)
9c08d1fa 8630
f7fbdd4a 8631(define_insn "*ior_scc"
9c08d1fa 8632 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8633 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8634 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8635 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8636 "TARGET_ARM"
e2348bcb 8637 "@
899850b0 8638 orr%d2\\t%0, %1, #1
8639 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8640 [(set_attr "conds" "use")
8641 (set_attr "length" "4,8")]
8642)
9c08d1fa 8643
2df9477b 8644; A series of splitters for the compare_scc pattern below. Note that
8645; order is important.
8646(define_split
8647 [(set (match_operand:SI 0 "s_register_operand" "")
8648 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8649 (const_int 0)))
8650 (clobber (reg:CC CC_REGNUM))]
8651 "TARGET_32BIT && reload_completed"
8652 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8653
8654(define_split
8655 [(set (match_operand:SI 0 "s_register_operand" "")
8656 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8657 (const_int 0)))
8658 (clobber (reg:CC CC_REGNUM))]
8659 "TARGET_32BIT && reload_completed"
8660 [(set (match_dup 0) (not:SI (match_dup 1)))
8661 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8662
8663(define_split
8664 [(set (match_operand:SI 0 "s_register_operand" "")
8665 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8666 (const_int 0)))
8667 (clobber (reg:CC CC_REGNUM))]
8668 "TARGET_32BIT && reload_completed"
8669 [(parallel
080c0b9a 8670 [(set (reg:CC CC_REGNUM)
8671 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8672 (set (match_dup 0)
8673 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8674 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8675 (set (match_dup 0) (const_int 0)))])
8676
8677(define_split
8678 [(set (match_operand:SI 0 "s_register_operand" "")
8679 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8680 (match_operand:SI 2 "const_int_operand" "")))
8681 (clobber (reg:CC CC_REGNUM))]
8682 "TARGET_32BIT && reload_completed"
8683 [(parallel
8684 [(set (reg:CC CC_REGNUM)
8685 (compare:CC (match_dup 1) (match_dup 2)))
8686 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8687 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8688 (set (match_dup 0) (const_int 1)))]
8689{
8690 operands[3] = GEN_INT (-INTVAL (operands[2]));
8691})
8692
8693(define_split
8694 [(set (match_operand:SI 0 "s_register_operand" "")
8695 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8696 (match_operand:SI 2 "arm_add_operand" "")))
8697 (clobber (reg:CC CC_REGNUM))]
8698 "TARGET_32BIT && reload_completed"
8699 [(parallel
8700 [(set (reg:CC_NOOV CC_REGNUM)
8701 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8702 (const_int 0)))
8703 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8704 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8705 (set (match_dup 0) (const_int 1)))])
8706
8707(define_insn_and_split "*compare_scc"
5565501b 8708 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8709 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8710 [(match_operand:SI 2 "s_register_operand" "r,r")
8711 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8712 (clobber (reg:CC CC_REGNUM))]
2df9477b 8713 "TARGET_32BIT"
8714 "#"
8715 "&& reload_completed"
8716 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8717 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8718 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8719{
8720 rtx tmp1;
8721 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8722 operands[2], operands[3]);
8723 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8724
2df9477b 8725 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8726
2df9477b 8727 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8728 if (mode == CCFPmode || mode == CCFPEmode)
8729 rc = reverse_condition_maybe_unordered (rc);
8730 else
8731 rc = reverse_condition (rc);
8732 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8733})
9c08d1fa 8734
080c0b9a 8735;; Attempt to improve the sequence generated by the compare_scc splitters
8736;; not to use conditional execution.
8737(define_peephole2
8738 [(set (reg:CC CC_REGNUM)
8739 (compare:CC (match_operand:SI 1 "register_operand" "")
8740 (match_operand:SI 2 "arm_rhs_operand" "")))
8741 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8742 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8743 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8744 (set (match_dup 0) (const_int 1)))
8745 (match_scratch:SI 3 "r")]
8746 "TARGET_32BIT"
8747 [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
8748 (parallel
8749 [(set (reg:CC CC_REGNUM)
8750 (compare:CC (const_int 0) (match_dup 3)))
8751 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8752 (set (match_dup 0)
8753 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8754 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
8755
f7fbdd4a 8756(define_insn "*cond_move"
9c08d1fa 8757 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8758 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8759 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8760 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8761 (const_int 0)])
8762 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8763 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8764 "TARGET_ARM"
9c08d1fa 8765 "*
8fa3ba89 8766 if (GET_CODE (operands[3]) == NE)
8767 {
8768 if (which_alternative != 1)
8769 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8770 if (which_alternative != 0)
8771 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8772 return \"\";
8773 }
8774 if (which_alternative != 0)
8775 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8776 if (which_alternative != 1)
8777 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8778 return \"\";
8779 "
8780 [(set_attr "conds" "use")
d2a518d1 8781 (set_attr "insn" "mov")
8fa3ba89 8782 (set_attr "length" "4,4,8")]
8783)
9c08d1fa 8784
f7fbdd4a 8785(define_insn "*cond_arith"
9c08d1fa 8786 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8787 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8788 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8789 [(match_operand:SI 2 "s_register_operand" "r,r")
8790 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8791 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8792 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8793 "TARGET_ARM"
9c08d1fa 8794 "*
8fa3ba89 8795 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8796 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8797
8fa3ba89 8798 output_asm_insn (\"cmp\\t%2, %3\", operands);
8799 if (GET_CODE (operands[5]) == AND)
8800 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8801 else if (GET_CODE (operands[5]) == MINUS)
8802 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8803 else if (which_alternative != 0)
8804 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8805 return \"%i5%d4\\t%0, %1, #1\";
8806 "
8807 [(set_attr "conds" "clob")
8808 (set_attr "length" "12")]
8809)
9c08d1fa 8810
f7fbdd4a 8811(define_insn "*cond_sub"
9c08d1fa 8812 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8813 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8814 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8815 [(match_operand:SI 2 "s_register_operand" "r,r")
8816 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8817 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8818 "TARGET_ARM"
9c08d1fa 8819 "*
8fa3ba89 8820 output_asm_insn (\"cmp\\t%2, %3\", operands);
8821 if (which_alternative != 0)
8822 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8823 return \"sub%d4\\t%0, %1, #1\";
8824 "
8825 [(set_attr "conds" "clob")
8826 (set_attr "length" "8,12")]
8827)
9c08d1fa 8828
25f905c2 8829;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 8830(define_insn "*cmp_ite0"
cffb2a26 8831 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8832 (compare
8833 (if_then_else:SI
8fa3ba89 8834 (match_operator 4 "arm_comparison_operator"
aea4c774 8835 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8836 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8837 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8838 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8839 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8840 (const_int 0))
8841 (const_int 0)))]
cffb2a26 8842 "TARGET_ARM"
9c08d1fa 8843 "*
aea4c774 8844 {
8fa3ba89 8845 static const char * const opcodes[4][2] =
8846 {
8847 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8848 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8849 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8850 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8851 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8852 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8853 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8854 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8855 };
8856 int swap =
8857 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8858
8859 return opcodes[which_alternative][swap];
8860 }"
8861 [(set_attr "conds" "set")
8862 (set_attr "length" "8")]
8863)
9c08d1fa 8864
aea4c774 8865(define_insn "*cmp_ite1"
cffb2a26 8866 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8867 (compare
8868 (if_then_else:SI
8fa3ba89 8869 (match_operator 4 "arm_comparison_operator"
aea4c774 8870 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8871 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8872 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8873 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8874 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8875 (const_int 1))
8876 (const_int 0)))]
cffb2a26 8877 "TARGET_ARM"
9c08d1fa 8878 "*
9c08d1fa 8879 {
215b30b3 8880 static const char * const opcodes[4][2] =
8881 {
8882 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8883 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8884 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8885 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8886 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8887 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8888 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8889 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8890 };
8891 int swap =
8892 comparison_dominates_p (GET_CODE (operands[5]),
8893 reverse_condition (GET_CODE (operands[4])));
8894
8895 return opcodes[which_alternative][swap];
8896 }"
8fa3ba89 8897 [(set_attr "conds" "set")
8898 (set_attr "length" "8")]
8899)
9c08d1fa 8900
f6c53574 8901(define_insn "*cmp_and"
8902 [(set (match_operand 6 "dominant_cc_register" "")
8903 (compare
8904 (and:SI
8905 (match_operator 4 "arm_comparison_operator"
8906 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8907 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8908 (match_operator:SI 5 "arm_comparison_operator"
8909 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8910 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8911 (const_int 0)))]
8912 "TARGET_ARM"
8913 "*
8914 {
35823b64 8915 static const char *const opcodes[4][2] =
f6c53574 8916 {
8917 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8918 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8919 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8920 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8921 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8922 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8923 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8924 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8925 };
8926 int swap =
8927 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8928
8929 return opcodes[which_alternative][swap];
8930 }"
8931 [(set_attr "conds" "set")
8932 (set_attr "predicable" "no")
8933 (set_attr "length" "8")]
8934)
8935
8936(define_insn "*cmp_ior"
8937 [(set (match_operand 6 "dominant_cc_register" "")
8938 (compare
8939 (ior:SI
8940 (match_operator 4 "arm_comparison_operator"
8941 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8942 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8943 (match_operator:SI 5 "arm_comparison_operator"
8944 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8945 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8946 (const_int 0)))]
8947 "TARGET_ARM"
8948 "*
8949{
35823b64 8950 static const char *const opcodes[4][2] =
f6c53574 8951 {
8952 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8953 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8954 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8955 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8956 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8957 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8958 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8959 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8960 };
8961 int swap =
8962 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8963
8964 return opcodes[which_alternative][swap];
8965}
8966"
8967 [(set_attr "conds" "set")
8968 (set_attr "length" "8")]
8969)
8970
3c5afce6 8971(define_insn_and_split "*ior_scc_scc"
8972 [(set (match_operand:SI 0 "s_register_operand" "=r")
8973 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8974 [(match_operand:SI 1 "s_register_operand" "r")
8975 (match_operand:SI 2 "arm_add_operand" "rIL")])
8976 (match_operator:SI 6 "arm_comparison_operator"
8977 [(match_operand:SI 4 "s_register_operand" "r")
8978 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8979 (clobber (reg:CC CC_REGNUM))]
8980 "TARGET_ARM
8981 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8982 != CCmode)"
8983 "#"
8984 "TARGET_ARM && reload_completed"
8985 [(set (match_dup 7)
8986 (compare
8987 (ior:SI
8988 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8989 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8990 (const_int 0)))
8991 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8992 "operands[7]
8993 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8994 DOM_CC_X_OR_Y),
601f584c 8995 CC_REGNUM);"
8996 [(set_attr "conds" "clob")
8997 (set_attr "length" "16")])
8998
8999; If the above pattern is followed by a CMP insn, then the compare is
9000; redundant, since we can rework the conditional instruction that follows.
9001(define_insn_and_split "*ior_scc_scc_cmp"
9002 [(set (match_operand 0 "dominant_cc_register" "")
9003 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9004 [(match_operand:SI 1 "s_register_operand" "r")
9005 (match_operand:SI 2 "arm_add_operand" "rIL")])
9006 (match_operator:SI 6 "arm_comparison_operator"
9007 [(match_operand:SI 4 "s_register_operand" "r")
9008 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9009 (const_int 0)))
9010 (set (match_operand:SI 7 "s_register_operand" "=r")
9011 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9012 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9013 "TARGET_ARM"
9014 "#"
9015 "TARGET_ARM && reload_completed"
9016 [(set (match_dup 0)
9017 (compare
9018 (ior:SI
9019 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9020 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9021 (const_int 0)))
9022 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9023 ""
9024 [(set_attr "conds" "set")
9025 (set_attr "length" "16")])
3c5afce6 9026
9027(define_insn_and_split "*and_scc_scc"
9028 [(set (match_operand:SI 0 "s_register_operand" "=r")
9029 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9030 [(match_operand:SI 1 "s_register_operand" "r")
9031 (match_operand:SI 2 "arm_add_operand" "rIL")])
9032 (match_operator:SI 6 "arm_comparison_operator"
9033 [(match_operand:SI 4 "s_register_operand" "r")
9034 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9035 (clobber (reg:CC CC_REGNUM))]
9036 "TARGET_ARM
9037 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9038 != CCmode)"
9039 "#"
601f584c 9040 "TARGET_ARM && reload_completed
9041 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9042 != CCmode)"
3c5afce6 9043 [(set (match_dup 7)
9044 (compare
9045 (and:SI
9046 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9047 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9048 (const_int 0)))
9049 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9050 "operands[7]
9051 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9052 DOM_CC_X_AND_Y),
601f584c 9053 CC_REGNUM);"
9054 [(set_attr "conds" "clob")
9055 (set_attr "length" "16")])
9056
9057; If the above pattern is followed by a CMP insn, then the compare is
9058; redundant, since we can rework the conditional instruction that follows.
9059(define_insn_and_split "*and_scc_scc_cmp"
9060 [(set (match_operand 0 "dominant_cc_register" "")
9061 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9062 [(match_operand:SI 1 "s_register_operand" "r")
9063 (match_operand:SI 2 "arm_add_operand" "rIL")])
9064 (match_operator:SI 6 "arm_comparison_operator"
9065 [(match_operand:SI 4 "s_register_operand" "r")
9066 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9067 (const_int 0)))
9068 (set (match_operand:SI 7 "s_register_operand" "=r")
9069 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9070 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9071 "TARGET_ARM"
9072 "#"
9073 "TARGET_ARM && reload_completed"
9074 [(set (match_dup 0)
9075 (compare
9076 (and:SI
9077 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9078 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9079 (const_int 0)))
9080 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9081 ""
9082 [(set_attr "conds" "set")
9083 (set_attr "length" "16")])
9084
9085;; If there is no dominance in the comparison, then we can still save an
9086;; instruction in the AND case, since we can know that the second compare
9087;; need only zero the value if false (if true, then the value is already
9088;; correct).
9089(define_insn_and_split "*and_scc_scc_nodom"
9090 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9091 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9092 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9093 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9094 (match_operator:SI 6 "arm_comparison_operator"
9095 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9096 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9097 (clobber (reg:CC CC_REGNUM))]
9098 "TARGET_ARM
9099 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9100 == CCmode)"
9101 "#"
9102 "TARGET_ARM && reload_completed"
9103 [(parallel [(set (match_dup 0)
9104 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9105 (clobber (reg:CC CC_REGNUM))])
9106 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9107 (set (match_dup 0)
9108 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9109 (match_dup 0)
9110 (const_int 0)))]
9111 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9112 operands[4], operands[5]),
9113 CC_REGNUM);
9114 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9115 operands[5]);"
9116 [(set_attr "conds" "clob")
9117 (set_attr "length" "20")])
3c5afce6 9118
3a0bdee0 9119(define_split
9120 [(set (reg:CC_NOOV CC_REGNUM)
9121 (compare:CC_NOOV (ior:SI
9122 (and:SI (match_operand:SI 0 "s_register_operand" "")
9123 (const_int 1))
b0694be0 9124 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9125 [(match_operand:SI 2 "s_register_operand" "")
9126 (match_operand:SI 3 "arm_add_operand" "")]))
9127 (const_int 0)))
9128 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9129 "TARGET_ARM"
9130 [(set (match_dup 4)
9131 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9132 (match_dup 0)))
9133 (set (reg:CC_NOOV CC_REGNUM)
9134 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9135 (const_int 0)))]
9136 "")
9137
9138(define_split
9139 [(set (reg:CC_NOOV CC_REGNUM)
9140 (compare:CC_NOOV (ior:SI
b0694be0 9141 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9142 [(match_operand:SI 2 "s_register_operand" "")
9143 (match_operand:SI 3 "arm_add_operand" "")])
9144 (and:SI (match_operand:SI 0 "s_register_operand" "")
9145 (const_int 1)))
9146 (const_int 0)))
9147 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9148 "TARGET_ARM"
9149 [(set (match_dup 4)
9150 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9151 (match_dup 0)))
9152 (set (reg:CC_NOOV CC_REGNUM)
9153 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9154 (const_int 0)))]
9155 "")
25f905c2 9156;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9157
f7fbdd4a 9158(define_insn "*negscc"
9c08d1fa 9159 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9160 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9161 [(match_operand:SI 1 "s_register_operand" "r")
9162 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9163 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9164 "TARGET_ARM"
9c08d1fa 9165 "*
2ca2ec2e 9166 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9167 return \"mov\\t%0, %1, asr #31\";
9168
9c08d1fa 9169 if (GET_CODE (operands[3]) == NE)
e2348bcb 9170 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9171
e2348bcb 9172 output_asm_insn (\"cmp\\t%1, %2\", operands);
9173 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9174 return \"mvn%d3\\t%0, #0\";
215b30b3 9175 "
8fa3ba89 9176 [(set_attr "conds" "clob")
9177 (set_attr "length" "12")]
9178)
9c08d1fa 9179
9180(define_insn "movcond"
9181 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9182 (if_then_else:SI
8fa3ba89 9183 (match_operator 5 "arm_comparison_operator"
5565501b 9184 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9185 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9186 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9187 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9188 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9189 "TARGET_ARM"
9c08d1fa 9190 "*
9191 if (GET_CODE (operands[5]) == LT
9192 && (operands[4] == const0_rtx))
9193 {
5565501b 9194 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9195 {
9c08d1fa 9196 if (operands[2] == const0_rtx)
e2348bcb 9197 return \"and\\t%0, %1, %3, asr #31\";
9198 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9199 }
9200 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9201 {
9c08d1fa 9202 if (operands[1] == const0_rtx)
e2348bcb 9203 return \"bic\\t%0, %2, %3, asr #31\";
9204 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9205 }
9206 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9207 are constants. */
9c08d1fa 9208 }
e2348bcb 9209
9c08d1fa 9210 if (GET_CODE (operands[5]) == GE
9211 && (operands[4] == const0_rtx))
9212 {
9213 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9214 {
9c08d1fa 9215 if (operands[2] == const0_rtx)
e2348bcb 9216 return \"bic\\t%0, %1, %3, asr #31\";
9217 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9218 }
9219 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9220 {
9c08d1fa 9221 if (operands[1] == const0_rtx)
e2348bcb 9222 return \"and\\t%0, %2, %3, asr #31\";
9223 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9224 }
9225 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9226 are constants. */
9c08d1fa 9227 }
9228 if (GET_CODE (operands[4]) == CONST_INT
9229 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9230 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9231 else
e2348bcb 9232 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9233 if (which_alternative != 0)
e2348bcb 9234 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9235 if (which_alternative != 1)
e2348bcb 9236 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9237 return \"\";
215b30b3 9238 "
8fa3ba89 9239 [(set_attr "conds" "clob")
9240 (set_attr "length" "8,8,12")]
9241)
9c08d1fa 9242
25f905c2 9243;; ??? The patterns below need checking for Thumb-2 usefulness.
9244
8a18b90c 9245(define_insn "*ifcompare_plus_move"
9246 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9247 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9248 [(match_operand:SI 4 "s_register_operand" "r,r")
9249 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9250 (plus:SI
9251 (match_operand:SI 2 "s_register_operand" "r,r")
9252 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9253 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9254 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9255 "TARGET_ARM"
8a18b90c 9256 "#"
8fa3ba89 9257 [(set_attr "conds" "clob")
9258 (set_attr "length" "8,12")]
9259)
8a18b90c 9260
9261(define_insn "*if_plus_move"
129a2fe4 9262 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9263 (if_then_else:SI
8fa3ba89 9264 (match_operator 4 "arm_comparison_operator"
8a18b90c 9265 [(match_operand 5 "cc_register" "") (const_int 0)])
9266 (plus:SI
129a2fe4 9267 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9268 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9269 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9270 "TARGET_ARM"
8a18b90c 9271 "@
9272 add%d4\\t%0, %2, %3
9273 sub%d4\\t%0, %2, #%n3
9274 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9275 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9276 [(set_attr "conds" "use")
9277 (set_attr "length" "4,4,8,8")
9278 (set_attr "type" "*,*,*,*")]
9279)
8a18b90c 9280
9281(define_insn "*ifcompare_move_plus"
5565501b 9282 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9283 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9284 [(match_operand:SI 4 "s_register_operand" "r,r")
9285 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9286 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9287 (plus:SI
9288 (match_operand:SI 2 "s_register_operand" "r,r")
9289 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9290 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9291 "TARGET_ARM"
8a18b90c 9292 "#"
8fa3ba89 9293 [(set_attr "conds" "clob")
9294 (set_attr "length" "8,12")]
9295)
8a18b90c 9296
9297(define_insn "*if_move_plus"
129a2fe4 9298 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9299 (if_then_else:SI
8fa3ba89 9300 (match_operator 4 "arm_comparison_operator"
8a18b90c 9301 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9302 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9303 (plus:SI
129a2fe4 9304 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9305 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9306 "TARGET_ARM"
8a18b90c 9307 "@
9308 add%D4\\t%0, %2, %3
9309 sub%D4\\t%0, %2, #%n3
9310 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9311 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9312 [(set_attr "conds" "use")
9313 (set_attr "length" "4,4,8,8")
9314 (set_attr "type" "*,*,*,*")]
9315)
8a18b90c 9316
9317(define_insn "*ifcompare_arith_arith"
9318 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9319 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9320 [(match_operand:SI 5 "s_register_operand" "r")
9321 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9322 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9323 [(match_operand:SI 1 "s_register_operand" "r")
9324 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9325 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9326 [(match_operand:SI 3 "s_register_operand" "r")
9327 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9328 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9329 "TARGET_ARM"
8a18b90c 9330 "#"
8fa3ba89 9331 [(set_attr "conds" "clob")
9332 (set_attr "length" "12")]
9333)
9c08d1fa 9334
8a18b90c 9335(define_insn "*if_arith_arith"
9336 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9337 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9338 [(match_operand 8 "cc_register" "") (const_int 0)])
9339 (match_operator:SI 6 "shiftable_operator"
9340 [(match_operand:SI 1 "s_register_operand" "r")
9341 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9342 (match_operator:SI 7 "shiftable_operator"
9343 [(match_operand:SI 3 "s_register_operand" "r")
9344 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9345 "TARGET_ARM"
8a18b90c 9346 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9347 [(set_attr "conds" "use")
9348 (set_attr "length" "8")]
9349)
8a18b90c 9350
f7fbdd4a 9351(define_insn "*ifcompare_arith_move"
9c08d1fa 9352 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9353 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9354 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9355 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9356 (match_operator:SI 7 "shiftable_operator"
9357 [(match_operand:SI 4 "s_register_operand" "r,r")
9358 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9359 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9360 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9361 "TARGET_ARM"
9c08d1fa 9362 "*
9c08d1fa 9363 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9364 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9365 everything is in registers then we can do this in two instructions. */
9c08d1fa 9366 if (operands[3] == const0_rtx
9367 && GET_CODE (operands[7]) != AND
9368 && GET_CODE (operands[5]) == REG
9369 && GET_CODE (operands[1]) == REG
9370 && REGNO (operands[1]) == REGNO (operands[4])
9371 && REGNO (operands[4]) != REGNO (operands[0]))
9372 {
9373 if (GET_CODE (operands[6]) == LT)
40dbec34 9374 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9375 else if (GET_CODE (operands[6]) == GE)
40dbec34 9376 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9377 }
9378 if (GET_CODE (operands[3]) == CONST_INT
9379 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9380 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9381 else
e2348bcb 9382 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9383 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9384 if (which_alternative != 0)
129a2fe4 9385 return \"mov%D6\\t%0, %1\";
9c08d1fa 9386 return \"\";
215b30b3 9387 "
8fa3ba89 9388 [(set_attr "conds" "clob")
9389 (set_attr "length" "8,12")]
9390)
9c08d1fa 9391
8a18b90c 9392(define_insn "*if_arith_move"
129a2fe4 9393 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9394 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9395 [(match_operand 6 "cc_register" "") (const_int 0)])
9396 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9397 [(match_operand:SI 2 "s_register_operand" "r,r")
9398 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9399 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9400 "TARGET_ARM"
8a18b90c 9401 "@
9402 %I5%d4\\t%0, %2, %3
129a2fe4 9403 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9404 [(set_attr "conds" "use")
9405 (set_attr "length" "4,8")
9406 (set_attr "type" "*,*")]
9407)
8a18b90c 9408
f7fbdd4a 9409(define_insn "*ifcompare_move_arith"
9c08d1fa 9410 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9411 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9412 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9413 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9414 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9415 (match_operator:SI 7 "shiftable_operator"
9416 [(match_operand:SI 2 "s_register_operand" "r,r")
9417 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9418 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9419 "TARGET_ARM"
9c08d1fa 9420 "*
9c08d1fa 9421 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9422 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9423 everything is in registers then we can do this in two instructions */
9424 if (operands[5] == const0_rtx
9425 && GET_CODE (operands[7]) != AND
9426 && GET_CODE (operands[3]) == REG
9427 && GET_CODE (operands[1]) == REG
9428 && REGNO (operands[1]) == REGNO (operands[2])
9429 && REGNO (operands[2]) != REGNO (operands[0]))
9430 {
9431 if (GET_CODE (operands[6]) == GE)
40dbec34 9432 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9433 else if (GET_CODE (operands[6]) == LT)
40dbec34 9434 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9435 }
40dbec34 9436
9c08d1fa 9437 if (GET_CODE (operands[5]) == CONST_INT
9438 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9439 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9440 else
e2348bcb 9441 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9442
9c08d1fa 9443 if (which_alternative != 0)
129a2fe4 9444 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9445 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9446 "
8fa3ba89 9447 [(set_attr "conds" "clob")
9448 (set_attr "length" "8,12")]
9449)
9c08d1fa 9450
8a18b90c 9451(define_insn "*if_move_arith"
129a2fe4 9452 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9453 (if_then_else:SI
8fa3ba89 9454 (match_operator 4 "arm_comparison_operator"
8a18b90c 9455 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9456 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9457 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9458 [(match_operand:SI 2 "s_register_operand" "r,r")
9459 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9460 "TARGET_ARM"
8a18b90c 9461 "@
9462 %I5%D4\\t%0, %2, %3
129a2fe4 9463 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9464 [(set_attr "conds" "use")
9465 (set_attr "length" "4,8")
9466 (set_attr "type" "*,*")]
9467)
8a18b90c 9468
9469(define_insn "*ifcompare_move_not"
9c08d1fa 9470 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9471 (if_then_else:SI
8fa3ba89 9472 (match_operator 5 "arm_comparison_operator"
8a18b90c 9473 [(match_operand:SI 3 "s_register_operand" "r,r")
9474 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9475 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9476 (not:SI
9477 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9478 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9479 "TARGET_ARM"
8a18b90c 9480 "#"
8fa3ba89 9481 [(set_attr "conds" "clob")
9482 (set_attr "length" "8,12")]
9483)
9c08d1fa 9484
8a18b90c 9485(define_insn "*if_move_not"
9486 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9487 (if_then_else:SI
8fa3ba89 9488 (match_operator 4 "arm_comparison_operator"
8a18b90c 9489 [(match_operand 3 "cc_register" "") (const_int 0)])
9490 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9491 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9492 "TARGET_ARM"
8a18b90c 9493 "@
9494 mvn%D4\\t%0, %2
9495 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9496 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9497 [(set_attr "conds" "use")
d2a518d1 9498 (set_attr "insn" "mvn")
8fa3ba89 9499 (set_attr "length" "4,8,8")]
9500)
8a18b90c 9501
9502(define_insn "*ifcompare_not_move"
9c08d1fa 9503 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9504 (if_then_else:SI
8fa3ba89 9505 (match_operator 5 "arm_comparison_operator"
8a18b90c 9506 [(match_operand:SI 3 "s_register_operand" "r,r")
9507 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9508 (not:SI
9509 (match_operand:SI 2 "s_register_operand" "r,r"))
9510 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9511 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9512 "TARGET_ARM"
8a18b90c 9513 "#"
8fa3ba89 9514 [(set_attr "conds" "clob")
9515 (set_attr "length" "8,12")]
9516)
9c08d1fa 9517
8a18b90c 9518(define_insn "*if_not_move"
9519 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9520 (if_then_else:SI
8fa3ba89 9521 (match_operator 4 "arm_comparison_operator"
8a18b90c 9522 [(match_operand 3 "cc_register" "") (const_int 0)])
9523 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9524 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9525 "TARGET_ARM"
8a18b90c 9526 "@
9527 mvn%d4\\t%0, %2
9528 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9529 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9530 [(set_attr "conds" "use")
d2a518d1 9531 (set_attr "insn" "mvn")
8fa3ba89 9532 (set_attr "length" "4,8,8")]
9533)
8a18b90c 9534
9535(define_insn "*ifcompare_shift_move"
9c08d1fa 9536 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9537 (if_then_else:SI
8fa3ba89 9538 (match_operator 6 "arm_comparison_operator"
8a18b90c 9539 [(match_operand:SI 4 "s_register_operand" "r,r")
9540 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9541 (match_operator:SI 7 "shift_operator"
9542 [(match_operand:SI 2 "s_register_operand" "r,r")
9543 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9544 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9545 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9546 "TARGET_ARM"
9c08d1fa 9547 "#"
8fa3ba89 9548 [(set_attr "conds" "clob")
9549 (set_attr "length" "8,12")]
9550)
9c08d1fa 9551
8a18b90c 9552(define_insn "*if_shift_move"
9553 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9554 (if_then_else:SI
8fa3ba89 9555 (match_operator 5 "arm_comparison_operator"
8a18b90c 9556 [(match_operand 6 "cc_register" "") (const_int 0)])
9557 (match_operator:SI 4 "shift_operator"
9558 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9559 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9560 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9561 "TARGET_ARM"
5565501b 9562 "@
8a18b90c 9563 mov%d5\\t%0, %2%S4
9564 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9565 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9566 [(set_attr "conds" "use")
331beb1a 9567 (set_attr "shift" "2")
a2cd141b 9568 (set_attr "length" "4,8,8")
d2a518d1 9569 (set_attr "insn" "mov")
a2cd141b 9570 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9571 (const_string "alu_shift")
9572 (const_string "alu_shift_reg")))]
8fa3ba89 9573)
5565501b 9574
8a18b90c 9575(define_insn "*ifcompare_move_shift"
9576 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9577 (if_then_else:SI
8fa3ba89 9578 (match_operator 6 "arm_comparison_operator"
8a18b90c 9579 [(match_operand:SI 4 "s_register_operand" "r,r")
9580 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9581 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9582 (match_operator:SI 7 "shift_operator"
8a18b90c 9583 [(match_operand:SI 2 "s_register_operand" "r,r")
9584 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9585 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9586 "TARGET_ARM"
8a18b90c 9587 "#"
8fa3ba89 9588 [(set_attr "conds" "clob")
9589 (set_attr "length" "8,12")]
9590)
5565501b 9591
8a18b90c 9592(define_insn "*if_move_shift"
9593 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9594 (if_then_else:SI
8fa3ba89 9595 (match_operator 5 "arm_comparison_operator"
8a18b90c 9596 [(match_operand 6 "cc_register" "") (const_int 0)])
9597 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9598 (match_operator:SI 4 "shift_operator"
9599 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9600 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9601 "TARGET_ARM"
5565501b 9602 "@
8a18b90c 9603 mov%D5\\t%0, %2%S4
9604 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9605 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9606 [(set_attr "conds" "use")
331beb1a 9607 (set_attr "shift" "2")
a2cd141b 9608 (set_attr "length" "4,8,8")
d2a518d1 9609 (set_attr "insn" "mov")
a2cd141b 9610 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9611 (const_string "alu_shift")
9612 (const_string "alu_shift_reg")))]
8fa3ba89 9613)
9c08d1fa 9614
f7fbdd4a 9615(define_insn "*ifcompare_shift_shift"
8a18b90c 9616 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9617 (if_then_else:SI
8fa3ba89 9618 (match_operator 7 "arm_comparison_operator"
8a18b90c 9619 [(match_operand:SI 5 "s_register_operand" "r")
9620 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9621 (match_operator:SI 8 "shift_operator"
8a18b90c 9622 [(match_operand:SI 1 "s_register_operand" "r")
9623 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9624 (match_operator:SI 9 "shift_operator"
8a18b90c 9625 [(match_operand:SI 3 "s_register_operand" "r")
9626 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9627 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9628 "TARGET_ARM"
8a18b90c 9629 "#"
8fa3ba89 9630 [(set_attr "conds" "clob")
9631 (set_attr "length" "12")]
9632)
9c08d1fa 9633
8a18b90c 9634(define_insn "*if_shift_shift"
9635 [(set (match_operand:SI 0 "s_register_operand" "=r")
9636 (if_then_else:SI
8fa3ba89 9637 (match_operator 5 "arm_comparison_operator"
8a18b90c 9638 [(match_operand 8 "cc_register" "") (const_int 0)])
9639 (match_operator:SI 6 "shift_operator"
9640 [(match_operand:SI 1 "s_register_operand" "r")
9641 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9642 (match_operator:SI 7 "shift_operator"
9643 [(match_operand:SI 3 "s_register_operand" "r")
9644 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9645 "TARGET_ARM"
8a18b90c 9646 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9647 [(set_attr "conds" "use")
331beb1a 9648 (set_attr "shift" "1")
a2cd141b 9649 (set_attr "length" "8")
d2a518d1 9650 (set_attr "insn" "mov")
a2cd141b 9651 (set (attr "type") (if_then_else
9652 (and (match_operand 2 "const_int_operand" "")
9653 (match_operand 4 "const_int_operand" ""))
9654 (const_string "alu_shift")
9655 (const_string "alu_shift_reg")))]
8fa3ba89 9656)
8a18b90c 9657
f7fbdd4a 9658(define_insn "*ifcompare_not_arith"
8a18b90c 9659 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9660 (if_then_else:SI
8fa3ba89 9661 (match_operator 6 "arm_comparison_operator"
8a18b90c 9662 [(match_operand:SI 4 "s_register_operand" "r")
9663 (match_operand:SI 5 "arm_add_operand" "rIL")])
9664 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9665 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9666 [(match_operand:SI 2 "s_register_operand" "r")
9667 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9668 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9669 "TARGET_ARM"
8a18b90c 9670 "#"
8fa3ba89 9671 [(set_attr "conds" "clob")
9672 (set_attr "length" "12")]
9673)
9c08d1fa 9674
8a18b90c 9675(define_insn "*if_not_arith"
9676 [(set (match_operand:SI 0 "s_register_operand" "=r")
9677 (if_then_else:SI
8fa3ba89 9678 (match_operator 5 "arm_comparison_operator"
8a18b90c 9679 [(match_operand 4 "cc_register" "") (const_int 0)])
9680 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9681 (match_operator:SI 6 "shiftable_operator"
9682 [(match_operand:SI 2 "s_register_operand" "r")
9683 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9684 "TARGET_ARM"
8a18b90c 9685 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9686 [(set_attr "conds" "use")
d2a518d1 9687 (set_attr "insn" "mvn")
8fa3ba89 9688 (set_attr "length" "8")]
9689)
8a18b90c 9690
9691(define_insn "*ifcompare_arith_not"
9692 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9693 (if_then_else:SI
8fa3ba89 9694 (match_operator 6 "arm_comparison_operator"
8a18b90c 9695 [(match_operand:SI 4 "s_register_operand" "r")
9696 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9697 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9698 [(match_operand:SI 2 "s_register_operand" "r")
9699 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9700 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9701 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9702 "TARGET_ARM"
8a18b90c 9703 "#"
8fa3ba89 9704 [(set_attr "conds" "clob")
9705 (set_attr "length" "12")]
9706)
9c08d1fa 9707
8a18b90c 9708(define_insn "*if_arith_not"
9709 [(set (match_operand:SI 0 "s_register_operand" "=r")
9710 (if_then_else:SI
8fa3ba89 9711 (match_operator 5 "arm_comparison_operator"
8a18b90c 9712 [(match_operand 4 "cc_register" "") (const_int 0)])
9713 (match_operator:SI 6 "shiftable_operator"
9714 [(match_operand:SI 2 "s_register_operand" "r")
9715 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9716 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9717 "TARGET_ARM"
8a18b90c 9718 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9719 [(set_attr "conds" "use")
d2a518d1 9720 (set_attr "insn" "mvn")
8fa3ba89 9721 (set_attr "length" "8")]
9722)
8a18b90c 9723
f7fbdd4a 9724(define_insn "*ifcompare_neg_move"
8a18b90c 9725 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9726 (if_then_else:SI
8fa3ba89 9727 (match_operator 5 "arm_comparison_operator"
8a18b90c 9728 [(match_operand:SI 3 "s_register_operand" "r,r")
9729 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9730 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9731 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9732 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9733 "TARGET_ARM"
8a18b90c 9734 "#"
8fa3ba89 9735 [(set_attr "conds" "clob")
9736 (set_attr "length" "8,12")]
9737)
8a18b90c 9738
9739(define_insn "*if_neg_move"
9740 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9741 (if_then_else:SI
8fa3ba89 9742 (match_operator 4 "arm_comparison_operator"
8a18b90c 9743 [(match_operand 3 "cc_register" "") (const_int 0)])
9744 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9745 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9746 "TARGET_ARM"
8a18b90c 9747 "@
9748 rsb%d4\\t%0, %2, #0
9749 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9750 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9751 [(set_attr "conds" "use")
9752 (set_attr "length" "4,8,8")]
9753)
9c08d1fa 9754
f7fbdd4a 9755(define_insn "*ifcompare_move_neg"
8a18b90c 9756 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9757 (if_then_else:SI
8fa3ba89 9758 (match_operator 5 "arm_comparison_operator"
8a18b90c 9759 [(match_operand:SI 3 "s_register_operand" "r,r")
9760 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9761 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9762 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9763 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9764 "TARGET_ARM"
8a18b90c 9765 "#"
8fa3ba89 9766 [(set_attr "conds" "clob")
9767 (set_attr "length" "8,12")]
9768)
8a18b90c 9769
9770(define_insn "*if_move_neg"
9771 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9772 (if_then_else:SI
8fa3ba89 9773 (match_operator 4 "arm_comparison_operator"
8a18b90c 9774 [(match_operand 3 "cc_register" "") (const_int 0)])
9775 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9776 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9777 "TARGET_ARM"
8a18b90c 9778 "@
9779 rsb%D4\\t%0, %2, #0
9780 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9781 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9782 [(set_attr "conds" "use")
9783 (set_attr "length" "4,8,8")]
9784)
9c08d1fa 9785
f7fbdd4a 9786(define_insn "*arith_adjacentmem"
9c08d1fa 9787 [(set (match_operand:SI 0 "s_register_operand" "=r")
9788 (match_operator:SI 1 "shiftable_operator"
9789 [(match_operand:SI 2 "memory_operand" "m")
9790 (match_operand:SI 3 "memory_operand" "m")]))
9791 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9792 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9793 "*
215b30b3 9794 {
9795 rtx ldm[3];
9796 rtx arith[4];
94dee231 9797 rtx base_reg;
9798 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9799
215b30b3 9800 if (REGNO (operands[0]) > REGNO (operands[4]))
9801 {
9802 ldm[1] = operands[4];
9803 ldm[2] = operands[0];
9804 }
9805 else
9806 {
9807 ldm[1] = operands[0];
9808 ldm[2] = operands[4];
9809 }
94dee231 9810
9811 base_reg = XEXP (operands[2], 0);
9812
9813 if (!REG_P (base_reg))
9814 {
9815 val1 = INTVAL (XEXP (base_reg, 1));
9816 base_reg = XEXP (base_reg, 0);
9817 }
9818
9819 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9820 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9821
215b30b3 9822 arith[0] = operands[0];
9823 arith[3] = operands[1];
94dee231 9824
215b30b3 9825 if (val1 < val2)
9826 {
9827 arith[1] = ldm[1];
9828 arith[2] = ldm[2];
9829 }
9830 else
9831 {
9832 arith[1] = ldm[2];
9833 arith[2] = ldm[1];
9834 }
94dee231 9835
9836 ldm[0] = base_reg;
9837 if (val1 !=0 && val2 != 0)
215b30b3 9838 {
cdb1295a 9839 rtx ops[3];
9840
94dee231 9841 if (val1 == 4 || val2 == 4)
9842 /* Other val must be 8, since we know they are adjacent and neither
9843 is zero. */
25f905c2 9844 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 9845 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 9846 {
94dee231 9847 ldm[0] = ops[0] = operands[4];
9848 ops[1] = base_reg;
9849 ops[2] = GEN_INT (val1);
9850 output_add_immediate (ops);
9851 if (val1 < val2)
25f905c2 9852 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 9853 else
25f905c2 9854 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 9855 }
cdb1295a 9856 else
9857 {
9858 /* Offset is out of range for a single add, so use two ldr. */
9859 ops[0] = ldm[1];
9860 ops[1] = base_reg;
9861 ops[2] = GEN_INT (val1);
9862 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9863 ops[0] = ldm[2];
9864 ops[2] = GEN_INT (val2);
9865 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9866 }
215b30b3 9867 }
94dee231 9868 else if (val1 != 0)
215b30b3 9869 {
215b30b3 9870 if (val1 < val2)
25f905c2 9871 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9872 else
25f905c2 9873 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9874 }
9875 else
9876 {
215b30b3 9877 if (val1 < val2)
25f905c2 9878 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9879 else
25f905c2 9880 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9881 }
9882 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9883 return \"\";
9884 }"
9885 [(set_attr "length" "12")
9886 (set_attr "predicable" "yes")
a2cd141b 9887 (set_attr "type" "load1")]
215b30b3 9888)
9c08d1fa 9889
9c08d1fa 9890; This pattern is never tried by combine, so do it as a peephole
9891
a0f94409 9892(define_peephole2
372575c7 9893 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9894 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9895 (set (reg:CC CC_REGNUM)
aea4c774 9896 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9897 "TARGET_ARM"
a0f94409 9898 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9899 (set (match_dup 0) (match_dup 1))])]
9900 ""
0d66636f 9901)
9c08d1fa 9902
9c08d1fa 9903(define_split
9904 [(set (match_operand:SI 0 "s_register_operand" "")
9905 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9906 (const_int 0))
8fa3ba89 9907 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9908 [(match_operand:SI 3 "s_register_operand" "")
9909 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9910 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9911 "TARGET_ARM"
9c08d1fa 9912 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9913 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9914 (match_dup 5)))]
215b30b3 9915 ""
9916)
9c08d1fa 9917
aea4c774 9918;; This split can be used because CC_Z mode implies that the following
9919;; branch will be an equality, or an unsigned inequality, so the sign
9920;; extension is not needed.
9c08d1fa 9921
aea4c774 9922(define_split
bd5b4116 9923 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9924 (compare:CC_Z
9925 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9926 (const_int 24))
aea4c774 9927 (match_operand 1 "const_int_operand" "")))
9928 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9929 "TARGET_ARM
9930 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9931 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9932 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9933 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9934 "
9c08d1fa 9935 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9936 "
9937)
25f905c2 9938;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 9939
87b22bf7 9940(define_expand "prologue"
9941 [(clobber (const_int 0))]
cffb2a26 9942 "TARGET_EITHER"
25f905c2 9943 "if (TARGET_32BIT)
cffb2a26 9944 arm_expand_prologue ();
9945 else
25f905c2 9946 thumb1_expand_prologue ();
87b22bf7 9947 DONE;
cffb2a26 9948 "
9949)
87b22bf7 9950
56d27660 9951(define_expand "epilogue"
4c44712e 9952 [(clobber (const_int 0))]
cffb2a26 9953 "TARGET_EITHER"
56d27660 9954 "
18d50ae6 9955 if (crtl->calls_eh_return)
4c44712e 9956 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 9957 if (TARGET_THUMB1)
9958 thumb1_expand_epilogue ();
cffb2a26 9959 else if (USE_RETURN_INSN (FALSE))
56d27660 9960 {
9961 emit_jump_insn (gen_return ());
9962 DONE;
9963 }
cffb2a26 9964 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9965 gen_rtvec (1,
9966 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9967 VUNSPEC_EPILOGUE));
cffb2a26 9968 DONE;
9969 "
9970)
56d27660 9971
ef5651d0 9972;; Note - although unspec_volatile's USE all hard registers,
9973;; USEs are ignored after relaod has completed. Thus we need
9974;; to add an unspec of the link register to ensure that flow
9975;; does not think that it is unused by the sibcall branch that
9976;; will replace the standard function epilogue.
1c494086 9977(define_insn "sibcall_epilogue"
ef5651d0 9978 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9979 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 9980 "TARGET_32BIT"
1c494086 9981 "*
ffc9d00c 9982 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9983 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9984 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9985 "
9986;; Length is absolute worst case
9987 [(set_attr "length" "44")
defc47cf 9988 (set_attr "type" "block")
9989 ;; We don't clobber the conditions, but the potential length of this
9990 ;; operation is sufficient to make conditionalizing the sequence
9991 ;; unlikely to be profitable.
9992 (set_attr "conds" "clob")]
1c494086 9993)
9994
cffb2a26 9995(define_insn "*epilogue_insns"
e1159bbe 9996 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9997 "TARGET_EITHER"
56d27660 9998 "*
25f905c2 9999 if (TARGET_32BIT)
ffc9d00c 10000 return arm_output_epilogue (NULL);
25f905c2 10001 else /* TARGET_THUMB1 */
cffb2a26 10002 return thumb_unexpanded_epilogue ();
10003 "
215b30b3 10004 ; Length is absolute worst case
cffb2a26 10005 [(set_attr "length" "44")
defc47cf 10006 (set_attr "type" "block")
10007 ;; We don't clobber the conditions, but the potential length of this
10008 ;; operation is sufficient to make conditionalizing the sequence
10009 ;; unlikely to be profitable.
10010 (set_attr "conds" "clob")]
cffb2a26 10011)
10012
10013(define_expand "eh_epilogue"
7db9af5d 10014 [(use (match_operand:SI 0 "register_operand" ""))
10015 (use (match_operand:SI 1 "register_operand" ""))
10016 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10017 "TARGET_EITHER"
10018 "
215b30b3 10019 {
10020 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10021 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10022 {
10023 rtx ra = gen_rtx_REG (Pmode, 2);
10024
10025 emit_move_insn (ra, operands[2]);
10026 operands[2] = ra;
10027 }
5cf3595a 10028 /* This is a hack -- we may have crystalized the function type too
10029 early. */
10030 cfun->machine->func_type = 0;
215b30b3 10031 }"
10032)
56d27660 10033
9c08d1fa 10034;; This split is only used during output to reduce the number of patterns
10035;; that need assembler instructions adding to them. We allowed the setting
10036;; of the conditions to be implicit during rtl generation so that
10037;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10038;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10039;; up again here.
10040
25f905c2 10041;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10042;; conditional execution sufficient?
10043
9c08d1fa 10044(define_split
10045 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10046 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10047 [(match_operand 2 "" "") (match_operand 3 "" "")])
10048 (match_dup 0)
10049 (match_operand 4 "" "")))
bd5b4116 10050 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10051 "TARGET_ARM && reload_completed"
8fa3ba89 10052 [(set (match_dup 5) (match_dup 6))
10053 (cond_exec (match_dup 7)
10054 (set (match_dup 0) (match_dup 4)))]
10055 "
10056 {
10057 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10058 operands[2], operands[3]);
10059 enum rtx_code rc = GET_CODE (operands[1]);
10060
bd5b4116 10061 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10062 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10063 if (mode == CCFPmode || mode == CCFPEmode)
10064 rc = reverse_condition_maybe_unordered (rc);
10065 else
10066 rc = reverse_condition (rc);
10067
10068 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10069 }"
10070)
10071
10072(define_split
10073 [(set (match_operand:SI 0 "s_register_operand" "")
10074 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10075 [(match_operand 2 "" "") (match_operand 3 "" "")])
10076 (match_operand 4 "" "")
10077 (match_dup 0)))
bd5b4116 10078 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10079 "TARGET_ARM && reload_completed"
8fa3ba89 10080 [(set (match_dup 5) (match_dup 6))
10081 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10082 (set (match_dup 0) (match_dup 4)))]
10083 "
10084 {
10085 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10086 operands[2], operands[3]);
10087
bd5b4116 10088 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10089 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10090 }"
10091)
10092
10093(define_split
10094 [(set (match_operand:SI 0 "s_register_operand" "")
10095 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10096 [(match_operand 2 "" "") (match_operand 3 "" "")])
10097 (match_operand 4 "" "")
10098 (match_operand 5 "" "")))
bd5b4116 10099 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10100 "TARGET_ARM && reload_completed"
8fa3ba89 10101 [(set (match_dup 6) (match_dup 7))
10102 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10103 (set (match_dup 0) (match_dup 4)))
10104 (cond_exec (match_dup 8)
10105 (set (match_dup 0) (match_dup 5)))]
10106 "
10107 {
10108 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10109 operands[2], operands[3]);
10110 enum rtx_code rc = GET_CODE (operands[1]);
10111
bd5b4116 10112 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10113 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10114 if (mode == CCFPmode || mode == CCFPEmode)
10115 rc = reverse_condition_maybe_unordered (rc);
10116 else
10117 rc = reverse_condition (rc);
10118
10119 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10120 }"
10121)
10122
cffb2a26 10123(define_split
10124 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10125 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10126 [(match_operand:SI 2 "s_register_operand" "")
10127 (match_operand:SI 3 "arm_add_operand" "")])
10128 (match_operand:SI 4 "arm_rhs_operand" "")
10129 (not:SI
10130 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10131 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10132 "TARGET_ARM && reload_completed"
cffb2a26 10133 [(set (match_dup 6) (match_dup 7))
f6c53574 10134 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10135 (set (match_dup 0) (match_dup 4)))
10136 (cond_exec (match_dup 8)
10137 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10138 "
215b30b3 10139 {
10140 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10141 operands[2], operands[3]);
f6c53574 10142 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10143
bd5b4116 10144 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10145 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10146 if (mode == CCFPmode || mode == CCFPEmode)
10147 rc = reverse_condition_maybe_unordered (rc);
10148 else
10149 rc = reverse_condition (rc);
10150
10151 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10152 }"
10153)
cffb2a26 10154
10155(define_insn "*cond_move_not"
10156 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10157 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10158 [(match_operand 3 "cc_register" "") (const_int 0)])
10159 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10160 (not:SI
10161 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10162 "TARGET_ARM"
10163 "@
10164 mvn%D4\\t%0, %2
10165 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10166 [(set_attr "conds" "use")
d2a518d1 10167 (set_attr "insn" "mvn")
0d66636f 10168 (set_attr "length" "4,8")]
10169)
cffb2a26 10170
9c08d1fa 10171;; The next two patterns occur when an AND operation is followed by a
10172;; scc insn sequence
10173
f7fbdd4a 10174(define_insn "*sign_extract_onebit"
9c08d1fa 10175 [(set (match_operand:SI 0 "s_register_operand" "=r")
10176 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10177 (const_int 1)
ed750274 10178 (match_operand:SI 2 "const_int_operand" "n")))
10179 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10180 "TARGET_ARM"
9c08d1fa 10181 "*
0d66636f 10182 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10183 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10184 return \"mvnne\\t%0, #0\";
10185 "
10186 [(set_attr "conds" "clob")
10187 (set_attr "length" "8")]
10188)
9c08d1fa 10189
f7fbdd4a 10190(define_insn "*not_signextract_onebit"
9c08d1fa 10191 [(set (match_operand:SI 0 "s_register_operand" "=r")
10192 (not:SI
10193 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10194 (const_int 1)
ed750274 10195 (match_operand:SI 2 "const_int_operand" "n"))))
10196 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10197 "TARGET_ARM"
9c08d1fa 10198 "*
0d66636f 10199 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10200 output_asm_insn (\"tst\\t%1, %2\", operands);
10201 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10202 return \"movne\\t%0, #0\";
10203 "
10204 [(set_attr "conds" "clob")
10205 (set_attr "length" "12")]
10206)
25f905c2 10207;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10208
0d66636f 10209;; Push multiple registers to the stack. Registers are in parallel (use ...)
10210;; expressions. For simplicity, the first register is also in the unspec
10211;; part.
f7fbdd4a 10212(define_insn "*push_multi"
87b22bf7 10213 [(match_parallel 2 "multi_register_push"
10214 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10215 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10216 UNSPEC_PUSH_MULT))])]
25f905c2 10217 "TARGET_32BIT"
87b22bf7 10218 "*
215b30b3 10219 {
10220 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10221
215b30b3 10222 /* For the StrongARM at least it is faster to
25f905c2 10223 use STR to store only a single register.
542d5028 10224 In Thumb mode always use push, and the assembler will pick
10225 something appropriate. */
25f905c2 10226 if (num_saves == 1 && TARGET_ARM)
215b30b3 10227 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10228 else
10229 {
10230 int i;
10231 char pattern[100];
ed593f11 10232
25f905c2 10233 if (TARGET_ARM)
10234 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10235 else
10236 strcpy (pattern, \"push\\t{%1\");
215b30b3 10237
6079f055 10238 for (i = 1; i < num_saves; i++)
215b30b3 10239 {
10240 strcat (pattern, \", %|\");
10241 strcat (pattern,
10242 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10243 }
10244
10245 strcat (pattern, \"}\");
10246 output_asm_insn (pattern, operands);
10247 }
10248
10249 return \"\";
10250 }"
10251 [(set_attr "type" "store4")]
10252)
f7fbdd4a 10253
4c58c898 10254(define_insn "stack_tie"
10255 [(set (mem:BLK (scratch))
aaa37ad6 10256 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10257 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10258 UNSPEC_PRLG_STK))]
10259 ""
10260 ""
10261 [(set_attr "length" "0")]
10262)
10263
3398e91d 10264;; Similarly for the floating point registers
7b1d2fc4 10265(define_insn "*push_fp_multi"
10266 [(match_parallel 2 "multi_register_push"
10267 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10268 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10269 UNSPEC_PUSH_MULT))])]
25f905c2 10270 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10271 "*
215b30b3 10272 {
10273 char pattern[100];
7b1d2fc4 10274
215b30b3 10275 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10276 output_asm_insn (pattern, operands);
10277 return \"\";
10278 }"
10279 [(set_attr "type" "f_store")]
10280)
7b1d2fc4 10281
f7fbdd4a 10282;; Special patterns for dealing with the constant pool
10283
cffb2a26 10284(define_insn "align_4"
e1159bbe 10285 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10286 "TARGET_EITHER"
f7fbdd4a 10287 "*
cffb2a26 10288 assemble_align (32);
f7fbdd4a 10289 return \"\";
cffb2a26 10290 "
10291)
f7fbdd4a 10292
755eb2b4 10293(define_insn "align_8"
10294 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10295 "TARGET_EITHER"
755eb2b4 10296 "*
10297 assemble_align (64);
10298 return \"\";
10299 "
10300)
10301
cffb2a26 10302(define_insn "consttable_end"
e1159bbe 10303 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10304 "TARGET_EITHER"
f7fbdd4a 10305 "*
cffb2a26 10306 making_const_table = FALSE;
f7fbdd4a 10307 return \"\";
cffb2a26 10308 "
10309)
f7fbdd4a 10310
cffb2a26 10311(define_insn "consttable_1"
e1159bbe 10312 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10313 "TARGET_THUMB1"
f7fbdd4a 10314 "*
cffb2a26 10315 making_const_table = TRUE;
09d688ff 10316 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10317 assemble_zeros (3);
f7fbdd4a 10318 return \"\";
cffb2a26 10319 "
10320 [(set_attr "length" "4")]
10321)
f7fbdd4a 10322
cffb2a26 10323(define_insn "consttable_2"
e1159bbe 10324 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10325 "TARGET_THUMB1"
f7fbdd4a 10326 "*
cffb2a26 10327 making_const_table = TRUE;
9b8516be 10328 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10329 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10330 assemble_zeros (2);
f7fbdd4a 10331 return \"\";
cffb2a26 10332 "
10333 [(set_attr "length" "4")]
10334)
10335
10336(define_insn "consttable_4"
e1159bbe 10337 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10338 "TARGET_EITHER"
10339 "*
10340 {
9b8516be 10341 rtx x = operands[0];
cffb2a26 10342 making_const_table = TRUE;
9b8516be 10343 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10344 {
10345 case MODE_FLOAT:
9b8516be 10346 if (GET_MODE (x) == HFmode)
10347 arm_emit_fp16_const (x);
10348 else
10349 {
10350 REAL_VALUE_TYPE r;
10351 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10352 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10353 }
10354 break;
cffb2a26 10355 default:
7b04c5d5 10356 /* XXX: Sometimes gcc does something really dumb and ends up with
10357 a HIGH in a constant pool entry, usually because it's trying to
10358 load into a VFP register. We know this will always be used in
10359 combination with a LO_SUM which ignores the high bits, so just
10360 strip off the HIGH. */
10361 if (GET_CODE (x) == HIGH)
10362 x = XEXP (x, 0);
9b8516be 10363 assemble_integer (x, 4, BITS_PER_WORD, 1);
10364 mark_symbol_refs_as_used (x);
cffb2a26 10365 break;
10366 }
10367 return \"\";
10368 }"
10369 [(set_attr "length" "4")]
10370)
10371
10372(define_insn "consttable_8"
e1159bbe 10373 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10374 "TARGET_EITHER"
10375 "*
10376 {
10377 making_const_table = TRUE;
10378 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10379 {
10380 case MODE_FLOAT:
10381 {
badfe841 10382 REAL_VALUE_TYPE r;
10383 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10384 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10385 break;
10386 }
10387 default:
09d688ff 10388 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10389 break;
10390 }
10391 return \"\";
10392 }"
10393 [(set_attr "length" "8")]
10394)
10395
d98a3884 10396(define_insn "consttable_16"
10397 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10398 "TARGET_EITHER"
10399 "*
10400 {
10401 making_const_table = TRUE;
10402 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10403 {
10404 case MODE_FLOAT:
10405 {
10406 REAL_VALUE_TYPE r;
10407 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10408 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10409 break;
10410 }
10411 default:
10412 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10413 break;
10414 }
10415 return \"\";
10416 }"
10417 [(set_attr "length" "16")]
10418)
10419
cffb2a26 10420;; Miscellaneous Thumb patterns
10421
fd957ef3 10422(define_expand "tablejump"
7db9af5d 10423 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10424 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10425 "TARGET_THUMB1"
fd957ef3 10426 "
10427 if (flag_pic)
10428 {
10429 /* Hopefully, CSE will eliminate this copy. */
10430 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10431 rtx reg2 = gen_reg_rtx (SImode);
10432
10433 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10434 operands[0] = reg2;
10435 }
10436 "
10437)
10438
f1039640 10439;; NB never uses BX.
25f905c2 10440(define_insn "*thumb1_tablejump"
cffb2a26 10441 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10442 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10443 "TARGET_THUMB1"
fd957ef3 10444 "mov\\t%|pc, %0"
cffb2a26 10445 [(set_attr "length" "2")]
10446)
0d66636f 10447
331beb1a 10448;; V5 Instructions,
10449
8f4be2be 10450(define_insn "clzsi2"
10451 [(set (match_operand:SI 0 "s_register_operand" "=r")
10452 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10453 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10454 "clz%?\\t%0, %1"
bcaec148 10455 [(set_attr "predicable" "yes")
10456 (set_attr "insn" "clz")])
331beb1a 10457
099ad98b 10458(define_insn "rbitsi2"
10459 [(set (match_operand:SI 0 "s_register_operand" "=r")
10460 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10461 "TARGET_32BIT && arm_arch_thumb2"
10462 "rbit%?\\t%0, %1"
10463 [(set_attr "predicable" "yes")
10464 (set_attr "insn" "clz")])
10465
10466(define_expand "ctzsi2"
10467 [(set (match_operand:SI 0 "s_register_operand" "")
10468 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10469 "TARGET_32BIT && arm_arch_thumb2"
10470 "
30191172 10471 {
10472 rtx tmp = gen_reg_rtx (SImode);
10473 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10474 emit_insn (gen_clzsi2 (operands[0], tmp));
10475 }
099ad98b 10476 DONE;
10477 "
10478)
10479
e1159bbe 10480;; V5E instructions.
331beb1a 10481
10482(define_insn "prefetch"
f4e79814 10483 [(prefetch (match_operand:SI 0 "address_operand" "p")
10484 (match_operand:SI 1 "" "")
10485 (match_operand:SI 2 "" ""))]
25f905c2 10486 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10487 "pld\\t%a0")
331beb1a 10488
0d66636f 10489;; General predication pattern
10490
10491(define_cond_exec
10492 [(match_operator 0 "arm_comparison_operator"
10493 [(match_operand 1 "cc_register" "")
10494 (const_int 0)])]
25f905c2 10495 "TARGET_32BIT"
0d66636f 10496 ""
10497)
10498
063a05c7 10499(define_insn "prologue_use"
10500 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10501 ""
10502 "%@ %0 needed for prologue"
02cfc9c9 10503 [(set_attr "length" "0")]
063a05c7 10504)
7db9af5d 10505
4c44712e 10506
10507;; Patterns for exception handling
10508
10509(define_expand "eh_return"
10510 [(use (match_operand 0 "general_operand" ""))]
10511 "TARGET_EITHER"
10512 "
10513 {
25f905c2 10514 if (TARGET_32BIT)
4c44712e 10515 emit_insn (gen_arm_eh_return (operands[0]));
10516 else
10517 emit_insn (gen_thumb_eh_return (operands[0]));
10518 DONE;
10519 }"
10520)
10521
10522;; We can't expand this before we know where the link register is stored.
10523(define_insn_and_split "arm_eh_return"
10524 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10525 VUNSPEC_EH_RETURN)
10526 (clobber (match_scratch:SI 1 "=&r"))]
10527 "TARGET_ARM"
10528 "#"
10529 "&& reload_completed"
10530 [(const_int 0)]
10531 "
10532 {
10533 arm_set_return_address (operands[0], operands[1]);
10534 DONE;
10535 }"
10536)
10537
10538(define_insn_and_split "thumb_eh_return"
10539 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10540 VUNSPEC_EH_RETURN)
10541 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10542 "TARGET_THUMB1"
4c44712e 10543 "#"
10544 "&& reload_completed"
10545 [(const_int 0)]
10546 "
10547 {
10548 thumb_set_return_address (operands[0], operands[1]);
10549 DONE;
10550 }"
10551)
10552
f655717d 10553\f
10554;; TLS support
10555
10556(define_insn "load_tp_hard"
10557 [(set (match_operand:SI 0 "register_operand" "=r")
10558 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10559 "TARGET_HARD_TP"
10560 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10561 [(set_attr "predicable" "yes")]
10562)
10563
10564;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10565(define_insn "load_tp_soft"
10566 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10567 (clobber (reg:SI LR_REGNUM))
10568 (clobber (reg:SI IP_REGNUM))
10569 (clobber (reg:CC CC_REGNUM))]
10570 "TARGET_SOFT_TP"
10571 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10572 [(set_attr "conds" "clob")]
10573)
10574
eca5c984 10575(define_insn "*arm_movtas_ze"
10576 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10577 (const_int 16)
10578 (const_int 16))
10579 (match_operand:SI 1 "const_int_operand" ""))]
10580 "TARGET_32BIT"
10581 "movt%?\t%0, %c1"
10582 [(set_attr "predicable" "yes")
10583 (set_attr "length" "4")]
10584)
10585
c0fc3696 10586(define_insn "*arm_rev"
ff82f757 10587 [(set (match_operand:SI 0 "s_register_operand" "=r")
10588 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 10589 "TARGET_32BIT && arm_arch6"
10590 "rev%?\t%0, %1"
10591 [(set_attr "predicable" "yes")
10592 (set_attr "length" "4")]
10593)
10594
10595(define_insn "*thumb1_rev"
10596 [(set (match_operand:SI 0 "s_register_operand" "=l")
10597 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10598 "TARGET_THUMB1 && arm_arch6"
10599 "rev\t%0, %1"
10600 [(set_attr "length" "2")]
ff82f757 10601)
10602
10603(define_expand "arm_legacy_rev"
10604 [(set (match_operand:SI 2 "s_register_operand" "")
10605 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10606 (const_int 16))
10607 (match_dup 1)))
10608 (set (match_dup 2)
10609 (lshiftrt:SI (match_dup 2)
10610 (const_int 8)))
10611 (set (match_operand:SI 3 "s_register_operand" "")
10612 (rotatert:SI (match_dup 1)
10613 (const_int 8)))
10614 (set (match_dup 2)
10615 (and:SI (match_dup 2)
10616 (const_int -65281)))
10617 (set (match_operand:SI 0 "s_register_operand" "")
10618 (xor:SI (match_dup 3)
10619 (match_dup 2)))]
10620 "TARGET_32BIT"
10621 ""
10622)
10623
10624;; Reuse temporaries to keep register pressure down.
10625(define_expand "thumb_legacy_rev"
10626 [(set (match_operand:SI 2 "s_register_operand" "")
10627 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10628 (const_int 24)))
10629 (set (match_operand:SI 3 "s_register_operand" "")
10630 (lshiftrt:SI (match_dup 1)
10631 (const_int 24)))
10632 (set (match_dup 3)
10633 (ior:SI (match_dup 3)
10634 (match_dup 2)))
10635 (set (match_operand:SI 4 "s_register_operand" "")
10636 (const_int 16))
10637 (set (match_operand:SI 5 "s_register_operand" "")
10638 (rotatert:SI (match_dup 1)
10639 (match_dup 4)))
10640 (set (match_dup 2)
10641 (ashift:SI (match_dup 5)
10642 (const_int 24)))
10643 (set (match_dup 5)
10644 (lshiftrt:SI (match_dup 5)
10645 (const_int 24)))
10646 (set (match_dup 5)
10647 (ior:SI (match_dup 5)
10648 (match_dup 2)))
10649 (set (match_dup 5)
10650 (rotatert:SI (match_dup 5)
10651 (match_dup 4)))
10652 (set (match_operand:SI 0 "s_register_operand" "")
10653 (ior:SI (match_dup 5)
10654 (match_dup 3)))]
10655 "TARGET_THUMB"
10656 ""
10657)
10658
10659(define_expand "bswapsi2"
10660 [(set (match_operand:SI 0 "s_register_operand" "=r")
10661 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10662"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10663"
8d1af482 10664 if (!arm_arch6)
10665 {
10666 rtx op2 = gen_reg_rtx (SImode);
10667 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10668
8d1af482 10669 if (TARGET_THUMB)
10670 {
10671 rtx op4 = gen_reg_rtx (SImode);
10672 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10673
8d1af482 10674 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10675 op2, op3, op4, op5));
10676 }
10677 else
10678 {
10679 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10680 op2, op3));
10681 }
ff82f757 10682
8d1af482 10683 DONE;
10684 }
ff82f757 10685 "
10686)
10687
320ea44d 10688;; Load the load/store multiple patterns
10689(include "ldmstm.md")
7db9af5d 10690;; Load the FPA co-processor patterns
10691(include "fpa.md")
10692;; Load the Maverick co-processor patterns
10693(include "cirrus.md")
d98a3884 10694;; Vector bits common to IWMMXT and Neon
10695(include "vec-common.md")
755eb2b4 10696;; Load the Intel Wireless Multimedia Extension patterns
10697(include "iwmmxt.md")
a2cd141b 10698;; Load the VFP co-processor patterns
10699(include "vfp.md")
25f905c2 10700;; Thumb-2 patterns
10701(include "thumb2.md")
d98a3884 10702;; Neon patterns
10703(include "neon.md")
06df6b17 10704;; Synchronization Primitives
10705(include "sync.md")