]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
fix typo in ChangeLog
[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.
013b9671 302; f_fpa_load a floating point load from memory. Only for the FPA.
303; f_fpa_store a floating point store to memory. Only for the FPA.
304; f_load[sd] A single/double load from memory. Used for VFP unit.
305; f_store[sd] A single/double store to memory. Used for VFP unit.
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"
013b9671 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_fpa_load,f_fpa_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
a2cd141b 330 (if_then_else
331 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
332 (const_string "mult")
333 (const_string "alu")))
9c08d1fa 334
9888ad6d 335; Load scheduling, set from the arm_ld_sched variable
4c834714 336; initialized by arm_option_override()
9888ad6d 337(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 338
c52acdd2 339;; Classification of NEON instructions for scheduling purposes.
340;; Do not set this attribute and the "type" attribute together in
341;; any one instruction pattern.
342(define_attr "neon_type"
343 "neon_int_1,\
344 neon_int_2,\
345 neon_int_3,\
346 neon_int_4,\
347 neon_int_5,\
348 neon_vqneg_vqabs,\
349 neon_vmov,\
350 neon_vaba,\
351 neon_vsma,\
352 neon_vaba_qqq,\
353 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
354 neon_mul_qqq_8_16_32_ddd_32,\
355 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
356 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
357 neon_mla_qqq_8_16,\
358 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
359 neon_mla_qqq_32_qqd_32_scalar,\
360 neon_mul_ddd_16_scalar_32_16_long_scalar,\
361 neon_mul_qqd_32_scalar,\
362 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
363 neon_shift_1,\
364 neon_shift_2,\
365 neon_shift_3,\
366 neon_vshl_ddd,\
367 neon_vqshl_vrshl_vqrshl_qqq,\
368 neon_vsra_vrsra,\
369 neon_fp_vadd_ddd_vabs_dd,\
370 neon_fp_vadd_qqq_vabs_qq,\
371 neon_fp_vsum,\
372 neon_fp_vmul_ddd,\
373 neon_fp_vmul_qqd,\
374 neon_fp_vmla_ddd,\
375 neon_fp_vmla_qqq,\
376 neon_fp_vmla_ddd_scalar,\
377 neon_fp_vmla_qqq_scalar,\
378 neon_fp_vrecps_vrsqrts_ddd,\
379 neon_fp_vrecps_vrsqrts_qqq,\
380 neon_bp_simple,\
381 neon_bp_2cycle,\
382 neon_bp_3cycle,\
383 neon_ldr,\
384 neon_str,\
385 neon_vld1_1_2_regs,\
386 neon_vld1_3_4_regs,\
387 neon_vld2_2_regs_vld1_vld2_all_lanes,\
388 neon_vld2_4_regs,\
389 neon_vld3_vld4,\
390 neon_vst1_1_2_regs_vst2_2_regs,\
391 neon_vst1_3_4_regs,\
392 neon_vst2_4_regs_vst3_vst4,\
393 neon_vst3_vst4,\
394 neon_vld1_vld2_lane,\
395 neon_vld3_vld4_lane,\
396 neon_vst1_vst2_lane,\
397 neon_vst3_vst4_lane,\
398 neon_vld3_vld4_all_lanes,\
399 neon_mcr,\
400 neon_mcr_2_mcrr,\
401 neon_mrc,\
402 neon_mrrc,\
403 neon_ldm_2,\
404 neon_stm_2,\
405 none"
406 (const_string "none"))
407
f7fbdd4a 408; condition codes: this one is used by final_prescan_insn to speed up
409; conditionalizing instructions. It saves having to scan the rtl to see if
410; it uses or alters the condition codes.
215b30b3 411;
f7fbdd4a 412; USE means that the condition codes are used by the insn in the process of
215b30b3 413; outputting code, this means (at present) that we can't use the insn in
414; inlined branches
415;
f7fbdd4a 416; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 417; well defined manner.
418;
f7fbdd4a 419; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 420; they are altered at all
421;
ad6d3e2a 422; UNCONDITIONAL means the instruction can not be conditionally executed and
423; that the instruction does not use or alter the condition codes.
c52acdd2 424;
ad6d3e2a 425; NOCOND means that the instruction does not use or alter the condition
426; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 427
b0694be0 428(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 429 (if_then_else
430 (ior (eq_attr "is_thumb1" "yes")
431 (eq_attr "type" "call"))
c1a66faf 432 (const_string "clob")
c52acdd2 433 (if_then_else (eq_attr "neon_type" "none")
434 (const_string "nocond")
435 (const_string "unconditional"))))
f7fbdd4a 436
215b30b3 437; Predicable means that the insn can be conditionally executed based on
438; an automatically added predicate (additional patterns are generated by
439; gen...). We default to 'no' because no Thumb patterns match this rule
440; and not all ARM patterns do.
0d66636f 441(define_attr "predicable" "no,yes" (const_string "no"))
442
129a2fe4 443; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
444; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 445; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 446; affect the schedule).
74a71f7d 447(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 448
215b30b3 449; WRITE_CONFLICT implies that a read following an unrelated write is likely
450; to stall the processor. Used with model_wbuf above.
9c08d1fa 451(define_attr "write_conflict" "no,yes"
452 (if_then_else (eq_attr "type"
013b9671 453 "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 454 (const_string "yes")
455 (const_string "no")))
456
215b30b3 457; Classify the insns into those that take one cycle and those that take more
458; than one on the main cpu execution unit.
f7fbdd4a 459(define_attr "core_cycles" "single,multi"
460 (if_then_else (eq_attr "type"
a2cd141b 461 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 462 (const_string "single")
463 (const_string "multi")))
464
cffb2a26 465;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 466;; distant label. Only applicable to Thumb code.
cffb2a26 467(define_attr "far_jump" "yes,no" (const_string "no"))
468
d51f92df 469
25f905c2 470;; The number of machine instructions this pattern expands to.
471;; Used for Thumb-2 conditional execution.
472(define_attr "ce_count" "" (const_int 1))
473
d51f92df 474;;---------------------------------------------------------------------------
fd781bb2 475;; Mode iterators
d51f92df 476
3de0dec6 477(include "iterators.md")
03770691 478
d51f92df 479;;---------------------------------------------------------------------------
480;; Predicates
481
9c9db025 482(include "predicates.md")
234f6557 483(include "constraints.md")
9c9db025 484
a2cd141b 485;;---------------------------------------------------------------------------
486;; Pipeline descriptions
215b30b3 487
06469f9e 488;; Processor type. This is created automatically from arm-cores.def.
489(include "arm-tune.md")
331beb1a 490
e3879fd0 491(define_attr "tune_cortexr4" "yes,no"
492 (const (if_then_else
493 (eq_attr "tune" "cortexr4,cortexr4f")
494 (const_string "yes")
495 (const_string "no"))))
496
a2cd141b 497;; True if the generic scheduling description should be used.
498
499(define_attr "generic_sched" "yes,no"
2546d93a 500 (const (if_then_else
0e266d06 501 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexm4")
2546d93a 502 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 503 (const_string "no")
504 (const_string "yes"))))
505
c0e1af52 506(define_attr "generic_vfp" "yes,no"
507 (const (if_then_else
508 (and (eq_attr "fpu" "vfp")
2546d93a 509 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 510 (eq_attr "tune_cortexr4" "no"))
c0e1af52 511 (const_string "yes")
512 (const_string "no"))))
513
a2cd141b 514(include "arm-generic.md")
515(include "arm926ejs.md")
c0e1af52 516(include "arm1020e.md")
a2cd141b 517(include "arm1026ejs.md")
518(include "arm1136jfs.md")
0e266d06 519(include "fa526.md")
520(include "fa606te.md")
521(include "fa626te.md")
522(include "fmp626.md")
523(include "fa726te.md")
3f1e069f 524(include "cortex-a5.md")
bcaec148 525(include "cortex-a8.md")
036068af 526(include "cortex-a9.md")
934a1e72 527(include "cortex-r4.md")
e3879fd0 528(include "cortex-r4f.md")
2546d93a 529(include "cortex-m4.md")
530(include "cortex-m4-fpu.md")
55e3ada8 531(include "vfp11.md")
3586df96 532
9c08d1fa 533\f
215b30b3 534;;---------------------------------------------------------------------------
e1159bbe 535;; Insn patterns
536;;
a0f94409 537;; Addition insns.
215b30b3 538
9c08d1fa 539;; Note: For DImode insns, there is normally no reason why operands should
540;; not be in the same register, what we don't want is for something being
541;; written to partially overlap something that is an input.
7d57ec45 542;; Cirrus 64bit additions should not be split because we have a native
543;; 64bit addition instructions.
9c08d1fa 544
cffb2a26 545(define_expand "adddi3"
546 [(parallel
215b30b3 547 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 548 (plus:DI (match_operand:DI 1 "s_register_operand" "")
549 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 550 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 551 "TARGET_EITHER"
552 "
a2cd141b 553 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 554 {
555 if (!cirrus_fp_register (operands[0], DImode))
556 operands[0] = force_reg (DImode, operands[0]);
557 if (!cirrus_fp_register (operands[1], DImode))
558 operands[1] = force_reg (DImode, operands[1]);
559 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
560 DONE;
561 }
562
25f905c2 563 if (TARGET_THUMB1)
cffb2a26 564 {
565 if (GET_CODE (operands[1]) != REG)
bc5a93af 566 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 567 if (GET_CODE (operands[2]) != REG)
bc5a93af 568 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 569 }
570 "
571)
572
25f905c2 573(define_insn "*thumb1_adddi3"
cffb2a26 574 [(set (match_operand:DI 0 "register_operand" "=l")
575 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 576 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 577 (clobber (reg:CC CC_REGNUM))
cffb2a26 578 ]
25f905c2 579 "TARGET_THUMB1"
cffb2a26 580 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
581 [(set_attr "length" "4")]
582)
583
a0f94409 584(define_insn_and_split "*arm_adddi3"
cffb2a26 585 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 586 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
587 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 588 (clobber (reg:CC CC_REGNUM))]
94829feb 589 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 590 "#"
94829feb 591 "TARGET_32BIT && reload_completed
592 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 593 [(parallel [(set (reg:CC_C CC_REGNUM)
594 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
595 (match_dup 1)))
596 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 597 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
598 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 599 "
600 {
601 operands[3] = gen_highpart (SImode, operands[0]);
602 operands[0] = gen_lowpart (SImode, operands[0]);
603 operands[4] = gen_highpart (SImode, operands[1]);
604 operands[1] = gen_lowpart (SImode, operands[1]);
605 operands[5] = gen_highpart (SImode, operands[2]);
606 operands[2] = gen_lowpart (SImode, operands[2]);
607 }"
cffb2a26 608 [(set_attr "conds" "clob")
609 (set_attr "length" "8")]
610)
9c08d1fa 611
a0f94409 612(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 613 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
614 (plus:DI (sign_extend:DI
97499065 615 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 616 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 617 (clobber (reg:CC CC_REGNUM))]
25f905c2 618 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 619 "#"
25f905c2 620 "TARGET_32BIT && reload_completed"
a0f94409 621 [(parallel [(set (reg:CC_C CC_REGNUM)
622 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
623 (match_dup 1)))
624 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 625 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 626 (const_int 31))
080c0b9a 627 (match_dup 4))
628 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 629 "
630 {
631 operands[3] = gen_highpart (SImode, operands[0]);
632 operands[0] = gen_lowpart (SImode, operands[0]);
633 operands[4] = gen_highpart (SImode, operands[1]);
634 operands[1] = gen_lowpart (SImode, operands[1]);
635 operands[2] = gen_lowpart (SImode, operands[2]);
636 }"
215b30b3 637 [(set_attr "conds" "clob")
638 (set_attr "length" "8")]
639)
9c08d1fa 640
a0f94409 641(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 642 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
643 (plus:DI (zero_extend:DI
97499065 644 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 645 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 646 (clobber (reg:CC CC_REGNUM))]
25f905c2 647 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 648 "#"
25f905c2 649 "TARGET_32BIT && reload_completed"
a0f94409 650 [(parallel [(set (reg:CC_C CC_REGNUM)
651 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
652 (match_dup 1)))
653 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 654 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
655 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 656 "
657 {
658 operands[3] = gen_highpart (SImode, operands[0]);
659 operands[0] = gen_lowpart (SImode, operands[0]);
660 operands[4] = gen_highpart (SImode, operands[1]);
661 operands[1] = gen_lowpart (SImode, operands[1]);
662 operands[2] = gen_lowpart (SImode, operands[2]);
663 }"
cffb2a26 664 [(set_attr "conds" "clob")
665 (set_attr "length" "8")]
666)
b11cae9e 667
87b22bf7 668(define_expand "addsi3"
cffb2a26 669 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 670 (plus:SI (match_operand:SI 1 "s_register_operand" "")
671 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 672 "TARGET_EITHER"
87b22bf7 673 "
25f905c2 674 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 675 {
96f57e36 676 arm_split_constant (PLUS, SImode, NULL_RTX,
677 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 678 optimize && can_create_pseudo_p ());
87b22bf7 679 DONE;
680 }
cffb2a26 681 "
682)
87b22bf7 683
5bd751ff 684; If there is a scratch available, this will be faster than synthesizing the
a0f94409 685; addition.
686(define_peephole2
687 [(match_scratch:SI 3 "r")
372575c7 688 (set (match_operand:SI 0 "arm_general_register_operand" "")
689 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 690 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 691 "TARGET_32BIT &&
a0f94409 692 !(const_ok_for_arm (INTVAL (operands[2]))
693 || const_ok_for_arm (-INTVAL (operands[2])))
694 && const_ok_for_arm (~INTVAL (operands[2]))"
695 [(set (match_dup 3) (match_dup 2))
696 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
697 ""
698)
87b22bf7 699
2f02c19f 700;; The r/r/k alternative is required when reloading the address
701;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
702;; put the duplicated register first, and not try the commutative version.
a0f94409 703(define_insn_and_split "*arm_addsi3"
bccb5444 704 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k,r")
705 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
706 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
25f905c2 707 "TARGET_32BIT"
5565501b 708 "@
709 add%?\\t%0, %1, %2
aaa37ad6 710 add%?\\t%0, %1, %2
2f02c19f 711 add%?\\t%0, %2, %1
aaa37ad6 712 sub%?\\t%0, %1, #%n2
87b22bf7 713 sub%?\\t%0, %1, #%n2
714 #"
a3ffc315 715 "TARGET_32BIT
716 && GET_CODE (operands[2]) == CONST_INT
a0f94409 717 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 718 || const_ok_for_arm (-INTVAL (operands[2])))
719 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 720 [(clobber (const_int 0))]
721 "
96f57e36 722 arm_split_constant (PLUS, SImode, curr_insn,
723 INTVAL (operands[2]), operands[0],
a0f94409 724 operands[1], 0);
725 DONE;
726 "
2f02c19f 727 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 728 (set_attr "predicable" "yes")]
cffb2a26 729)
730
0bdb6455 731(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 732 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
733 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
734 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 735 "TARGET_THUMB1"
cffb2a26 736 "*
0d66636f 737 static const char * const asms[] =
cffb2a26 738 {
739 \"add\\t%0, %0, %2\",
740 \"sub\\t%0, %0, #%n2\",
741 \"add\\t%0, %1, %2\",
742 \"add\\t%0, %0, %2\",
743 \"add\\t%0, %0, %2\",
744 \"add\\t%0, %1, %2\",
0bdb6455 745 \"add\\t%0, %1, %2\",
746 \"#\",
bf7bc2f6 747 \"#\",
0bdb6455 748 \"#\"
cffb2a26 749 };
750 if ((which_alternative == 2 || which_alternative == 6)
751 && GET_CODE (operands[2]) == CONST_INT
752 && INTVAL (operands[2]) < 0)
753 return \"sub\\t%0, %1, #%n2\";
754 return asms[which_alternative];
755 "
0bdb6455 756 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 757 && ((operands[1] != stack_pointer_rtx
758 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
759 || (operands[1] == stack_pointer_rtx
760 && INTVAL (operands[2]) > 1020))"
0bdb6455 761 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
762 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
763 {
764 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 765 if (operands[1] == stack_pointer_rtx)
766 offset -= 1020;
767 else
768 {
769 if (offset > 255)
770 offset = 255;
771 else if (offset < -255)
772 offset = -255;
773 }
0bdb6455 774 operands[3] = GEN_INT (offset);
775 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
776 }
bf7bc2f6 777 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 778)
779
780;; Reloading and elimination of the frame pointer can
781;; sometimes cause this optimization to be missed.
a0f94409 782(define_peephole2
372575c7 783 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 784 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 785 (set (match_dup 0)
372575c7 786 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 787 "TARGET_THUMB1
cffb2a26 788 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
789 && (INTVAL (operands[1]) & 3) == 0"
372575c7 790 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 791 ""
cffb2a26 792)
b11cae9e 793
f7fbdd4a 794(define_insn "*addsi3_compare0"
bd5b4116 795 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 796 (compare:CC_NOOV
215b30b3 797 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
798 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 799 (const_int 0)))
800 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 801 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 802 "TARGET_ARM"
5565501b 803 "@
25f905c2 804 add%.\\t%0, %1, %2
805 sub%.\\t%0, %1, #%n2"
cffb2a26 806 [(set_attr "conds" "set")]
807)
9c08d1fa 808
aea4c774 809(define_insn "*addsi3_compare0_scratch"
bd5b4116 810 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 811 (compare:CC_NOOV
215b30b3 812 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
813 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 814 (const_int 0)))]
ec792a7b 815 "TARGET_ARM"
cffb2a26 816 "@
817 cmn%?\\t%0, %1
818 cmp%?\\t%0, #%n1"
0d66636f 819 [(set_attr "conds" "set")]
820)
cffb2a26 821
aed179ae 822(define_insn "*compare_negsi_si"
823 [(set (reg:CC_Z CC_REGNUM)
824 (compare:CC_Z
825 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
826 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 827 "TARGET_32BIT"
aed179ae 828 "cmn%?\\t%1, %0"
0d66636f 829 [(set_attr "conds" "set")]
830)
aea4c774 831
203c488f 832;; This is the canonicalization of addsi3_compare0_for_combiner when the
833;; addend is a constant.
834(define_insn "*cmpsi2_addneg"
835 [(set (reg:CC CC_REGNUM)
836 (compare:CC
837 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 838 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 839 (set (match_operand:SI 0 "s_register_operand" "=r,r")
840 (plus:SI (match_dup 1)
2a977b78 841 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 842 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 843 "@
2a977b78 844 add%.\\t%0, %1, %3
845 sub%.\\t%0, %1, #%n3"
203c488f 846 [(set_attr "conds" "set")]
847)
848
849;; Convert the sequence
850;; sub rd, rn, #1
851;; cmn rd, #1 (equivalent to cmp rd, #-1)
852;; bne dest
853;; into
854;; subs rd, rn, #1
855;; bcs dest ((unsigned)rn >= 1)
856;; similarly for the beq variant using bcc.
857;; This is a common looping idiom (while (n--))
858(define_peephole2
372575c7 859 [(set (match_operand:SI 0 "arm_general_register_operand" "")
860 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 861 (const_int -1)))
862 (set (match_operand 2 "cc_register" "")
863 (compare (match_dup 0) (const_int -1)))
864 (set (pc)
865 (if_then_else (match_operator 3 "equality_operator"
866 [(match_dup 2) (const_int 0)])
867 (match_operand 4 "" "")
868 (match_operand 5 "" "")))]
25f905c2 869 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 870 [(parallel[
871 (set (match_dup 2)
872 (compare:CC
873 (match_dup 1) (const_int 1)))
874 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
875 (set (pc)
876 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
877 (match_dup 4)
878 (match_dup 5)))]
879 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
880 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
881 ? GEU : LTU),
882 VOIDmode,
883 operands[2], const0_rtx);"
884)
885
ebcc79bc 886;; The next four insns work because they compare the result with one of
887;; the operands, and we know that the use of the condition code is
888;; either GEU or LTU, so we can use the carry flag from the addition
889;; instead of doing the compare a second time.
890(define_insn "*addsi3_compare_op1"
bd5b4116 891 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 892 (compare:CC_C
893 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
894 (match_operand:SI 2 "arm_add_operand" "rI,L"))
895 (match_dup 1)))
896 (set (match_operand:SI 0 "s_register_operand" "=r,r")
897 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 898 "TARGET_32BIT"
ebcc79bc 899 "@
25f905c2 900 add%.\\t%0, %1, %2
901 sub%.\\t%0, %1, #%n2"
0d66636f 902 [(set_attr "conds" "set")]
903)
ebcc79bc 904
905(define_insn "*addsi3_compare_op2"
bd5b4116 906 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 907 (compare:CC_C
908 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
909 (match_operand:SI 2 "arm_add_operand" "rI,L"))
910 (match_dup 2)))
5565501b 911 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 912 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 913 "TARGET_32BIT"
5565501b 914 "@
25f905c2 915 add%.\\t%0, %1, %2
916 sub%.\\t%0, %1, #%n2"
0d66636f 917 [(set_attr "conds" "set")]
918)
9c08d1fa 919
ebcc79bc 920(define_insn "*compare_addsi2_op0"
bd5b4116 921 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 922 (compare:CC_C
923 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
924 (match_operand:SI 1 "arm_add_operand" "rI,L"))
925 (match_dup 0)))]
25f905c2 926 "TARGET_32BIT"
ebcc79bc 927 "@
928 cmn%?\\t%0, %1
929 cmp%?\\t%0, #%n1"
0d66636f 930 [(set_attr "conds" "set")]
931)
ebcc79bc 932
933(define_insn "*compare_addsi2_op1"
bd5b4116 934 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 935 (compare:CC_C
936 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
937 (match_operand:SI 1 "arm_add_operand" "rI,L"))
938 (match_dup 1)))]
25f905c2 939 "TARGET_32BIT"
ebcc79bc 940 "@
941 cmn%?\\t%0, %1
942 cmp%?\\t%0, #%n1"
0d66636f 943 [(set_attr "conds" "set")]
944)
ebcc79bc 945
080c0b9a 946(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 947 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 948 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 949 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 950 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 951 "TARGET_32BIT"
ebcc79bc 952 "adc%?\\t%0, %1, %2"
cffb2a26 953 [(set_attr "conds" "use")]
954)
ebcc79bc 955
080c0b9a 956(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 957 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 958 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
959 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 960 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 961 "TARGET_32BIT"
ebcc79bc 962 "adc%?\\t%0, %1, %2"
0d66636f 963 [(set_attr "conds" "use")]
964)
ebcc79bc 965
080c0b9a 966(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 967 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 968 (plus:SI (plus:SI
969 (match_operator:SI 2 "shift_operator"
970 [(match_operand:SI 3 "s_register_operand" "r")
971 (match_operand:SI 4 "reg_or_int_operand" "rM")])
972 (match_operand:SI 1 "s_register_operand" "r"))
973 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 974 "TARGET_32BIT"
080c0b9a 975 "adc%?\\t%0, %1, %3%S2"
976 [(set_attr "conds" "use")
977 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
978 (const_string "alu_shift")
979 (const_string "alu_shift_reg")))]
cffb2a26 980)
ebcc79bc 981
25f905c2 982(define_expand "incscc"
983 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
984 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
985 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
986 (match_operand:SI 1 "s_register_operand" "0,?r")))]
987 "TARGET_32BIT"
988 ""
989)
990
991(define_insn "*arm_incscc"
9c08d1fa 992 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 993 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 994 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 995 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 996 "TARGET_ARM"
5565501b 997 "@
998 add%d2\\t%0, %1, #1
999 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 1000 [(set_attr "conds" "use")
215b30b3 1001 (set_attr "length" "4,8")]
1002)
9c08d1fa 1003
d795fb69 1004; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1005(define_split
1006 [(set (match_operand:SI 0 "s_register_operand" "")
1007 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1008 (match_operand:SI 2 "s_register_operand" ""))
1009 (const_int -1)))
1010 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1011 "TARGET_32BIT"
d795fb69 1012 [(set (match_dup 3) (match_dup 1))
1013 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1014 "
1015 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1016")
1017
604f3a0a 1018(define_expand "addsf3"
1019 [(set (match_operand:SF 0 "s_register_operand" "")
1020 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1021 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 1022 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1023 "
a2cd141b 1024 if (TARGET_MAVERICK
604f3a0a 1025 && !cirrus_fp_register (operands[2], SFmode))
1026 operands[2] = force_reg (SFmode, operands[2]);
1027")
1028
604f3a0a 1029(define_expand "adddf3"
1030 [(set (match_operand:DF 0 "s_register_operand" "")
1031 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1032 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1033 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1034 "
a2cd141b 1035 if (TARGET_MAVERICK
604f3a0a 1036 && !cirrus_fp_register (operands[2], DFmode))
1037 operands[2] = force_reg (DFmode, operands[2]);
1038")
1039
cffb2a26 1040(define_expand "subdi3"
1041 [(parallel
1042 [(set (match_operand:DI 0 "s_register_operand" "")
1043 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1044 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1045 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1046 "TARGET_EITHER"
1047 "
a2cd141b 1048 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1049 && TARGET_32BIT
7d57ec45 1050 && cirrus_fp_register (operands[0], DImode)
1051 && cirrus_fp_register (operands[1], DImode))
1052 {
1053 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1054 DONE;
1055 }
1056
25f905c2 1057 if (TARGET_THUMB1)
cffb2a26 1058 {
1059 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1060 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1061 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1062 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1063 }
1064 "
1065)
1066
1067(define_insn "*arm_subdi3"
1068 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1069 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1070 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1071 (clobber (reg:CC CC_REGNUM))]
94829feb 1072 "TARGET_32BIT && !TARGET_NEON"
97499065 1073 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1074 [(set_attr "conds" "clob")
1075 (set_attr "length" "8")]
1076)
1077
1078(define_insn "*thumb_subdi3"
1079 [(set (match_operand:DI 0 "register_operand" "=l")
1080 (minus:DI (match_operand:DI 1 "register_operand" "0")
1081 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1082 (clobber (reg:CC CC_REGNUM))]
25f905c2 1083 "TARGET_THUMB1"
cffb2a26 1084 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1085 [(set_attr "length" "4")]
1086)
9c08d1fa 1087
f7fbdd4a 1088(define_insn "*subdi_di_zesidi"
cffb2a26 1089 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1090 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1091 (zero_extend:DI
cffb2a26 1092 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1093 (clobber (reg:CC CC_REGNUM))]
25f905c2 1094 "TARGET_32BIT"
97499065 1095 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1096 [(set_attr "conds" "clob")
1097 (set_attr "length" "8")]
1098)
9c08d1fa 1099
f7fbdd4a 1100(define_insn "*subdi_di_sesidi"
cffb2a26 1101 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1102 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1103 (sign_extend:DI
cffb2a26 1104 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1105 (clobber (reg:CC CC_REGNUM))]
25f905c2 1106 "TARGET_32BIT"
97499065 1107 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1108 [(set_attr "conds" "clob")
1109 (set_attr "length" "8")]
1110)
9c08d1fa 1111
f7fbdd4a 1112(define_insn "*subdi_zesidi_di"
cffb2a26 1113 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1114 (minus:DI (zero_extend:DI
cffb2a26 1115 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1116 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1117 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1118 "TARGET_ARM"
97499065 1119 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1120 [(set_attr "conds" "clob")
1121 (set_attr "length" "8")]
1122)
9c08d1fa 1123
f7fbdd4a 1124(define_insn "*subdi_sesidi_di"
cffb2a26 1125 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1126 (minus:DI (sign_extend:DI
cffb2a26 1127 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1128 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1129 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1130 "TARGET_ARM"
97499065 1131 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1132 [(set_attr "conds" "clob")
1133 (set_attr "length" "8")]
1134)
9c08d1fa 1135
f7fbdd4a 1136(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1137 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1138 (minus:DI (zero_extend:DI
cffb2a26 1139 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1140 (zero_extend:DI
cffb2a26 1141 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1142 (clobber (reg:CC CC_REGNUM))]
25f905c2 1143 "TARGET_32BIT"
1144 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1145 [(set_attr "conds" "clob")
1146 (set_attr "length" "8")]
1147)
b11cae9e 1148
87b22bf7 1149(define_expand "subsi3"
cffb2a26 1150 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1151 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1152 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1153 "TARGET_EITHER"
87b22bf7 1154 "
1155 if (GET_CODE (operands[1]) == CONST_INT)
1156 {
25f905c2 1157 if (TARGET_32BIT)
cffb2a26 1158 {
96f57e36 1159 arm_split_constant (MINUS, SImode, NULL_RTX,
1160 INTVAL (operands[1]), operands[0],
e1ba4a27 1161 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1162 DONE;
1163 }
25f905c2 1164 else /* TARGET_THUMB1 */
cffb2a26 1165 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1166 }
cffb2a26 1167 "
1168)
87b22bf7 1169
747b7458 1170(define_insn "thumb1_subsi3_insn"
cffb2a26 1171 [(set (match_operand:SI 0 "register_operand" "=l")
1172 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1173 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1174 "TARGET_THUMB1"
cffb2a26 1175 "sub\\t%0, %1, %2"
747b7458 1176 [(set_attr "length" "2")
1177 (set_attr "conds" "set")])
cffb2a26 1178
25f905c2 1179; ??? Check Thumb-2 split length
a0f94409 1180(define_insn_and_split "*arm_subsi3_insn"
080c0b9a 1181 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
bccb5444 1182 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1183 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
25f905c2 1184 "TARGET_32BIT"
e2348bcb 1185 "@
87b22bf7 1186 rsb%?\\t%0, %2, %1
aaa37ad6 1187 sub%?\\t%0, %1, %2
080c0b9a 1188 sub%?\\t%0, %1, %2
1189 #
87b22bf7 1190 #"
080c0b9a 1191 "&& ((GET_CODE (operands[1]) == CONST_INT
1192 && !const_ok_for_arm (INTVAL (operands[1])))
1193 || (GET_CODE (operands[2]) == CONST_INT
1194 && !const_ok_for_arm (INTVAL (operands[2]))))"
87b22bf7 1195 [(clobber (const_int 0))]
1196 "
96f57e36 1197 arm_split_constant (MINUS, SImode, curr_insn,
1198 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1199 DONE;
cffb2a26 1200 "
080c0b9a 1201 [(set_attr "length" "4,4,4,16,16")
a0f94409 1202 (set_attr "predicable" "yes")]
1203)
1204
1205(define_peephole2
1206 [(match_scratch:SI 3 "r")
372575c7 1207 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1208 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1209 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1210 "TARGET_32BIT
a0f94409 1211 && !const_ok_for_arm (INTVAL (operands[1]))
1212 && const_ok_for_arm (~INTVAL (operands[1]))"
1213 [(set (match_dup 3) (match_dup 1))
1214 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1215 ""
cffb2a26 1216)
b11cae9e 1217
f7fbdd4a 1218(define_insn "*subsi3_compare0"
bd5b4116 1219 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1220 (compare:CC_NOOV
1221 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1222 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1223 (const_int 0)))
9c08d1fa 1224 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1225 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1226 "TARGET_32BIT"
e2348bcb 1227 "@
25f905c2 1228 sub%.\\t%0, %1, %2
1229 rsb%.\\t%0, %2, %1"
cffb2a26 1230 [(set_attr "conds" "set")]
1231)
9c08d1fa 1232
080c0b9a 1233(define_insn "*subsi3_compare"
1234 [(set (reg:CC CC_REGNUM)
1235 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1236 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1237 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1238 (minus:SI (match_dup 1) (match_dup 2)))]
1239 "TARGET_32BIT"
1240 "@
1241 sub%.\\t%0, %1, %2
1242 rsb%.\\t%0, %2, %1"
1243 [(set_attr "conds" "set")]
1244)
1245
25f905c2 1246(define_expand "decscc"
1247 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1248 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1249 (match_operator:SI 2 "arm_comparison_operator"
1250 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1251 "TARGET_32BIT"
1252 ""
1253)
1254
1255(define_insn "*arm_decscc"
cffb2a26 1256 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1257 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1258 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1259 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1260 "TARGET_ARM"
e2348bcb 1261 "@
215b30b3 1262 sub%d2\\t%0, %1, #1
1263 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1264 [(set_attr "conds" "use")
1265 (set_attr "length" "*,8")]
1266)
9c08d1fa 1267
604f3a0a 1268(define_expand "subsf3"
1269 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1270 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1271 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1272 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1273 "
a2cd141b 1274 if (TARGET_MAVERICK)
604f3a0a 1275 {
1276 if (!cirrus_fp_register (operands[1], SFmode))
1277 operands[1] = force_reg (SFmode, operands[1]);
1278 if (!cirrus_fp_register (operands[2], SFmode))
1279 operands[2] = force_reg (SFmode, operands[2]);
1280 }
1281")
1282
604f3a0a 1283(define_expand "subdf3"
1284 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1285 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1286 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1287 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1288 "
a2cd141b 1289 if (TARGET_MAVERICK)
604f3a0a 1290 {
1291 if (!cirrus_fp_register (operands[1], DFmode))
1292 operands[1] = force_reg (DFmode, operands[1]);
1293 if (!cirrus_fp_register (operands[2], DFmode))
1294 operands[2] = force_reg (DFmode, operands[2]);
1295 }
1296")
1297
b11cae9e 1298\f
1299;; Multiplication insns
1300
cffb2a26 1301(define_expand "mulsi3"
1302 [(set (match_operand:SI 0 "s_register_operand" "")
1303 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1304 (match_operand:SI 1 "s_register_operand" "")))]
1305 "TARGET_EITHER"
1306 ""
1307)
1308
9c08d1fa 1309;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1310(define_insn "*arm_mulsi3"
1311 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1312 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1313 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1314 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1315 "mul%?\\t%0, %2, %1"
a2cd141b 1316 [(set_attr "insn" "mul")
0d66636f 1317 (set_attr "predicable" "yes")]
cffb2a26 1318)
1319
58d7d654 1320(define_insn "*arm_mulsi3_v6"
1321 [(set (match_operand:SI 0 "s_register_operand" "=r")
1322 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1323 (match_operand:SI 2 "s_register_operand" "r")))]
1324 "TARGET_32BIT && arm_arch6"
1325 "mul%?\\t%0, %1, %2"
1326 [(set_attr "insn" "mul")
1327 (set_attr "predicable" "yes")]
1328)
1329
215b30b3 1330; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1331; 1 and 2; are the same, because reload will make operand 0 match
1332; operand 1 without realizing that this conflicts with operand 2. We fix
1333; this by adding another alternative to match this case, and then `reload'
1334; it ourselves. This alternative must come first.
cffb2a26 1335(define_insn "*thumb_mulsi3"
1336 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1337 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1338 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1339 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1340 "*
1341 if (which_alternative < 2)
20c4e896 1342 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1343 else
20c4e896 1344 return \"mul\\t%0, %2\";
cffb2a26 1345 "
1346 [(set_attr "length" "4,4,2")
a2cd141b 1347 (set_attr "insn" "mul")]
cffb2a26 1348)
b11cae9e 1349
58d7d654 1350(define_insn "*thumb_mulsi3_v6"
1351 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1352 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1353 (match_operand:SI 2 "register_operand" "l,0,0")))]
1354 "TARGET_THUMB1 && arm_arch6"
1355 "@
1490694c 1356 mul\\t%0, %2
1357 mul\\t%0, %1
58d7d654 1358 mul\\t%0, %1"
1359 [(set_attr "length" "2")
1360 (set_attr "insn" "mul")]
1361)
1362
f7fbdd4a 1363(define_insn "*mulsi3_compare0"
bd5b4116 1364 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1365 (compare:CC_NOOV (mult:SI
1366 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1367 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1368 (const_int 0)))
1369 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1370 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1371 "TARGET_ARM && !arm_arch6"
1372 "mul%.\\t%0, %2, %1"
1373 [(set_attr "conds" "set")
1374 (set_attr "insn" "muls")]
1375)
1376
1377(define_insn "*mulsi3_compare0_v6"
1378 [(set (reg:CC_NOOV CC_REGNUM)
1379 (compare:CC_NOOV (mult:SI
1380 (match_operand:SI 2 "s_register_operand" "r")
1381 (match_operand:SI 1 "s_register_operand" "r"))
1382 (const_int 0)))
1383 (set (match_operand:SI 0 "s_register_operand" "=r")
1384 (mult:SI (match_dup 2) (match_dup 1)))]
1385 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1386 "mul%.\\t%0, %2, %1"
cffb2a26 1387 [(set_attr "conds" "set")
a2cd141b 1388 (set_attr "insn" "muls")]
cffb2a26 1389)
9c08d1fa 1390
f7fbdd4a 1391(define_insn "*mulsi_compare0_scratch"
bd5b4116 1392 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1393 (compare:CC_NOOV (mult:SI
1394 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1395 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1396 (const_int 0)))
1397 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1398 "TARGET_ARM && !arm_arch6"
1399 "mul%.\\t%0, %2, %1"
1400 [(set_attr "conds" "set")
1401 (set_attr "insn" "muls")]
1402)
1403
1404(define_insn "*mulsi_compare0_scratch_v6"
1405 [(set (reg:CC_NOOV CC_REGNUM)
1406 (compare:CC_NOOV (mult:SI
1407 (match_operand:SI 2 "s_register_operand" "r")
1408 (match_operand:SI 1 "s_register_operand" "r"))
1409 (const_int 0)))
1410 (clobber (match_scratch:SI 0 "=r"))]
1411 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1412 "mul%.\\t%0, %2, %1"
cffb2a26 1413 [(set_attr "conds" "set")
a2cd141b 1414 (set_attr "insn" "muls")]
cffb2a26 1415)
9c08d1fa 1416
b11cae9e 1417;; Unnamed templates to match MLA instruction.
1418
f7fbdd4a 1419(define_insn "*mulsi3addsi"
9c08d1fa 1420 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1421 (plus:SI
9c08d1fa 1422 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1423 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1424 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1425 "TARGET_32BIT && !arm_arch6"
1426 "mla%?\\t%0, %2, %1, %3"
1427 [(set_attr "insn" "mla")
1428 (set_attr "predicable" "yes")]
1429)
1430
1431(define_insn "*mulsi3addsi_v6"
1432 [(set (match_operand:SI 0 "s_register_operand" "=r")
1433 (plus:SI
1434 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1435 (match_operand:SI 1 "s_register_operand" "r"))
1436 (match_operand:SI 3 "s_register_operand" "r")))]
1437 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1438 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1439 [(set_attr "insn" "mla")
0d66636f 1440 (set_attr "predicable" "yes")]
1441)
b11cae9e 1442
f7fbdd4a 1443(define_insn "*mulsi3addsi_compare0"
bd5b4116 1444 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1445 (compare:CC_NOOV
1446 (plus:SI (mult:SI
1447 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1448 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1449 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1450 (const_int 0)))
9c08d1fa 1451 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1452 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1453 (match_dup 3)))]
58d7d654 1454 "TARGET_ARM && arm_arch6"
1455 "mla%.\\t%0, %2, %1, %3"
1456 [(set_attr "conds" "set")
1457 (set_attr "insn" "mlas")]
1458)
1459
1460(define_insn "*mulsi3addsi_compare0_v6"
1461 [(set (reg:CC_NOOV CC_REGNUM)
1462 (compare:CC_NOOV
1463 (plus:SI (mult:SI
1464 (match_operand:SI 2 "s_register_operand" "r")
1465 (match_operand:SI 1 "s_register_operand" "r"))
1466 (match_operand:SI 3 "s_register_operand" "r"))
1467 (const_int 0)))
1468 (set (match_operand:SI 0 "s_register_operand" "=r")
1469 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1470 (match_dup 3)))]
1471 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1472 "mla%.\\t%0, %2, %1, %3"
0d66636f 1473 [(set_attr "conds" "set")
a2cd141b 1474 (set_attr "insn" "mlas")]
0d66636f 1475)
9c08d1fa 1476
f7fbdd4a 1477(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1478 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1479 (compare:CC_NOOV
1480 (plus:SI (mult:SI
1481 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1482 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1483 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1484 (const_int 0)))
9c08d1fa 1485 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1486 "TARGET_ARM && !arm_arch6"
1487 "mla%.\\t%0, %2, %1, %3"
1488 [(set_attr "conds" "set")
1489 (set_attr "insn" "mlas")]
1490)
1491
1492(define_insn "*mulsi3addsi_compare0_scratch_v6"
1493 [(set (reg:CC_NOOV CC_REGNUM)
1494 (compare:CC_NOOV
1495 (plus:SI (mult:SI
1496 (match_operand:SI 2 "s_register_operand" "r")
1497 (match_operand:SI 1 "s_register_operand" "r"))
1498 (match_operand:SI 3 "s_register_operand" "r"))
1499 (const_int 0)))
1500 (clobber (match_scratch:SI 0 "=r"))]
1501 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1502 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1503 [(set_attr "conds" "set")
a2cd141b 1504 (set_attr "insn" "mlas")]
cffb2a26 1505)
f7fbdd4a 1506
89545238 1507(define_insn "*mulsi3subsi"
1508 [(set (match_operand:SI 0 "s_register_operand" "=r")
1509 (minus:SI
1510 (match_operand:SI 3 "s_register_operand" "r")
1511 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1512 (match_operand:SI 1 "s_register_operand" "r"))))]
1513 "TARGET_32BIT && arm_arch_thumb2"
1514 "mls%?\\t%0, %2, %1, %3"
1515 [(set_attr "insn" "mla")
1516 (set_attr "predicable" "yes")]
1517)
1518
5cdca009 1519(define_expand "maddsidi4"
1520 [(set (match_operand:DI 0 "s_register_operand" "")
1521 (plus:DI
1522 (mult:DI
1523 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1524 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1525 (match_operand:DI 3 "s_register_operand" "")))]
1526 "TARGET_32BIT && arm_arch3m"
1527 "")
82b85d08 1528
1529(define_insn "*mulsidi3adddi"
fe8dbf85 1530 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1531 (plus:DI
215b30b3 1532 (mult:DI
fe8dbf85 1533 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1534 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1535 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1536 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1537 "smlal%?\\t%Q0, %R0, %3, %2"
1538 [(set_attr "insn" "smlal")
1539 (set_attr "predicable" "yes")]
1540)
1541
1542(define_insn "*mulsidi3adddi_v6"
1543 [(set (match_operand:DI 0 "s_register_operand" "=r")
1544 (plus:DI
1545 (mult:DI
1546 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1547 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1548 (match_operand:DI 1 "s_register_operand" "0")))]
1549 "TARGET_32BIT && arm_arch6"
fe8dbf85 1550 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1551 [(set_attr "insn" "smlal")
0d66636f 1552 (set_attr "predicable" "yes")]
1553)
82b85d08 1554
957788b0 1555;; 32x32->64 widening multiply.
1556;; As with mulsi3, the only difference between the v3-5 and v6+
1557;; versions of these patterns is the requirement that the output not
1558;; overlap the inputs, but that still means we have to have a named
1559;; expander and two different starred insns.
1560
1561(define_expand "mulsidi3"
1562 [(set (match_operand:DI 0 "s_register_operand" "")
1563 (mult:DI
1564 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1565 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1566 "TARGET_32BIT && arm_arch3m"
1567 ""
1568)
1569
1570(define_insn "*mulsidi3_nov6"
f7fbdd4a 1571 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1572 (mult:DI
1573 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1574 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1575 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1576 "smull%?\\t%Q0, %R0, %1, %2"
1577 [(set_attr "insn" "smull")
1578 (set_attr "predicable" "yes")]
1579)
1580
957788b0 1581(define_insn "*mulsidi3_v6"
58d7d654 1582 [(set (match_operand:DI 0 "s_register_operand" "=r")
1583 (mult:DI
1584 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1585 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1586 "TARGET_32BIT && arm_arch6"
97499065 1587 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1588 [(set_attr "insn" "smull")
0d66636f 1589 (set_attr "predicable" "yes")]
1590)
f7fbdd4a 1591
957788b0 1592(define_expand "umulsidi3"
1593 [(set (match_operand:DI 0 "s_register_operand" "")
1594 (mult:DI
1595 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1596 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1597 "TARGET_32BIT && arm_arch3m"
1598 ""
1599)
1600
1601(define_insn "*umulsidi3_nov6"
f7fbdd4a 1602 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1603 (mult:DI
1604 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1605 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1606 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1607 "umull%?\\t%Q0, %R0, %1, %2"
1608 [(set_attr "insn" "umull")
1609 (set_attr "predicable" "yes")]
1610)
1611
957788b0 1612(define_insn "*umulsidi3_v6"
58d7d654 1613 [(set (match_operand:DI 0 "s_register_operand" "=r")
1614 (mult:DI
1615 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1616 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1617 "TARGET_32BIT && arm_arch6"
97499065 1618 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1619 [(set_attr "insn" "umull")
0d66636f 1620 (set_attr "predicable" "yes")]
1621)
b11cae9e 1622
5cdca009 1623(define_expand "umaddsidi4"
1624 [(set (match_operand:DI 0 "s_register_operand" "")
1625 (plus:DI
1626 (mult:DI
1627 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1628 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1629 (match_operand:DI 3 "s_register_operand" "")))]
1630 "TARGET_32BIT && arm_arch3m"
1631 "")
82b85d08 1632
1633(define_insn "*umulsidi3adddi"
8ead09f9 1634 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1635 (plus:DI
215b30b3 1636 (mult:DI
fe8dbf85 1637 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1638 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1639 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1640 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1641 "umlal%?\\t%Q0, %R0, %3, %2"
1642 [(set_attr "insn" "umlal")
1643 (set_attr "predicable" "yes")]
1644)
1645
1646(define_insn "*umulsidi3adddi_v6"
1647 [(set (match_operand:DI 0 "s_register_operand" "=r")
1648 (plus:DI
1649 (mult:DI
1650 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1651 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1652 (match_operand:DI 1 "s_register_operand" "0")))]
1653 "TARGET_32BIT && arm_arch6"
fe8dbf85 1654 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1655 [(set_attr "insn" "umlal")
0d66636f 1656 (set_attr "predicable" "yes")]
1657)
82b85d08 1658
957788b0 1659(define_expand "smulsi3_highpart"
1660 [(parallel
1661 [(set (match_operand:SI 0 "s_register_operand" "")
1662 (truncate:SI
1663 (lshiftrt:DI
1664 (mult:DI
1665 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1666 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1667 (const_int 32))))
1668 (clobber (match_scratch:SI 3 ""))])]
1669 "TARGET_32BIT && arm_arch3m"
1670 ""
1671)
1672
1673(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1674 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1675 (truncate:SI
1676 (lshiftrt:DI
215b30b3 1677 (mult:DI
e5fea38e 1678 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1679 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1680 (const_int 32))))
1681 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1682 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1683 "smull%?\\t%3, %0, %2, %1"
1684 [(set_attr "insn" "smull")
1685 (set_attr "predicable" "yes")]
1686)
1687
957788b0 1688(define_insn "*smulsi3_highpart_v6"
58d7d654 1689 [(set (match_operand:SI 0 "s_register_operand" "=r")
1690 (truncate:SI
1691 (lshiftrt:DI
1692 (mult:DI
1693 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1694 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1695 (const_int 32))))
1696 (clobber (match_scratch:SI 3 "=r"))]
1697 "TARGET_32BIT && arm_arch6"
f082f1c4 1698 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1699 [(set_attr "insn" "smull")
0d66636f 1700 (set_attr "predicable" "yes")]
cffb2a26 1701)
f082f1c4 1702
957788b0 1703(define_expand "umulsi3_highpart"
1704 [(parallel
1705 [(set (match_operand:SI 0 "s_register_operand" "")
1706 (truncate:SI
1707 (lshiftrt:DI
1708 (mult:DI
1709 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1710 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1711 (const_int 32))))
1712 (clobber (match_scratch:SI 3 ""))])]
1713 "TARGET_32BIT && arm_arch3m"
1714 ""
1715)
1716
1717(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1718 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1719 (truncate:SI
1720 (lshiftrt:DI
215b30b3 1721 (mult:DI
e5fea38e 1722 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1723 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1724 (const_int 32))))
1725 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1726 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1727 "umull%?\\t%3, %0, %2, %1"
1728 [(set_attr "insn" "umull")
1729 (set_attr "predicable" "yes")]
1730)
1731
957788b0 1732(define_insn "*umulsi3_highpart_v6"
58d7d654 1733 [(set (match_operand:SI 0 "s_register_operand" "=r")
1734 (truncate:SI
1735 (lshiftrt:DI
1736 (mult:DI
1737 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1738 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1739 (const_int 32))))
1740 (clobber (match_scratch:SI 3 "=r"))]
1741 "TARGET_32BIT && arm_arch6"
f082f1c4 1742 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1743 [(set_attr "insn" "umull")
0d66636f 1744 (set_attr "predicable" "yes")]
cffb2a26 1745)
f082f1c4 1746
331beb1a 1747(define_insn "mulhisi3"
1748 [(set (match_operand:SI 0 "s_register_operand" "=r")
1749 (mult:SI (sign_extend:SI
1750 (match_operand:HI 1 "s_register_operand" "%r"))
1751 (sign_extend:SI
1752 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1753 "TARGET_DSP_MULTIPLY"
61a2d04c 1754 "smulbb%?\\t%0, %1, %2"
a2cd141b 1755 [(set_attr "insn" "smulxy")
fec538d9 1756 (set_attr "predicable" "yes")]
1757)
1758
1759(define_insn "*mulhisi3tb"
1760 [(set (match_operand:SI 0 "s_register_operand" "=r")
1761 (mult:SI (ashiftrt:SI
1762 (match_operand:SI 1 "s_register_operand" "r")
1763 (const_int 16))
1764 (sign_extend:SI
1765 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1766 "TARGET_DSP_MULTIPLY"
fec538d9 1767 "smultb%?\\t%0, %1, %2"
a2cd141b 1768 [(set_attr "insn" "smulxy")
fec538d9 1769 (set_attr "predicable" "yes")]
1770)
1771
1772(define_insn "*mulhisi3bt"
1773 [(set (match_operand:SI 0 "s_register_operand" "=r")
1774 (mult:SI (sign_extend:SI
1775 (match_operand:HI 1 "s_register_operand" "r"))
1776 (ashiftrt:SI
1777 (match_operand:SI 2 "s_register_operand" "r")
1778 (const_int 16))))]
25f905c2 1779 "TARGET_DSP_MULTIPLY"
fec538d9 1780 "smulbt%?\\t%0, %1, %2"
a2cd141b 1781 [(set_attr "insn" "smulxy")
fec538d9 1782 (set_attr "predicable" "yes")]
1783)
1784
1785(define_insn "*mulhisi3tt"
1786 [(set (match_operand:SI 0 "s_register_operand" "=r")
1787 (mult:SI (ashiftrt:SI
1788 (match_operand:SI 1 "s_register_operand" "r")
1789 (const_int 16))
1790 (ashiftrt:SI
1791 (match_operand:SI 2 "s_register_operand" "r")
1792 (const_int 16))))]
25f905c2 1793 "TARGET_DSP_MULTIPLY"
fec538d9 1794 "smultt%?\\t%0, %1, %2"
a2cd141b 1795 [(set_attr "insn" "smulxy")
fec538d9 1796 (set_attr "predicable" "yes")]
331beb1a 1797)
1798
5cdca009 1799(define_insn "maddhisi4"
331beb1a 1800 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1801 (plus:SI (mult:SI (sign_extend:SI
1802 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1803 (sign_extend:SI
cfa6c608 1804 (match_operand:HI 2 "s_register_operand" "r")))
1805 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1806 "TARGET_DSP_MULTIPLY"
5cdca009 1807 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1808 [(set_attr "insn" "smlaxy")
fec538d9 1809 (set_attr "predicable" "yes")]
331beb1a 1810)
1811
5cdca009 1812(define_insn "*maddhidi4"
331beb1a 1813 [(set (match_operand:DI 0 "s_register_operand" "=r")
1814 (plus:DI
331beb1a 1815 (mult:DI (sign_extend:DI
cfa6c608 1816 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1817 (sign_extend:DI
cfa6c608 1818 (match_operand:HI 2 "s_register_operand" "r")))
1819 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1820 "TARGET_DSP_MULTIPLY"
5cdca009 1821 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1822 [(set_attr "insn" "smlalxy")
fec538d9 1823 (set_attr "predicable" "yes")])
331beb1a 1824
604f3a0a 1825(define_expand "mulsf3"
1826 [(set (match_operand:SF 0 "s_register_operand" "")
1827 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1828 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1829 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1830 "
a2cd141b 1831 if (TARGET_MAVERICK
604f3a0a 1832 && !cirrus_fp_register (operands[2], SFmode))
1833 operands[2] = force_reg (SFmode, operands[2]);
1834")
1835
604f3a0a 1836(define_expand "muldf3"
1837 [(set (match_operand:DF 0 "s_register_operand" "")
1838 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1839 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1840 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1841 "
a2cd141b 1842 if (TARGET_MAVERICK
604f3a0a 1843 && !cirrus_fp_register (operands[2], DFmode))
1844 operands[2] = force_reg (DFmode, operands[2]);
1845")
b11cae9e 1846\f
1847;; Division insns
1848
7db9af5d 1849(define_expand "divsf3"
1850 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1851 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1852 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1853 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1854 "")
9c08d1fa 1855
7db9af5d 1856(define_expand "divdf3"
1857 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1858 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1859 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1860 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1861 "")
b11cae9e 1862\f
1863;; Modulo insns
1864
7db9af5d 1865(define_expand "modsf3"
1866 [(set (match_operand:SF 0 "s_register_operand" "")
1867 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1868 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1869 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1870 "")
9c08d1fa 1871
7db9af5d 1872(define_expand "moddf3"
1873 [(set (match_operand:DF 0 "s_register_operand" "")
1874 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1875 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1876 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1877 "")
b11cae9e 1878\f
1879;; Boolean and,ior,xor insns
1880
f6ebffac 1881;; Split up double word logical operations
1882
1883;; Split up simple DImode logical operations. Simply perform the logical
1884;; operation on the upper and lower halves of the registers.
1885(define_split
1886 [(set (match_operand:DI 0 "s_register_operand" "")
1887 (match_operator:DI 6 "logical_binary_operator"
1888 [(match_operand:DI 1 "s_register_operand" "")
1889 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1890 "TARGET_32BIT && reload_completed
e2669ea7 1891 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1892 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1893 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1894 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1895 "
215b30b3 1896 {
1897 operands[3] = gen_highpart (SImode, operands[0]);
1898 operands[0] = gen_lowpart (SImode, operands[0]);
1899 operands[4] = gen_highpart (SImode, operands[1]);
1900 operands[1] = gen_lowpart (SImode, operands[1]);
1901 operands[5] = gen_highpart (SImode, operands[2]);
1902 operands[2] = gen_lowpart (SImode, operands[2]);
1903 }"
1904)
f6ebffac 1905
f6ebffac 1906(define_split
1907 [(set (match_operand:DI 0 "s_register_operand" "")
1908 (match_operator:DI 6 "logical_binary_operator"
1909 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1910 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1911 "TARGET_32BIT && reload_completed"
f6ebffac 1912 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1913 (set (match_dup 3) (match_op_dup:SI 6
1914 [(ashiftrt:SI (match_dup 2) (const_int 31))
1915 (match_dup 4)]))]
1916 "
215b30b3 1917 {
1918 operands[3] = gen_highpart (SImode, operands[0]);
1919 operands[0] = gen_lowpart (SImode, operands[0]);
1920 operands[4] = gen_highpart (SImode, operands[1]);
1921 operands[1] = gen_lowpart (SImode, operands[1]);
1922 operands[5] = gen_highpart (SImode, operands[2]);
1923 operands[2] = gen_lowpart (SImode, operands[2]);
1924 }"
1925)
f6ebffac 1926
f6ebffac 1927;; The zero extend of operand 2 means we can just copy the high part of
1928;; operand1 into operand0.
1929(define_split
1930 [(set (match_operand:DI 0 "s_register_operand" "")
1931 (ior:DI
1932 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1933 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1934 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1935 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1936 (set (match_dup 3) (match_dup 4))]
1937 "
215b30b3 1938 {
1939 operands[4] = gen_highpart (SImode, operands[1]);
1940 operands[3] = gen_highpart (SImode, operands[0]);
1941 operands[0] = gen_lowpart (SImode, operands[0]);
1942 operands[1] = gen_lowpart (SImode, operands[1]);
1943 }"
1944)
f6ebffac 1945
1946;; The zero extend of operand 2 means we can just copy the high part of
1947;; operand1 into operand0.
1948(define_split
1949 [(set (match_operand:DI 0 "s_register_operand" "")
1950 (xor:DI
1951 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1952 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1953 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1954 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1955 (set (match_dup 3) (match_dup 4))]
1956 "
215b30b3 1957 {
1958 operands[4] = gen_highpart (SImode, operands[1]);
1959 operands[3] = gen_highpart (SImode, operands[0]);
1960 operands[0] = gen_lowpart (SImode, operands[0]);
1961 operands[1] = gen_lowpart (SImode, operands[1]);
1962 }"
1963)
f6ebffac 1964
e2669ea7 1965(define_expand "anddi3"
1966 [(set (match_operand:DI 0 "s_register_operand" "")
1967 (and:DI (match_operand:DI 1 "s_register_operand" "")
1968 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1969 "TARGET_32BIT"
1970 ""
1971)
1972
1973(define_insn "*anddi3_insn"
cffb2a26 1974 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1975 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1976 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 1977 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 1978 "#"
215b30b3 1979 [(set_attr "length" "8")]
1980)
b11cae9e 1981
a0f94409 1982(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1983 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1984 (and:DI (zero_extend:DI
1985 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1986 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1987 "TARGET_32BIT"
f6ebffac 1988 "#"
25f905c2 1989 "TARGET_32BIT && reload_completed"
a0f94409 1990 ; The zero extend of operand 2 clears the high word of the output
1991 ; operand.
1992 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1993 (set (match_dup 3) (const_int 0))]
1994 "
1995 {
1996 operands[3] = gen_highpart (SImode, operands[0]);
1997 operands[0] = gen_lowpart (SImode, operands[0]);
1998 operands[1] = gen_lowpart (SImode, operands[1]);
1999 }"
215b30b3 2000 [(set_attr "length" "8")]
2001)
b11cae9e 2002
f7fbdd4a 2003(define_insn "*anddi_sesdi_di"
cffb2a26 2004 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2005 (and:DI (sign_extend:DI
2006 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2007 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2008 "TARGET_32BIT"
f6ebffac 2009 "#"
cffb2a26 2010 [(set_attr "length" "8")]
2011)
b11cae9e 2012
87b22bf7 2013(define_expand "andsi3"
cffb2a26 2014 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2015 (and:SI (match_operand:SI 1 "s_register_operand" "")
2016 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2017 "TARGET_EITHER"
87b22bf7 2018 "
25f905c2 2019 if (TARGET_32BIT)
87b22bf7 2020 {
cffb2a26 2021 if (GET_CODE (operands[2]) == CONST_INT)
2022 {
47b5b27b 2023 if (INTVAL (operands[2]) == 255 && arm_arch6)
2024 {
2025 operands[1] = convert_to_mode (QImode, operands[1], 1);
2026 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2027 operands[1]));
2028 }
2029 else
2030 arm_split_constant (AND, SImode, NULL_RTX,
2031 INTVAL (operands[2]), operands[0],
2032 operands[1],
2033 optimize && can_create_pseudo_p ());
615caa51 2034
cffb2a26 2035 DONE;
2036 }
87b22bf7 2037 }
25f905c2 2038 else /* TARGET_THUMB1 */
cffb2a26 2039 {
2040 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2041 {
2042 rtx tmp = force_reg (SImode, operands[2]);
2043 if (rtx_equal_p (operands[0], operands[1]))
2044 operands[2] = tmp;
2045 else
2046 {
2047 operands[2] = operands[1];
2048 operands[1] = tmp;
2049 }
2050 }
cffb2a26 2051 else
2052 {
2053 int i;
2054
215b30b3 2055 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2056 {
215b30b3 2057 operands[2] = force_reg (SImode,
2058 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2059
747b7458 2060 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2061
2062 DONE;
2063 }
87b22bf7 2064
cffb2a26 2065 for (i = 9; i <= 31; i++)
2066 {
2067 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2068 {
2069 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2070 const0_rtx));
2071 DONE;
2072 }
215b30b3 2073 else if ((((HOST_WIDE_INT) 1) << i) - 1
2074 == ~INTVAL (operands[2]))
cffb2a26 2075 {
2076 rtx shift = GEN_INT (i);
2077 rtx reg = gen_reg_rtx (SImode);
2078
2079 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2080 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2081
2082 DONE;
2083 }
2084 }
2085
2086 operands[2] = force_reg (SImode, operands[2]);
2087 }
215b30b3 2088 }
2089 "
cffb2a26 2090)
2091
25f905c2 2092; ??? Check split length for Thumb-2
a0f94409 2093(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2094 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2095 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2096 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2097 "TARGET_32BIT"
5565501b 2098 "@
2099 and%?\\t%0, %1, %2
87b22bf7 2100 bic%?\\t%0, %1, #%B2
2101 #"
25f905c2 2102 "TARGET_32BIT
a0f94409 2103 && GET_CODE (operands[2]) == CONST_INT
2104 && !(const_ok_for_arm (INTVAL (operands[2]))
2105 || const_ok_for_arm (~INTVAL (operands[2])))"
2106 [(clobber (const_int 0))]
2107 "
96f57e36 2108 arm_split_constant (AND, SImode, curr_insn,
2109 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2110 DONE;
2111 "
0d66636f 2112 [(set_attr "length" "4,4,16")
2113 (set_attr "predicable" "yes")]
cffb2a26 2114)
2115
25f905c2 2116(define_insn "*thumb1_andsi3_insn"
cffb2a26 2117 [(set (match_operand:SI 0 "register_operand" "=l")
2118 (and:SI (match_operand:SI 1 "register_operand" "%0")
2119 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2120 "TARGET_THUMB1"
747b7458 2121 "and\\t%0, %2"
2122 [(set_attr "length" "2")
2123 (set_attr "conds" "set")])
87b22bf7 2124
f7fbdd4a 2125(define_insn "*andsi3_compare0"
bd5b4116 2126 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2127 (compare:CC_NOOV
2128 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2129 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2130 (const_int 0)))
cffb2a26 2131 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2132 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2133 "TARGET_32BIT"
5565501b 2134 "@
25f905c2 2135 and%.\\t%0, %1, %2
2136 bic%.\\t%0, %1, #%B2"
cffb2a26 2137 [(set_attr "conds" "set")]
2138)
9c08d1fa 2139
f7fbdd4a 2140(define_insn "*andsi3_compare0_scratch"
bd5b4116 2141 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2142 (compare:CC_NOOV
2143 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2144 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2145 (const_int 0)))
dd193d7c 2146 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2147 "TARGET_32BIT"
5565501b 2148 "@
2149 tst%?\\t%0, %1
25f905c2 2150 bic%.\\t%2, %0, #%B1"
0d66636f 2151 [(set_attr "conds" "set")]
2152)
9c08d1fa 2153
f7fbdd4a 2154(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2155 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2156 (compare:CC_NOOV (zero_extract:SI
2157 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2158 (match_operand 1 "const_int_operand" "n")
2159 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2160 (const_int 0)))]
25f905c2 2161 "TARGET_32BIT
cffb2a26 2162 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2163 && INTVAL (operands[1]) > 0
2164 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2165 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2166 "*
5c49a439 2167 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2168 << INTVAL (operands[2]));
40dbec34 2169 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2170 return \"\";
0d66636f 2171 "
2172 [(set_attr "conds" "set")]
2173)
9c08d1fa 2174
f4462328 2175(define_insn_and_split "*ne_zeroextractsi"
c4034607 2176 [(set (match_operand:SI 0 "s_register_operand" "=r")
2177 (ne:SI (zero_extract:SI
2178 (match_operand:SI 1 "s_register_operand" "r")
2179 (match_operand:SI 2 "const_int_operand" "n")
2180 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2181 (const_int 0)))
2182 (clobber (reg:CC CC_REGNUM))]
25f905c2 2183 "TARGET_32BIT
cffb2a26 2184 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2185 && INTVAL (operands[2]) > 0
2186 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2187 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2188 "#"
25f905c2 2189 "TARGET_32BIT
f4462328 2190 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2191 && INTVAL (operands[2]) > 0
2192 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2193 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2194 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2195 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2196 (const_int 0)))
2197 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2198 (set (match_dup 0)
2199 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2200 (match_dup 0) (const_int 1)))]
2201 "
2202 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2203 << INTVAL (operands[3]));
2204 "
2205 [(set_attr "conds" "clob")
25f905c2 2206 (set (attr "length")
2207 (if_then_else (eq_attr "is_thumb" "yes")
2208 (const_int 12)
2209 (const_int 8)))]
f4462328 2210)
2211
2212(define_insn_and_split "*ne_zeroextractsi_shifted"
2213 [(set (match_operand:SI 0 "s_register_operand" "=r")
2214 (ne:SI (zero_extract:SI
2215 (match_operand:SI 1 "s_register_operand" "r")
2216 (match_operand:SI 2 "const_int_operand" "n")
2217 (const_int 0))
2218 (const_int 0)))
2219 (clobber (reg:CC CC_REGNUM))]
2220 "TARGET_ARM"
2221 "#"
2222 "TARGET_ARM"
2223 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2224 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2225 (const_int 0)))
2226 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2227 (set (match_dup 0)
2228 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2229 (match_dup 0) (const_int 1)))]
2230 "
2231 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2232 "
2233 [(set_attr "conds" "clob")
2234 (set_attr "length" "8")]
2235)
2236
2237(define_insn_and_split "*ite_ne_zeroextractsi"
2238 [(set (match_operand:SI 0 "s_register_operand" "=r")
2239 (if_then_else:SI (ne (zero_extract:SI
2240 (match_operand:SI 1 "s_register_operand" "r")
2241 (match_operand:SI 2 "const_int_operand" "n")
2242 (match_operand:SI 3 "const_int_operand" "n"))
2243 (const_int 0))
2244 (match_operand:SI 4 "arm_not_operand" "rIK")
2245 (const_int 0)))
2246 (clobber (reg:CC CC_REGNUM))]
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 "#"
2254 "TARGET_ARM
2255 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2256 && INTVAL (operands[2]) > 0
2257 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2258 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2259 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2260 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2261 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2262 (const_int 0)))
2263 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2264 (set (match_dup 0)
2265 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2266 (match_dup 0) (match_dup 4)))]
2267 "
c4034607 2268 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2269 << INTVAL (operands[3]));
2270 "
2271 [(set_attr "conds" "clob")
2272 (set_attr "length" "8")]
2273)
2274
2275(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2276 [(set (match_operand:SI 0 "s_register_operand" "=r")
2277 (if_then_else:SI (ne (zero_extract:SI
2278 (match_operand:SI 1 "s_register_operand" "r")
2279 (match_operand:SI 2 "const_int_operand" "n")
2280 (const_int 0))
2281 (const_int 0))
2282 (match_operand:SI 3 "arm_not_operand" "rIK")
2283 (const_int 0)))
2284 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2285 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2286 "#"
f8d7bf2f 2287 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2288 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2289 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2290 (const_int 0)))
2291 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2292 (set (match_dup 0)
2293 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2294 (match_dup 0) (match_dup 3)))]
2295 "
2296 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2297 "
2298 [(set_attr "conds" "clob")
215b30b3 2299 (set_attr "length" "8")]
2300)
9c08d1fa 2301
58d6528b 2302(define_split
2303 [(set (match_operand:SI 0 "s_register_operand" "")
2304 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2305 (match_operand:SI 2 "const_int_operand" "")
2306 (match_operand:SI 3 "const_int_operand" "")))
2307 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2308 "TARGET_THUMB1"
58d6528b 2309 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2310 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2311 "{
2312 HOST_WIDE_INT temp = INTVAL (operands[2]);
2313
2314 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2315 operands[3] = GEN_INT (32 - temp);
2316 }"
2317)
2318
25f905c2 2319;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2320(define_split
2321 [(set (match_operand:SI 0 "s_register_operand" "")
2322 (match_operator:SI 1 "shiftable_operator"
2323 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2324 (match_operand:SI 3 "const_int_operand" "")
2325 (match_operand:SI 4 "const_int_operand" ""))
2326 (match_operand:SI 5 "s_register_operand" "")]))
2327 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2328 "TARGET_ARM"
2329 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2330 (set (match_dup 0)
2331 (match_op_dup 1
2332 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2333 (match_dup 5)]))]
2334 "{
2335 HOST_WIDE_INT temp = INTVAL (operands[3]);
2336
2337 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2338 operands[4] = GEN_INT (32 - temp);
2339 }"
2340)
2341
58d6528b 2342(define_split
2343 [(set (match_operand:SI 0 "s_register_operand" "")
2344 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2345 (match_operand:SI 2 "const_int_operand" "")
2346 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2347 "TARGET_THUMB1"
58d6528b 2348 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2349 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2350 "{
2351 HOST_WIDE_INT temp = INTVAL (operands[2]);
2352
2353 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2354 operands[3] = GEN_INT (32 - temp);
2355 }"
2356)
2357
d7863cfe 2358(define_split
2359 [(set (match_operand:SI 0 "s_register_operand" "")
2360 (match_operator:SI 1 "shiftable_operator"
2361 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2362 (match_operand:SI 3 "const_int_operand" "")
2363 (match_operand:SI 4 "const_int_operand" ""))
2364 (match_operand:SI 5 "s_register_operand" "")]))
2365 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2366 "TARGET_ARM"
2367 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2368 (set (match_dup 0)
2369 (match_op_dup 1
2370 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2371 (match_dup 5)]))]
2372 "{
2373 HOST_WIDE_INT temp = INTVAL (operands[3]);
2374
2375 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2376 operands[4] = GEN_INT (32 - temp);
2377 }"
2378)
2379
a42059fd 2380;;; ??? This pattern is bogus. If operand3 has bits outside the range
2381;;; represented by the bitfield, then this will produce incorrect results.
2382;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2383;;; which have a real bit-field insert instruction, the truncation happens
2384;;; in the bit-field insert instruction itself. Since arm does not have a
2385;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2386;;; the value before we insert. This loses some of the advantage of having
2387;;; this insv pattern, so this pattern needs to be reevalutated.
2388
8a18b90c 2389(define_expand "insv"
2390 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2391 (match_operand:SI 1 "general_operand" "")
2392 (match_operand:SI 2 "general_operand" ""))
19335226 2393 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2394 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2395 "
215b30b3 2396 {
2397 int start_bit = INTVAL (operands[2]);
2398 int width = INTVAL (operands[1]);
2399 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2400 rtx target, subtarget;
2401
8b054d5a 2402 if (arm_arch_thumb2)
2403 {
2404 bool use_bfi = TRUE;
2405
2406 if (GET_CODE (operands[3]) == CONST_INT)
2407 {
2408 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2409
2410 if (val == 0)
2411 {
2412 emit_insn (gen_insv_zero (operands[0], operands[1],
2413 operands[2]));
2414 DONE;
2415 }
2416
2417 /* See if the set can be done with a single orr instruction. */
2418 if (val == mask && const_ok_for_arm (val << start_bit))
2419 use_bfi = FALSE;
2420 }
2421
2422 if (use_bfi)
2423 {
2424 if (GET_CODE (operands[3]) != REG)
2425 operands[3] = force_reg (SImode, operands[3]);
2426
2427 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2428 operands[3]));
2429 DONE;
2430 }
2431 }
2432
3f8fde42 2433 target = copy_rtx (operands[0]);
215b30b3 2434 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2435 subreg as the final target. */
2436 if (GET_CODE (target) == SUBREG)
2437 {
2438 subtarget = gen_reg_rtx (SImode);
2439 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2440 < GET_MODE_SIZE (SImode))
2441 target = SUBREG_REG (target);
2442 }
2443 else
2444 subtarget = target;
8a18b90c 2445
215b30b3 2446 if (GET_CODE (operands[3]) == CONST_INT)
2447 {
2448 /* Since we are inserting a known constant, we may be able to
2449 reduce the number of bits that we have to clear so that
2450 the mask becomes simple. */
2451 /* ??? This code does not check to see if the new mask is actually
2452 simpler. It may not be. */
2453 rtx op1 = gen_reg_rtx (SImode);
2454 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2455 start of this pattern. */
2456 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2457 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2458
c5b3a71b 2459 emit_insn (gen_andsi3 (op1, operands[0],
2460 gen_int_mode (~mask2, SImode)));
215b30b3 2461 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2462 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2463 }
2464 else if (start_bit == 0
2465 && !(const_ok_for_arm (mask)
2466 || const_ok_for_arm (~mask)))
2467 {
2468 /* A Trick, since we are setting the bottom bits in the word,
2469 we can shift operand[3] up, operand[0] down, OR them together
2470 and rotate the result back again. This takes 3 insns, and
5910bb95 2471 the third might be mergeable into another op. */
215b30b3 2472 /* The shift up copes with the possibility that operand[3] is
2473 wider than the bitfield. */
2474 rtx op0 = gen_reg_rtx (SImode);
2475 rtx op1 = gen_reg_rtx (SImode);
2476
2477 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2478 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2479 emit_insn (gen_iorsi3 (op1, op1, op0));
2480 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2481 }
2482 else if ((width + start_bit == 32)
2483 && !(const_ok_for_arm (mask)
2484 || const_ok_for_arm (~mask)))
2485 {
2486 /* Similar trick, but slightly less efficient. */
8a18b90c 2487
215b30b3 2488 rtx op0 = gen_reg_rtx (SImode);
2489 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2490
215b30b3 2491 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2492 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2493 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2494 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2495 }
2496 else
2497 {
c5b3a71b 2498 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2499 rtx op1 = gen_reg_rtx (SImode);
2500 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2501
215b30b3 2502 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2503 {
2504 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2505
215b30b3 2506 emit_insn (gen_movsi (tmp, op0));
2507 op0 = tmp;
2508 }
8a18b90c 2509
215b30b3 2510 /* Mask out any bits in operand[3] that are not needed. */
2511 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2512
215b30b3 2513 if (GET_CODE (op0) == CONST_INT
2514 && (const_ok_for_arm (mask << start_bit)
2515 || const_ok_for_arm (~(mask << start_bit))))
2516 {
c5b3a71b 2517 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2518 emit_insn (gen_andsi3 (op2, operands[0], op0));
2519 }
2520 else
2521 {
2522 if (GET_CODE (op0) == CONST_INT)
2523 {
2524 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2525
215b30b3 2526 emit_insn (gen_movsi (tmp, op0));
2527 op0 = tmp;
2528 }
2529
2530 if (start_bit != 0)
2531 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2532
215b30b3 2533 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2534 }
8a18b90c 2535
215b30b3 2536 if (start_bit != 0)
2537 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2538
215b30b3 2539 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2540 }
f082f1c4 2541
215b30b3 2542 if (subtarget != target)
2543 {
2544 /* If TARGET is still a SUBREG, then it must be wider than a word,
2545 so we must be careful only to set the subword we were asked to. */
2546 if (GET_CODE (target) == SUBREG)
2547 emit_move_insn (target, subtarget);
2548 else
2549 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2550 }
8a18b90c 2551
215b30b3 2552 DONE;
2553 }"
2554)
8a18b90c 2555
8b054d5a 2556(define_insn "insv_zero"
2557 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2558 (match_operand:SI 1 "const_int_operand" "M")
2559 (match_operand:SI 2 "const_int_operand" "M"))
2560 (const_int 0))]
2561 "arm_arch_thumb2"
2562 "bfc%?\t%0, %2, %1"
2563 [(set_attr "length" "4")
2564 (set_attr "predicable" "yes")]
2565)
2566
2567(define_insn "insv_t2"
2568 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2569 (match_operand:SI 1 "const_int_operand" "M")
2570 (match_operand:SI 2 "const_int_operand" "M"))
2571 (match_operand:SI 3 "s_register_operand" "r"))]
2572 "arm_arch_thumb2"
2573 "bfi%?\t%0, %3, %2, %1"
2574 [(set_attr "length" "4")
2575 (set_attr "predicable" "yes")]
2576)
2577
215b30b3 2578; constants for op 2 will never be given to these patterns.
a0f94409 2579(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2580 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2581 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2582 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2583 "TARGET_32BIT"
f6ebffac 2584 "#"
e2669ea7 2585 "TARGET_32BIT && reload_completed
2586 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2587 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2588 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2589 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2590 "
2591 {
2592 operands[3] = gen_highpart (SImode, operands[0]);
2593 operands[0] = gen_lowpart (SImode, operands[0]);
2594 operands[4] = gen_highpart (SImode, operands[1]);
2595 operands[1] = gen_lowpart (SImode, operands[1]);
2596 operands[5] = gen_highpart (SImode, operands[2]);
2597 operands[2] = gen_lowpart (SImode, operands[2]);
2598 }"
0d66636f 2599 [(set_attr "length" "8")
2600 (set_attr "predicable" "yes")]
2601)
9c08d1fa 2602
a0f94409 2603(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2604 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2605 (and:DI (not:DI (zero_extend:DI
2606 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2607 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2608 "TARGET_32BIT"
e2348bcb 2609 "@
97499065 2610 bic%?\\t%Q0, %Q1, %2
f6ebffac 2611 #"
a0f94409 2612 ; (not (zero_extend ...)) allows us to just copy the high word from
2613 ; operand1 to operand0.
25f905c2 2614 "TARGET_32BIT
a0f94409 2615 && reload_completed
2616 && operands[0] != operands[1]"
5a097f7d 2617 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2618 (set (match_dup 3) (match_dup 4))]
2619 "
2620 {
2621 operands[3] = gen_highpart (SImode, operands[0]);
2622 operands[0] = gen_lowpart (SImode, operands[0]);
2623 operands[4] = gen_highpart (SImode, operands[1]);
2624 operands[1] = gen_lowpart (SImode, operands[1]);
2625 }"
0d66636f 2626 [(set_attr "length" "4,8")
2627 (set_attr "predicable" "yes")]
2628)
9c08d1fa 2629
a0f94409 2630(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2631 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2632 (and:DI (not:DI (sign_extend:DI
2633 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2634 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2635 "TARGET_32BIT"
f6ebffac 2636 "#"
25f905c2 2637 "TARGET_32BIT && reload_completed"
5a097f7d 2638 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2639 (set (match_dup 3) (and:SI (not:SI
2640 (ashiftrt:SI (match_dup 2) (const_int 31)))
2641 (match_dup 4)))]
2642 "
2643 {
2644 operands[3] = gen_highpart (SImode, operands[0]);
2645 operands[0] = gen_lowpart (SImode, operands[0]);
2646 operands[4] = gen_highpart (SImode, operands[1]);
2647 operands[1] = gen_lowpart (SImode, operands[1]);
2648 }"
0d66636f 2649 [(set_attr "length" "8")
2650 (set_attr "predicable" "yes")]
2651)
9c08d1fa 2652
8a18b90c 2653(define_insn "andsi_notsi_si"
9c08d1fa 2654 [(set (match_operand:SI 0 "s_register_operand" "=r")
2655 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2656 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2657 "TARGET_32BIT"
0d66636f 2658 "bic%?\\t%0, %1, %2"
2659 [(set_attr "predicable" "yes")]
2660)
b11cae9e 2661
747b7458 2662(define_insn "thumb1_bicsi3"
cffb2a26 2663 [(set (match_operand:SI 0 "register_operand" "=l")
2664 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2665 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2666 "TARGET_THUMB1"
747b7458 2667 "bic\\t%0, %1"
2668 [(set_attr "length" "2")
2669 (set_attr "conds" "set")])
cffb2a26 2670
8a18b90c 2671(define_insn "andsi_not_shiftsi_si"
a2cd141b 2672 [(set (match_operand:SI 0 "s_register_operand" "=r")
2673 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2674 [(match_operand:SI 2 "s_register_operand" "r")
2675 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2676 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2677 "TARGET_ARM"
6c4c2133 2678 "bic%?\\t%0, %1, %2%S4"
344495ea 2679 [(set_attr "predicable" "yes")
331beb1a 2680 (set_attr "shift" "2")
a2cd141b 2681 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2682 (const_string "alu_shift")
2683 (const_string "alu_shift_reg")))]
6c4c2133 2684)
8a18b90c 2685
f7fbdd4a 2686(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2687 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2688 (compare:CC_NOOV
2689 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2690 (match_operand:SI 1 "s_register_operand" "r"))
2691 (const_int 0)))
9c08d1fa 2692 (set (match_operand:SI 0 "s_register_operand" "=r")
2693 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2694 "TARGET_32BIT"
2695 "bic%.\\t%0, %1, %2"
0d66636f 2696 [(set_attr "conds" "set")]
2697)
9c08d1fa 2698
f7fbdd4a 2699(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2700 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2701 (compare:CC_NOOV
2702 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2703 (match_operand:SI 1 "s_register_operand" "r"))
2704 (const_int 0)))
9c08d1fa 2705 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2706 "TARGET_32BIT"
2707 "bic%.\\t%0, %1, %2"
0d66636f 2708 [(set_attr "conds" "set")]
2709)
9c08d1fa 2710
e2669ea7 2711(define_expand "iordi3"
2712 [(set (match_operand:DI 0 "s_register_operand" "")
2713 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2714 (match_operand:DI 2 "neon_logic_op2" "")))]
2715 "TARGET_32BIT"
2716 ""
2717)
2718
2719(define_insn "*iordi3_insn"
cffb2a26 2720 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2721 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2722 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2723 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2724 "#"
0d66636f 2725 [(set_attr "length" "8")
2726 (set_attr "predicable" "yes")]
cffb2a26 2727)
9c08d1fa 2728
f7fbdd4a 2729(define_insn "*iordi_zesidi_di"
9c08d1fa 2730 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2731 (ior:DI (zero_extend:DI
2732 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2733 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2734 "TARGET_32BIT"
e2348bcb 2735 "@
97499065 2736 orr%?\\t%Q0, %Q1, %2
f6ebffac 2737 #"
0d66636f 2738 [(set_attr "length" "4,8")
2739 (set_attr "predicable" "yes")]
cffb2a26 2740)
9c08d1fa 2741
f7fbdd4a 2742(define_insn "*iordi_sesidi_di"
9c08d1fa 2743 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2744 (ior:DI (sign_extend:DI
2745 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2746 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2747 "TARGET_32BIT"
f6ebffac 2748 "#"
0d66636f 2749 [(set_attr "length" "8")
2750 (set_attr "predicable" "yes")]
cffb2a26 2751)
9c08d1fa 2752
87b22bf7 2753(define_expand "iorsi3"
cffb2a26 2754 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2755 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2756 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2757 "TARGET_EITHER"
87b22bf7 2758 "
2759 if (GET_CODE (operands[2]) == CONST_INT)
2760 {
25f905c2 2761 if (TARGET_32BIT)
cffb2a26 2762 {
96f57e36 2763 arm_split_constant (IOR, SImode, NULL_RTX,
2764 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2765 optimize && can_create_pseudo_p ());
cffb2a26 2766 DONE;
2767 }
25f905c2 2768 else /* TARGET_THUMB1 */
923ffadb 2769 {
2770 rtx tmp = force_reg (SImode, operands[2]);
2771 if (rtx_equal_p (operands[0], operands[1]))
2772 operands[2] = tmp;
2773 else
2774 {
2775 operands[2] = operands[1];
2776 operands[1] = tmp;
2777 }
2778 }
87b22bf7 2779 }
cffb2a26 2780 "
2781)
87b22bf7 2782
d5d4dc8d 2783(define_insn_and_split "*iorsi3_insn"
2784 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2785 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2786 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2787 "TARGET_32BIT"
87b22bf7 2788 "@
2789 orr%?\\t%0, %1, %2
d5d4dc8d 2790 orn%?\\t%0, %1, #%B2
87b22bf7 2791 #"
d5d4dc8d 2792 "TARGET_32BIT
a0f94409 2793 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2794 && !(const_ok_for_arm (INTVAL (operands[2]))
2795 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2796 [(clobber (const_int 0))]
d5d4dc8d 2797{
96f57e36 2798 arm_split_constant (IOR, SImode, curr_insn,
2799 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2800 DONE;
d5d4dc8d 2801}
2802 [(set_attr "length" "4,4,16")
2803 (set_attr "arch" "32,t2,32")
2804 (set_attr "predicable" "yes")])
cffb2a26 2805
747b7458 2806(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2807 [(set (match_operand:SI 0 "register_operand" "=l")
2808 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2809 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2810 "TARGET_THUMB1"
747b7458 2811 "orr\\t%0, %2"
2812 [(set_attr "length" "2")
2813 (set_attr "conds" "set")])
9c08d1fa 2814
a0f94409 2815(define_peephole2
2816 [(match_scratch:SI 3 "r")
372575c7 2817 (set (match_operand:SI 0 "arm_general_register_operand" "")
2818 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2819 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2820 "TARGET_ARM
a0f94409 2821 && !const_ok_for_arm (INTVAL (operands[2]))
2822 && const_ok_for_arm (~INTVAL (operands[2]))"
2823 [(set (match_dup 3) (match_dup 2))
2824 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2825 ""
215b30b3 2826)
a0f94409 2827
f7fbdd4a 2828(define_insn "*iorsi3_compare0"
bd5b4116 2829 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2830 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2831 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2832 (const_int 0)))
2833 (set (match_operand:SI 0 "s_register_operand" "=r")
2834 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2835 "TARGET_32BIT"
2836 "orr%.\\t%0, %1, %2"
cffb2a26 2837 [(set_attr "conds" "set")]
2838)
9c08d1fa 2839
f7fbdd4a 2840(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2841 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2842 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2843 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2844 (const_int 0)))
2845 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2846 "TARGET_32BIT"
2847 "orr%.\\t%0, %1, %2"
0d66636f 2848 [(set_attr "conds" "set")]
2849)
9c08d1fa 2850
e2669ea7 2851(define_expand "xordi3"
2852 [(set (match_operand:DI 0 "s_register_operand" "")
2853 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2854 (match_operand:DI 2 "s_register_operand" "")))]
2855 "TARGET_32BIT"
2856 ""
2857)
2858
2859(define_insn "*xordi3_insn"
cffb2a26 2860 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2861 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2862 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2863 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2864 "#"
0d66636f 2865 [(set_attr "length" "8")
2866 (set_attr "predicable" "yes")]
cffb2a26 2867)
9c08d1fa 2868
f7fbdd4a 2869(define_insn "*xordi_zesidi_di"
9c08d1fa 2870 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2871 (xor:DI (zero_extend:DI
2872 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2873 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2874 "TARGET_32BIT"
e2348bcb 2875 "@
97499065 2876 eor%?\\t%Q0, %Q1, %2
f6ebffac 2877 #"
0d66636f 2878 [(set_attr "length" "4,8")
2879 (set_attr "predicable" "yes")]
cffb2a26 2880)
9c08d1fa 2881
f7fbdd4a 2882(define_insn "*xordi_sesidi_di"
9c08d1fa 2883 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2884 (xor:DI (sign_extend:DI
2885 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2886 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2887 "TARGET_32BIT"
f6ebffac 2888 "#"
0d66636f 2889 [(set_attr "length" "8")
2890 (set_attr "predicable" "yes")]
cffb2a26 2891)
9c08d1fa 2892
cffb2a26 2893(define_expand "xorsi3"
2894 [(set (match_operand:SI 0 "s_register_operand" "")
2895 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2896 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2897 "TARGET_EITHER"
923ffadb 2898 "if (GET_CODE (operands[2]) == CONST_INT)
2899 {
2900 if (TARGET_32BIT)
2901 {
2902 arm_split_constant (XOR, SImode, NULL_RTX,
2903 INTVAL (operands[2]), operands[0], operands[1],
2904 optimize && can_create_pseudo_p ());
2905 DONE;
2906 }
2907 else /* TARGET_THUMB1 */
2908 {
2909 rtx tmp = force_reg (SImode, operands[2]);
2910 if (rtx_equal_p (operands[0], operands[1]))
2911 operands[2] = tmp;
2912 else
2913 {
2914 operands[2] = operands[1];
2915 operands[1] = tmp;
2916 }
2917 }
2918 }"
cffb2a26 2919)
2920
2921(define_insn "*arm_xorsi3"
2922 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2923 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2924 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2925 "TARGET_32BIT"
cffb2a26 2926 "eor%?\\t%0, %1, %2"
0d66636f 2927 [(set_attr "predicable" "yes")]
cffb2a26 2928)
2929
747b7458 2930(define_insn "*thumb1_xorsi3_insn"
cffb2a26 2931 [(set (match_operand:SI 0 "register_operand" "=l")
2932 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2933 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2934 "TARGET_THUMB1"
747b7458 2935 "eor\\t%0, %2"
2936 [(set_attr "length" "2")
2937 (set_attr "conds" "set")])
9c08d1fa 2938
f7fbdd4a 2939(define_insn "*xorsi3_compare0"
bd5b4116 2940 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2941 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2942 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2943 (const_int 0)))
2944 (set (match_operand:SI 0 "s_register_operand" "=r")
2945 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2946 "TARGET_32BIT"
2947 "eor%.\\t%0, %1, %2"
0d66636f 2948 [(set_attr "conds" "set")]
2949)
9c08d1fa 2950
f7fbdd4a 2951(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2952 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2953 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2954 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2955 (const_int 0)))]
25f905c2 2956 "TARGET_32BIT"
40dbec34 2957 "teq%?\\t%0, %1"
cffb2a26 2958 [(set_attr "conds" "set")]
2959)
9c08d1fa 2960
215b30b3 2961; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2962; (NOT D) we can sometimes merge the final NOT into one of the following
2963; insns.
9c08d1fa 2964
2965(define_split
a058e94a 2966 [(set (match_operand:SI 0 "s_register_operand" "")
2967 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2968 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2969 (match_operand:SI 3 "arm_rhs_operand" "")))
2970 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2971 "TARGET_32BIT"
9c08d1fa 2972 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2973 (not:SI (match_dup 3))))
2974 (set (match_dup 0) (not:SI (match_dup 4)))]
2975 ""
2976)
2977
f7fbdd4a 2978(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2979 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 2980 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 2981 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2982 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2983 "TARGET_32BIT"
40dbec34 2984 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2985 [(set_attr "length" "8")
25f905c2 2986 (set_attr "ce_count" "2")
0d66636f 2987 (set_attr "predicable" "yes")]
cffb2a26 2988)
9c08d1fa 2989
25f905c2 2990; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2991; insns are available?
d7863cfe 2992(define_split
2993 [(set (match_operand:SI 0 "s_register_operand" "")
2994 (match_operator:SI 1 "logical_binary_operator"
2995 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2996 (match_operand:SI 3 "const_int_operand" "")
2997 (match_operand:SI 4 "const_int_operand" ""))
2998 (match_operator:SI 9 "logical_binary_operator"
2999 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3000 (match_operand:SI 6 "const_int_operand" ""))
3001 (match_operand:SI 7 "s_register_operand" "")])]))
3002 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3003 "TARGET_32BIT
d7863cfe 3004 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3005 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3006 [(set (match_dup 8)
3007 (match_op_dup 1
3008 [(ashift:SI (match_dup 2) (match_dup 4))
3009 (match_dup 5)]))
3010 (set (match_dup 0)
3011 (match_op_dup 1
3012 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3013 (match_dup 7)]))]
3014 "
3015 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3016")
3017
3018(define_split
3019 [(set (match_operand:SI 0 "s_register_operand" "")
3020 (match_operator:SI 1 "logical_binary_operator"
3021 [(match_operator:SI 9 "logical_binary_operator"
3022 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3023 (match_operand:SI 6 "const_int_operand" ""))
3024 (match_operand:SI 7 "s_register_operand" "")])
3025 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3026 (match_operand:SI 3 "const_int_operand" "")
3027 (match_operand:SI 4 "const_int_operand" ""))]))
3028 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3029 "TARGET_32BIT
d7863cfe 3030 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3031 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3032 [(set (match_dup 8)
3033 (match_op_dup 1
3034 [(ashift:SI (match_dup 2) (match_dup 4))
3035 (match_dup 5)]))
3036 (set (match_dup 0)
3037 (match_op_dup 1
3038 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3039 (match_dup 7)]))]
3040 "
3041 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3042")
3043
3044(define_split
3045 [(set (match_operand:SI 0 "s_register_operand" "")
3046 (match_operator:SI 1 "logical_binary_operator"
3047 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3048 (match_operand:SI 3 "const_int_operand" "")
3049 (match_operand:SI 4 "const_int_operand" ""))
3050 (match_operator:SI 9 "logical_binary_operator"
3051 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3052 (match_operand:SI 6 "const_int_operand" ""))
3053 (match_operand:SI 7 "s_register_operand" "")])]))
3054 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3055 "TARGET_32BIT
d7863cfe 3056 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3057 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3058 [(set (match_dup 8)
3059 (match_op_dup 1
3060 [(ashift:SI (match_dup 2) (match_dup 4))
3061 (match_dup 5)]))
3062 (set (match_dup 0)
3063 (match_op_dup 1
3064 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3065 (match_dup 7)]))]
3066 "
3067 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3068")
3069
3070(define_split
3071 [(set (match_operand:SI 0 "s_register_operand" "")
3072 (match_operator:SI 1 "logical_binary_operator"
3073 [(match_operator:SI 9 "logical_binary_operator"
3074 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3075 (match_operand:SI 6 "const_int_operand" ""))
3076 (match_operand:SI 7 "s_register_operand" "")])
3077 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3078 (match_operand:SI 3 "const_int_operand" "")
3079 (match_operand:SI 4 "const_int_operand" ""))]))
3080 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3081 "TARGET_32BIT
d7863cfe 3082 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3083 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3084 [(set (match_dup 8)
3085 (match_op_dup 1
3086 [(ashift:SI (match_dup 2) (match_dup 4))
3087 (match_dup 5)]))
3088 (set (match_dup 0)
3089 (match_op_dup 1
3090 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3091 (match_dup 7)]))]
3092 "
3093 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3094")
9c08d1fa 3095\f
3096
3097;; Minimum and maximum insns
3098
8b9dc177 3099(define_expand "smaxsi3"
3100 [(parallel [
3101 (set (match_operand:SI 0 "s_register_operand" "")
3102 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3103 (match_operand:SI 2 "arm_rhs_operand" "")))
3104 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3105 "TARGET_32BIT"
8b9dc177 3106 "
8774928b 3107 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3108 {
3109 /* No need for a clobber of the condition code register here. */
3110 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3111 gen_rtx_SMAX (SImode, operands[1],
3112 operands[2])));
3113 DONE;
3114 }
3115")
3116
3117(define_insn "*smax_0"
3118 [(set (match_operand:SI 0 "s_register_operand" "=r")
3119 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3120 (const_int 0)))]
25f905c2 3121 "TARGET_32BIT"
8b9dc177 3122 "bic%?\\t%0, %1, %1, asr #31"
3123 [(set_attr "predicable" "yes")]
3124)
3125
8774928b 3126(define_insn "*smax_m1"
3127 [(set (match_operand:SI 0 "s_register_operand" "=r")
3128 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3129 (const_int -1)))]
25f905c2 3130 "TARGET_32BIT"
8774928b 3131 "orr%?\\t%0, %1, %1, asr #31"
3132 [(set_attr "predicable" "yes")]
3133)
3134
25f905c2 3135(define_insn "*arm_smax_insn"
8b9dc177 3136 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3137 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3138 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3139 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3140 "TARGET_ARM"
e2348bcb 3141 "@
3142 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3143 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3144 [(set_attr "conds" "clob")
8b9dc177 3145 (set_attr "length" "8,12")]
cffb2a26 3146)
9c08d1fa 3147
8b9dc177 3148(define_expand "sminsi3"
3149 [(parallel [
3150 (set (match_operand:SI 0 "s_register_operand" "")
3151 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3152 (match_operand:SI 2 "arm_rhs_operand" "")))
3153 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3154 "TARGET_32BIT"
8b9dc177 3155 "
3156 if (operands[2] == const0_rtx)
3157 {
3158 /* No need for a clobber of the condition code register here. */
3159 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3160 gen_rtx_SMIN (SImode, operands[1],
3161 operands[2])));
3162 DONE;
3163 }
3164")
3165
3166(define_insn "*smin_0"
3167 [(set (match_operand:SI 0 "s_register_operand" "=r")
3168 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3169 (const_int 0)))]
25f905c2 3170 "TARGET_32BIT"
8b9dc177 3171 "and%?\\t%0, %1, %1, asr #31"
3172 [(set_attr "predicable" "yes")]
3173)
3174
25f905c2 3175(define_insn "*arm_smin_insn"
8b9dc177 3176 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3177 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3178 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3179 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3180 "TARGET_ARM"
e2348bcb 3181 "@
3182 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3183 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3184 [(set_attr "conds" "clob")
8b9dc177 3185 (set_attr "length" "8,12")]
0d66636f 3186)
9c08d1fa 3187
25f905c2 3188(define_expand "umaxsi3"
3189 [(parallel [
3190 (set (match_operand:SI 0 "s_register_operand" "")
3191 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3192 (match_operand:SI 2 "arm_rhs_operand" "")))
3193 (clobber (reg:CC CC_REGNUM))])]
3194 "TARGET_32BIT"
3195 ""
3196)
3197
3198(define_insn "*arm_umaxsi3"
9c08d1fa 3199 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3200 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3201 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3202 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3203 "TARGET_ARM"
e2348bcb 3204 "@
3205 cmp\\t%1, %2\;movcc\\t%0, %2
3206 cmp\\t%1, %2\;movcs\\t%0, %1
3207 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3208 [(set_attr "conds" "clob")
3209 (set_attr "length" "8,8,12")]
3210)
9c08d1fa 3211
25f905c2 3212(define_expand "uminsi3"
3213 [(parallel [
3214 (set (match_operand:SI 0 "s_register_operand" "")
3215 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3216 (match_operand:SI 2 "arm_rhs_operand" "")))
3217 (clobber (reg:CC CC_REGNUM))])]
3218 "TARGET_32BIT"
3219 ""
3220)
3221
3222(define_insn "*arm_uminsi3"
9c08d1fa 3223 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3224 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3225 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3226 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3227 "TARGET_ARM"
e2348bcb 3228 "@
3229 cmp\\t%1, %2\;movcs\\t%0, %2
3230 cmp\\t%1, %2\;movcc\\t%0, %1
3231 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3232 [(set_attr "conds" "clob")
3233 (set_attr "length" "8,8,12")]
3234)
9c08d1fa 3235
8a18b90c 3236(define_insn "*store_minmaxsi"
9c08d1fa 3237 [(set (match_operand:SI 0 "memory_operand" "=m")
3238 (match_operator:SI 3 "minmax_operator"
3239 [(match_operand:SI 1 "s_register_operand" "r")
3240 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3241 (clobber (reg:CC CC_REGNUM))]
25f905c2 3242 "TARGET_32BIT"
9c08d1fa 3243 "*
dc55b8a9 3244 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3245 operands[1], operands[2]);
e2348bcb 3246 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3247 if (TARGET_THUMB2)
3248 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3249 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3250 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3251 return \"\";
0d66636f 3252 "
3253 [(set_attr "conds" "clob")
25f905c2 3254 (set (attr "length")
3255 (if_then_else (eq_attr "is_thumb" "yes")
3256 (const_int 14)
3257 (const_int 12)))
0d66636f 3258 (set_attr "type" "store1")]
3259)
9c08d1fa 3260
8a18b90c 3261; Reject the frame pointer in operand[1], since reloading this after
3262; it has been eliminated can cause carnage.
f7fbdd4a 3263(define_insn "*minmax_arithsi"
9c08d1fa 3264 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3265 (match_operator:SI 4 "shiftable_operator"
3266 [(match_operator:SI 5 "minmax_operator"
3267 [(match_operand:SI 2 "s_register_operand" "r,r")
3268 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3269 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3270 (clobber (reg:CC CC_REGNUM))]
25f905c2 3271 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3272 "*
0d66636f 3273 {
3274 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3275 bool need_else;
3276
3277 if (which_alternative != 0 || operands[3] != const0_rtx
3278 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3279 need_else = true;
3280 else
3281 need_else = false;
0d66636f 3282
dc55b8a9 3283 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3284 operands[2], operands[3]);
0d66636f 3285 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3286 if (TARGET_THUMB2)
3287 {
3288 if (need_else)
3289 output_asm_insn (\"ite\\t%d5\", operands);
3290 else
3291 output_asm_insn (\"it\\t%d5\", operands);
3292 }
0d66636f 3293 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3294 if (need_else)
0d66636f 3295 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3296 return \"\";
215b30b3 3297 }"
0d66636f 3298 [(set_attr "conds" "clob")
25f905c2 3299 (set (attr "length")
3300 (if_then_else (eq_attr "is_thumb" "yes")
3301 (const_int 14)
3302 (const_int 12)))]
0d66636f 3303)
9c08d1fa 3304
b11cae9e 3305\f
3306;; Shift and rotation insns
3307
a2cd141b 3308(define_expand "ashldi3"
3309 [(set (match_operand:DI 0 "s_register_operand" "")
3310 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3311 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3312 "TARGET_32BIT"
a2cd141b 3313 "
3314 if (GET_CODE (operands[2]) == CONST_INT)
3315 {
3316 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3317 {
3318 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3319 DONE;
3320 }
3321 /* Ideally we shouldn't fail here if we could know that operands[1]
3322 ends up already living in an iwmmxt register. Otherwise it's
3323 cheaper to have the alternate code being generated than moving
1d60d981 3324 values to iwmmxt regs and back. */
a2cd141b 3325 FAIL;
3326 }
3327 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3328 FAIL;
3329 "
3330)
3331
3332(define_insn "arm_ashldi3_1bit"
50ad1bf9 3333 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3334 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3335 (const_int 1)))
3336 (clobber (reg:CC CC_REGNUM))]
25f905c2 3337 "TARGET_32BIT"
a2cd141b 3338 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3339 [(set_attr "conds" "clob")
3340 (set_attr "length" "8")]
3341)
3342
87b22bf7 3343(define_expand "ashlsi3"
cffb2a26 3344 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3345 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3346 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3347 "TARGET_EITHER"
87b22bf7 3348 "
3349 if (GET_CODE (operands[2]) == CONST_INT
3350 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3351 {
3352 emit_insn (gen_movsi (operands[0], const0_rtx));
3353 DONE;
3354 }
cffb2a26 3355 "
3356)
3357
25f905c2 3358(define_insn "*thumb1_ashlsi3"
cffb2a26 3359 [(set (match_operand:SI 0 "register_operand" "=l,l")
3360 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3361 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3362 "TARGET_THUMB1"
cffb2a26 3363 "lsl\\t%0, %1, %2"
747b7458 3364 [(set_attr "length" "2")
3365 (set_attr "conds" "set")])
b11cae9e 3366
a2cd141b 3367(define_expand "ashrdi3"
3368 [(set (match_operand:DI 0 "s_register_operand" "")
3369 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3370 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3371 "TARGET_32BIT"
a2cd141b 3372 "
3373 if (GET_CODE (operands[2]) == CONST_INT)
3374 {
3375 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3376 {
3377 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3378 DONE;
3379 }
3380 /* Ideally we shouldn't fail here if we could know that operands[1]
3381 ends up already living in an iwmmxt register. Otherwise it's
3382 cheaper to have the alternate code being generated than moving
1d60d981 3383 values to iwmmxt regs and back. */
a2cd141b 3384 FAIL;
3385 }
3386 else if (!TARGET_REALLY_IWMMXT)
3387 FAIL;
3388 "
3389)
3390
3391(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3392 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3393 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3394 (const_int 1)))
3395 (clobber (reg:CC CC_REGNUM))]
25f905c2 3396 "TARGET_32BIT"
a2cd141b 3397 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3398 [(set_attr "conds" "clob")
d2a518d1 3399 (set_attr "insn" "mov")
a2cd141b 3400 (set_attr "length" "8")]
3401)
3402
87b22bf7 3403(define_expand "ashrsi3"
cffb2a26 3404 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3405 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3406 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3407 "TARGET_EITHER"
87b22bf7 3408 "
3409 if (GET_CODE (operands[2]) == CONST_INT
3410 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3411 operands[2] = GEN_INT (31);
cffb2a26 3412 "
3413)
3414
25f905c2 3415(define_insn "*thumb1_ashrsi3"
cffb2a26 3416 [(set (match_operand:SI 0 "register_operand" "=l,l")
3417 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3418 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3419 "TARGET_THUMB1"
cffb2a26 3420 "asr\\t%0, %1, %2"
747b7458 3421 [(set_attr "length" "2")
3422 (set_attr "conds" "set")])
b11cae9e 3423
a2cd141b 3424(define_expand "lshrdi3"
3425 [(set (match_operand:DI 0 "s_register_operand" "")
3426 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3427 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3428 "TARGET_32BIT"
a2cd141b 3429 "
3430 if (GET_CODE (operands[2]) == CONST_INT)
3431 {
3432 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3433 {
3434 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3435 DONE;
3436 }
3437 /* Ideally we shouldn't fail here if we could know that operands[1]
3438 ends up already living in an iwmmxt register. Otherwise it's
3439 cheaper to have the alternate code being generated than moving
1d60d981 3440 values to iwmmxt regs and back. */
a2cd141b 3441 FAIL;
3442 }
3443 else if (!TARGET_REALLY_IWMMXT)
3444 FAIL;
3445 "
3446)
3447
3448(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3449 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3450 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3451 (const_int 1)))
3452 (clobber (reg:CC CC_REGNUM))]
25f905c2 3453 "TARGET_32BIT"
a2cd141b 3454 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3455 [(set_attr "conds" "clob")
d2a518d1 3456 (set_attr "insn" "mov")
a2cd141b 3457 (set_attr "length" "8")]
3458)
3459
87b22bf7 3460(define_expand "lshrsi3"
cffb2a26 3461 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3462 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3463 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3464 "TARGET_EITHER"
87b22bf7 3465 "
3466 if (GET_CODE (operands[2]) == CONST_INT
3467 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3468 {
3469 emit_insn (gen_movsi (operands[0], const0_rtx));
3470 DONE;
3471 }
cffb2a26 3472 "
3473)
3474
25f905c2 3475(define_insn "*thumb1_lshrsi3"
cffb2a26 3476 [(set (match_operand:SI 0 "register_operand" "=l,l")
3477 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3478 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3479 "TARGET_THUMB1"
cffb2a26 3480 "lsr\\t%0, %1, %2"
747b7458 3481 [(set_attr "length" "2")
3482 (set_attr "conds" "set")])
b11cae9e 3483
87b22bf7 3484(define_expand "rotlsi3"
cffb2a26 3485 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3486 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3487 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3488 "TARGET_32BIT"
87b22bf7 3489 "
3490 if (GET_CODE (operands[2]) == CONST_INT)
3491 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3492 else
b11cae9e 3493 {
87b22bf7 3494 rtx reg = gen_reg_rtx (SImode);
3495 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3496 operands[2] = reg;
b11cae9e 3497 }
cffb2a26 3498 "
3499)
9c08d1fa 3500
87b22bf7 3501(define_expand "rotrsi3"
cffb2a26 3502 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3503 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3504 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3505 "TARGET_EITHER"
87b22bf7 3506 "
25f905c2 3507 if (TARGET_32BIT)
cffb2a26 3508 {
3509 if (GET_CODE (operands[2]) == CONST_INT
3510 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3511 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3512 }
25f905c2 3513 else /* TARGET_THUMB1 */
cffb2a26 3514 {
3515 if (GET_CODE (operands [2]) == CONST_INT)
3516 operands [2] = force_reg (SImode, operands[2]);
3517 }
3518 "
3519)
87b22bf7 3520
25f905c2 3521(define_insn "*thumb1_rotrsi3"
cffb2a26 3522 [(set (match_operand:SI 0 "register_operand" "=l")
3523 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3524 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3525 "TARGET_THUMB1"
cffb2a26 3526 "ror\\t%0, %0, %2"
3527 [(set_attr "length" "2")]
3528)
3529
3530(define_insn "*arm_shiftsi3"
3531 [(set (match_operand:SI 0 "s_register_operand" "=r")
3532 (match_operator:SI 3 "shift_operator"
3533 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3534 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3535 "TARGET_32BIT"
3536 "* return arm_output_shift(operands, 0);"
344495ea 3537 [(set_attr "predicable" "yes")
331beb1a 3538 (set_attr "shift" "1")
a2cd141b 3539 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3540 (const_string "alu_shift")
3541 (const_string "alu_shift_reg")))]
6c4c2133 3542)
87b22bf7 3543
f7fbdd4a 3544(define_insn "*shiftsi3_compare0"
bd5b4116 3545 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3546 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3547 [(match_operand:SI 1 "s_register_operand" "r")
3548 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3549 (const_int 0)))
3550 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3551 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3552 "TARGET_32BIT"
3553 "* return arm_output_shift(operands, 1);"
344495ea 3554 [(set_attr "conds" "set")
331beb1a 3555 (set_attr "shift" "1")
a2cd141b 3556 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3557 (const_string "alu_shift")
3558 (const_string "alu_shift_reg")))]
0d66636f 3559)
9c08d1fa 3560
f7fbdd4a 3561(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3562 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3563 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3564 [(match_operand:SI 1 "s_register_operand" "r")
3565 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3566 (const_int 0)))
3567 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3568 "TARGET_32BIT"
3569 "* return arm_output_shift(operands, 1);"
344495ea 3570 [(set_attr "conds" "set")
a2cd141b 3571 (set_attr "shift" "1")]
0d66636f 3572)
9c08d1fa 3573
d5d4dc8d 3574(define_insn "*not_shiftsi"
3575 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3576 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3577 [(match_operand:SI 1 "s_register_operand" "r,r")
3578 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3579 "TARGET_32BIT"
6c4c2133 3580 "mvn%?\\t%0, %1%S3"
344495ea 3581 [(set_attr "predicable" "yes")
331beb1a 3582 (set_attr "shift" "1")
d2a518d1 3583 (set_attr "insn" "mvn")
d5d4dc8d 3584 (set_attr "arch" "32,a")
3585 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3586
d5d4dc8d 3587(define_insn "*not_shiftsi_compare0"
bd5b4116 3588 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3589 (compare:CC_NOOV
3590 (not:SI (match_operator:SI 3 "shift_operator"
3591 [(match_operand:SI 1 "s_register_operand" "r,r")
3592 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3593 (const_int 0)))
3594 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3595 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3596 "TARGET_32BIT"
25f905c2 3597 "mvn%.\\t%0, %1%S3"
344495ea 3598 [(set_attr "conds" "set")
331beb1a 3599 (set_attr "shift" "1")
d2a518d1 3600 (set_attr "insn" "mvn")
d5d4dc8d 3601 (set_attr "arch" "32,a")
3602 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3603
d5d4dc8d 3604(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3605 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3606 (compare:CC_NOOV
3607 (not:SI (match_operator:SI 3 "shift_operator"
3608 [(match_operand:SI 1 "s_register_operand" "r,r")
3609 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3610 (const_int 0)))
3611 (clobber (match_scratch:SI 0 "=r,r"))]
3612 "TARGET_32BIT"
25f905c2 3613 "mvn%.\\t%0, %1%S3"
344495ea 3614 [(set_attr "conds" "set")
331beb1a 3615 (set_attr "shift" "1")
d2a518d1 3616 (set_attr "insn" "mvn")
d5d4dc8d 3617 (set_attr "arch" "32,a")
3618 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3619
cffb2a26 3620;; We don't really have extzv, but defining this using shifts helps
3621;; to reduce register pressure later on.
3622
3623(define_expand "extzv"
3624 [(set (match_dup 4)
3625 (ashift:SI (match_operand:SI 1 "register_operand" "")
3626 (match_operand:SI 2 "const_int_operand" "")))
3627 (set (match_operand:SI 0 "register_operand" "")
3628 (lshiftrt:SI (match_dup 4)
215b30b3 3629 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3630 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3631 "
3632 {
3633 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3634 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3635
8b054d5a 3636 if (arm_arch_thumb2)
3637 {
3638 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3639 operands[3]));
3640 DONE;
3641 }
3642
cffb2a26 3643 operands[3] = GEN_INT (rshift);
3644
3645 if (lshift == 0)
3646 {
3647 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3648 DONE;
3649 }
3650
3651 operands[2] = GEN_INT (lshift);
3652 operands[4] = gen_reg_rtx (SImode);
215b30b3 3653 }"
cffb2a26 3654)
3655
8b054d5a 3656(define_insn "extv"
3657 [(set (match_operand:SI 0 "s_register_operand" "=r")
3658 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3659 (match_operand:SI 2 "const_int_operand" "M")
3660 (match_operand:SI 3 "const_int_operand" "M")))]
3661 "arm_arch_thumb2"
3662 "sbfx%?\t%0, %1, %3, %2"
3663 [(set_attr "length" "4")
3664 (set_attr "predicable" "yes")]
3665)
3666
3667(define_insn "extzv_t2"
3668 [(set (match_operand:SI 0 "s_register_operand" "=r")
3669 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3670 (match_operand:SI 2 "const_int_operand" "M")
3671 (match_operand:SI 3 "const_int_operand" "M")))]
3672 "arm_arch_thumb2"
3673 "ubfx%?\t%0, %1, %3, %2"
3674 [(set_attr "length" "4")
3675 (set_attr "predicable" "yes")]
3676)
3677
b11cae9e 3678\f
3679;; Unary arithmetic insns
3680
cffb2a26 3681(define_expand "negdi2"
3682 [(parallel
8135a42b 3683 [(set (match_operand:DI 0 "s_register_operand" "")
3684 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3685 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3686 "TARGET_EITHER"
8135a42b 3687 ""
cffb2a26 3688)
3689
3690;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 3691;; The first alternative allows the common case of a *full* overlap.
cffb2a26 3692(define_insn "*arm_negdi2"
3693 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3694 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 3695 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3696 "TARGET_ARM"
97499065 3697 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3698 [(set_attr "conds" "clob")
3699 (set_attr "length" "8")]
3700)
b11cae9e 3701
25f905c2 3702(define_insn "*thumb1_negdi2"
8135a42b 3703 [(set (match_operand:DI 0 "register_operand" "=&l")
3704 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3705 (clobber (reg:CC CC_REGNUM))]
25f905c2 3706 "TARGET_THUMB1"
cffb2a26 3707 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3708 [(set_attr "length" "6")]
3709)
3710
3711(define_expand "negsi2"
3712 [(set (match_operand:SI 0 "s_register_operand" "")
3713 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3714 "TARGET_EITHER"
b11cae9e 3715 ""
cffb2a26 3716)
3717
3718(define_insn "*arm_negsi2"
3719 [(set (match_operand:SI 0 "s_register_operand" "=r")
3720 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3721 "TARGET_32BIT"
cffb2a26 3722 "rsb%?\\t%0, %1, #0"
0d66636f 3723 [(set_attr "predicable" "yes")]
cffb2a26 3724)
3725
25f905c2 3726(define_insn "*thumb1_negsi2"
cffb2a26 3727 [(set (match_operand:SI 0 "register_operand" "=l")
3728 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3729 "TARGET_THUMB1"
cffb2a26 3730 "neg\\t%0, %1"
3731 [(set_attr "length" "2")]
3732)
b11cae9e 3733
604f3a0a 3734(define_expand "negsf2"
3735 [(set (match_operand:SF 0 "s_register_operand" "")
3736 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3737 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3738 ""
3739)
3740
3741(define_expand "negdf2"
3742 [(set (match_operand:DF 0 "s_register_operand" "")
3743 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3744 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3745 "")
3746
9c08d1fa 3747;; abssi2 doesn't really clobber the condition codes if a different register
3748;; is being set. To keep things simple, assume during rtl manipulations that
3749;; it does, but tell the final scan operator the truth. Similarly for
3750;; (neg (abs...))
3751
604f3a0a 3752(define_expand "abssi2"
3753 [(parallel
3754 [(set (match_operand:SI 0 "s_register_operand" "")
3755 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3756 (clobber (match_dup 2))])]
3757 "TARGET_EITHER"
3758 "
25f905c2 3759 if (TARGET_THUMB1)
ba156559 3760 operands[2] = gen_rtx_SCRATCH (SImode);
3761 else
3762 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3763")
604f3a0a 3764
7d57ec45 3765(define_insn "*arm_abssi2"
ba156559 3766 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3767 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3768 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3769 "TARGET_ARM"
e2348bcb 3770 "@
3771 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3772 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3773 [(set_attr "conds" "clob,*")
331beb1a 3774 (set_attr "shift" "1")
0d66636f 3775 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3776 (set_attr "length" "8")]
3777)
9c08d1fa 3778
25f905c2 3779(define_insn_and_split "*thumb1_abssi2"
ba156559 3780 [(set (match_operand:SI 0 "s_register_operand" "=l")
3781 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3782 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3783 "TARGET_THUMB1"
ba156559 3784 "#"
25f905c2 3785 "TARGET_THUMB1 && reload_completed"
ba156559 3786 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3787 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3788 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3789 ""
3790 [(set_attr "length" "6")]
3791)
3792
3793(define_insn "*arm_neg_abssi2"
9c08d1fa 3794 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3795 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3796 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3797 "TARGET_ARM"
e2348bcb 3798 "@
3799 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3800 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3801 [(set_attr "conds" "clob,*")
331beb1a 3802 (set_attr "shift" "1")
0d66636f 3803 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3804 (set_attr "length" "8")]
3805)
b11cae9e 3806
25f905c2 3807(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3808 [(set (match_operand:SI 0 "s_register_operand" "=l")
3809 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3810 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3811 "TARGET_THUMB1"
ba156559 3812 "#"
25f905c2 3813 "TARGET_THUMB1 && reload_completed"
ba156559 3814 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3815 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3816 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3817 ""
3818 [(set_attr "length" "6")]
3819)
3820
604f3a0a 3821(define_expand "abssf2"
3822 [(set (match_operand:SF 0 "s_register_operand" "")
3823 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3824 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3825 "")
3826
604f3a0a 3827(define_expand "absdf2"
3828 [(set (match_operand:DF 0 "s_register_operand" "")
3829 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3830 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3831 "")
3832
7db9af5d 3833(define_expand "sqrtsf2"
3834 [(set (match_operand:SF 0 "s_register_operand" "")
3835 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3836 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3837 "")
9c08d1fa 3838
7db9af5d 3839(define_expand "sqrtdf2"
3840 [(set (match_operand:DF 0 "s_register_operand" "")
3841 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3842 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3843 "")
9c08d1fa 3844
a0f94409 3845(define_insn_and_split "one_cmpldi2"
9c08d1fa 3846 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3847 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3848 "TARGET_32BIT"
f6ebffac 3849 "#"
25f905c2 3850 "TARGET_32BIT && reload_completed"
a0f94409 3851 [(set (match_dup 0) (not:SI (match_dup 1)))
3852 (set (match_dup 2) (not:SI (match_dup 3)))]
3853 "
3854 {
3855 operands[2] = gen_highpart (SImode, operands[0]);
3856 operands[0] = gen_lowpart (SImode, operands[0]);
3857 operands[3] = gen_highpart (SImode, operands[1]);
3858 operands[1] = gen_lowpart (SImode, operands[1]);
3859 }"
0d66636f 3860 [(set_attr "length" "8")
3861 (set_attr "predicable" "yes")]
cffb2a26 3862)
b11cae9e 3863
cffb2a26 3864(define_expand "one_cmplsi2"
3865 [(set (match_operand:SI 0 "s_register_operand" "")
3866 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3867 "TARGET_EITHER"
b11cae9e 3868 ""
cffb2a26 3869)
3870
3871(define_insn "*arm_one_cmplsi2"
3872 [(set (match_operand:SI 0 "s_register_operand" "=r")
3873 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3874 "TARGET_32BIT"
cffb2a26 3875 "mvn%?\\t%0, %1"
d2a518d1 3876 [(set_attr "predicable" "yes")
3877 (set_attr "insn" "mvn")]
cffb2a26 3878)
3879
25f905c2 3880(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3881 [(set (match_operand:SI 0 "register_operand" "=l")
3882 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3883 "TARGET_THUMB1"
cffb2a26 3884 "mvn\\t%0, %1"
d2a518d1 3885 [(set_attr "length" "2")
3886 (set_attr "insn" "mvn")]
cffb2a26 3887)
9c08d1fa 3888
f7fbdd4a 3889(define_insn "*notsi_compare0"
bd5b4116 3890 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3891 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3892 (const_int 0)))
3893 (set (match_operand:SI 0 "s_register_operand" "=r")
3894 (not:SI (match_dup 1)))]
25f905c2 3895 "TARGET_32BIT"
3896 "mvn%.\\t%0, %1"
d2a518d1 3897 [(set_attr "conds" "set")
3898 (set_attr "insn" "mvn")]
cffb2a26 3899)
9c08d1fa 3900
f7fbdd4a 3901(define_insn "*notsi_compare0_scratch"
bd5b4116 3902 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3903 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3904 (const_int 0)))
3905 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3906 "TARGET_32BIT"
3907 "mvn%.\\t%0, %1"
d2a518d1 3908 [(set_attr "conds" "set")
3909 (set_attr "insn" "mvn")]
cffb2a26 3910)
b11cae9e 3911\f
3912;; Fixed <--> Floating conversion insns
3913
9b8516be 3914(define_expand "floatsihf2"
3915 [(set (match_operand:HF 0 "general_operand" "")
3916 (float:HF (match_operand:SI 1 "general_operand" "")))]
3917 "TARGET_EITHER"
3918 "
3919 {
3920 rtx op1 = gen_reg_rtx (SFmode);
3921 expand_float (op1, operands[1], 0);
3922 op1 = convert_to_mode (HFmode, op1, 0);
3923 emit_move_insn (operands[0], op1);
3924 DONE;
3925 }"
3926)
3927
3928(define_expand "floatdihf2"
3929 [(set (match_operand:HF 0 "general_operand" "")
3930 (float:HF (match_operand:DI 1 "general_operand" "")))]
3931 "TARGET_EITHER"
3932 "
3933 {
3934 rtx op1 = gen_reg_rtx (SFmode);
3935 expand_float (op1, operands[1], 0);
3936 op1 = convert_to_mode (HFmode, op1, 0);
3937 emit_move_insn (operands[0], op1);
3938 DONE;
3939 }"
3940)
3941
604f3a0a 3942(define_expand "floatsisf2"
3943 [(set (match_operand:SF 0 "s_register_operand" "")
3944 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3945 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3946 "
a2cd141b 3947 if (TARGET_MAVERICK)
604f3a0a 3948 {
3949 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3950 DONE;
3951 }
3952")
3953
604f3a0a 3954(define_expand "floatsidf2"
3955 [(set (match_operand:DF 0 "s_register_operand" "")
3956 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 3957 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3958 "
a2cd141b 3959 if (TARGET_MAVERICK)
604f3a0a 3960 {
3961 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3962 DONE;
3963 }
3964")
3965
9b8516be 3966(define_expand "fix_trunchfsi2"
3967 [(set (match_operand:SI 0 "general_operand" "")
3968 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3969 "TARGET_EITHER"
3970 "
3971 {
3972 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3973 expand_fix (operands[0], op1, 0);
3974 DONE;
3975 }"
3976)
3977
3978(define_expand "fix_trunchfdi2"
3979 [(set (match_operand:DI 0 "general_operand" "")
3980 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3981 "TARGET_EITHER"
3982 "
3983 {
3984 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3985 expand_fix (operands[0], op1, 0);
3986 DONE;
3987 }"
3988)
3989
604f3a0a 3990(define_expand "fix_truncsfsi2"
3991 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3992 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3993 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3994 "
a2cd141b 3995 if (TARGET_MAVERICK)
604f3a0a 3996 {
3997 if (!cirrus_fp_register (operands[0], SImode))
3998 operands[0] = force_reg (SImode, operands[0]);
3999 if (!cirrus_fp_register (operands[1], SFmode))
4000 operands[1] = force_reg (SFmode, operands[0]);
4001 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4002 DONE;
4003 }
4004")
4005
604f3a0a 4006(define_expand "fix_truncdfsi2"
4007 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4008 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4009 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4010 "
a2cd141b 4011 if (TARGET_MAVERICK)
604f3a0a 4012 {
4013 if (!cirrus_fp_register (operands[1], DFmode))
4014 operands[1] = force_reg (DFmode, operands[0]);
4015 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4016 DONE;
4017 }
4018")
4019
f544c6d2 4020;; Truncation insns
b11cae9e 4021
604f3a0a 4022(define_expand "truncdfsf2"
4023 [(set (match_operand:SF 0 "s_register_operand" "")
4024 (float_truncate:SF
4025 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4026 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4027 ""
4028)
9b8516be 4029
4030/* DFmode -> HFmode conversions have to go through SFmode. */
4031(define_expand "truncdfhf2"
4032 [(set (match_operand:HF 0 "general_operand" "")
4033 (float_truncate:HF
4034 (match_operand:DF 1 "general_operand" "")))]
4035 "TARGET_EITHER"
4036 "
4037 {
4038 rtx op1;
4039 op1 = convert_to_mode (SFmode, operands[1], 0);
4040 op1 = convert_to_mode (HFmode, op1, 0);
4041 emit_move_insn (operands[0], op1);
4042 DONE;
4043 }"
4044)
b11cae9e 4045\f
9c08d1fa 4046;; Zero and sign extension instructions.
b11cae9e 4047
848e66ac 4048(define_insn "zero_extend<mode>di2"
4049 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4050 (zero_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4051 "<qhs_extenddi_cstr>")))]
848e66ac 4052 "TARGET_32BIT <qhs_zextenddi_cond>"
4053 "#"
4054 [(set_attr "length" "8")
4055 (set_attr "ce_count" "2")
4056 (set_attr "predicable" "yes")]
25f905c2 4057)
4058
848e66ac 4059(define_insn "extend<mode>di2"
9c08d1fa 4060 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4061 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4062 "<qhs_extenddi_cstr>")))]
848e66ac 4063 "TARGET_32BIT <qhs_sextenddi_cond>"
4064 "#"
0d66636f 4065 [(set_attr "length" "8")
848e66ac 4066 (set_attr "ce_count" "2")
4067 (set_attr "shift" "1")
0d66636f 4068 (set_attr "predicable" "yes")]
4069)
9c08d1fa 4070
848e66ac 4071;; Splits for all extensions to DImode
4072(define_split
4073 [(set (match_operand:DI 0 "s_register_operand" "")
4074 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4075 "TARGET_32BIT"
848e66ac 4076 [(set (match_dup 0) (match_dup 1))]
4077{
848e66ac 4078 rtx lo_part = gen_lowpart (SImode, operands[0]);
4079 enum machine_mode src_mode = GET_MODE (operands[1]);
4080
4081 if (REG_P (operands[0])
4082 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4083 emit_clobber (operands[0]);
4084 if (!REG_P (lo_part) || src_mode != SImode
4085 || !rtx_equal_p (lo_part, operands[1]))
4086 {
4087 if (src_mode == SImode)
4088 emit_move_insn (lo_part, operands[1]);
4089 else
4090 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4091 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4092 operands[1] = lo_part;
4093 }
4094 operands[0] = gen_highpart (SImode, operands[0]);
4095 operands[1] = const0_rtx;
4096})
9c08d1fa 4097
848e66ac 4098(define_split
25f905c2 4099 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4100 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4101 "TARGET_32BIT"
848e66ac 4102 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4103{
4104 rtx lo_part = gen_lowpart (SImode, operands[0]);
4105 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4106
848e66ac 4107 if (REG_P (operands[0])
4108 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4109 emit_clobber (operands[0]);
4110
4111 if (!REG_P (lo_part) || src_mode != SImode
4112 || !rtx_equal_p (lo_part, operands[1]))
4113 {
4114 if (src_mode == SImode)
4115 emit_move_insn (lo_part, operands[1]);
4116 else
4117 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4118 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4119 operands[1] = lo_part;
4120 }
4121 operands[0] = gen_highpart (SImode, operands[0]);
4122})
9c08d1fa 4123
4124(define_expand "zero_extendhisi2"
ef51b8e1 4125 [(set (match_operand:SI 0 "s_register_operand" "")
4126 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4127 "TARGET_EITHER"
ef51b8e1 4128{
4129 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4130 {
ef51b8e1 4131 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4132 DONE;
25f7a26e 4133 }
ef51b8e1 4134 if (!arm_arch6 && !MEM_P (operands[1]))
4135 {
4136 rtx t = gen_lowpart (SImode, operands[1]);
4137 rtx tmp = gen_reg_rtx (SImode);
4138 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4139 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4140 DONE;
4141 }
4142})
9c08d1fa 4143
ef51b8e1 4144(define_split
b146458f 4145 [(set (match_operand:SI 0 "s_register_operand" "")
4146 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4147 "!TARGET_THUMB2 && !arm_arch6"
4148 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4149 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4150{
4151 operands[2] = gen_lowpart (SImode, operands[1]);
4152})
4153
4154(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4155 [(set (match_operand:SI 0 "register_operand" "=l,l")
4156 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4157 "TARGET_THUMB1"
848e66ac 4158{
a2cd141b 4159 rtx mem;
4160
ef51b8e1 4161 if (which_alternative == 0 && arm_arch6)
848e66ac 4162 return "uxth\t%0, %1";
ef51b8e1 4163 if (which_alternative == 0)
848e66ac 4164 return "#";
a2cd141b 4165
4166 mem = XEXP (operands[1], 0);
4167
4168 if (GET_CODE (mem) == CONST)
4169 mem = XEXP (mem, 0);
4170
a2cd141b 4171 if (GET_CODE (mem) == PLUS)
4172 {
4173 rtx a = XEXP (mem, 0);
a2cd141b 4174
4175 /* This can happen due to bugs in reload. */
4176 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4177 {
4178 rtx ops[2];
4179 ops[0] = operands[0];
4180 ops[1] = a;
4181
848e66ac 4182 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4183
4184 XEXP (mem, 0) = operands[0];
4185 }
a2cd141b 4186 }
4187
848e66ac 4188 return "ldrh\t%0, %1";
4189}
ef51b8e1 4190 [(set_attr_alternative "length"
4191 [(if_then_else (eq_attr "is_arch6" "yes")
4192 (const_int 2) (const_int 4))
4193 (const_int 4)])
848e66ac 4194 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4195)
4196
cffb2a26 4197(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4198 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4199 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4200 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4201 "@
4202 #
4203 ldr%(h%)\\t%0, %1"
4204 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4205 (set_attr "predicable" "yes")]
cffb2a26 4206)
f7fbdd4a 4207
a2cd141b 4208(define_insn "*arm_zero_extendhisi2_v6"
4209 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4210 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4211 "TARGET_ARM && arm_arch6"
4212 "@
4213 uxth%?\\t%0, %1
25f905c2 4214 ldr%(h%)\\t%0, %1"
a2cd141b 4215 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4216 (set_attr "predicable" "yes")]
a2cd141b 4217)
4218
4219(define_insn "*arm_zero_extendhisi2addsi"
4220 [(set (match_operand:SI 0 "s_register_operand" "=r")
4221 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4222 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4223 "TARGET_INT_SIMD"
a2cd141b 4224 "uxtah%?\\t%0, %2, %1"
4225 [(set_attr "type" "alu_shift")
4226 (set_attr "predicable" "yes")]
4227)
4228
87b22bf7 4229(define_expand "zero_extendqisi2"
cffb2a26 4230 [(set (match_operand:SI 0 "s_register_operand" "")
4231 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4232 "TARGET_EITHER"
ef51b8e1 4233{
4234 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4235 {
ef51b8e1 4236 emit_insn (gen_andsi3 (operands[0],
4237 gen_lowpart (SImode, operands[1]),
4238 GEN_INT (255)));
4239 DONE;
4240 }
4241 if (!arm_arch6 && !MEM_P (operands[1]))
4242 {
4243 rtx t = gen_lowpart (SImode, operands[1]);
4244 rtx tmp = gen_reg_rtx (SImode);
4245 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4246 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4247 DONE;
4248 }
4249})
cffb2a26 4250
ef51b8e1 4251(define_split
b146458f 4252 [(set (match_operand:SI 0 "s_register_operand" "")
4253 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4254 "!arm_arch6"
4255 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4256 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4257{
4258 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4259 if (TARGET_ARM)
4260 {
4261 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4262 DONE;
4263 }
ef51b8e1 4264})
9c08d1fa 4265
25f905c2 4266(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4267 [(set (match_operand:SI 0 "register_operand" "=l,l")
4268 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4269 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4270 "@
4271 #
4272 ldrb\\t%0, %1"
4273 [(set_attr "length" "4,2")
4274 (set_attr "type" "alu_shift,load_byte")
4275 (set_attr "pool_range" "*,32")]
cffb2a26 4276)
4277
25f905c2 4278(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4279 [(set (match_operand:SI 0 "register_operand" "=l,l")
4280 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4281 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4282 "@
4283 uxtb\\t%0, %1
4284 ldrb\\t%0, %1"
848e66ac 4285 [(set_attr "length" "2")
4286 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4287)
4288
cffb2a26 4289(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4290 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4291 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4292 "TARGET_ARM && !arm_arch6"
ef51b8e1 4293 "@
4294 #
4295 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4296 [(set_attr "length" "8,4")
4297 (set_attr "type" "alu_shift,load_byte")
848e66ac 4298 (set_attr "predicable" "yes")]
cffb2a26 4299)
87b22bf7 4300
a2cd141b 4301(define_insn "*arm_zero_extendqisi2_v6"
4302 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4303 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4304 "TARGET_ARM && arm_arch6"
4305 "@
25f905c2 4306 uxtb%(%)\\t%0, %1
4307 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4308 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4309 (set_attr "predicable" "yes")]
a2cd141b 4310)
4311
4312(define_insn "*arm_zero_extendqisi2addsi"
4313 [(set (match_operand:SI 0 "s_register_operand" "=r")
4314 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4315 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4316 "TARGET_INT_SIMD"
a2cd141b 4317 "uxtab%?\\t%0, %2, %1"
4318 [(set_attr "predicable" "yes")
bcaec148 4319 (set_attr "insn" "xtab")
a2cd141b 4320 (set_attr "type" "alu_shift")]
4321)
4322
87b22bf7 4323(define_split
4324 [(set (match_operand:SI 0 "s_register_operand" "")
4325 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4326 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4327 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4328 [(set (match_dup 2) (match_dup 1))
4329 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4330 ""
4331)
9c08d1fa 4332
8a4d25d6 4333(define_split
4334 [(set (match_operand:SI 0 "s_register_operand" "")
4335 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4336 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4337 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4338 [(set (match_dup 2) (match_dup 1))
4339 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4340 ""
4341)
4342
1c274529 4343
4344(define_split
4345 [(set (match_operand:SI 0 "s_register_operand" "")
4346 (ior_xor:SI (and:SI (ashift:SI
4347 (match_operand:SI 1 "s_register_operand" "")
4348 (match_operand:SI 2 "const_int_operand" ""))
4349 (match_operand:SI 3 "const_int_operand" ""))
4350 (zero_extend:SI
4351 (match_operator 5 "subreg_lowpart_operator"
4352 [(match_operand:SI 4 "s_register_operand" "")]))))]
4353 "TARGET_32BIT
63787642 4354 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4355 == (GET_MODE_MASK (GET_MODE (operands[5]))
4356 & (GET_MODE_MASK (GET_MODE (operands[5]))
4357 << (INTVAL (operands[2])))))"
4358 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4359 (match_dup 4)))
4360 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4361 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4362)
4363
f7fbdd4a 4364(define_insn "*compareqi_eq0"
bd5b4116 4365 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4366 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4367 (const_int 0)))]
25f905c2 4368 "TARGET_32BIT"
87b22bf7 4369 "tst\\t%0, #255"
cffb2a26 4370 [(set_attr "conds" "set")]
4371)
b11cae9e 4372
b11cae9e 4373(define_expand "extendhisi2"
ef51b8e1 4374 [(set (match_operand:SI 0 "s_register_operand" "")
4375 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4376 "TARGET_EITHER"
ef51b8e1 4377{
4378 if (TARGET_THUMB1)
4379 {
4380 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4381 DONE;
4382 }
4383 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4384 {
4385 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4386 DONE;
4387 }
ed29c566 4388
ef51b8e1 4389 if (!arm_arch6 && !MEM_P (operands[1]))
4390 {
4391 rtx t = gen_lowpart (SImode, operands[1]);
4392 rtx tmp = gen_reg_rtx (SImode);
4393 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4394 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4395 DONE;
4396 }
4397})
cffb2a26 4398
ef51b8e1 4399(define_split
4400 [(parallel
4401 [(set (match_operand:SI 0 "register_operand" "")
4402 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4403 (clobber (match_scratch:SI 2 ""))])]
4404 "!arm_arch6"
4405 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4406 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4407{
4408 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4409})
25f7a26e 4410
a2cd141b 4411;; We used to have an early-clobber on the scratch register here.
4412;; However, there's a bug somewhere in reload which means that this
4413;; can be partially ignored during spill allocation if the memory
ed29c566 4414;; address also needs reloading; this causes us to die later on when
a2cd141b 4415;; we try to verify the operands. Fortunately, we don't really need
4416;; the early-clobber: we can always use operand 0 if operand 2
4417;; overlaps the address.
ef51b8e1 4418(define_insn "thumb1_extendhisi2"
a2cd141b 4419 [(set (match_operand:SI 0 "register_operand" "=l,l")
4420 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4421 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4422 "TARGET_THUMB1"
a2cd141b 4423 "*
4424 {
4425 rtx ops[4];
4426 rtx mem;
4427
ef51b8e1 4428 if (which_alternative == 0 && !arm_arch6)
4429 return \"#\";
a2cd141b 4430 if (which_alternative == 0)
4431 return \"sxth\\t%0, %1\";
4432
4433 mem = XEXP (operands[1], 0);
4434
4435 /* This code used to try to use 'V', and fix the address only if it was
4436 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4437 range of QImode offsets, and offsettable_address_p does a QImode
4438 address check. */
4439
4440 if (GET_CODE (mem) == CONST)
4441 mem = XEXP (mem, 0);
4442
4443 if (GET_CODE (mem) == LABEL_REF)
4444 return \"ldr\\t%0, %1\";
4445
4446 if (GET_CODE (mem) == PLUS)
4447 {
4448 rtx a = XEXP (mem, 0);
4449 rtx b = XEXP (mem, 1);
4450
4451 if (GET_CODE (a) == LABEL_REF
4452 && GET_CODE (b) == CONST_INT)
4453 return \"ldr\\t%0, %1\";
4454
4455 if (GET_CODE (b) == REG)
4456 return \"ldrsh\\t%0, %1\";
4457
4458 ops[1] = a;
4459 ops[2] = b;
4460 }
4461 else
4462 {
4463 ops[1] = mem;
4464 ops[2] = const0_rtx;
4465 }
4466
ed29c566 4467 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4468
4469 ops[0] = operands[0];
4470 if (reg_mentioned_p (operands[2], ops[1]))
4471 ops[3] = ops[0];
4472 else
4473 ops[3] = operands[2];
4474 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4475 return \"\";
4476 }"
ef51b8e1 4477 [(set_attr_alternative "length"
4478 [(if_then_else (eq_attr "is_arch6" "yes")
4479 (const_int 2) (const_int 4))
4480 (const_int 4)])
a2cd141b 4481 (set_attr "type" "alu_shift,load_byte")
4482 (set_attr "pool_range" "*,1020")]
4483)
4484
25f905c2 4485;; This pattern will only be used when ldsh is not available
25f7a26e 4486(define_expand "extendhisi2_mem"
eab14235 4487 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4488 (set (match_dup 3)
eab14235 4489 (zero_extend:SI (match_dup 7)))
25f7a26e 4490 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4491 (set (match_operand:SI 0 "" "")
4492 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4493 "TARGET_ARM"
25f7a26e 4494 "
215b30b3 4495 {
4496 rtx mem1, mem2;
4497 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4498
788fcce0 4499 mem1 = change_address (operands[1], QImode, addr);
4500 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4501 operands[0] = gen_lowpart (SImode, operands[0]);
4502 operands[1] = mem1;
4503 operands[2] = gen_reg_rtx (SImode);
4504 operands[3] = gen_reg_rtx (SImode);
4505 operands[6] = gen_reg_rtx (SImode);
4506 operands[7] = mem2;
25f7a26e 4507
215b30b3 4508 if (BYTES_BIG_ENDIAN)
4509 {
4510 operands[4] = operands[2];
4511 operands[5] = operands[3];
4512 }
4513 else
4514 {
4515 operands[4] = operands[3];
4516 operands[5] = operands[2];
4517 }
4518 }"
4519)
b11cae9e 4520
ef51b8e1 4521(define_split
4522 [(set (match_operand:SI 0 "register_operand" "")
4523 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4524 "!arm_arch6"
4525 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4526 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4527{
4528 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4529})
4530
a2cd141b 4531(define_insn "*arm_extendhisi2"
ef51b8e1 4532 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4533 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4534 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4535 "@
4536 #
4537 ldr%(sh%)\\t%0, %1"
4538 [(set_attr "length" "8,4")
4539 (set_attr "type" "alu_shift,load_byte")
0d66636f 4540 (set_attr "predicable" "yes")
ef51b8e1 4541 (set_attr "pool_range" "*,256")
4542 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4543)
f7fbdd4a 4544
25f905c2 4545;; ??? Check Thumb-2 pool range
a2cd141b 4546(define_insn "*arm_extendhisi2_v6"
4547 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4548 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4549 "TARGET_32BIT && arm_arch6"
a2cd141b 4550 "@
4551 sxth%?\\t%0, %1
25f905c2 4552 ldr%(sh%)\\t%0, %1"
a2cd141b 4553 [(set_attr "type" "alu_shift,load_byte")
4554 (set_attr "predicable" "yes")
4555 (set_attr "pool_range" "*,256")
4556 (set_attr "neg_pool_range" "*,244")]
4557)
4558
4559(define_insn "*arm_extendhisi2addsi"
4560 [(set (match_operand:SI 0 "s_register_operand" "=r")
4561 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4562 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4563 "TARGET_INT_SIMD"
a2cd141b 4564 "sxtah%?\\t%0, %2, %1"
4565)
4566
c8f69309 4567(define_expand "extendqihi2"
4568 [(set (match_dup 2)
bed7d9a5 4569 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4570 (const_int 24)))
9c08d1fa 4571 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4572 (ashiftrt:SI (match_dup 2)
4573 (const_int 24)))]
cffb2a26 4574 "TARGET_ARM"
c8f69309 4575 "
215b30b3 4576 {
4577 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4578 {
4579 emit_insn (gen_rtx_SET (VOIDmode,
4580 operands[0],
4581 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4582 DONE;
4583 }
4584 if (!s_register_operand (operands[1], QImode))
4585 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4586 operands[0] = gen_lowpart (SImode, operands[0]);
4587 operands[1] = gen_lowpart (SImode, operands[1]);
4588 operands[2] = gen_reg_rtx (SImode);
4589 }"
4590)
f7fbdd4a 4591
25f905c2 4592(define_insn "*arm_extendqihi_insn"
b4e8a300 4593 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4594 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4595 "TARGET_ARM && arm_arch4"
25f905c2 4596 "ldr%(sb%)\\t%0, %1"
a2cd141b 4597 [(set_attr "type" "load_byte")
0d66636f 4598 (set_attr "predicable" "yes")
cffb2a26 4599 (set_attr "pool_range" "256")
4600 (set_attr "neg_pool_range" "244")]
4601)
3fc2009e 4602
b11cae9e 4603(define_expand "extendqisi2"
ef51b8e1 4604 [(set (match_operand:SI 0 "s_register_operand" "")
4605 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 4606 "TARGET_EITHER"
ef51b8e1 4607{
4608 if (!arm_arch4 && MEM_P (operands[1]))
4609 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4610
ef51b8e1 4611 if (!arm_arch6 && !MEM_P (operands[1]))
4612 {
4613 rtx t = gen_lowpart (SImode, operands[1]);
4614 rtx tmp = gen_reg_rtx (SImode);
4615 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4616 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4617 DONE;
4618 }
4619})
a2cd141b 4620
ef51b8e1 4621(define_split
4622 [(set (match_operand:SI 0 "register_operand" "")
4623 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4624 "!arm_arch6"
4625 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4626 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4627{
4628 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4629})
f7fbdd4a 4630
a2cd141b 4631(define_insn "*arm_extendqisi"
ef51b8e1 4632 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4633 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4634 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4635 "@
4636 #
4637 ldr%(sb%)\\t%0, %1"
4638 [(set_attr "length" "8,4")
4639 (set_attr "type" "alu_shift,load_byte")
0d66636f 4640 (set_attr "predicable" "yes")
ef51b8e1 4641 (set_attr "pool_range" "*,256")
4642 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4643)
3fc2009e 4644
a2cd141b 4645(define_insn "*arm_extendqisi_v6"
4646 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4647 (sign_extend:SI
4648 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4649 "TARGET_ARM && arm_arch6"
b4e8a300 4650 "@
4651 sxtb%?\\t%0, %1
25f905c2 4652 ldr%(sb%)\\t%0, %1"
a2cd141b 4653 [(set_attr "type" "alu_shift,load_byte")
4654 (set_attr "predicable" "yes")
a2cd141b 4655 (set_attr "pool_range" "*,256")
4656 (set_attr "neg_pool_range" "*,244")]
4657)
4658
4659(define_insn "*arm_extendqisi2addsi"
4660 [(set (match_operand:SI 0 "s_register_operand" "=r")
4661 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4662 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4663 "TARGET_INT_SIMD"
a2cd141b 4664 "sxtab%?\\t%0, %2, %1"
4665 [(set_attr "type" "alu_shift")
bcaec148 4666 (set_attr "insn" "xtab")
a2cd141b 4667 (set_attr "predicable" "yes")]
4668)
4669
ef51b8e1 4670(define_split
4671 [(set (match_operand:SI 0 "register_operand" "")
4672 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4673 "TARGET_THUMB1 && reload_completed"
4674 [(set (match_dup 0) (match_dup 2))
4675 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4676{
4677 rtx addr = XEXP (operands[1], 0);
cffb2a26 4678
ef51b8e1 4679 if (GET_CODE (addr) == CONST)
4680 addr = XEXP (addr, 0);
cffb2a26 4681
ef51b8e1 4682 if (GET_CODE (addr) == PLUS
4683 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4684 /* No split necessary. */
4685 FAIL;
4686
4687 if (GET_CODE (addr) == PLUS
4688 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4689 FAIL;
4690
4691 if (reg_overlap_mentioned_p (operands[0], addr))
4692 {
4693 rtx t = gen_lowpart (QImode, operands[0]);
4694 emit_move_insn (t, operands[1]);
4695 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4696 DONE;
4697 }
4698
4699 if (REG_P (addr))
4700 {
4701 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4702 operands[2] = const0_rtx;
4703 }
4704 else if (GET_CODE (addr) != PLUS)
4705 FAIL;
4706 else if (REG_P (XEXP (addr, 0)))
4707 {
4708 operands[2] = XEXP (addr, 1);
4709 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4710 }
4711 else
4712 {
4713 operands[2] = XEXP (addr, 0);
4714 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4715 }
cffb2a26 4716
ef51b8e1 4717 operands[3] = change_address (operands[1], QImode, addr);
4718})
4719
8a3b73a1 4720(define_peephole2
4721 [(set (match_operand:SI 0 "register_operand" "")
4722 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4723 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4724 (set (match_operand:SI 3 "register_operand" "")
4725 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4726 "TARGET_THUMB1
4727 && GET_CODE (XEXP (operands[4], 0)) == PLUS
4728 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4729 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4730 && (peep2_reg_dead_p (3, operands[0])
4731 || rtx_equal_p (operands[0], operands[3]))
4732 && (peep2_reg_dead_p (3, operands[2])
4733 || rtx_equal_p (operands[2], operands[3]))"
4734 [(set (match_dup 2) (match_dup 1))
4735 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4736{
4737 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4738 operands[4] = change_address (operands[4], QImode, addr);
4739})
4740
ef51b8e1 4741(define_insn "thumb1_extendqisi2"
a2cd141b 4742 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4743 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 4744 "TARGET_THUMB1"
4745{
4746 rtx addr;
a2cd141b 4747
ef51b8e1 4748 if (which_alternative == 0 && arm_arch6)
4749 return "sxtb\\t%0, %1";
4750 if (which_alternative == 0)
4751 return "#";
a2cd141b 4752
ef51b8e1 4753 addr = XEXP (operands[1], 0);
4754 if (GET_CODE (addr) == PLUS
4755 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4756 return "ldrsb\\t%0, %1";
a2cd141b 4757
ef51b8e1 4758 return "#";
4759}
4760 [(set_attr_alternative "length"
4761 [(if_then_else (eq_attr "is_arch6" "yes")
4762 (const_int 2) (const_int 4))
4763 (const_int 2)
4764 (if_then_else (eq_attr "is_arch6" "yes")
4765 (const_int 4) (const_int 6))])
4766 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 4767)
4768
caedf871 4769(define_expand "extendsfdf2"
4770 [(set (match_operand:DF 0 "s_register_operand" "")
4771 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4772 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4773 ""
4774)
9b8516be 4775
4776/* HFmode -> DFmode conversions have to go through SFmode. */
4777(define_expand "extendhfdf2"
4778 [(set (match_operand:DF 0 "general_operand" "")
4779 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4780 "TARGET_EITHER"
4781 "
4782 {
4783 rtx op1;
4784 op1 = convert_to_mode (SFmode, operands[1], 0);
4785 op1 = convert_to_mode (DFmode, op1, 0);
4786 emit_insn (gen_movdf (operands[0], op1));
4787 DONE;
4788 }"
4789)
b11cae9e 4790\f
4791;; Move insns (including loads and stores)
4792
4793;; XXX Just some ideas about movti.
9c08d1fa 4794;; I don't think these are a good idea on the arm, there just aren't enough
4795;; registers
b11cae9e 4796;;(define_expand "loadti"
9c08d1fa 4797;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4798;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4799;; "" "")
4800
4801;;(define_expand "storeti"
4802;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4803;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4804;; "" "")
4805
4806;;(define_expand "movti"
4807;; [(set (match_operand:TI 0 "general_operand" "")
4808;; (match_operand:TI 1 "general_operand" ""))]
4809;; ""
4810;; "
4811;;{
4812;; rtx insn;
4813;;
4814;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4815;; operands[1] = copy_to_reg (operands[1]);
4816;; if (GET_CODE (operands[0]) == MEM)
4817;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4818;; else if (GET_CODE (operands[1]) == MEM)
4819;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4820;; else
4821;; FAIL;
4822;;
4823;; emit_insn (insn);
4824;; DONE;
4825;;}")
4826
a2f10574 4827;; Recognize garbage generated above.
b11cae9e 4828
4829;;(define_insn ""
4830;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4831;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4832;; ""
4833;; "*
4834;; {
4835;; register mem = (which_alternative < 3);
0d66636f 4836;; register const char *template;
b11cae9e 4837;;
4838;; operands[mem] = XEXP (operands[mem], 0);
4839;; switch (which_alternative)
4840;; {
4841;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4842;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4843;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4844;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4845;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4846;; case 5: template = \"stmia\\t%0, %M1\"; break;
4847;; }
e2348bcb 4848;; output_asm_insn (template, operands);
4849;; return \"\";
b11cae9e 4850;; }")
4851
cffb2a26 4852(define_expand "movdi"
4853 [(set (match_operand:DI 0 "general_operand" "")
4854 (match_operand:DI 1 "general_operand" ""))]
4855 "TARGET_EITHER"
4856 "
e1ba4a27 4857 if (can_create_pseudo_p ())
cffb2a26 4858 {
b2778788 4859 if (GET_CODE (operands[0]) != REG)
4860 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4861 }
4862 "
4863)
b11cae9e 4864
cffb2a26 4865(define_insn "*arm_movdi"
d51f92df 4866 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4867 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 4868 "TARGET_32BIT
b2778788 4869 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4870 && !TARGET_IWMMXT
4871 && ( register_operand (operands[0], DImode)
4872 || register_operand (operands[1], DImode))"
b11cae9e 4873 "*
d51f92df 4874 switch (which_alternative)
4875 {
4876 case 0:
4877 case 1:
4878 case 2:
4879 return \"#\";
4880 default:
4881 return output_move_double (operands);
4882 }
cffb2a26 4883 "
359a6e9f 4884 [(set_attr "length" "8,12,16,8,8")
4885 (set_attr "type" "*,*,*,load2,store2")
cde1623a 4886 (set_attr "arm_pool_range" "*,*,*,1020,*")
4887 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
4888 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
4889 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 4890)
4891
d51f92df 4892(define_split
4893 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4894 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4895 "TARGET_32BIT
d51f92df 4896 && reload_completed
4897 && (arm_const_double_inline_cost (operands[1])
4898 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4899 [(const_int 0)]
4900 "
4901 arm_split_constant (SET, SImode, curr_insn,
4902 INTVAL (gen_lowpart (SImode, operands[1])),
4903 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4904 arm_split_constant (SET, SImode, curr_insn,
4905 INTVAL (gen_highpart_mode (SImode,
4906 GET_MODE (operands[0]),
4907 operands[1])),
4908 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4909 DONE;
4910 "
4911)
4912
e5ba9289 4913; If optimizing for size, or if we have load delay slots, then
4914; we want to split the constant into two separate operations.
4915; In both cases this may split a trivial part into a single data op
4916; leaving a single complex constant to load. We can also get longer
4917; offsets in a LDR which means we get better chances of sharing the pool
4918; entries. Finally, we can normally do a better job of scheduling
4919; LDR instructions than we can with LDM.
4920; This pattern will only match if the one above did not.
4921(define_split
4922 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4923 (match_operand:ANY64 1 "const_double_operand" ""))]
4924 "TARGET_ARM && reload_completed
4925 && arm_const_double_by_parts (operands[1])"
4926 [(set (match_dup 0) (match_dup 1))
4927 (set (match_dup 2) (match_dup 3))]
4928 "
4929 operands[2] = gen_highpart (SImode, operands[0]);
4930 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4931 operands[1]);
4932 operands[0] = gen_lowpart (SImode, operands[0]);
4933 operands[1] = gen_lowpart (SImode, operands[1]);
4934 "
4935)
4936
d51f92df 4937(define_split
4938 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4939 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4940 "TARGET_EITHER && reload_completed"
4941 [(set (match_dup 0) (match_dup 1))
4942 (set (match_dup 2) (match_dup 3))]
4943 "
4944 operands[2] = gen_highpart (SImode, operands[0]);
4945 operands[3] = gen_highpart (SImode, operands[1]);
4946 operands[0] = gen_lowpart (SImode, operands[0]);
4947 operands[1] = gen_lowpart (SImode, operands[1]);
4948
4949 /* Handle a partial overlap. */
4950 if (rtx_equal_p (operands[0], operands[3]))
4951 {
4952 rtx tmp0 = operands[0];
4953 rtx tmp1 = operands[1];
4954
4955 operands[0] = operands[2];
4956 operands[1] = operands[3];
4957 operands[2] = tmp0;
4958 operands[3] = tmp1;
4959 }
4960 "
4961)
4962
a8a3b539 4963;; We can't actually do base+index doubleword loads if the index and
4964;; destination overlap. Split here so that we at least have chance to
4965;; schedule.
4966(define_split
4967 [(set (match_operand:DI 0 "s_register_operand" "")
4968 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4969 (match_operand:SI 2 "s_register_operand" ""))))]
4970 "TARGET_LDRD
4971 && reg_overlap_mentioned_p (operands[0], operands[1])
4972 && reg_overlap_mentioned_p (operands[0], operands[2])"
4973 [(set (match_dup 4)
4974 (plus:SI (match_dup 1)
4975 (match_dup 2)))
4976 (set (match_dup 0)
4977 (mem:DI (match_dup 4)))]
4978 "
4979 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4980 "
4981)
4982
cffb2a26 4983;;; ??? This should have alternatives for constants.
4984;;; ??? This was originally identical to the movdf_insn pattern.
4985;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4986;;; thumb_reorg with a memory reference.
25f905c2 4987(define_insn "*thumb1_movdi_insn"
215b30b3 4988 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4989 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4990 "TARGET_THUMB1
a2cd141b 4991 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4992 && ( register_operand (operands[0], DImode)
4993 || register_operand (operands[1], DImode))"
4994 "*
4995 {
4996 switch (which_alternative)
4997 {
4998 default:
4999 case 0:
5000 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5001 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5002 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5003 case 1:
5004 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5005 case 2:
5006 operands[1] = GEN_INT (- INTVAL (operands[1]));
5007 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5008 case 3:
5009 return \"ldmia\\t%1, {%0, %H0}\";
5010 case 4:
5011 return \"stmia\\t%0, {%1, %H1}\";
5012 case 5:
5013 return thumb_load_double_from_address (operands);
5014 case 6:
1a83b3ff 5015 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5016 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5017 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5018 return \"\";
5019 case 7:
5020 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5021 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5022 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5023 }
5024 }"
5025 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5026 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5027 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5028 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5029)
b11cae9e 5030
9c08d1fa 5031(define_expand "movsi"
5032 [(set (match_operand:SI 0 "general_operand" "")
5033 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5034 "TARGET_EITHER"
9c08d1fa 5035 "
befb0bac 5036 {
e348ff3e 5037 rtx base, offset, tmp;
5038
25f905c2 5039 if (TARGET_32BIT)
9c08d1fa 5040 {
674a8f0b 5041 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5042 if (GET_CODE (operands[0]) == MEM)
5043 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5044 if (arm_general_register_operand (operands[0], SImode)
5045 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5046 && !(const_ok_for_arm (INTVAL (operands[1]))
5047 || const_ok_for_arm (~INTVAL (operands[1]))))
5048 {
96f57e36 5049 arm_split_constant (SET, SImode, NULL_RTX,
5050 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5051 optimize && can_create_pseudo_p ());
cffb2a26 5052 DONE;
5053 }
d0e6a121 5054
5055 if (TARGET_USE_MOVT && !target_word_relocations
5056 && GET_CODE (operands[1]) == SYMBOL_REF
5057 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5058 {
5059 arm_emit_movpair (operands[0], operands[1]);
5060 DONE;
5061 }
cffb2a26 5062 }
25f905c2 5063 else /* TARGET_THUMB1... */
cffb2a26 5064 {
e1ba4a27 5065 if (can_create_pseudo_p ())
cffb2a26 5066 {
5067 if (GET_CODE (operands[0]) != REG)
5068 operands[1] = force_reg (SImode, operands[1]);
5069 }
9c08d1fa 5070 }
f655717d 5071
e348ff3e 5072 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5073 {
5074 split_const (operands[1], &base, &offset);
5075 if (GET_CODE (base) == SYMBOL_REF
5076 && !offset_within_block_p (base, INTVAL (offset)))
5077 {
b308ddcf 5078 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5079 emit_move_insn (tmp, base);
5080 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5081 DONE;
5082 }
5083 }
5084
f655717d 5085 /* Recognize the case where operand[1] is a reference to thread-local
5086 data and load its address to a register. */
5087 if (arm_tls_referenced_p (operands[1]))
5088 {
5089 rtx tmp = operands[1];
5090 rtx addend = NULL;
5091
5092 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5093 {
5094 addend = XEXP (XEXP (tmp, 0), 1);
5095 tmp = XEXP (XEXP (tmp, 0), 0);
5096 }
5097
5098 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5099 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5100
e1ba4a27 5101 tmp = legitimize_tls_address (tmp,
5102 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5103 if (addend)
5104 {
5105 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5106 tmp = force_operand (tmp, operands[0]);
5107 }
5108 operands[1] = tmp;
5109 }
5110 else if (flag_pic
5111 && (CONSTANT_P (operands[1])
5112 || symbol_mentioned_p (operands[1])
5113 || label_mentioned_p (operands[1])))
5114 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5115 (!can_create_pseudo_p ()
5116 ? operands[0]
5117 : 0));
befb0bac 5118 }
215b30b3 5119 "
5120)
9c08d1fa 5121
d0e6a121 5122;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5123;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5124;; so this does not matter.
5125(define_insn "*arm_movt"
5126 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5127 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5128 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5129 "arm_arch_thumb2"
d0e6a121 5130 "movt%?\t%0, #:upper16:%c2"
5131 [(set_attr "predicable" "yes")
5132 (set_attr "length" "4")]
5133)
5134
cffb2a26 5135(define_insn "*arm_movsi_insn"
aaa37ad6 5136 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5137 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5138 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5139 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5140 && ( register_operand (operands[0], SImode)
5141 || register_operand (operands[1], SImode))"
f7fbdd4a 5142 "@
aaa37ad6 5143 mov%?\\t%0, %1
f7fbdd4a 5144 mov%?\\t%0, %1
5145 mvn%?\\t%0, #%B1
25f905c2 5146 movw%?\\t%0, %1
f7fbdd4a 5147 ldr%?\\t%0, %1
5148 str%?\\t%1, %0"
aaa37ad6 5149 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5150 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5151 (set_attr "predicable" "yes")
aaa37ad6 5152 (set_attr "pool_range" "*,*,*,*,4096,*")
5153 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5154)
87b22bf7 5155
5156(define_split
a2cd141b 5157 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5158 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5159 "TARGET_32BIT
215b30b3 5160 && (!(const_ok_for_arm (INTVAL (operands[1]))
5161 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5162 [(clobber (const_int 0))]
5163 "
96f57e36 5164 arm_split_constant (SET, SImode, NULL_RTX,
5165 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5166 DONE;
215b30b3 5167 "
5168)
9c08d1fa 5169
25f905c2 5170(define_insn "*thumb1_movsi_insn"
55a0d64c 5171 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5172 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 5173 "TARGET_THUMB1
cffb2a26 5174 && ( register_operand (operands[0], SImode)
5175 || register_operand (operands[1], SImode))"
5176 "@
5177 mov %0, %1
5178 mov %0, %1
5179 #
5180 #
5181 ldmia\\t%1, {%0}
5182 stmia\\t%0, {%1}
5183 ldr\\t%0, %1
5184 str\\t%1, %0
5185 mov\\t%0, %1"
5186 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5187 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5188 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5189 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5190
5191(define_split
5192 [(set (match_operand:SI 0 "register_operand" "")
5193 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5194 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5195 [(set (match_dup 2) (match_dup 1))
5196 (set (match_dup 0) (neg:SI (match_dup 2)))]
5197 "
5198 {
5199 operands[1] = GEN_INT (- INTVAL (operands[1]));
5200 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5201 }"
cffb2a26 5202)
5203
5204(define_split
5205 [(set (match_operand:SI 0 "register_operand" "")
5206 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5207 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5208 [(set (match_dup 2) (match_dup 1))
5209 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5210 "
5211 {
e4aeee53 5212 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5213 unsigned HOST_WIDE_INT mask = 0xff;
5214 int i;
5215
5216 for (i = 0; i < 25; i++)
5217 if ((val & (mask << i)) == val)
5218 break;
5219
1276f1b8 5220 /* Don't split if the shift is zero. */
cffb2a26 5221 if (i == 0)
5222 FAIL;
5223
5224 operands[1] = GEN_INT (val >> i);
1276f1b8 5225 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5226 operands[3] = GEN_INT (i);
cffb2a26 5227 }"
5228)
5229
67336bcf 5230;; When generating pic, we need to load the symbol offset into a register.
5231;; So that the optimizer does not confuse this with a normal symbol load
5232;; we use an unspec. The offset will be loaded from a constant pool entry,
5233;; since that is the only type of relocation we can use.
5234
94f8caca 5235;; Wrap calculation of the whole PIC address in a single pattern for the
5236;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5237;; a PIC address involves two loads from memory, so we want to CSE it
5238;; as often as possible.
5239;; This pattern will be split into one of the pic_load_addr_* patterns
5240;; and a move after GCSE optimizations.
5241;;
5242;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5243(define_expand "calculate_pic_address"
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)
5250
5251;; Split calculate_pic_address into pic_load_addr_* and a move.
5252(define_split
5253 [(set (match_operand:SI 0 "register_operand" "")
5254 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5255 (unspec:SI [(match_operand:SI 2 "" "")]
5256 UNSPEC_PIC_SYM))))]
5257 "flag_pic"
5258 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5259 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5260 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5261)
5262
67336bcf 5263;; The rather odd constraints on the following are to force reload to leave
5264;; the insn alone, and to force the minipool generation pass to then move
5265;; the GOT symbol to memory.
849170fd 5266
b3cd5f55 5267(define_insn "pic_load_addr_32bit"
849170fd 5268 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5269 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5270 "TARGET_32BIT && flag_pic"
67336bcf 5271 "ldr%?\\t%0, %1"
a2cd141b 5272 [(set_attr "type" "load1")
b3cd5f55 5273 (set_attr "pool_range" "4096")
5274 (set (attr "neg_pool_range")
5275 (if_then_else (eq_attr "is_thumb" "no")
5276 (const_int 4084)
5277 (const_int 0)))]
8c4d8060 5278)
5279
25f905c2 5280(define_insn "pic_load_addr_thumb1"
8c4d8060 5281 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5282 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5283 "TARGET_THUMB1 && flag_pic"
8c4d8060 5284 "ldr\\t%0, %1"
a2cd141b 5285 [(set_attr "type" "load1")
8c4d8060 5286 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5287)
849170fd 5288
cffb2a26 5289(define_insn "pic_add_dot_plus_four"
15d5d060 5290 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5291 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5292 (const_int 4)
beef0fb5 5293 (match_operand 2 "" "")]
5294 UNSPEC_PIC_BASE))]
b3cd5f55 5295 "TARGET_THUMB"
cffb2a26 5296 "*
6cdcb15c 5297 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5298 INTVAL (operands[2]));
cffb2a26 5299 return \"add\\t%0, %|pc\";
5300 "
5301 [(set_attr "length" "2")]
5302)
849170fd 5303
5304(define_insn "pic_add_dot_plus_eight"
15d5d060 5305 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5306 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5307 (const_int 8)
beef0fb5 5308 (match_operand 2 "" "")]
5309 UNSPEC_PIC_BASE))]
f655717d 5310 "TARGET_ARM"
c4034607 5311 "*
6cdcb15c 5312 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5313 INTVAL (operands[2]));
15d5d060 5314 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5315 "
0d66636f 5316 [(set_attr "predicable" "yes")]
cffb2a26 5317)
849170fd 5318
f655717d 5319(define_insn "tls_load_dot_plus_eight"
cc071db6 5320 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5321 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5322 (const_int 8)
beef0fb5 5323 (match_operand 2 "" "")]
5324 UNSPEC_PIC_BASE)))]
f655717d 5325 "TARGET_ARM"
5326 "*
6cdcb15c 5327 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5328 INTVAL (operands[2]));
f655717d 5329 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5330 "
5331 [(set_attr "predicable" "yes")]
5332)
5333
5334;; PIC references to local variables can generate pic_add_dot_plus_eight
5335;; followed by a load. These sequences can be crunched down to
5336;; tls_load_dot_plus_eight by a peephole.
5337
5338(define_peephole2
c0c1fba5 5339 [(set (match_operand:SI 0 "register_operand" "")
5340 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5341 (const_int 8)
5342 (match_operand 1 "" "")]
5343 UNSPEC_PIC_BASE))
f655717d 5344 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5345 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5346 [(set (match_dup 2)
5347 (mem:SI (unspec:SI [(match_dup 3)
5348 (const_int 8)
5349 (match_dup 1)]
5350 UNSPEC_PIC_BASE)))]
f655717d 5351 ""
5352)
5353
bac7fc85 5354(define_insn "pic_offset_arm"
5355 [(set (match_operand:SI 0 "register_operand" "=r")
5356 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5357 (unspec:SI [(match_operand:SI 2 "" "X")]
5358 UNSPEC_PIC_OFFSET))))]
5359 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5360 "ldr%?\\t%0, [%1,%2]"
5361 [(set_attr "type" "load1")]
5362)
5363
95373f08 5364(define_expand "builtin_setjmp_receiver"
5365 [(label_ref (match_operand 0 "" ""))]
5366 "flag_pic"
5367 "
5368{
b935b306 5369 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5370 register. */
2cb7d577 5371 if (arm_pic_register != INVALID_REGNUM)
5372 arm_load_pic_register (1UL << 3);
95373f08 5373 DONE;
5374}")
5375
9c08d1fa 5376;; If copying one reg to another we can set the condition codes according to
5377;; its value. Such a move is common after a return from subroutine and the
5378;; result is being tested against zero.
5379
f7fbdd4a 5380(define_insn "*movsi_compare0"
bd5b4116 5381 [(set (reg:CC CC_REGNUM)
cffb2a26 5382 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5383 (const_int 0)))
5384 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5385 (match_dup 1))]
25f905c2 5386 "TARGET_32BIT"
e2348bcb 5387 "@
40dbec34 5388 cmp%?\\t%0, #0
25f905c2 5389 sub%.\\t%0, %1, #0"
cffb2a26 5390 [(set_attr "conds" "set")]
5391)
b11cae9e 5392
b11cae9e 5393;; Subroutine to store a half word from a register into memory.
5394;; Operand 0 is the source register (HImode)
c8f69309 5395;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5396
9c08d1fa 5397;; In both this routine and the next, we must be careful not to spill
01cc3b75 5398;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5399;; can generate unrecognizable rtl.
5400
b11cae9e 5401(define_expand "storehi"
c8f69309 5402 [;; store the low byte
f082f1c4 5403 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5404 ;; extract the high byte
c8f69309 5405 (set (match_dup 2)
5406 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5407 ;; store the high byte
787f8210 5408 (set (match_dup 4) (match_dup 5))]
cffb2a26 5409 "TARGET_ARM"
b11cae9e 5410 "
215b30b3 5411 {
537ffcfc 5412 rtx op1 = operands[1];
5413 rtx addr = XEXP (op1, 0);
215b30b3 5414 enum rtx_code code = GET_CODE (addr);
5415
5416 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5417 || code == MINUS)
537ffcfc 5418 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5419
537ffcfc 5420 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5421 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5422 operands[3] = gen_lowpart (QImode, operands[0]);
5423 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5424 operands[2] = gen_reg_rtx (SImode);
5425 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5426 }"
5427)
b11cae9e 5428
c7597b5d 5429(define_expand "storehi_bigend"
f082f1c4 5430 [(set (match_dup 4) (match_dup 3))
c7597b5d 5431 (set (match_dup 2)
5432 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5433 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5434 "TARGET_ARM"
b11cae9e 5435 "
215b30b3 5436 {
537ffcfc 5437 rtx op1 = operands[1];
5438 rtx addr = XEXP (op1, 0);
215b30b3 5439 enum rtx_code code = GET_CODE (addr);
5440
5441 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5442 || code == MINUS)
537ffcfc 5443 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5444
537ffcfc 5445 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5446 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5447 operands[3] = gen_lowpart (QImode, operands[0]);
5448 operands[0] = gen_lowpart (SImode, operands[0]);
5449 operands[2] = gen_reg_rtx (SImode);
787f8210 5450 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5451 }"
5452)
c7597b5d 5453
5454;; Subroutine to store a half word integer constant into memory.
5455(define_expand "storeinthi"
f082f1c4 5456 [(set (match_operand 0 "" "")
787f8210 5457 (match_operand 1 "" ""))
9e8503e6 5458 (set (match_dup 3) (match_dup 2))]
cffb2a26 5459 "TARGET_ARM"
c7597b5d 5460 "
215b30b3 5461 {
5462 HOST_WIDE_INT value = INTVAL (operands[1]);
5463 rtx addr = XEXP (operands[0], 0);
537ffcfc 5464 rtx op0 = operands[0];
215b30b3 5465 enum rtx_code code = GET_CODE (addr);
c7597b5d 5466
215b30b3 5467 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5468 || code == MINUS)
537ffcfc 5469 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5470
215b30b3 5471 operands[1] = gen_reg_rtx (SImode);
5472 if (BYTES_BIG_ENDIAN)
5473 {
5474 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5475 if ((value & 255) == ((value >> 8) & 255))
5476 operands[2] = operands[1];
5477 else
5478 {
5479 operands[2] = gen_reg_rtx (SImode);
5480 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5481 }
5482 }
5483 else
5484 {
5485 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5486 if ((value & 255) == ((value >> 8) & 255))
5487 operands[2] = operands[1];
5488 else
5489 {
5490 operands[2] = gen_reg_rtx (SImode);
5491 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5492 }
5493 }
c7597b5d 5494
537ffcfc 5495 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5496 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5497 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5498 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5499 }"
5500)
b11cae9e 5501
f7fbdd4a 5502(define_expand "storehi_single_op"
5503 [(set (match_operand:HI 0 "memory_operand" "")
5504 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5505 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5506 "
215b30b3 5507 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5508 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5509 "
5510)
f7fbdd4a 5511
b11cae9e 5512(define_expand "movhi"
5513 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5514 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5515 "TARGET_EITHER"
b11cae9e 5516 "
cffb2a26 5517 if (TARGET_ARM)
b11cae9e 5518 {
e1ba4a27 5519 if (can_create_pseudo_p ())
cffb2a26 5520 {
5521 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5522 {
cffb2a26 5523 if (arm_arch4)
5524 {
5525 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5526 DONE;
5527 }
5528 if (GET_CODE (operands[1]) == CONST_INT)
5529 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5530 else
cffb2a26 5531 {
5532 if (GET_CODE (operands[1]) == MEM)
5533 operands[1] = force_reg (HImode, operands[1]);
5534 if (BYTES_BIG_ENDIAN)
5535 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5536 else
5537 emit_insn (gen_storehi (operands[1], operands[0]));
5538 }
5539 DONE;
b11cae9e 5540 }
cffb2a26 5541 /* Sign extend a constant, and keep it in an SImode reg. */
5542 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5543 {
cffb2a26 5544 rtx reg = gen_reg_rtx (SImode);
5545 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5546
5547 /* If the constant is already valid, leave it alone. */
215b30b3 5548 if (!const_ok_for_arm (val))
cffb2a26 5549 {
5550 /* If setting all the top bits will make the constant
5551 loadable in a single instruction, then set them.
5552 Otherwise, sign extend the number. */
5553
215b30b3 5554 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5555 val |= ~0xffff;
5556 else if (val & 0x8000)
5557 val |= ~0xffff;
5558 }
5559
5560 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5561 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5562 }
e1ba4a27 5563 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5564 && GET_CODE (operands[1]) == MEM)
5565 {
5566 rtx reg = gen_reg_rtx (SImode);
5567
5568 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5569 operands[1] = gen_lowpart (HImode, reg);
5570 }
215b30b3 5571 else if (!arm_arch4)
f7fbdd4a 5572 {
cffb2a26 5573 if (GET_CODE (operands[1]) == MEM)
5574 {
c1a66faf 5575 rtx base;
5576 rtx offset = const0_rtx;
5577 rtx reg = gen_reg_rtx (SImode);
5578
5579 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5580 || (GET_CODE (base) == PLUS
5581 && (GET_CODE (offset = XEXP (base, 1))
5582 == CONST_INT)
5583 && ((INTVAL(offset) & 1) != 1)
5584 && GET_CODE (base = XEXP (base, 0)) == REG))
5585 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5586 {
8deb3959 5587 rtx new_rtx;
c1a66faf 5588
8deb3959 5589 new_rtx = widen_memory_access (operands[1], SImode,
5590 ((INTVAL (offset) & ~3)
5591 - INTVAL (offset)));
5592 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5593 if (((INTVAL (offset) & 2) != 0)
5594 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5595 {
5596 rtx reg2 = gen_reg_rtx (SImode);
5597
5598 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5599 reg = reg2;
5600 }
206ee9a2 5601 }
c1a66faf 5602 else
5603 emit_insn (gen_movhi_bytes (reg, operands[1]));
5604
5605 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5606 }
5607 }
5608 }
674a8f0b 5609 /* Handle loading a large integer during reload. */
cffb2a26 5610 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5611 && !const_ok_for_arm (INTVAL (operands[1]))
5612 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5613 {
5614 /* Writing a constant to memory needs a scratch, which should
5615 be handled with SECONDARY_RELOADs. */
ed29c566 5616 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5617
5618 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5619 emit_insn (gen_movsi (operands[0], operands[1]));
5620 DONE;
5621 }
5622 }
25f905c2 5623 else if (TARGET_THUMB2)
5624 {
5625 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5626 if (can_create_pseudo_p ())
25f905c2 5627 {
5628 if (GET_CODE (operands[0]) != REG)
5629 operands[1] = force_reg (HImode, operands[1]);
5630 /* Zero extend a constant, and keep it in an SImode reg. */
5631 else if (GET_CODE (operands[1]) == CONST_INT)
5632 {
5633 rtx reg = gen_reg_rtx (SImode);
5634 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5635
5636 emit_insn (gen_movsi (reg, GEN_INT (val)));
5637 operands[1] = gen_lowpart (HImode, reg);
5638 }
5639 }
5640 }
5641 else /* TARGET_THUMB1 */
cffb2a26 5642 {
e1ba4a27 5643 if (can_create_pseudo_p ())
cffb2a26 5644 {
6cffc037 5645 if (GET_CODE (operands[1]) == CONST_INT)
5646 {
5647 rtx reg = gen_reg_rtx (SImode);
5648
5649 emit_insn (gen_movsi (reg, operands[1]));
5650 operands[1] = gen_lowpart (HImode, reg);
5651 }
cffb2a26 5652
5653 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5654 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5655 virtual register (also rejected as illegitimate for HImode/QImode)
5656 relative address. */
cffb2a26 5657 /* ??? This should perhaps be fixed elsewhere, for instance, in
5658 fixup_stack_1, by checking for other kinds of invalid addresses,
5659 e.g. a bare reference to a virtual register. This may confuse the
5660 alpha though, which must handle this case differently. */
5661 if (GET_CODE (operands[0]) == MEM
215b30b3 5662 && !memory_address_p (GET_MODE (operands[0]),
5663 XEXP (operands[0], 0)))
537ffcfc 5664 operands[0]
5665 = replace_equiv_address (operands[0],
5666 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5667
5668 if (GET_CODE (operands[1]) == MEM
215b30b3 5669 && !memory_address_p (GET_MODE (operands[1]),
5670 XEXP (operands[1], 0)))
537ffcfc 5671 operands[1]
5672 = replace_equiv_address (operands[1],
5673 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5674
5675 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5676 {
5677 rtx reg = gen_reg_rtx (SImode);
5678
5679 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5680 operands[1] = gen_lowpart (HImode, reg);
5681 }
5682
5683 if (GET_CODE (operands[0]) == MEM)
5684 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5685 }
cffb2a26 5686 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5687 && !satisfies_constraint_I (operands[1]))
cffb2a26 5688 {
6cffc037 5689 /* Handle loading a large integer during reload. */
5690
cffb2a26 5691 /* Writing a constant to memory needs a scratch, which should
5692 be handled with SECONDARY_RELOADs. */
ed29c566 5693 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5694
1a83b3ff 5695 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5696 emit_insn (gen_movsi (operands[0], operands[1]));
5697 DONE;
5698 }
b11cae9e 5699 }
cffb2a26 5700 "
5701)
5702
25f905c2 5703(define_insn "*thumb1_movhi_insn"
a941568e 5704 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5705 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5706 "TARGET_THUMB1
cffb2a26 5707 && ( register_operand (operands[0], HImode)
5708 || register_operand (operands[1], HImode))"
5709 "*
5710 switch (which_alternative)
d79300ac 5711 {
cffb2a26 5712 case 0: return \"add %0, %1, #0\";
5713 case 2: return \"strh %1, %0\";
5714 case 3: return \"mov %0, %1\";
5715 case 4: return \"mov %0, %1\";
5716 case 5: return \"mov %0, %1\";
ed29c566 5717 default: gcc_unreachable ();
cffb2a26 5718 case 1:
5719 /* The stack pointer can end up being taken as an index register.
5720 Catch this case here and deal with it. */
5721 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5722 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5723 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5724 {
5725 rtx ops[2];
5726 ops[0] = operands[0];
5727 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5728
5729 output_asm_insn (\"mov %0, %1\", ops);
5730
5731 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5732
5733 }
5734 return \"ldrh %0, %1\";
5735 }"
5736 [(set_attr "length" "2,4,2,2,2,2")
747b7458 5737 (set_attr "type" "*,load1,store1,*,*,*")
5738 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 5739
b11cae9e 5740
25f7a26e 5741(define_expand "movhi_bytes"
eab14235 5742 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5743 (set (match_dup 3)
eab14235 5744 (zero_extend:SI (match_dup 6)))
25f7a26e 5745 (set (match_operand:SI 0 "" "")
5746 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5747 "TARGET_ARM"
25f7a26e 5748 "
215b30b3 5749 {
5750 rtx mem1, mem2;
5751 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5752
788fcce0 5753 mem1 = change_address (operands[1], QImode, addr);
5754 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5755 operands[0] = gen_lowpart (SImode, operands[0]);
5756 operands[1] = mem1;
5757 operands[2] = gen_reg_rtx (SImode);
5758 operands[3] = gen_reg_rtx (SImode);
5759 operands[6] = mem2;
25f7a26e 5760
215b30b3 5761 if (BYTES_BIG_ENDIAN)
5762 {
5763 operands[4] = operands[2];
5764 operands[5] = operands[3];
5765 }
5766 else
5767 {
5768 operands[4] = operands[3];
5769 operands[5] = operands[2];
5770 }
5771 }"
5772)
25f7a26e 5773
c7597b5d 5774(define_expand "movhi_bigend"
5775 [(set (match_dup 2)
5776 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5777 (const_int 16)))
5778 (set (match_dup 3)
5779 (ashiftrt:SI (match_dup 2) (const_int 16)))
5780 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5781 (match_dup 4))]
cffb2a26 5782 "TARGET_ARM"
c7597b5d 5783 "
5784 operands[2] = gen_reg_rtx (SImode);
5785 operands[3] = gen_reg_rtx (SImode);
787f8210 5786 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5787 "
5788)
b11cae9e 5789
a2f10574 5790;; Pattern to recognize insn generated default case above
f7fbdd4a 5791(define_insn "*movhi_insn_arch4"
cde1623a 5792 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 5793 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 5794 "TARGET_ARM
5795 && arm_arch4
85e02ccb 5796 && (register_operand (operands[0], HImode)
5797 || register_operand (operands[1], HImode))"
f7fbdd4a 5798 "@
5799 mov%?\\t%0, %1\\t%@ movhi
5800 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5801 str%(h%)\\t%1, %0\\t%@ movhi
5802 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5803 [(set_attr "type" "*,*,store1,load1")
0d66636f 5804 (set_attr "predicable" "yes")
d2a518d1 5805 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 5806 (set_attr "pool_range" "*,*,*,256")
5807 (set_attr "neg_pool_range" "*,*,*,244")]
5808)
f7fbdd4a 5809
f7fbdd4a 5810(define_insn "*movhi_bytes"
25f7a26e 5811 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5812 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5813 "TARGET_ARM"
25f7a26e 5814 "@
5815 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5816 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 5817 [(set_attr "predicable" "yes")
5818 (set_attr "insn" "mov,mvn")]
0d66636f 5819)
25f7a26e 5820
f90b51f1 5821(define_expand "thumb_movhi_clobber"
5822 [(set (match_operand:HI 0 "memory_operand" "")
5823 (match_operand:HI 1 "register_operand" ""))
5824 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5825 "TARGET_THUMB1"
f90b51f1 5826 "
5827 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5828 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5829 {
5830 emit_insn (gen_movhi (operands[0], operands[1]));
5831 DONE;
5832 }
5833 /* XXX Fixme, need to handle other cases here as well. */
5834 gcc_unreachable ();
5835 "
cffb2a26 5836)
5837
bc5c7e08 5838;; We use a DImode scratch because we may occasionally need an additional
5839;; temporary if the address isn't offsettable -- push_reload doesn't seem
5840;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5841(define_expand "reload_outhi"
cffb2a26 5842 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5843 (match_operand:HI 1 "s_register_operand" "r")
5844 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5845 "TARGET_EITHER"
5846 "if (TARGET_ARM)
5847 arm_reload_out_hi (operands);
5848 else
5849 thumb_reload_out_hi (operands);
d3373b54 5850 DONE;
cffb2a26 5851 "
5852)
d3373b54 5853
25f7a26e 5854(define_expand "reload_inhi"
5855 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5856 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5857 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5858 "TARGET_EITHER"
25f7a26e 5859 "
cffb2a26 5860 if (TARGET_ARM)
5861 arm_reload_in_hi (operands);
5862 else
5863 thumb_reload_out_hi (operands);
25f7a26e 5864 DONE;
5865")
5866
9c08d1fa 5867(define_expand "movqi"
5868 [(set (match_operand:QI 0 "general_operand" "")
5869 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5870 "TARGET_EITHER"
9c08d1fa 5871 "
6cffc037 5872 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5873
e1ba4a27 5874 if (can_create_pseudo_p ())
cffb2a26 5875 {
6cffc037 5876 if (GET_CODE (operands[1]) == CONST_INT)
5877 {
5878 rtx reg = gen_reg_rtx (SImode);
5879
03770691 5880 /* For thumb we want an unsigned immediate, then we are more likely
5881 to be able to use a movs insn. */
5882 if (TARGET_THUMB)
5883 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5884
6cffc037 5885 emit_insn (gen_movsi (reg, operands[1]));
5886 operands[1] = gen_lowpart (QImode, reg);
5887 }
cffb2a26 5888
6cffc037 5889 if (TARGET_THUMB)
5890 {
cffb2a26 5891 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5892 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5893 virtual register (also rejected as illegitimate for HImode/QImode)
5894 relative address. */
cffb2a26 5895 /* ??? This should perhaps be fixed elsewhere, for instance, in
5896 fixup_stack_1, by checking for other kinds of invalid addresses,
5897 e.g. a bare reference to a virtual register. This may confuse the
5898 alpha though, which must handle this case differently. */
5899 if (GET_CODE (operands[0]) == MEM
215b30b3 5900 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5901 XEXP (operands[0], 0)))
537ffcfc 5902 operands[0]
5903 = replace_equiv_address (operands[0],
5904 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5905 if (GET_CODE (operands[1]) == MEM
5906 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5907 XEXP (operands[1], 0)))
537ffcfc 5908 operands[1]
5909 = replace_equiv_address (operands[1],
5910 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5911 }
5912
5913 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5914 {
5915 rtx reg = gen_reg_rtx (SImode);
5916
5917 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5918 operands[1] = gen_lowpart (QImode, reg);
5919 }
5920
5921 if (GET_CODE (operands[0]) == MEM)
5922 operands[1] = force_reg (QImode, operands[1]);
5923 }
5924 else if (TARGET_THUMB
5925 && GET_CODE (operands[1]) == CONST_INT
234f6557 5926 && !satisfies_constraint_I (operands[1]))
6cffc037 5927 {
674a8f0b 5928 /* Handle loading a large integer during reload. */
cffb2a26 5929
6cffc037 5930 /* Writing a constant to memory needs a scratch, which should
5931 be handled with SECONDARY_RELOADs. */
5932 gcc_assert (GET_CODE (operands[0]) == REG);
5933
5934 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5935 emit_insn (gen_movsi (operands[0], operands[1]));
5936 DONE;
cffb2a26 5937 }
5938 "
5939)
b11cae9e 5940
9c08d1fa 5941
cffb2a26 5942(define_insn "*arm_movqi_insn"
5943 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5944 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5945 "TARGET_32BIT
cffb2a26 5946 && ( register_operand (operands[0], QImode)
5947 || register_operand (operands[1], QImode))"
5565501b 5948 "@
5949 mov%?\\t%0, %1
5950 mvn%?\\t%0, #%B1
25f905c2 5951 ldr%(b%)\\t%0, %1
5952 str%(b%)\\t%1, %0"
a2cd141b 5953 [(set_attr "type" "*,*,load1,store1")
d2a518d1 5954 (set_attr "insn" "mov,mvn,*,*")
0d66636f 5955 (set_attr "predicable" "yes")]
cffb2a26 5956)
5957
25f905c2 5958(define_insn "*thumb1_movqi_insn"
cffb2a26 5959 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5960 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5961 "TARGET_THUMB1
cffb2a26 5962 && ( register_operand (operands[0], QImode)
5963 || register_operand (operands[1], QImode))"
5964 "@
5965 add\\t%0, %1, #0
5966 ldrb\\t%0, %1
5967 strb\\t%1, %0
5968 mov\\t%0, %1
5969 mov\\t%0, %1
5970 mov\\t%0, %1"
5971 [(set_attr "length" "2")
a2cd141b 5972 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 5973 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 5974 (set_attr "pool_range" "*,32,*,*,*,*")
5975 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 5976
9b8516be 5977;; HFmode moves
5978(define_expand "movhf"
5979 [(set (match_operand:HF 0 "general_operand" "")
5980 (match_operand:HF 1 "general_operand" ""))]
5981 "TARGET_EITHER"
5982 "
5983 if (TARGET_32BIT)
5984 {
5985 if (GET_CODE (operands[0]) == MEM)
5986 operands[1] = force_reg (HFmode, operands[1]);
5987 }
5988 else /* TARGET_THUMB1 */
5989 {
5990 if (can_create_pseudo_p ())
5991 {
5992 if (GET_CODE (operands[0]) != REG)
5993 operands[1] = force_reg (HFmode, operands[1]);
5994 }
5995 }
5996 "
5997)
5998
5999(define_insn "*arm32_movhf"
6000 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6001 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 6002 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6003 && ( s_register_operand (operands[0], HFmode)
6004 || s_register_operand (operands[1], HFmode))"
6005 "*
6006 switch (which_alternative)
6007 {
6008 case 0: /* ARM register from memory */
6009 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6010 case 1: /* memory from ARM register */
6011 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6012 case 2: /* ARM register from ARM register */
6013 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6014 case 3: /* ARM register from constant */
6015 {
6016 REAL_VALUE_TYPE r;
6017 long bits;
6018 rtx ops[4];
6019
6020 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6021 bits = real_to_target (NULL, &r, HFmode);
6022 ops[0] = operands[0];
6023 ops[1] = GEN_INT (bits);
6024 ops[2] = GEN_INT (bits & 0xff00);
6025 ops[3] = GEN_INT (bits & 0x00ff);
6026
6027 if (arm_arch_thumb2)
6028 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6029 else
6030 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6031 return \"\";
6032 }
6033 default:
6034 gcc_unreachable ();
6035 }
6036 "
6037 [(set_attr "conds" "unconditional")
6038 (set_attr "type" "load1,store1,*,*")
d2a518d1 6039 (set_attr "insn" "*,*,mov,mov")
9b8516be 6040 (set_attr "length" "4,4,4,8")
d2a518d1 6041 (set_attr "predicable" "yes")]
9b8516be 6042)
6043
6044(define_insn "*thumb1_movhf"
6045 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6046 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6047 "TARGET_THUMB1
6048 && ( s_register_operand (operands[0], HFmode)
6049 || s_register_operand (operands[1], HFmode))"
6050 "*
6051 switch (which_alternative)
6052 {
6053 case 1:
6054 {
6055 rtx addr;
6056 gcc_assert (GET_CODE(operands[1]) == MEM);
6057 addr = XEXP (operands[1], 0);
6058 if (GET_CODE (addr) == LABEL_REF
6059 || (GET_CODE (addr) == CONST
6060 && GET_CODE (XEXP (addr, 0)) == PLUS
6061 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6062 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6063 {
6064 /* Constant pool entry. */
6065 return \"ldr\\t%0, %1\";
6066 }
6067 return \"ldrh\\t%0, %1\";
6068 }
6069 case 2: return \"strh\\t%1, %0\";
6070 default: return \"mov\\t%0, %1\";
6071 }
6072 "
6073 [(set_attr "length" "2")
6074 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6075 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6076 (set_attr "pool_range" "*,1020,*,*,*")
6077 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6078
87b22bf7 6079(define_expand "movsf"
6080 [(set (match_operand:SF 0 "general_operand" "")
6081 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6082 "TARGET_EITHER"
87b22bf7 6083 "
25f905c2 6084 if (TARGET_32BIT)
cffb2a26 6085 {
6086 if (GET_CODE (operands[0]) == MEM)
6087 operands[1] = force_reg (SFmode, operands[1]);
6088 }
25f905c2 6089 else /* TARGET_THUMB1 */
cffb2a26 6090 {
e1ba4a27 6091 if (can_create_pseudo_p ())
cffb2a26 6092 {
6093 if (GET_CODE (operands[0]) != REG)
6094 operands[1] = force_reg (SFmode, operands[1]);
6095 }
6096 }
6097 "
6098)
6099
03d440a6 6100;; Transform a floating-point move of a constant into a core register into
6101;; an SImode operation.
cffb2a26 6102(define_split
03d440a6 6103 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6104 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6105 "TARGET_EITHER
cffb2a26 6106 && reload_completed
6107 && GET_CODE (operands[1]) == CONST_DOUBLE"
6108 [(set (match_dup 2) (match_dup 3))]
6109 "
6110 operands[2] = gen_lowpart (SImode, operands[0]);
6111 operands[3] = gen_lowpart (SImode, operands[1]);
6112 if (operands[2] == 0 || operands[3] == 0)
6113 FAIL;
215b30b3 6114 "
6115)
87b22bf7 6116
cffb2a26 6117(define_insn "*arm_movsf_soft_insn"
6118 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6119 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6120 "TARGET_32BIT
cffb2a26 6121 && TARGET_SOFT_FLOAT
215b30b3 6122 && (GET_CODE (operands[0]) != MEM
6123 || register_operand (operands[1], SFmode))"
9a1112d7 6124 "@
6125 mov%?\\t%0, %1
6126 ldr%?\\t%0, %1\\t%@ float
6127 str%?\\t%1, %0\\t%@ float"
cde1623a 6128 [(set_attr "predicable" "yes")
a2cd141b 6129 (set_attr "type" "*,load1,store1")
d2a518d1 6130 (set_attr "insn" "mov,*,*")
cffb2a26 6131 (set_attr "pool_range" "*,4096,*")
cde1623a 6132 (set_attr "arm_neg_pool_range" "*,4084,*")
6133 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6134)
6135
6136;;; ??? This should have alternatives for constants.
25f905c2 6137(define_insn "*thumb1_movsf_insn"
215b30b3 6138 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6139 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6140 "TARGET_THUMB1
cffb2a26 6141 && ( register_operand (operands[0], SFmode)
6142 || register_operand (operands[1], SFmode))"
6143 "@
6144 add\\t%0, %1, #0
6145 ldmia\\t%1, {%0}
6146 stmia\\t%0, {%1}
6147 ldr\\t%0, %1
6148 str\\t%1, %0
6149 mov\\t%0, %1
6150 mov\\t%0, %1"
6151 [(set_attr "length" "2")
a2cd141b 6152 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6153 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6154 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6155 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6156)
9a1112d7 6157
9c08d1fa 6158(define_expand "movdf"
87b22bf7 6159 [(set (match_operand:DF 0 "general_operand" "")
6160 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6161 "TARGET_EITHER"
9c08d1fa 6162 "
25f905c2 6163 if (TARGET_32BIT)
cffb2a26 6164 {
6165 if (GET_CODE (operands[0]) == MEM)
6166 operands[1] = force_reg (DFmode, operands[1]);
6167 }
6168 else /* TARGET_THUMB */
6169 {
e1ba4a27 6170 if (can_create_pseudo_p ())
cffb2a26 6171 {
6172 if (GET_CODE (operands[0]) != REG)
6173 operands[1] = force_reg (DFmode, operands[1]);
6174 }
6175 }
6176 "
6177)
b11cae9e 6178
9c08d1fa 6179;; Reloading a df mode value stored in integer regs to memory can require a
6180;; scratch reg.
6181(define_expand "reload_outdf"
cffb2a26 6182 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6183 (match_operand:DF 1 "s_register_operand" "r")
6184 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6185 "TARGET_32BIT"
87b22bf7 6186 "
215b30b3 6187 {
6188 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6189
215b30b3 6190 if (code == REG)
6191 operands[2] = XEXP (operands[0], 0);
6192 else if (code == POST_INC || code == PRE_DEC)
6193 {
6194 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6195 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6196 emit_insn (gen_movdi (operands[0], operands[1]));
6197 DONE;
6198 }
6199 else if (code == PRE_INC)
6200 {
6201 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6202
215b30b3 6203 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6204 operands[2] = reg;
6205 }
6206 else if (code == POST_DEC)
6207 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6208 else
6209 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6210 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6211
788fcce0 6212 emit_insn (gen_rtx_SET (VOIDmode,
6213 replace_equiv_address (operands[0], operands[2]),
215b30b3 6214 operands[1]));
f7fbdd4a 6215
215b30b3 6216 if (code == POST_DEC)
6217 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6218
6219 DONE;
6220 }"
6221)
9c08d1fa 6222
9a1112d7 6223(define_insn "*movdf_soft_insn"
359a6e9f 6224 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6225 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6226 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6227 && ( register_operand (operands[0], DFmode)
6228 || register_operand (operands[1], DFmode))"
d51f92df 6229 "*
6230 switch (which_alternative)
6231 {
6232 case 0:
6233 case 1:
6234 case 2:
6235 return \"#\";
6236 default:
6237 return output_move_double (operands);
6238 }
6239 "
359a6e9f 6240 [(set_attr "length" "8,12,16,8,8")
6241 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6242 (set_attr "pool_range" "*,*,*,1020,*")
6243 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6244 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6245)
6246
6247;;; ??? This should have alternatives for constants.
6248;;; ??? This was originally identical to the movdi_insn pattern.
6249;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6250;;; thumb_reorg with a memory reference.
6251(define_insn "*thumb_movdf_insn"
215b30b3 6252 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6253 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6254 "TARGET_THUMB1
cffb2a26 6255 && ( register_operand (operands[0], DFmode)
6256 || register_operand (operands[1], DFmode))"
6257 "*
6258 switch (which_alternative)
6259 {
6260 default:
6261 case 0:
6262 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6263 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6264 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6265 case 1:
6266 return \"ldmia\\t%1, {%0, %H0}\";
6267 case 2:
6268 return \"stmia\\t%0, {%1, %H1}\";
6269 case 3:
6270 return thumb_load_double_from_address (operands);
6271 case 4:
1a83b3ff 6272 operands[2] = gen_rtx_MEM (SImode,
6273 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6274 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6275 return \"\";
6276 case 5:
6277 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6278 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6279 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6280 }
6281 "
6282 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6283 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6284 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6285 (set_attr "pool_range" "*,*,*,1020,*,*")]
6286)
755eb2b4 6287
ccd90aaa 6288(define_expand "movxf"
6289 [(set (match_operand:XF 0 "general_operand" "")
6290 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6291 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6292 "
6293 if (GET_CODE (operands[0]) == MEM)
6294 operands[1] = force_reg (XFmode, operands[1]);
6295 "
6296)
6297
b11cae9e 6298\f
b11cae9e 6299
9c08d1fa 6300;; load- and store-multiple insns
6301;; The arm can load/store any set of registers, provided that they are in
320ea44d 6302;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6303
9c08d1fa 6304(define_expand "load_multiple"
6305 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6306 (match_operand:SI 1 "" ""))
6307 (use (match_operand:SI 2 "" ""))])]
25f905c2 6308 "TARGET_32BIT"
9580c25f 6309{
6310 HOST_WIDE_INT offset = 0;
6311
bd5b4116 6312 /* Support only fixed point registers. */
9c08d1fa 6313 if (GET_CODE (operands[2]) != CONST_INT
6314 || INTVAL (operands[2]) > 14
6315 || INTVAL (operands[2]) < 2
6316 || GET_CODE (operands[1]) != MEM
6317 || GET_CODE (operands[0]) != REG
bd5b4116 6318 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6319 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6320 FAIL;
6321
6322 operands[3]
320ea44d 6323 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6324 INTVAL (operands[2]),
f082f1c4 6325 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6326 FALSE, operands[1], &offset);
9580c25f 6327})
b11cae9e 6328
9c08d1fa 6329(define_expand "store_multiple"
6330 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6331 (match_operand:SI 1 "" ""))
6332 (use (match_operand:SI 2 "" ""))])]
25f905c2 6333 "TARGET_32BIT"
9580c25f 6334{
6335 HOST_WIDE_INT offset = 0;
6336
674a8f0b 6337 /* Support only fixed point registers. */
9c08d1fa 6338 if (GET_CODE (operands[2]) != CONST_INT
6339 || INTVAL (operands[2]) > 14
6340 || INTVAL (operands[2]) < 2
6341 || GET_CODE (operands[1]) != REG
6342 || GET_CODE (operands[0]) != MEM
bd5b4116 6343 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6344 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6345 FAIL;
6346
6347 operands[3]
320ea44d 6348 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6349 INTVAL (operands[2]),
f082f1c4 6350 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6351 FALSE, operands[0], &offset);
9580c25f 6352})
b11cae9e 6353
9c08d1fa 6354
6355;; Move a block of memory if it is word aligned and MORE than 2 words long.
6356;; We could let this apply for blocks of less than this, but it clobbers so
6357;; many registers that there is then probably a better way.
6358
008c057d 6359(define_expand "movmemqi"
34191dd1 6360 [(match_operand:BLK 0 "general_operand" "")
6361 (match_operand:BLK 1 "general_operand" "")
6362 (match_operand:SI 2 "const_int_operand" "")
6363 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6364 "TARGET_EITHER"
9c08d1fa 6365 "
25f905c2 6366 if (TARGET_32BIT)
cffb2a26 6367 {
008c057d 6368 if (arm_gen_movmemqi (operands))
cffb2a26 6369 DONE;
6370 FAIL;
6371 }
25f905c2 6372 else /* TARGET_THUMB1 */
cffb2a26 6373 {
6374 if ( INTVAL (operands[3]) != 4
6375 || INTVAL (operands[2]) > 48)
6376 FAIL;
6377
008c057d 6378 thumb_expand_movmemqi (operands);
cffb2a26 6379 DONE;
6380 }
6381 "
6382)
6383
2162064c 6384;; Thumb block-move insns
cffb2a26 6385
6386(define_insn "movmem12b"
960f3acf 6387 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6388 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6389 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6390 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6391 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6392 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6393 (set (match_operand:SI 0 "register_operand" "=l")
6394 (plus:SI (match_dup 2) (const_int 12)))
6395 (set (match_operand:SI 1 "register_operand" "=l")
6396 (plus:SI (match_dup 3) (const_int 12)))
6397 (clobber (match_scratch:SI 4 "=&l"))
6398 (clobber (match_scratch:SI 5 "=&l"))
6399 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6400 "TARGET_THUMB1"
cffb2a26 6401 "* return thumb_output_move_mem_multiple (3, operands);"
6402 [(set_attr "length" "4")
215b30b3 6403 ; This isn't entirely accurate... It loads as well, but in terms of
6404 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6405 (set_attr "type" "store3")]
6406)
6407
6408(define_insn "movmem8b"
960f3acf 6409 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6410 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6411 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6412 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6413 (set (match_operand:SI 0 "register_operand" "=l")
6414 (plus:SI (match_dup 2) (const_int 8)))
6415 (set (match_operand:SI 1 "register_operand" "=l")
6416 (plus:SI (match_dup 3) (const_int 8)))
6417 (clobber (match_scratch:SI 4 "=&l"))
6418 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6419 "TARGET_THUMB1"
cffb2a26 6420 "* return thumb_output_move_mem_multiple (2, operands);"
6421 [(set_attr "length" "4")
215b30b3 6422 ; This isn't entirely accurate... It loads as well, but in terms of
6423 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6424 (set_attr "type" "store2")]
6425)
6426
9c08d1fa 6427\f
b11cae9e 6428
341940e8 6429;; Compare & branch insns
8d232dc7 6430;; The range calculations are based as follows:
341940e8 6431;; For forward branches, the address calculation returns the address of
6432;; the next instruction. This is 2 beyond the branch instruction.
6433;; For backward branches, the address calculation returns the address of
6434;; the first instruction in this pattern (cmp). This is 2 before the branch
6435;; instruction for the shortest sequence, and 4 before the branch instruction
6436;; if we have to jump around an unconditional branch.
6437;; To the basic branch range the PC offset must be added (this is +4).
6438;; So for forward branches we have
6439;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6440;; And for backward branches we have
6441;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6442;;
6443;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6444;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6445
aeac46d4 6446(define_expand "cbranchsi4"
6447 [(set (pc) (if_then_else
6448 (match_operator 0 "arm_comparison_operator"
6449 [(match_operand:SI 1 "s_register_operand" "")
6450 (match_operand:SI 2 "nonmemory_operand" "")])
6451 (label_ref (match_operand 3 "" ""))
6452 (pc)))]
74f4459c 6453 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6454 "
74f4459c 6455 if (!TARGET_THUMB1)
6456 {
6457 if (!arm_add_operand (operands[2], SImode))
6458 operands[2] = force_reg (SImode, operands[2]);
6459 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6460 operands[3]));
6461 DONE;
6462 }
25f905c2 6463 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6464 {
6465 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6466 operands[3], operands[0]));
6467 DONE;
6468 }
25f905c2 6469 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6470 operands[2] = force_reg (SImode, operands[2]);
6471 ")
6472
a8e6c15d 6473;; A pattern to recognize a special situation and optimize for it.
6474;; On the thumb, zero-extension from memory is preferrable to sign-extension
6475;; due to the available addressing modes. Hence, convert a signed comparison
6476;; with zero into an unsigned comparison with 127 if possible.
6477(define_expand "cbranchqi4"
6478 [(set (pc) (if_then_else
6479 (match_operator 0 "lt_ge_comparison_operator"
6480 [(match_operand:QI 1 "memory_operand" "")
6481 (match_operand:QI 2 "const0_operand" "")])
6482 (label_ref (match_operand 3 "" ""))
6483 (pc)))]
6484 "TARGET_THUMB1"
6485{
d0f6c30d 6486 rtx xops[4];
a8e6c15d 6487 xops[1] = gen_reg_rtx (SImode);
6488 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6489 xops[2] = GEN_INT (127);
6490 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6491 VOIDmode, xops[1], xops[2]);
6492 xops[3] = operands[3];
6493 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6494 DONE;
6495})
6496
74f4459c 6497(define_expand "cbranchsf4"
6498 [(set (pc) (if_then_else
6499 (match_operator 0 "arm_comparison_operator"
6500 [(match_operand:SF 1 "s_register_operand" "")
6501 (match_operand:SF 2 "arm_float_compare_operand" "")])
6502 (label_ref (match_operand 3 "" ""))
6503 (pc)))]
6504 "TARGET_32BIT && TARGET_HARD_FLOAT"
6505 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6506 operands[3])); DONE;"
6507)
6508
6509(define_expand "cbranchdf4"
6510 [(set (pc) (if_then_else
6511 (match_operator 0 "arm_comparison_operator"
6512 [(match_operand:DF 1 "s_register_operand" "")
6513 (match_operand:DF 2 "arm_float_compare_operand" "")])
6514 (label_ref (match_operand 3 "" ""))
6515 (pc)))]
a50d7267 6516 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6517 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6518 operands[3])); DONE;"
6519)
6520
74f4459c 6521(define_expand "cbranchdi4"
6522 [(set (pc) (if_then_else
6523 (match_operator 0 "arm_comparison_operator"
a8045a4f 6524 [(match_operand:DI 1 "cmpdi_operand" "")
6525 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6526 (label_ref (match_operand 3 "" ""))
6527 (pc)))]
a8045a4f 6528 "TARGET_32BIT"
6529 "{
6530 rtx swap = NULL_RTX;
6531 enum rtx_code code = GET_CODE (operands[0]);
6532
6533 /* We should not have two constants. */
6534 gcc_assert (GET_MODE (operands[1]) == DImode
6535 || GET_MODE (operands[2]) == DImode);
6536
6537 /* Flip unimplemented DImode comparisons to a form that
6538 arm_gen_compare_reg can handle. */
6539 switch (code)
6540 {
6541 case GT:
6542 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6543 case LE:
6544 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6545 case GTU:
6546 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6547 case LEU:
6548 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6549 default:
6550 break;
6551 }
6552 if (swap)
6553 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6554 operands[3]));
6555 else
6556 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6557 operands[3]));
6558 DONE;
6559 }"
74f4459c 6560)
6561
d60047aa 6562(define_insn "cbranchsi4_insn"
aeac46d4 6563 [(set (pc) (if_then_else
6564 (match_operator 0 "arm_comparison_operator"
747b7458 6565 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 6566 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6567 (label_ref (match_operand 3 "" ""))
6568 (pc)))]
25f905c2 6569 "TARGET_THUMB1"
747b7458 6570{
6571 rtx t = cfun->machine->thumb1_cc_insn;
6572 if (t != NULL_RTX)
d60047aa 6573 {
747b7458 6574 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6575 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6576 t = NULL_RTX;
6577 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6578 {
6579 if (!noov_comparison_operator (operands[0], VOIDmode))
6580 t = NULL_RTX;
6581 }
6582 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 6583 t = NULL_RTX;
6584 }
d60047aa 6585 if (t == NULL_RTX)
747b7458 6586 {
6587 output_asm_insn ("cmp\t%1, %2", operands);
6588 cfun->machine->thumb1_cc_insn = insn;
6589 cfun->machine->thumb1_cc_op0 = operands[1];
6590 cfun->machine->thumb1_cc_op1 = operands[2];
6591 cfun->machine->thumb1_cc_mode = CCmode;
6592 }
6593 else
6594 /* Ensure we emit the right type of condition code on the jump. */
6595 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6596 CC_REGNUM);
aeac46d4 6597
cffb2a26 6598 switch (get_attr_length (insn))
6599 {
6600 case 4: return \"b%d0\\t%l3\";
6601 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6602 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6603 }
747b7458 6604}
cffb2a26 6605 [(set (attr "far_jump")
6606 (if_then_else
6607 (eq_attr "length" "8")
6608 (const_string "yes")
6609 (const_string "no")))
6610 (set (attr "length")
6611 (if_then_else
6612 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6613 (le (minus (match_dup 3) (pc)) (const_int 256)))
6614 (const_int 4)
6615 (if_then_else
6616 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6617 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6618 (const_int 6)
6619 (const_int 8))))]
6620)
6621
aeac46d4 6622(define_insn "cbranchsi4_scratch"
6623 [(set (pc) (if_then_else
6624 (match_operator 4 "arm_comparison_operator"
6625 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6626 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6627 (label_ref (match_operand 3 "" ""))
6628 (pc)))
6629 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6630 "TARGET_THUMB1"
aeac46d4 6631 "*
6632 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6633
6634 switch (get_attr_length (insn))
6635 {
6636 case 4: return \"b%d4\\t%l3\";
6637 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6638 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6639 }
6640 "
6641 [(set (attr "far_jump")
6642 (if_then_else
6643 (eq_attr "length" "8")
6644 (const_string "yes")
6645 (const_string "no")))
6646 (set (attr "length")
6647 (if_then_else
6648 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6649 (le (minus (match_dup 3) (pc)) (const_int 256)))
6650 (const_int 4)
6651 (if_then_else
6652 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6653 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6654 (const_int 6)
6655 (const_int 8))))]
6656)
446a1e96 6657
747b7458 6658;; Two peepholes to generate subtract of 0 instead of a move if the
6659;; condition codes will be useful.
446a1e96 6660(define_peephole2
6661 [(set (match_operand:SI 0 "low_register_operand" "")
6662 (match_operand:SI 1 "low_register_operand" ""))
6663 (set (pc)
6664 (if_then_else (match_operator 2 "arm_comparison_operator"
6665 [(match_dup 1) (const_int 0)])
6666 (label_ref (match_operand 3 "" ""))
6667 (pc)))]
6668 "TARGET_THUMB1"
747b7458 6669 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6670 (set (pc)
6671 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6672 (label_ref (match_dup 3))
747b7458 6673 (pc)))]
6674 "")
446a1e96 6675
6676;; Sigh! This variant shouldn't be needed, but combine often fails to
6677;; merge cases like this because the op1 is a hard register in
07d32235 6678;; arm_class_likely_spilled_p.
446a1e96 6679(define_peephole2
6680 [(set (match_operand:SI 0 "low_register_operand" "")
6681 (match_operand:SI 1 "low_register_operand" ""))
6682 (set (pc)
6683 (if_then_else (match_operator 2 "arm_comparison_operator"
6684 [(match_dup 0) (const_int 0)])
6685 (label_ref (match_operand 3 "" ""))
6686 (pc)))]
6687 "TARGET_THUMB1"
747b7458 6688 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6689 (set (pc)
6690 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6691 (label_ref (match_dup 3))
747b7458 6692 (pc)))]
6693 "")
446a1e96 6694
cffb2a26 6695(define_insn "*negated_cbranchsi4"
6696 [(set (pc)
6697 (if_then_else
aed179ae 6698 (match_operator 0 "equality_operator"
aeac46d4 6699 [(match_operand:SI 1 "s_register_operand" "l")
6700 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6701 (label_ref (match_operand 3 "" ""))
215b30b3 6702 (pc)))]
25f905c2 6703 "TARGET_THUMB1"
cffb2a26 6704 "*
6705 output_asm_insn (\"cmn\\t%1, %2\", operands);
6706 switch (get_attr_length (insn))
6707 {
6708 case 4: return \"b%d0\\t%l3\";
6709 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6710 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6711 }
6712 "
6713 [(set (attr "far_jump")
6714 (if_then_else
6715 (eq_attr "length" "8")
6716 (const_string "yes")
6717 (const_string "no")))
6718 (set (attr "length")
6719 (if_then_else
6720 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6721 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6722 (const_int 4)
6723 (if_then_else
341940e8 6724 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6725 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6726 (const_int 6)
6727 (const_int 8))))]
6728)
6729
58d6528b 6730(define_insn "*tbit_cbranch"
6731 [(set (pc)
6732 (if_then_else
6733 (match_operator 0 "equality_operator"
6734 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6735 (const_int 1)
6736 (match_operand:SI 2 "const_int_operand" "i"))
6737 (const_int 0)])
6738 (label_ref (match_operand 3 "" ""))
6739 (pc)))
6740 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6741 "TARGET_THUMB1"
58d6528b 6742 "*
6743 {
6744 rtx op[3];
6745 op[0] = operands[4];
6746 op[1] = operands[1];
6747 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6748
86efa74d 6749 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6750 switch (get_attr_length (insn))
6751 {
6752 case 4: return \"b%d0\\t%l3\";
6753 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6754 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6755 }
6756 }"
6757 [(set (attr "far_jump")
6758 (if_then_else
6759 (eq_attr "length" "8")
6760 (const_string "yes")
6761 (const_string "no")))
6762 (set (attr "length")
6763 (if_then_else
6764 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6765 (le (minus (match_dup 3) (pc)) (const_int 256)))
6766 (const_int 4)
6767 (if_then_else
6768 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6769 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6770 (const_int 6)
6771 (const_int 8))))]
6772)
6773
6774(define_insn "*tlobits_cbranch"
6775 [(set (pc)
6776 (if_then_else
6777 (match_operator 0 "equality_operator"
6778 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6779 (match_operand:SI 2 "const_int_operand" "i")
6780 (const_int 0))
6781 (const_int 0)])
6782 (label_ref (match_operand 3 "" ""))
6783 (pc)))
6784 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6785 "TARGET_THUMB1"
86efa74d 6786 "*
6787 {
6788 rtx op[3];
6789 op[0] = operands[4];
6790 op[1] = operands[1];
6791 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6792
58d6528b 6793 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6794 switch (get_attr_length (insn))
6795 {
6796 case 4: return \"b%d0\\t%l3\";
6797 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6798 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6799 }
6800 }"
6801 [(set (attr "far_jump")
6802 (if_then_else
6803 (eq_attr "length" "8")
6804 (const_string "yes")
6805 (const_string "no")))
6806 (set (attr "length")
6807 (if_then_else
6808 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6809 (le (minus (match_dup 3) (pc)) (const_int 256)))
6810 (const_int 4)
6811 (if_then_else
6812 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6813 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6814 (const_int 6)
6815 (const_int 8))))]
6816)
747b7458 6817
aeac46d4 6818(define_insn "*tstsi3_cbranch"
58d6528b 6819 [(set (pc)
6820 (if_then_else
aeac46d4 6821 (match_operator 3 "equality_operator"
6822 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6823 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6824 (const_int 0)])
aeac46d4 6825 (label_ref (match_operand 2 "" ""))
6826 (pc)))]
25f905c2 6827 "TARGET_THUMB1"
58d6528b 6828 "*
6829 {
aeac46d4 6830 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6831 switch (get_attr_length (insn))
6832 {
aeac46d4 6833 case 4: return \"b%d3\\t%l2\";
6834 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6835 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6836 }
6837 }"
6838 [(set (attr "far_jump")
6839 (if_then_else
6840 (eq_attr "length" "8")
6841 (const_string "yes")
6842 (const_string "no")))
6843 (set (attr "length")
6844 (if_then_else
aeac46d4 6845 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6846 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6847 (const_int 4)
6848 (if_then_else
aeac46d4 6849 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6850 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6851 (const_int 6)
6852 (const_int 8))))]
6853)
6854
203c488f 6855(define_insn "*cbranchne_decr1"
6856 [(set (pc)
6857 (if_then_else (match_operator 3 "equality_operator"
6858 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6859 (const_int 0)])
6860 (label_ref (match_operand 4 "" ""))
6861 (pc)))
aeac46d4 6862 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6863 (plus:SI (match_dup 2) (const_int -1)))
6864 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6865 "TARGET_THUMB1"
203c488f 6866 "*
6867 {
6868 rtx cond[2];
6869 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6870 ? GEU : LTU),
58d6528b 6871 VOIDmode, operands[2], const1_rtx);
203c488f 6872 cond[1] = operands[4];
6873
6874 if (which_alternative == 0)
6875 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6876 else if (which_alternative == 1)
6877 {
6878 /* We must provide an alternative for a hi reg because reload
6879 cannot handle output reloads on a jump instruction, but we
6880 can't subtract into that. Fortunately a mov from lo to hi
6881 does not clobber the condition codes. */
6882 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6883 output_asm_insn (\"mov\\t%0, %1\", operands);
6884 }
6885 else
6886 {
6887 /* Similarly, but the target is memory. */
6888 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6889 output_asm_insn (\"str\\t%1, %0\", operands);
6890 }
6891
6892 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6893 {
6894 case 4:
8aea555f 6895 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6896 return \"\";
6897 case 6:
8aea555f 6898 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6899 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6900 default:
8aea555f 6901 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6902 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6903 }
6904 }
6905 "
6906 [(set (attr "far_jump")
6907 (if_then_else
6908 (ior (and (eq (symbol_ref ("which_alternative"))
6909 (const_int 0))
6910 (eq_attr "length" "8"))
6911 (eq_attr "length" "10"))
6912 (const_string "yes")
6913 (const_string "no")))
6914 (set_attr_alternative "length"
6915 [
6916 ;; Alternative 0
6917 (if_then_else
6918 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6919 (le (minus (match_dup 4) (pc)) (const_int 256)))
6920 (const_int 4)
6921 (if_then_else
6922 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6923 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6924 (const_int 6)
6925 (const_int 8)))
6926 ;; Alternative 1
6927 (if_then_else
6928 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6929 (le (minus (match_dup 4) (pc)) (const_int 256)))
6930 (const_int 6)
6931 (if_then_else
6932 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6933 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6934 (const_int 8)
6935 (const_int 10)))
6936 ;; Alternative 2
6937 (if_then_else
6938 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6939 (le (minus (match_dup 4) (pc)) (const_int 256)))
6940 (const_int 6)
6941 (if_then_else
6942 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6943 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6944 (const_int 8)
6945 (const_int 10)))
6946 ;; Alternative 3
6947 (if_then_else
6948 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6949 (le (minus (match_dup 4) (pc)) (const_int 256)))
6950 (const_int 6)
6951 (if_then_else
6952 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6953 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6954 (const_int 8)
6955 (const_int 10)))])]
6956)
cffb2a26 6957
58d6528b 6958(define_insn "*addsi3_cbranch"
6959 [(set (pc)
6960 (if_then_else
b0694be0 6961 (match_operator 4 "arm_comparison_operator"
58d6528b 6962 [(plus:SI
e54011cb 6963 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
6964 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 6965 (const_int 0)])
6966 (label_ref (match_operand 5 "" ""))
6967 (pc)))
aeac46d4 6968 (set
6969 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6970 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 6971 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 6972 "TARGET_THUMB1
58d6528b 6973 && (GET_CODE (operands[4]) == EQ
6974 || GET_CODE (operands[4]) == NE
6975 || GET_CODE (operands[4]) == GE
6976 || GET_CODE (operands[4]) == LT)"
6977 "*
6978 {
6979 rtx cond[3];
6980
956a6170 6981 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 6982 cond[1] = operands[2];
6983 cond[2] = operands[3];
6984
6985 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6986 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6987 else
6988 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6989
956a6170 6990 if (which_alternative >= 2
58d6528b 6991 && which_alternative < 4)
6992 output_asm_insn (\"mov\\t%0, %1\", operands);
6993 else if (which_alternative >= 4)
6994 output_asm_insn (\"str\\t%1, %0\", operands);
6995
d0f6c30d 6996 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 6997 {
6998 case 4:
6999 return \"b%d4\\t%l5\";
7000 case 6:
7001 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7002 default:
7003 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7004 }
7005 }
7006 "
7007 [(set (attr "far_jump")
7008 (if_then_else
7009 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7010 (const_int 2))
58d6528b 7011 (eq_attr "length" "8"))
7012 (eq_attr "length" "10"))
7013 (const_string "yes")
7014 (const_string "no")))
7015 (set (attr "length")
7016 (if_then_else
7017 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7018 (const_int 2))
58d6528b 7019 (if_then_else
7020 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7021 (le (minus (match_dup 5) (pc)) (const_int 256)))
7022 (const_int 4)
7023 (if_then_else
7024 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7025 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7026 (const_int 6)
7027 (const_int 8)))
7028 (if_then_else
7029 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7030 (le (minus (match_dup 5) (pc)) (const_int 256)))
7031 (const_int 6)
7032 (if_then_else
7033 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7034 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7035 (const_int 8)
7036 (const_int 10)))))]
7037)
7038
7039(define_insn "*addsi3_cbranch_scratch"
7040 [(set (pc)
7041 (if_then_else
b0694be0 7042 (match_operator 3 "arm_comparison_operator"
58d6528b 7043 [(plus:SI
7044 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7045 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7046 (const_int 0)])
7047 (label_ref (match_operand 4 "" ""))
7048 (pc)))
7049 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7050 "TARGET_THUMB1
58d6528b 7051 && (GET_CODE (operands[3]) == EQ
7052 || GET_CODE (operands[3]) == NE
7053 || GET_CODE (operands[3]) == GE
7054 || GET_CODE (operands[3]) == LT)"
7055 "*
7056 {
7057 switch (which_alternative)
7058 {
7059 case 0:
7060 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7061 break;
7062 case 1:
7063 output_asm_insn (\"cmn\t%1, %2\", operands);
7064 break;
0f5e9701 7065 case 2:
3a445a04 7066 if (INTVAL (operands[2]) < 0)
7067 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7068 else
7069 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7070 break;
0f5e9701 7071 case 3:
3a445a04 7072 if (INTVAL (operands[2]) < 0)
7073 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7074 else
7075 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7076 break;
7077 }
7078
7079 switch (get_attr_length (insn))
7080 {
7081 case 4:
7082 return \"b%d3\\t%l4\";
7083 case 6:
7084 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7085 default:
7086 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7087 }
7088 }
7089 "
7090 [(set (attr "far_jump")
7091 (if_then_else
7092 (eq_attr "length" "8")
7093 (const_string "yes")
7094 (const_string "no")))
7095 (set (attr "length")
7096 (if_then_else
7097 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7098 (le (minus (match_dup 4) (pc)) (const_int 256)))
7099 (const_int 4)
7100 (if_then_else
7101 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7102 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7103 (const_int 6)
7104 (const_int 8))))]
7105)
7106
58d6528b 7107
9c08d1fa 7108;; Comparison and test insns
7109
cffb2a26 7110(define_insn "*arm_cmpsi_insn"
bd5b4116 7111 [(set (reg:CC CC_REGNUM)
aea4c774 7112 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7113 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7114 "TARGET_32BIT"
5565501b 7115 "@
aea4c774 7116 cmp%?\\t%0, %1
7117 cmn%?\\t%0, #%n1"
cffb2a26 7118 [(set_attr "conds" "set")]
7119)
b11cae9e 7120
d5d4dc8d 7121(define_insn "*cmpsi_shiftsi"
bd5b4116 7122 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7123 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7124 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7125 [(match_operand:SI 1 "s_register_operand" "r,r")
7126 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7127 "TARGET_32BIT"
aea4c774 7128 "cmp%?\\t%0, %1%S3"
344495ea 7129 [(set_attr "conds" "set")
331beb1a 7130 (set_attr "shift" "1")
d5d4dc8d 7131 (set_attr "arch" "32,a")
7132 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7133
d5d4dc8d 7134(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7135 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7136 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7137 [(match_operand:SI 1 "s_register_operand" "r,r")
7138 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7139 (match_operand:SI 0 "s_register_operand" "r,r")))]
7140 "TARGET_32BIT"
aea4c774 7141 "cmp%?\\t%0, %1%S3"
344495ea 7142 [(set_attr "conds" "set")
331beb1a 7143 (set_attr "shift" "1")
d5d4dc8d 7144 (set_attr "arch" "32,a")
7145 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7146
25f905c2 7147(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7148 [(set (reg:CC_Z CC_REGNUM)
7149 (compare:CC_Z
7150 (neg:SI (match_operator:SI 1 "shift_operator"
7151 [(match_operand:SI 2 "s_register_operand" "r")
7152 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7153 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7154 "TARGET_ARM"
aed179ae 7155 "cmn%?\\t%0, %2%S1"
344495ea 7156 [(set_attr "conds" "set")
aed179ae 7157 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7158 (const_string "alu_shift")
7159 (const_string "alu_shift_reg")))]
0d66636f 7160)
b11cae9e 7161
a8045a4f 7162;; DImode comparisons. The generic code generates branches that
7163;; if-conversion can not reduce to a conditional compare, so we do
7164;; that directly.
7165
7166(define_insn "*arm_cmpdi_insn"
7167 [(set (reg:CC_NCV CC_REGNUM)
7168 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7169 (match_operand:DI 1 "arm_di_operand" "rDi")))
7170 (clobber (match_scratch:SI 2 "=r"))]
7171 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7172 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7173 [(set_attr "conds" "set")
7174 (set_attr "length" "8")]
7175)
7176
7177(define_insn "*arm_cmpdi_unsigned"
7178 [(set (reg:CC_CZ CC_REGNUM)
7179 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7180 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7181 "TARGET_ARM"
7182 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7183 [(set_attr "conds" "set")
7184 (set_attr "length" "8")]
7185)
7186
7187(define_insn "*arm_cmpdi_zero"
7188 [(set (reg:CC_Z CC_REGNUM)
7189 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7190 (const_int 0)))
7191 (clobber (match_scratch:SI 1 "=r"))]
7192 "TARGET_32BIT"
7193 "orr%.\\t%1, %Q0, %R0"
7194 [(set_attr "conds" "set")]
7195)
7196
7197(define_insn "*thumb_cmpdi_zero"
7198 [(set (reg:CC_Z CC_REGNUM)
7199 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7200 (const_int 0)))
7201 (clobber (match_scratch:SI 1 "=l"))]
7202 "TARGET_THUMB1"
7203 "orr\\t%1, %Q0, %R0"
7204 [(set_attr "conds" "set")
7205 (set_attr "length" "2")]
7206)
7207
7d57ec45 7208;; Cirrus SF compare instruction
7209(define_insn "*cirrus_cmpsf"
7210 [(set (reg:CCFP CC_REGNUM)
7211 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7212 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7213 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7214 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7215 [(set_attr "type" "mav_farith")
7d57ec45 7216 (set_attr "cirrus" "compare")]
7217)
7218
7219;; Cirrus DF compare instruction
7220(define_insn "*cirrus_cmpdf"
7221 [(set (reg:CCFP CC_REGNUM)
7222 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7223 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7224 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7225 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7226 [(set_attr "type" "mav_farith")
7d57ec45 7227 (set_attr "cirrus" "compare")]
7228)
7229
7d57ec45 7230(define_insn "*cirrus_cmpdi"
7231 [(set (reg:CC CC_REGNUM)
7232 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7233 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7234 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7235 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7236 [(set_attr "type" "mav_farith")
7d57ec45 7237 (set_attr "cirrus" "compare")]
7238)
7239
9c08d1fa 7240; This insn allows redundant compares to be removed by cse, nothing should
7241; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7242; is deleted later on. The match_dup will match the mode here, so that
7243; mode changes of the condition codes aren't lost by this even though we don't
7244; specify what they are.
7245
8a18b90c 7246(define_insn "*deleted_compare"
9c08d1fa 7247 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7248 "TARGET_32BIT"
40dbec34 7249 "\\t%@ deleted compare"
cffb2a26 7250 [(set_attr "conds" "set")
7251 (set_attr "length" "0")]
7252)
9c08d1fa 7253
7254\f
7255;; Conditional branch insns
7256
74f4459c 7257(define_expand "cbranch_cc"
9c08d1fa 7258 [(set (pc)
74f4459c 7259 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7260 (match_operand 2 "" "")])
7261 (label_ref (match_operand 3 "" ""))
9c08d1fa 7262 (pc)))]
25f905c2 7263 "TARGET_32BIT"
74f4459c 7264 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7265 operands[1], operands[2]);
7266 operands[2] = const0_rtx;"
8fa3ba89 7267)
7268
7269;;
7270;; Patterns to match conditional branch insns.
7271;;
7272
cffb2a26 7273(define_insn "*arm_cond_branch"
9c08d1fa 7274 [(set (pc)
8fa3ba89 7275 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7276 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7277 (label_ref (match_operand 0 "" ""))
7278 (pc)))]
25f905c2 7279 "TARGET_32BIT"
d75350ce 7280 "*
9c08d1fa 7281 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7282 {
7283 arm_ccfsm_state += 2;
7284 return \"\";
7285 }
e2348bcb 7286 return \"b%d1\\t%l0\";
cffb2a26 7287 "
a2cd141b 7288 [(set_attr "conds" "use")
7289 (set_attr "type" "branch")]
cffb2a26 7290)
d75350ce 7291
cffb2a26 7292(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7293 [(set (pc)
8fa3ba89 7294 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7295 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7296 (pc)
7297 (label_ref (match_operand 0 "" ""))))]
25f905c2 7298 "TARGET_32BIT"
d75350ce 7299 "*
9c08d1fa 7300 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7301 {
7302 arm_ccfsm_state += 2;
7303 return \"\";
7304 }
e2348bcb 7305 return \"b%D1\\t%l0\";
cffb2a26 7306 "
a2cd141b 7307 [(set_attr "conds" "use")
7308 (set_attr "type" "branch")]
cffb2a26 7309)
7310
b11cae9e 7311\f
9c08d1fa 7312
7313; scc insns
7314
74f4459c 7315(define_expand "cstore_cc"
7db9af5d 7316 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7317 (match_operator:SI 1 "" [(match_operand 2 "" "")
7318 (match_operand 3 "" "")]))]
25f905c2 7319 "TARGET_32BIT"
74f4459c 7320 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7321 operands[2], operands[3]);
7322 operands[3] = const0_rtx;"
8fa3ba89 7323)
7324
f7fbdd4a 7325(define_insn "*mov_scc"
9c08d1fa 7326 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7327 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7328 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7329 "TARGET_ARM"
4d61e570 7330 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7331 [(set_attr "conds" "use")
d2a518d1 7332 (set_attr "insn" "mov")
cffb2a26 7333 (set_attr "length" "8")]
7334)
9c08d1fa 7335
f7fbdd4a 7336(define_insn "*mov_negscc"
9c08d1fa 7337 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7338 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7339 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7340 "TARGET_ARM"
4d61e570 7341 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7342 [(set_attr "conds" "use")
d2a518d1 7343 (set_attr "insn" "mov")
cffb2a26 7344 (set_attr "length" "8")]
7345)
9c08d1fa 7346
f7fbdd4a 7347(define_insn "*mov_notscc"
9c08d1fa 7348 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7349 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7350 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7351 "TARGET_ARM"
4d61e570 7352 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7353 [(set_attr "conds" "use")
d2a518d1 7354 (set_attr "insn" "mov")
cffb2a26 7355 (set_attr "length" "8")]
7356)
9c08d1fa 7357
595d88b5 7358(define_expand "cstoresi4"
7359 [(set (match_operand:SI 0 "s_register_operand" "")
7360 (match_operator:SI 1 "arm_comparison_operator"
7361 [(match_operand:SI 2 "s_register_operand" "")
7362 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7363 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7364 "{
7365 rtx op3, scratch, scratch2;
7366
74f4459c 7367 if (!TARGET_THUMB1)
7368 {
7369 if (!arm_add_operand (operands[3], SImode))
7370 operands[3] = force_reg (SImode, operands[3]);
7371 emit_insn (gen_cstore_cc (operands[0], operands[1],
7372 operands[2], operands[3]));
7373 DONE;
7374 }
7375
595d88b5 7376 if (operands[3] == const0_rtx)
7377 {
7378 switch (GET_CODE (operands[1]))
7379 {
7380 case EQ:
25f905c2 7381 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7382 break;
7383
7384 case NE:
25f905c2 7385 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7386 break;
7387
7388 case LE:
7389 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7390 NULL_RTX, 0, OPTAB_WIDEN);
7391 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7392 NULL_RTX, 0, OPTAB_WIDEN);
7393 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7394 operands[0], 1, OPTAB_WIDEN);
7395 break;
7396
7397 case GE:
7398 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7399 NULL_RTX, 1);
7400 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7401 NULL_RTX, 1, OPTAB_WIDEN);
7402 break;
7403
7404 case GT:
7405 scratch = expand_binop (SImode, ashr_optab, operands[2],
7406 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7407 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7408 NULL_RTX, 0, OPTAB_WIDEN);
7409 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7410 0, OPTAB_WIDEN);
7411 break;
7412
7413 /* LT is handled by generic code. No need for unsigned with 0. */
7414 default:
7415 FAIL;
7416 }
7417 DONE;
7418 }
7419
7420 switch (GET_CODE (operands[1]))
7421 {
7422 case EQ:
7423 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7424 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7425 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7426 break;
7427
7428 case NE:
7429 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7430 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7431 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7432 break;
7433
7434 case LE:
7435 op3 = force_reg (SImode, operands[3]);
7436
7437 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7438 NULL_RTX, 1, OPTAB_WIDEN);
7439 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7440 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7441 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7442 op3, operands[2]));
7443 break;
7444
7445 case GE:
7446 op3 = operands[3];
25f905c2 7447 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7448 op3 = force_reg (SImode, op3);
7449 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7450 NULL_RTX, 0, OPTAB_WIDEN);
7451 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7452 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7453 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7454 operands[2], op3));
7455 break;
7456
7457 case LEU:
7458 op3 = force_reg (SImode, operands[3]);
7459 scratch = force_reg (SImode, const0_rtx);
25f905c2 7460 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7461 op3, operands[2]));
7462 break;
7463
7464 case GEU:
7465 op3 = operands[3];
25f905c2 7466 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7467 op3 = force_reg (SImode, op3);
7468 scratch = force_reg (SImode, const0_rtx);
25f905c2 7469 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7470 operands[2], op3));
7471 break;
7472
7473 case LTU:
7474 op3 = operands[3];
25f905c2 7475 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7476 op3 = force_reg (SImode, op3);
7477 scratch = gen_reg_rtx (SImode);
408b7ae5 7478 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7479 break;
7480
7481 case GTU:
7482 op3 = force_reg (SImode, operands[3]);
7483 scratch = gen_reg_rtx (SImode);
408b7ae5 7484 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7485 break;
7486
7487 /* No good sequences for GT, LT. */
7488 default:
7489 FAIL;
7490 }
7491 DONE;
7492}")
7493
74f4459c 7494(define_expand "cstoresf4"
7495 [(set (match_operand:SI 0 "s_register_operand" "")
7496 (match_operator:SI 1 "arm_comparison_operator"
7497 [(match_operand:SF 2 "s_register_operand" "")
7498 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7499 "TARGET_32BIT && TARGET_HARD_FLOAT"
7500 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7501 operands[2], operands[3])); DONE;"
7502)
7503
7504(define_expand "cstoredf4"
7505 [(set (match_operand:SI 0 "s_register_operand" "")
7506 (match_operator:SI 1 "arm_comparison_operator"
7507 [(match_operand:DF 2 "s_register_operand" "")
7508 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7509 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7510 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7511 operands[2], operands[3])); DONE;"
7512)
7513
74f4459c 7514(define_expand "cstoredi4"
7515 [(set (match_operand:SI 0 "s_register_operand" "")
7516 (match_operator:SI 1 "arm_comparison_operator"
a8045a4f 7517 [(match_operand:DI 2 "cmpdi_operand" "")
7518 (match_operand:DI 3 "cmpdi_operand" "")]))]
7519 "TARGET_32BIT"
7520 "{
7521 rtx swap = NULL_RTX;
7522 enum rtx_code code = GET_CODE (operands[1]);
7523
7524 /* We should not have two constants. */
7525 gcc_assert (GET_MODE (operands[2]) == DImode
7526 || GET_MODE (operands[3]) == DImode);
7527
7528 /* Flip unimplemented DImode comparisons to a form that
7529 arm_gen_compare_reg can handle. */
7530 switch (code)
7531 {
7532 case GT:
7533 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7534 case LE:
7535 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7536 case GTU:
7537 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7538 case LEU:
7539 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7540 default:
7541 break;
7542 }
7543 if (swap)
7544 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7545 operands[2]));
7546 else
7547 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7548 operands[3]));
7549 DONE;
7550 }"
74f4459c 7551)
7552
25f905c2 7553(define_expand "cstoresi_eq0_thumb1"
595d88b5 7554 [(parallel
7555 [(set (match_operand:SI 0 "s_register_operand" "")
7556 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7557 (const_int 0)))
7558 (clobber (match_dup:SI 2))])]
25f905c2 7559 "TARGET_THUMB1"
595d88b5 7560 "operands[2] = gen_reg_rtx (SImode);"
7561)
7562
25f905c2 7563(define_expand "cstoresi_ne0_thumb1"
595d88b5 7564 [(parallel
7565 [(set (match_operand:SI 0 "s_register_operand" "")
7566 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7567 (const_int 0)))
7568 (clobber (match_dup:SI 2))])]
25f905c2 7569 "TARGET_THUMB1"
595d88b5 7570 "operands[2] = gen_reg_rtx (SImode);"
7571)
7572
25f905c2 7573(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7574 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7575 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7576 (const_int 0)))
7577 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7578 "TARGET_THUMB1"
595d88b5 7579 "@
7580 neg\\t%0, %1\;adc\\t%0, %0, %1
7581 neg\\t%2, %1\;adc\\t%0, %1, %2"
7582 [(set_attr "length" "4")]
7583)
7584
25f905c2 7585(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7586 [(set (match_operand:SI 0 "s_register_operand" "=l")
7587 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7588 (const_int 0)))
7589 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7590 "TARGET_THUMB1"
595d88b5 7591 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7592 [(set_attr "length" "4")]
7593)
7594
408b7ae5 7595;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 7596(define_insn "cstoresi_nltu_thumb1"
595d88b5 7597 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7598 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7599 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7600 "TARGET_THUMB1"
595d88b5 7601 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7602 [(set_attr "length" "4")]
7603)
7604
408b7ae5 7605(define_insn_and_split "cstoresi_ltu_thumb1"
7606 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7607 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7608 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7609 "TARGET_THUMB1"
7610 "#"
7611 "TARGET_THUMB1"
7612 [(set (match_dup 3)
7613 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7614 (set (match_dup 0) (neg:SI (match_dup 3)))]
7615 "operands[3] = gen_reg_rtx (SImode);"
7616 [(set_attr "length" "4")]
7617)
7618
595d88b5 7619;; Used as part of the expansion of thumb les sequence.
25f905c2 7620(define_insn "thumb1_addsi3_addgeu"
595d88b5 7621 [(set (match_operand:SI 0 "s_register_operand" "=l")
7622 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7623 (match_operand:SI 2 "s_register_operand" "l"))
7624 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 7625 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7626 "TARGET_THUMB1"
595d88b5 7627 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7628 [(set_attr "length" "4")]
7629)
7630
9c08d1fa 7631\f
39b5e676 7632;; Conditional move insns
7633
7634(define_expand "movsicc"
8a18b90c 7635 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7636 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7637 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7638 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7639 "TARGET_32BIT"
39b5e676 7640 "
215b30b3 7641 {
7642 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7643 rtx ccreg;
7644
7645 if (code == UNEQ || code == LTGT)
7646 FAIL;
39b5e676 7647
74f4459c 7648 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7649 XEXP (operands[1], 1));
29bb088d 7650 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7651 }"
7652)
39b5e676 7653
7654(define_expand "movsfcc"
8a18b90c 7655 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7656 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7657 (match_operand:SF 2 "s_register_operand" "")
7658 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 7659 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7660 "
215b30b3 7661 {
7662 enum rtx_code code = GET_CODE (operands[1]);
7663 rtx ccreg;
f082f1c4 7664
278b301d 7665 if (code == UNEQ || code == LTGT)
7666 FAIL;
7667
215b30b3 7668 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7669 Otherwise, ensure it is a valid FP add operand */
7670 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7671 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7672 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7673
74f4459c 7674 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7675 XEXP (operands[1], 1));
29bb088d 7676 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7677 }"
7678)
39b5e676 7679
7680(define_expand "movdfcc"
8a18b90c 7681 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7682 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7683 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7684 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 7685 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 7686 "
215b30b3 7687 {
7688 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7689 rtx ccreg;
39b5e676 7690
278b301d 7691 if (code == UNEQ || code == LTGT)
7692 FAIL;
7693
74f4459c 7694 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7695 XEXP (operands[1], 1));
29bb088d 7696 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7697 }"
7698)
39b5e676 7699
7700(define_insn "*movsicc_insn"
f082f1c4 7701 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7702 (if_then_else:SI
8fa3ba89 7703 (match_operator 3 "arm_comparison_operator"
8a18b90c 7704 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7705 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7706 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7707 "TARGET_ARM"
39b5e676 7708 "@
8a18b90c 7709 mov%D3\\t%0, %2
7710 mvn%D3\\t%0, #%B2
f082f1c4 7711 mov%d3\\t%0, %1
7712 mvn%d3\\t%0, #%B1
8a18b90c 7713 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7714 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7715 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7716 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7717 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7718 (set_attr "conds" "use")
7719 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 7720)
39b5e676 7721
39b5e676 7722(define_insn "*movsfcc_soft_insn"
f082f1c4 7723 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7724 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7725 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7726 (match_operand:SF 1 "s_register_operand" "0,r")
7727 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7728 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7729 "@
7730 mov%D3\\t%0, %2
7731 mov%d3\\t%0, %1"
d2a518d1 7732 [(set_attr "conds" "use")
7733 (set_attr "insn" "mov")]
8fa3ba89 7734)
39b5e676 7735
39b5e676 7736\f
9c08d1fa 7737;; Jump and linkage insns
7738
cffb2a26 7739(define_expand "jump"
9c08d1fa 7740 [(set (pc)
7741 (label_ref (match_operand 0 "" "")))]
cffb2a26 7742 "TARGET_EITHER"
9c08d1fa 7743 ""
cffb2a26 7744)
7745
7746(define_insn "*arm_jump"
7747 [(set (pc)
7748 (label_ref (match_operand 0 "" "")))]
25f905c2 7749 "TARGET_32BIT"
9c08d1fa 7750 "*
0d66636f 7751 {
7752 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7753 {
7754 arm_ccfsm_state += 2;
7755 return \"\";
7756 }
7757 return \"b%?\\t%l0\";
7758 }
7759 "
7760 [(set_attr "predicable" "yes")]
7761)
9c08d1fa 7762
cffb2a26 7763(define_insn "*thumb_jump"
7764 [(set (pc)
7765 (label_ref (match_operand 0 "" "")))]
25f905c2 7766 "TARGET_THUMB1"
cffb2a26 7767 "*
7768 if (get_attr_length (insn) == 2)
7769 return \"b\\t%l0\";
7770 return \"bl\\t%l0\\t%@ far jump\";
7771 "
7772 [(set (attr "far_jump")
7773 (if_then_else
7774 (eq_attr "length" "4")
7775 (const_string "yes")
7776 (const_string "no")))
7777 (set (attr "length")
7778 (if_then_else
911ed8af 7779 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7780 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7781 (const_int 2)
7782 (const_int 4)))]
7783)
7784
d3373b54 7785(define_expand "call"
7786 [(parallel [(call (match_operand 0 "memory_operand" "")
7787 (match_operand 1 "general_operand" ""))
cffb2a26 7788 (use (match_operand 2 "" ""))
bd5b4116 7789 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7790 "TARGET_EITHER"
6c4c2133 7791 "
7792 {
bac7fc85 7793 rtx callee, pat;
bbe777ea 7794
bbe777ea 7795 /* In an untyped call, we can get NULL for operand 2. */
7796 if (operands[2] == NULL_RTX)
7797 operands[2] = const0_rtx;
7798
de55252a 7799 /* Decide if we should generate indirect calls by loading the
85c36fd1 7800 32-bit address of the callee into a register before performing the
de55252a 7801 branch and link. */
7802 callee = XEXP (operands[0], 0);
7803 if (GET_CODE (callee) == SYMBOL_REF
7804 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7805 : !REG_P (callee))
bbe777ea 7806 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7807
7808 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7809 arm_emit_call_insn (pat, XEXP (operands[0], 0));
7810 DONE;
6c4c2133 7811 }"
7812)
d3373b54 7813
bac7fc85 7814(define_expand "call_internal"
7815 [(parallel [(call (match_operand 0 "memory_operand" "")
7816 (match_operand 1 "general_operand" ""))
7817 (use (match_operand 2 "" ""))
7818 (clobber (reg:SI LR_REGNUM))])])
7819
f1039640 7820(define_insn "*call_reg_armv5"
d3373b54 7821 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7822 (match_operand 1 "" ""))
7823 (use (match_operand 2 "" ""))
bd5b4116 7824 (clobber (reg:SI LR_REGNUM))]
f1039640 7825 "TARGET_ARM && arm_arch5"
7826 "blx%?\\t%0"
7827 [(set_attr "type" "call")]
7828)
7829
7830(define_insn "*call_reg_arm"
7831 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7832 (match_operand 1 "" ""))
7833 (use (match_operand 2 "" ""))
7834 (clobber (reg:SI LR_REGNUM))]
7835 "TARGET_ARM && !arm_arch5"
9c08d1fa 7836 "*
5565501b 7837 return output_call (operands);
cffb2a26 7838 "
7839 ;; length is worst case, normally it is only two
7840 [(set_attr "length" "12")
7841 (set_attr "type" "call")]
7842)
9c08d1fa 7843
89504fc1 7844
7845;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7846;; considered a function call by the branch predictor of some cores (PR40887).
7847;; Falls back to blx rN (*call_reg_armv5).
7848
f7fbdd4a 7849(define_insn "*call_mem"
a3c63a9d 7850 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7851 (match_operand 1 "" ""))
7852 (use (match_operand 2 "" ""))
bd5b4116 7853 (clobber (reg:SI LR_REGNUM))]
89504fc1 7854 "TARGET_ARM && !arm_arch5"
9c08d1fa 7855 "*
5565501b 7856 return output_call_mem (operands);
cffb2a26 7857 "
7858 [(set_attr "length" "12")
7859 (set_attr "type" "call")]
7860)
7861
25f905c2 7862(define_insn "*call_reg_thumb1_v5"
cffb2a26 7863 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7864 (match_operand 1 "" ""))
7865 (use (match_operand 2 "" ""))
bd5b4116 7866 (clobber (reg:SI LR_REGNUM))]
25f905c2 7867 "TARGET_THUMB1 && arm_arch5"
f1039640 7868 "blx\\t%0"
7869 [(set_attr "length" "2")
7870 (set_attr "type" "call")]
cffb2a26 7871)
7872
25f905c2 7873(define_insn "*call_reg_thumb1"
f1039640 7874 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7875 (match_operand 1 "" ""))
7876 (use (match_operand 2 "" ""))
bd5b4116 7877 (clobber (reg:SI LR_REGNUM))]
25f905c2 7878 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 7879 "*
7880 {
150502c9 7881 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7882 return thumb_call_via_reg (operands[0]);
150502c9 7883 else if (operands[1] == const0_rtx)
f1039640 7884 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7885 else if (frame_pointer_needed)
7886 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7887 else
150502c9 7888 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7889 }"
7890 [(set_attr "type" "call")]
7891)
9c08d1fa 7892
d3373b54 7893(define_expand "call_value"
e0698af7 7894 [(parallel [(set (match_operand 0 "" "")
7895 (call (match_operand 1 "memory_operand" "")
7896 (match_operand 2 "general_operand" "")))
cffb2a26 7897 (use (match_operand 3 "" ""))
bd5b4116 7898 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7899 "TARGET_EITHER"
6c4c2133 7900 "
7901 {
bac7fc85 7902 rtx pat, callee;
bbe777ea 7903
7904 /* In an untyped call, we can get NULL for operand 2. */
7905 if (operands[3] == 0)
7906 operands[3] = const0_rtx;
7907
de55252a 7908 /* Decide if we should generate indirect calls by loading the
7909 32-bit address of the callee into a register before performing the
7910 branch and link. */
7911 callee = XEXP (operands[1], 0);
7912 if (GET_CODE (callee) == SYMBOL_REF
7913 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7914 : !REG_P (callee))
78fe751b 7915 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7916
7917 pat = gen_call_value_internal (operands[0], operands[1],
7918 operands[2], operands[3]);
7919 arm_emit_call_insn (pat, XEXP (operands[1], 0));
7920 DONE;
6c4c2133 7921 }"
7922)
d3373b54 7923
bac7fc85 7924(define_expand "call_value_internal"
7925 [(parallel [(set (match_operand 0 "" "")
7926 (call (match_operand 1 "memory_operand" "")
7927 (match_operand 2 "general_operand" "")))
7928 (use (match_operand 3 "" ""))
7929 (clobber (reg:SI LR_REGNUM))])])
7930
f1039640 7931(define_insn "*call_value_reg_armv5"
27ed6835 7932 [(set (match_operand 0 "" "")
755eb2b4 7933 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7934 (match_operand 2 "" "")))
bbe777ea 7935 (use (match_operand 3 "" ""))
bd5b4116 7936 (clobber (reg:SI LR_REGNUM))]
f1039640 7937 "TARGET_ARM && arm_arch5"
7938 "blx%?\\t%1"
7939 [(set_attr "type" "call")]
7940)
7941
7942(define_insn "*call_value_reg_arm"
7943 [(set (match_operand 0 "" "")
7944 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7945 (match_operand 2 "" "")))
7946 (use (match_operand 3 "" ""))
7947 (clobber (reg:SI LR_REGNUM))]
7948 "TARGET_ARM && !arm_arch5"
9c08d1fa 7949 "*
215b30b3 7950 return output_call (&operands[1]);
cffb2a26 7951 "
7952 [(set_attr "length" "12")
7953 (set_attr "type" "call")]
7954)
9c08d1fa 7955
89504fc1 7956;; Note: see *call_mem
7957
f7fbdd4a 7958(define_insn "*call_value_mem"
27ed6835 7959 [(set (match_operand 0 "" "")
a3c63a9d 7960 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7961 (match_operand 2 "" "")))
bbe777ea 7962 (use (match_operand 3 "" ""))
bd5b4116 7963 (clobber (reg:SI LR_REGNUM))]
89504fc1 7964 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7965 "*
215b30b3 7966 return output_call_mem (&operands[1]);
cffb2a26 7967 "
7968 [(set_attr "length" "12")
7969 (set_attr "type" "call")]
7970)
9c08d1fa 7971
25f905c2 7972(define_insn "*call_value_reg_thumb1_v5"
f1039640 7973 [(set (match_operand 0 "" "")
7974 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7975 (match_operand 2 "" "")))
7976 (use (match_operand 3 "" ""))
7977 (clobber (reg:SI LR_REGNUM))]
25f905c2 7978 "TARGET_THUMB1 && arm_arch5"
f1039640 7979 "blx\\t%1"
7980 [(set_attr "length" "2")
7981 (set_attr "type" "call")]
7982)
7983
25f905c2 7984(define_insn "*call_value_reg_thumb1"
f1039640 7985 [(set (match_operand 0 "" "")
7986 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7987 (match_operand 2 "" "")))
7988 (use (match_operand 3 "" ""))
7989 (clobber (reg:SI LR_REGNUM))]
25f905c2 7990 "TARGET_THUMB1 && !arm_arch5"
f1039640 7991 "*
7992 {
150502c9 7993 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7994 return thumb_call_via_reg (operands[1]);
150502c9 7995 else if (operands[2] == const0_rtx)
f1039640 7996 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7997 else if (frame_pointer_needed)
7998 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7999 else
150502c9 8000 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8001 }"
8002 [(set_attr "type" "call")]
8003)
8004
9c08d1fa 8005;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8006;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8007
f7fbdd4a 8008(define_insn "*call_symbol"
27ed6835 8009 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8010 (match_operand 1 "" ""))
bbe777ea 8011 (use (match_operand 2 "" ""))
bd5b4116 8012 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8013 "TARGET_32BIT
cffb2a26 8014 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8015 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8016 "*
8017 {
55c1e470 8018 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8019 }"
cffb2a26 8020 [(set_attr "type" "call")]
8021)
9c08d1fa 8022
f7fbdd4a 8023(define_insn "*call_value_symbol"
ccd90aaa 8024 [(set (match_operand 0 "" "")
27ed6835 8025 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8026 (match_operand:SI 2 "" "")))
bbe777ea 8027 (use (match_operand 3 "" ""))
bd5b4116 8028 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8029 "TARGET_32BIT
cffb2a26 8030 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8031 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8032 "*
8033 {
55c1e470 8034 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8035 }"
cffb2a26 8036 [(set_attr "type" "call")]
8037)
8038
8039(define_insn "*call_insn"
27ed6835 8040 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8041 (match_operand:SI 1 "" ""))
8042 (use (match_operand 2 "" ""))
bd5b4116 8043 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8044 "TARGET_THUMB1
1675c6e9 8045 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8046 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8047 "bl\\t%a0"
8048 [(set_attr "length" "4")
8049 (set_attr "type" "call")]
8050)
8051
8052(define_insn "*call_value_insn"
ccd90aaa 8053 [(set (match_operand 0 "" "")
27ed6835 8054 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8055 (match_operand 2 "" "")))
8056 (use (match_operand 3 "" ""))
bd5b4116 8057 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8058 "TARGET_THUMB1
1675c6e9 8059 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8060 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8061 "bl\\t%a1"
8062 [(set_attr "length" "4")
8063 (set_attr "type" "call")]
8064)
9c08d1fa 8065
1c494086 8066;; We may also be able to do sibcalls for Thumb, but it's much harder...
8067(define_expand "sibcall"
8068 [(parallel [(call (match_operand 0 "memory_operand" "")
8069 (match_operand 1 "general_operand" ""))
2ba80634 8070 (return)
8071 (use (match_operand 2 "" ""))])]
d68c2c10 8072 "TARGET_32BIT"
1c494086 8073 "
8074 {
8075 if (operands[2] == NULL_RTX)
8076 operands[2] = const0_rtx;
1c494086 8077 }"
8078)
8079
8080(define_expand "sibcall_value"
ccd90aaa 8081 [(parallel [(set (match_operand 0 "" "")
1c494086 8082 (call (match_operand 1 "memory_operand" "")
8083 (match_operand 2 "general_operand" "")))
2ba80634 8084 (return)
8085 (use (match_operand 3 "" ""))])]
d68c2c10 8086 "TARGET_32BIT"
1c494086 8087 "
8088 {
8089 if (operands[3] == NULL_RTX)
8090 operands[3] = const0_rtx;
1c494086 8091 }"
8092)
8093
8094(define_insn "*sibcall_insn"
8095 [(call (mem:SI (match_operand:SI 0 "" "X"))
8096 (match_operand 1 "" ""))
2ba80634 8097 (return)
8098 (use (match_operand 2 "" ""))]
d68c2c10 8099 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8100 "*
8101 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8102 "
8103 [(set_attr "type" "call")]
8104)
8105
8106(define_insn "*sibcall_value_insn"
ccd90aaa 8107 [(set (match_operand 0 "" "")
755eb2b4 8108 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8109 (match_operand 2 "" "")))
2ba80634 8110 (return)
8111 (use (match_operand 3 "" ""))]
d68c2c10 8112 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8113 "*
8114 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8115 "
8116 [(set_attr "type" "call")]
8117)
8118
d68c2c10 8119(define_expand "return"
8120 [(return)]
8121 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8122 "")
8123
9c08d1fa 8124;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8125(define_insn "*arm_return"
9c08d1fa 8126 [(return)]
cffb2a26 8127 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8128 "*
9c08d1fa 8129 {
cffb2a26 8130 if (arm_ccfsm_state == 2)
8131 {
8132 arm_ccfsm_state += 2;
8133 return \"\";
8134 }
5db468b7 8135 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8136 }"
a2cd141b 8137 [(set_attr "type" "load1")
755eb2b4 8138 (set_attr "length" "12")
0d66636f 8139 (set_attr "predicable" "yes")]
cffb2a26 8140)
9c08d1fa 8141
f7fbdd4a 8142(define_insn "*cond_return"
9c08d1fa 8143 [(set (pc)
8fa3ba89 8144 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8145 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8146 (return)
8147 (pc)))]
cffb2a26 8148 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8149 "*
8fa3ba89 8150 {
8151 if (arm_ccfsm_state == 2)
8152 {
8153 arm_ccfsm_state += 2;
8154 return \"\";
8155 }
8156 return output_return_instruction (operands[0], TRUE, FALSE);
8157 }"
8158 [(set_attr "conds" "use")
755eb2b4 8159 (set_attr "length" "12")
a2cd141b 8160 (set_attr "type" "load1")]
8fa3ba89 8161)
9c08d1fa 8162
f7fbdd4a 8163(define_insn "*cond_return_inverted"
9c08d1fa 8164 [(set (pc)
8fa3ba89 8165 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8166 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8167 (pc)
8168 (return)))]
cffb2a26 8169 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8170 "*
8fa3ba89 8171 {
8172 if (arm_ccfsm_state == 2)
8173 {
8174 arm_ccfsm_state += 2;
8175 return \"\";
8176 }
8177 return output_return_instruction (operands[0], TRUE, TRUE);
8178 }"
8179 [(set_attr "conds" "use")
37a1317b 8180 (set_attr "length" "12")
a2cd141b 8181 (set_attr "type" "load1")]
8fa3ba89 8182)
9c08d1fa 8183
68121397 8184;; Generate a sequence of instructions to determine if the processor is
8185;; in 26-bit or 32-bit mode, and return the appropriate return address
8186;; mask.
8187
8188(define_expand "return_addr_mask"
8189 [(set (match_dup 1)
8190 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8191 (const_int 0)))
8192 (set (match_operand:SI 0 "s_register_operand" "")
8193 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8194 (const_int -1)
8195 (const_int 67108860)))] ; 0x03fffffc
8196 "TARGET_ARM"
8197 "
62eddbd4 8198 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8199 ")
8200
8201(define_insn "*check_arch2"
8202 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8203 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8204 (const_int 0)))]
8205 "TARGET_ARM"
8206 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8207 [(set_attr "length" "8")
8208 (set_attr "conds" "set")]
8209)
8210
9c08d1fa 8211;; Call subroutine returning any type.
8212
8213(define_expand "untyped_call"
8214 [(parallel [(call (match_operand 0 "" "")
8215 (const_int 0))
8216 (match_operand 1 "" "")
8217 (match_operand 2 "" "")])]
ccd90aaa 8218 "TARGET_EITHER"
9c08d1fa 8219 "
215b30b3 8220 {
8221 int i;
ccd90aaa 8222 rtx par = gen_rtx_PARALLEL (VOIDmode,
8223 rtvec_alloc (XVECLEN (operands[2], 0)));
8224 rtx addr = gen_reg_rtx (Pmode);
8225 rtx mem;
8226 int size = 0;
9c08d1fa 8227
ccd90aaa 8228 emit_move_insn (addr, XEXP (operands[1], 0));
8229 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8230
215b30b3 8231 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8232 {
ccd90aaa 8233 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8234
ccd90aaa 8235 /* Default code only uses r0 as a return value, but we could
8236 be using anything up to 4 registers. */
8237 if (REGNO (src) == R0_REGNUM)
8238 src = gen_rtx_REG (TImode, R0_REGNUM);
8239
8240 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8241 GEN_INT (size));
8242 size += GET_MODE_SIZE (GET_MODE (src));
8243 }
8244
8245 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8246 const0_rtx));
8247
8248 size = 0;
8249
8250 for (i = 0; i < XVECLEN (par, 0); i++)
8251 {
8252 HOST_WIDE_INT offset = 0;
8253 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8254
8255 if (size != 0)
8256 emit_move_insn (addr, plus_constant (addr, size));
8257
8258 mem = change_address (mem, GET_MODE (reg), NULL);
8259 if (REGNO (reg) == R0_REGNUM)
8260 {
8261 /* On thumb we have to use a write-back instruction. */
320ea44d 8262 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8263 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8264 size = TARGET_ARM ? 16 : 0;
8265 }
8266 else
8267 {
8268 emit_move_insn (mem, reg);
8269 size = GET_MODE_SIZE (GET_MODE (reg));
8270 }
215b30b3 8271 }
9c08d1fa 8272
215b30b3 8273 /* The optimizer does not know that the call sets the function value
8274 registers we stored in the result block. We avoid problems by
8275 claiming that all hard registers are used and clobbered at this
8276 point. */
8277 emit_insn (gen_blockage ());
8278
8279 DONE;
8280 }"
8281)
9c08d1fa 8282
ccd90aaa 8283(define_expand "untyped_return"
8284 [(match_operand:BLK 0 "memory_operand" "")
8285 (match_operand 1 "" "")]
8286 "TARGET_EITHER"
8287 "
8288 {
8289 int i;
8290 rtx addr = gen_reg_rtx (Pmode);
8291 rtx mem;
8292 int size = 0;
8293
8294 emit_move_insn (addr, XEXP (operands[0], 0));
8295 mem = change_address (operands[0], BLKmode, addr);
8296
8297 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8298 {
8299 HOST_WIDE_INT offset = 0;
8300 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8301
8302 if (size != 0)
8303 emit_move_insn (addr, plus_constant (addr, size));
8304
8305 mem = change_address (mem, GET_MODE (reg), NULL);
8306 if (REGNO (reg) == R0_REGNUM)
8307 {
8308 /* On thumb we have to use a write-back instruction. */
320ea44d 8309 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8310 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8311 size = TARGET_ARM ? 16 : 0;
8312 }
8313 else
8314 {
8315 emit_move_insn (reg, mem);
8316 size = GET_MODE_SIZE (GET_MODE (reg));
8317 }
8318 }
8319
8320 /* Emit USE insns before the return. */
8321 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8322 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8323
8324 /* Construct the return. */
8325 expand_naked_return ();
8326
8327 DONE;
8328 }"
8329)
8330
9c08d1fa 8331;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8332;; all of memory. This blocks insns from being moved across this point.
8333
8334(define_insn "blockage"
e1159bbe 8335 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8336 "TARGET_EITHER"
9c08d1fa 8337 ""
cffb2a26 8338 [(set_attr "length" "0")
8339 (set_attr "type" "block")]
8340)
9c08d1fa 8341
f7fbdd4a 8342(define_expand "casesi"
8343 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8344 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8345 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8346 (match_operand:SI 3 "" "") ; table label
8347 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8348 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8349 "
215b30b3 8350 {
e6ac8414 8351 enum insn_code code;
215b30b3 8352 if (operands[1] != const0_rtx)
8353 {
e6ac8414 8354 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8355
215b30b3 8356 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8357 gen_int_mode (-INTVAL (operands[1]),
8358 SImode)));
215b30b3 8359 operands[0] = reg;
8360 }
9c08d1fa 8361
25f905c2 8362 if (TARGET_ARM)
e6ac8414 8363 code = CODE_FOR_arm_casesi_internal;
3db2019b 8364 else if (TARGET_THUMB1)
e6ac8414 8365 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8366 else if (flag_pic)
e6ac8414 8367 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8368 else
e6ac8414 8369 code = CODE_FOR_thumb2_casesi_internal;
8370
8371 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8372 operands[2] = force_reg (SImode, operands[2]);
8373
8374 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8375 operands[3], operands[4]));
215b30b3 8376 DONE;
8377 }"
8378)
f7fbdd4a 8379
f082f1c4 8380;; The USE in this pattern is needed to tell flow analysis that this is
8381;; a CASESI insn. It has no other purpose.
25f905c2 8382(define_insn "arm_casesi_internal"
f082f1c4 8383 [(parallel [(set (pc)
8384 (if_then_else
8385 (leu (match_operand:SI 0 "s_register_operand" "r")
8386 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8387 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8388 (label_ref (match_operand 2 "" ""))))
8389 (label_ref (match_operand 3 "" ""))))
bd5b4116 8390 (clobber (reg:CC CC_REGNUM))
f082f1c4 8391 (use (label_ref (match_dup 2)))])]
cffb2a26 8392 "TARGET_ARM"
f7fbdd4a 8393 "*
0d66636f 8394 if (flag_pic)
8395 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8396 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8397 "
8398 [(set_attr "conds" "clob")
8399 (set_attr "length" "12")]
8400)
9c08d1fa 8401
e6ac8414 8402(define_expand "thumb1_casesi_internal_pic"
8403 [(match_operand:SI 0 "s_register_operand" "")
8404 (match_operand:SI 1 "thumb1_cmp_operand" "")
8405 (match_operand 2 "" "")
8406 (match_operand 3 "" "")]
3db2019b 8407 "TARGET_THUMB1"
e6ac8414 8408 {
8409 rtx reg0;
8410 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8411 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8412 operands[3]));
8413 reg0 = gen_rtx_REG (SImode, 0);
8414 emit_move_insn (reg0, operands[0]);
8415 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8416 DONE;
8417 }
8418)
8419
8420(define_insn "thumb1_casesi_dispatch"
8421 [(parallel [(set (pc) (unspec [(reg:SI 0)
8422 (label_ref (match_operand 0 "" ""))
8423;; (label_ref (match_operand 1 "" ""))
8424]
8425 UNSPEC_THUMB1_CASESI))
8426 (clobber (reg:SI IP_REGNUM))
8427 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8428 "TARGET_THUMB1"
e6ac8414 8429 "* return thumb1_output_casesi(operands);"
8430 [(set_attr "length" "4")]
8431)
8432
cffb2a26 8433(define_expand "indirect_jump"
9c08d1fa 8434 [(set (pc)
cffb2a26 8435 (match_operand:SI 0 "s_register_operand" ""))]
8436 "TARGET_EITHER"
25f905c2 8437 "
8438 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8439 address and use bx. */
8440 if (TARGET_THUMB2)
8441 {
8442 rtx tmp;
8443 tmp = gen_reg_rtx (SImode);
8444 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8445 operands[0] = tmp;
8446 }
8447 "
cffb2a26 8448)
8449
f1039640 8450;; NB Never uses BX.
cffb2a26 8451(define_insn "*arm_indirect_jump"
8452 [(set (pc)
8453 (match_operand:SI 0 "s_register_operand" "r"))]
8454 "TARGET_ARM"
8455 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8456 [(set_attr "predicable" "yes")]
cffb2a26 8457)
9c08d1fa 8458
f7fbdd4a 8459(define_insn "*load_indirect_jump"
9c08d1fa 8460 [(set (pc)
8461 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8462 "TARGET_ARM"
8463 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8464 [(set_attr "type" "load1")
61a2d04c 8465 (set_attr "pool_range" "4096")
8466 (set_attr "neg_pool_range" "4084")
0d66636f 8467 (set_attr "predicable" "yes")]
cffb2a26 8468)
8469
f1039640 8470;; NB Never uses BX.
25f905c2 8471(define_insn "*thumb1_indirect_jump"
cffb2a26 8472 [(set (pc)
8473 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8474 "TARGET_THUMB1"
cffb2a26 8475 "mov\\tpc, %0"
8476 [(set_attr "conds" "clob")
8477 (set_attr "length" "2")]
8478)
8479
9c08d1fa 8480\f
8481;; Misc insns
8482
8483(define_insn "nop"
8484 [(const_int 0)]
cffb2a26 8485 "TARGET_EITHER"
8486 "*
25f905c2 8487 if (TARGET_UNIFIED_ASM)
8488 return \"nop\";
cffb2a26 8489 if (TARGET_ARM)
8490 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8491 return \"mov\\tr8, r8\";
8492 "
8493 [(set (attr "length")
8494 (if_then_else (eq_attr "is_thumb" "yes")
8495 (const_int 2)
8496 (const_int 4)))]
8497)
8498
9c08d1fa 8499\f
8500;; Patterns to allow combination of arithmetic, cond code and shifts
8501
f7fbdd4a 8502(define_insn "*arith_shiftsi"
d5d4dc8d 8503 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8504 (match_operator:SI 1 "shiftable_operator"
8505 [(match_operator:SI 3 "shift_operator"
d5d4dc8d 8506 [(match_operand:SI 4 "s_register_operand" "r,r")
8507 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8508 (match_operand:SI 2 "s_register_operand" "rk,rk")]))]
8509 "TARGET_32BIT"
6c4c2133 8510 "%i1%?\\t%0, %2, %4%S3"
344495ea 8511 [(set_attr "predicable" "yes")
331beb1a 8512 (set_attr "shift" "4")
d5d4dc8d 8513 (set_attr "arch" "32,a")
8514 ;; We have to make sure to disable the second alternative if
8515 ;; the shift_operator is MULT, since otherwise the insn will
8516 ;; also match a multiply_accumulate pattern and validate_change
8517 ;; will allow a replacement of the constant with a register
8518 ;; despite the checks done in shift_operator.
8519 (set_attr_alternative "insn_enabled"
8520 [(const_string "yes")
8521 (if_then_else
8522 (match_operand:SI 3 "mult_operator" "")
8523 (const_string "no") (const_string "yes"))])
8524 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8525
d7863cfe 8526(define_split
8527 [(set (match_operand:SI 0 "s_register_operand" "")
8528 (match_operator:SI 1 "shiftable_operator"
8529 [(match_operator:SI 2 "shiftable_operator"
8530 [(match_operator:SI 3 "shift_operator"
8531 [(match_operand:SI 4 "s_register_operand" "")
8532 (match_operand:SI 5 "reg_or_int_operand" "")])
8533 (match_operand:SI 6 "s_register_operand" "")])
8534 (match_operand:SI 7 "arm_rhs_operand" "")]))
8535 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8536 "TARGET_32BIT"
d7863cfe 8537 [(set (match_dup 8)
8538 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8539 (match_dup 6)]))
8540 (set (match_dup 0)
8541 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8542 "")
8543
f7fbdd4a 8544(define_insn "*arith_shiftsi_compare0"
bd5b4116 8545 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8546 (compare:CC_NOOV
8547 (match_operator:SI 1 "shiftable_operator"
8548 [(match_operator:SI 3 "shift_operator"
8549 [(match_operand:SI 4 "s_register_operand" "r,r")
8550 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8551 (match_operand:SI 2 "s_register_operand" "r,r")])
8552 (const_int 0)))
8553 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8554 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8555 (match_dup 2)]))]
d5d4dc8d 8556 "TARGET_32BIT"
25f905c2 8557 "%i1%.\\t%0, %2, %4%S3"
344495ea 8558 [(set_attr "conds" "set")
331beb1a 8559 (set_attr "shift" "4")
d5d4dc8d 8560 (set_attr "arch" "32,a")
8561 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8562
f7fbdd4a 8563(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8564 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8565 (compare:CC_NOOV
8566 (match_operator:SI 1 "shiftable_operator"
8567 [(match_operator:SI 3 "shift_operator"
8568 [(match_operand:SI 4 "s_register_operand" "r,r")
8569 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8570 (match_operand:SI 2 "s_register_operand" "r,r")])
8571 (const_int 0)))
8572 (clobber (match_scratch:SI 0 "=r,r"))]
8573 "TARGET_32BIT"
25f905c2 8574 "%i1%.\\t%0, %2, %4%S3"
344495ea 8575 [(set_attr "conds" "set")
331beb1a 8576 (set_attr "shift" "4")
d5d4dc8d 8577 (set_attr "arch" "32,a")
8578 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8579
f7fbdd4a 8580(define_insn "*sub_shiftsi"
d5d4dc8d 8581 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8582 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8583 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8584 [(match_operand:SI 3 "s_register_operand" "r,r")
8585 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8586 "TARGET_32BIT"
6c4c2133 8587 "sub%?\\t%0, %1, %3%S2"
344495ea 8588 [(set_attr "predicable" "yes")
331beb1a 8589 (set_attr "shift" "3")
d5d4dc8d 8590 (set_attr "arch" "32,a")
8591 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8592
f7fbdd4a 8593(define_insn "*sub_shiftsi_compare0"
bd5b4116 8594 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8595 (compare:CC_NOOV
d5d4dc8d 8596 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8597 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8598 [(match_operand:SI 3 "s_register_operand" "r,r")
8599 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8600 (const_int 0)))
d5d4dc8d 8601 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8602 (minus:SI (match_dup 1)
8603 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8604 "TARGET_32BIT"
25f905c2 8605 "sub%.\\t%0, %1, %3%S2"
344495ea 8606 [(set_attr "conds" "set")
a2cd141b 8607 (set_attr "shift" "3")
d5d4dc8d 8608 (set_attr "arch" "32,a")
8609 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8610
f7fbdd4a 8611(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8612 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8613 (compare:CC_NOOV
d5d4dc8d 8614 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8615 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8616 [(match_operand:SI 3 "s_register_operand" "r,r")
8617 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8618 (const_int 0)))
d5d4dc8d 8619 (clobber (match_scratch:SI 0 "=r,r"))]
8620 "TARGET_32BIT"
25f905c2 8621 "sub%.\\t%0, %1, %3%S2"
344495ea 8622 [(set_attr "conds" "set")
a2cd141b 8623 (set_attr "shift" "3")
d5d4dc8d 8624 (set_attr "arch" "32,a")
8625 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8626\f
8627
f7fbdd4a 8628(define_insn "*and_scc"
9c08d1fa 8629 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8630 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8631 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8632 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8633 "TARGET_ARM"
e2348bcb 8634 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8635 [(set_attr "conds" "use")
d2a518d1 8636 (set_attr "insn" "mov")
8fa3ba89 8637 (set_attr "length" "8")]
8638)
9c08d1fa 8639
f7fbdd4a 8640(define_insn "*ior_scc"
9c08d1fa 8641 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8642 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8643 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8644 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8645 "TARGET_ARM"
e2348bcb 8646 "@
899850b0 8647 orr%d2\\t%0, %1, #1
8648 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8649 [(set_attr "conds" "use")
8650 (set_attr "length" "4,8")]
8651)
9c08d1fa 8652
2df9477b 8653; A series of splitters for the compare_scc pattern below. Note that
8654; order is important.
8655(define_split
8656 [(set (match_operand:SI 0 "s_register_operand" "")
8657 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8658 (const_int 0)))
8659 (clobber (reg:CC CC_REGNUM))]
8660 "TARGET_32BIT && reload_completed"
8661 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8662
8663(define_split
8664 [(set (match_operand:SI 0 "s_register_operand" "")
8665 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8666 (const_int 0)))
8667 (clobber (reg:CC CC_REGNUM))]
8668 "TARGET_32BIT && reload_completed"
8669 [(set (match_dup 0) (not:SI (match_dup 1)))
8670 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8671
8672(define_split
8673 [(set (match_operand:SI 0 "s_register_operand" "")
8674 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8675 (const_int 0)))
8676 (clobber (reg:CC CC_REGNUM))]
8677 "TARGET_32BIT && reload_completed"
8678 [(parallel
080c0b9a 8679 [(set (reg:CC CC_REGNUM)
8680 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8681 (set (match_dup 0)
8682 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8683 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8684 (set (match_dup 0) (const_int 0)))])
8685
8686(define_split
8687 [(set (match_operand:SI 0 "s_register_operand" "")
8688 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8689 (match_operand:SI 2 "const_int_operand" "")))
8690 (clobber (reg:CC CC_REGNUM))]
8691 "TARGET_32BIT && reload_completed"
8692 [(parallel
8693 [(set (reg:CC CC_REGNUM)
8694 (compare:CC (match_dup 1) (match_dup 2)))
8695 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8696 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8697 (set (match_dup 0) (const_int 1)))]
8698{
8699 operands[3] = GEN_INT (-INTVAL (operands[2]));
8700})
8701
8702(define_split
8703 [(set (match_operand:SI 0 "s_register_operand" "")
8704 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8705 (match_operand:SI 2 "arm_add_operand" "")))
8706 (clobber (reg:CC CC_REGNUM))]
8707 "TARGET_32BIT && reload_completed"
8708 [(parallel
8709 [(set (reg:CC_NOOV CC_REGNUM)
8710 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8711 (const_int 0)))
8712 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8713 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8714 (set (match_dup 0) (const_int 1)))])
8715
8716(define_insn_and_split "*compare_scc"
5565501b 8717 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8718 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8719 [(match_operand:SI 2 "s_register_operand" "r,r")
8720 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8721 (clobber (reg:CC CC_REGNUM))]
2df9477b 8722 "TARGET_32BIT"
8723 "#"
8724 "&& reload_completed"
8725 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8726 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8727 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8728{
8729 rtx tmp1;
8730 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8731 operands[2], operands[3]);
8732 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8733
2df9477b 8734 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8735
2df9477b 8736 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8737 if (mode == CCFPmode || mode == CCFPEmode)
8738 rc = reverse_condition_maybe_unordered (rc);
8739 else
8740 rc = reverse_condition (rc);
8741 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8742})
9c08d1fa 8743
080c0b9a 8744;; Attempt to improve the sequence generated by the compare_scc splitters
8745;; not to use conditional execution.
8746(define_peephole2
8747 [(set (reg:CC CC_REGNUM)
8748 (compare:CC (match_operand:SI 1 "register_operand" "")
8749 (match_operand:SI 2 "arm_rhs_operand" "")))
8750 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8751 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8752 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8753 (set (match_dup 0) (const_int 1)))
8754 (match_scratch:SI 3 "r")]
8755 "TARGET_32BIT"
8756 [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
8757 (parallel
8758 [(set (reg:CC CC_REGNUM)
8759 (compare:CC (const_int 0) (match_dup 3)))
8760 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8761 (set (match_dup 0)
8762 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8763 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
8764
f7fbdd4a 8765(define_insn "*cond_move"
9c08d1fa 8766 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8767 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8768 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8769 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8770 (const_int 0)])
8771 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8772 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8773 "TARGET_ARM"
9c08d1fa 8774 "*
8fa3ba89 8775 if (GET_CODE (operands[3]) == NE)
8776 {
8777 if (which_alternative != 1)
8778 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8779 if (which_alternative != 0)
8780 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8781 return \"\";
8782 }
8783 if (which_alternative != 0)
8784 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8785 if (which_alternative != 1)
8786 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8787 return \"\";
8788 "
8789 [(set_attr "conds" "use")
d2a518d1 8790 (set_attr "insn" "mov")
8fa3ba89 8791 (set_attr "length" "4,4,8")]
8792)
9c08d1fa 8793
f7fbdd4a 8794(define_insn "*cond_arith"
9c08d1fa 8795 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8796 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8797 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8798 [(match_operand:SI 2 "s_register_operand" "r,r")
8799 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8800 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8801 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8802 "TARGET_ARM"
9c08d1fa 8803 "*
8fa3ba89 8804 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8805 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8806
8fa3ba89 8807 output_asm_insn (\"cmp\\t%2, %3\", operands);
8808 if (GET_CODE (operands[5]) == AND)
8809 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8810 else if (GET_CODE (operands[5]) == MINUS)
8811 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8812 else if (which_alternative != 0)
8813 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8814 return \"%i5%d4\\t%0, %1, #1\";
8815 "
8816 [(set_attr "conds" "clob")
8817 (set_attr "length" "12")]
8818)
9c08d1fa 8819
f7fbdd4a 8820(define_insn "*cond_sub"
9c08d1fa 8821 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8822 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8823 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8824 [(match_operand:SI 2 "s_register_operand" "r,r")
8825 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8826 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8827 "TARGET_ARM"
9c08d1fa 8828 "*
8fa3ba89 8829 output_asm_insn (\"cmp\\t%2, %3\", operands);
8830 if (which_alternative != 0)
8831 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8832 return \"sub%d4\\t%0, %1, #1\";
8833 "
8834 [(set_attr "conds" "clob")
8835 (set_attr "length" "8,12")]
8836)
9c08d1fa 8837
25f905c2 8838;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 8839(define_insn "*cmp_ite0"
cffb2a26 8840 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8841 (compare
8842 (if_then_else:SI
8fa3ba89 8843 (match_operator 4 "arm_comparison_operator"
aea4c774 8844 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8845 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8846 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8847 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8848 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8849 (const_int 0))
8850 (const_int 0)))]
cffb2a26 8851 "TARGET_ARM"
9c08d1fa 8852 "*
aea4c774 8853 {
8fa3ba89 8854 static const char * const opcodes[4][2] =
8855 {
8856 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8857 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8858 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8859 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8860 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8861 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8862 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8863 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8864 };
8865 int swap =
8866 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8867
8868 return opcodes[which_alternative][swap];
8869 }"
8870 [(set_attr "conds" "set")
8871 (set_attr "length" "8")]
8872)
9c08d1fa 8873
aea4c774 8874(define_insn "*cmp_ite1"
cffb2a26 8875 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8876 (compare
8877 (if_then_else:SI
8fa3ba89 8878 (match_operator 4 "arm_comparison_operator"
aea4c774 8879 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8880 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8881 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8882 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8883 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8884 (const_int 1))
8885 (const_int 0)))]
cffb2a26 8886 "TARGET_ARM"
9c08d1fa 8887 "*
9c08d1fa 8888 {
215b30b3 8889 static const char * const opcodes[4][2] =
8890 {
8891 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8892 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8893 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8894 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8895 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8896 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8897 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8898 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8899 };
8900 int swap =
8901 comparison_dominates_p (GET_CODE (operands[5]),
8902 reverse_condition (GET_CODE (operands[4])));
8903
8904 return opcodes[which_alternative][swap];
8905 }"
8fa3ba89 8906 [(set_attr "conds" "set")
8907 (set_attr "length" "8")]
8908)
9c08d1fa 8909
f6c53574 8910(define_insn "*cmp_and"
8911 [(set (match_operand 6 "dominant_cc_register" "")
8912 (compare
8913 (and:SI
8914 (match_operator 4 "arm_comparison_operator"
8915 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8916 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8917 (match_operator:SI 5 "arm_comparison_operator"
8918 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8919 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8920 (const_int 0)))]
8921 "TARGET_ARM"
8922 "*
8923 {
35823b64 8924 static const char *const opcodes[4][2] =
f6c53574 8925 {
8926 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8927 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8928 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8929 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8930 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8931 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8932 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8933 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8934 };
8935 int swap =
8936 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8937
8938 return opcodes[which_alternative][swap];
8939 }"
8940 [(set_attr "conds" "set")
8941 (set_attr "predicable" "no")
8942 (set_attr "length" "8")]
8943)
8944
8945(define_insn "*cmp_ior"
8946 [(set (match_operand 6 "dominant_cc_register" "")
8947 (compare
8948 (ior:SI
8949 (match_operator 4 "arm_comparison_operator"
8950 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8951 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8952 (match_operator:SI 5 "arm_comparison_operator"
8953 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8954 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8955 (const_int 0)))]
8956 "TARGET_ARM"
8957 "*
8958{
35823b64 8959 static const char *const opcodes[4][2] =
f6c53574 8960 {
8961 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8962 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8963 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8964 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8965 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8966 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8967 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8968 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8969 };
8970 int swap =
8971 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8972
8973 return opcodes[which_alternative][swap];
8974}
8975"
8976 [(set_attr "conds" "set")
8977 (set_attr "length" "8")]
8978)
8979
3c5afce6 8980(define_insn_and_split "*ior_scc_scc"
8981 [(set (match_operand:SI 0 "s_register_operand" "=r")
8982 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8983 [(match_operand:SI 1 "s_register_operand" "r")
8984 (match_operand:SI 2 "arm_add_operand" "rIL")])
8985 (match_operator:SI 6 "arm_comparison_operator"
8986 [(match_operand:SI 4 "s_register_operand" "r")
8987 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8988 (clobber (reg:CC CC_REGNUM))]
8989 "TARGET_ARM
8990 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8991 != CCmode)"
8992 "#"
8993 "TARGET_ARM && reload_completed"
8994 [(set (match_dup 7)
8995 (compare
8996 (ior:SI
8997 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8998 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8999 (const_int 0)))
9000 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9001 "operands[7]
9002 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9003 DOM_CC_X_OR_Y),
601f584c 9004 CC_REGNUM);"
9005 [(set_attr "conds" "clob")
9006 (set_attr "length" "16")])
9007
9008; If the above pattern is followed by a CMP insn, then the compare is
9009; redundant, since we can rework the conditional instruction that follows.
9010(define_insn_and_split "*ior_scc_scc_cmp"
9011 [(set (match_operand 0 "dominant_cc_register" "")
9012 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9013 [(match_operand:SI 1 "s_register_operand" "r")
9014 (match_operand:SI 2 "arm_add_operand" "rIL")])
9015 (match_operator:SI 6 "arm_comparison_operator"
9016 [(match_operand:SI 4 "s_register_operand" "r")
9017 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9018 (const_int 0)))
9019 (set (match_operand:SI 7 "s_register_operand" "=r")
9020 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9021 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9022 "TARGET_ARM"
9023 "#"
9024 "TARGET_ARM && reload_completed"
9025 [(set (match_dup 0)
9026 (compare
9027 (ior:SI
9028 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9029 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9030 (const_int 0)))
9031 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9032 ""
9033 [(set_attr "conds" "set")
9034 (set_attr "length" "16")])
3c5afce6 9035
9036(define_insn_and_split "*and_scc_scc"
9037 [(set (match_operand:SI 0 "s_register_operand" "=r")
9038 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9039 [(match_operand:SI 1 "s_register_operand" "r")
9040 (match_operand:SI 2 "arm_add_operand" "rIL")])
9041 (match_operator:SI 6 "arm_comparison_operator"
9042 [(match_operand:SI 4 "s_register_operand" "r")
9043 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9044 (clobber (reg:CC CC_REGNUM))]
9045 "TARGET_ARM
9046 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9047 != CCmode)"
9048 "#"
601f584c 9049 "TARGET_ARM && reload_completed
9050 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9051 != CCmode)"
3c5afce6 9052 [(set (match_dup 7)
9053 (compare
9054 (and:SI
9055 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9056 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9057 (const_int 0)))
9058 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9059 "operands[7]
9060 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9061 DOM_CC_X_AND_Y),
601f584c 9062 CC_REGNUM);"
9063 [(set_attr "conds" "clob")
9064 (set_attr "length" "16")])
9065
9066; If the above pattern is followed by a CMP insn, then the compare is
9067; redundant, since we can rework the conditional instruction that follows.
9068(define_insn_and_split "*and_scc_scc_cmp"
9069 [(set (match_operand 0 "dominant_cc_register" "")
9070 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9071 [(match_operand:SI 1 "s_register_operand" "r")
9072 (match_operand:SI 2 "arm_add_operand" "rIL")])
9073 (match_operator:SI 6 "arm_comparison_operator"
9074 [(match_operand:SI 4 "s_register_operand" "r")
9075 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9076 (const_int 0)))
9077 (set (match_operand:SI 7 "s_register_operand" "=r")
9078 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9079 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9080 "TARGET_ARM"
9081 "#"
9082 "TARGET_ARM && reload_completed"
9083 [(set (match_dup 0)
9084 (compare
9085 (and:SI
9086 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9087 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9088 (const_int 0)))
9089 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9090 ""
9091 [(set_attr "conds" "set")
9092 (set_attr "length" "16")])
9093
9094;; If there is no dominance in the comparison, then we can still save an
9095;; instruction in the AND case, since we can know that the second compare
9096;; need only zero the value if false (if true, then the value is already
9097;; correct).
9098(define_insn_and_split "*and_scc_scc_nodom"
9099 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9100 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9101 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9102 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9103 (match_operator:SI 6 "arm_comparison_operator"
9104 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9105 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9106 (clobber (reg:CC CC_REGNUM))]
9107 "TARGET_ARM
9108 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9109 == CCmode)"
9110 "#"
9111 "TARGET_ARM && reload_completed"
9112 [(parallel [(set (match_dup 0)
9113 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9114 (clobber (reg:CC CC_REGNUM))])
9115 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9116 (set (match_dup 0)
9117 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9118 (match_dup 0)
9119 (const_int 0)))]
9120 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9121 operands[4], operands[5]),
9122 CC_REGNUM);
9123 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9124 operands[5]);"
9125 [(set_attr "conds" "clob")
9126 (set_attr "length" "20")])
3c5afce6 9127
3a0bdee0 9128(define_split
9129 [(set (reg:CC_NOOV CC_REGNUM)
9130 (compare:CC_NOOV (ior:SI
9131 (and:SI (match_operand:SI 0 "s_register_operand" "")
9132 (const_int 1))
b0694be0 9133 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9134 [(match_operand:SI 2 "s_register_operand" "")
9135 (match_operand:SI 3 "arm_add_operand" "")]))
9136 (const_int 0)))
9137 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9138 "TARGET_ARM"
9139 [(set (match_dup 4)
9140 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9141 (match_dup 0)))
9142 (set (reg:CC_NOOV CC_REGNUM)
9143 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9144 (const_int 0)))]
9145 "")
9146
9147(define_split
9148 [(set (reg:CC_NOOV CC_REGNUM)
9149 (compare:CC_NOOV (ior:SI
b0694be0 9150 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9151 [(match_operand:SI 2 "s_register_operand" "")
9152 (match_operand:SI 3 "arm_add_operand" "")])
9153 (and:SI (match_operand:SI 0 "s_register_operand" "")
9154 (const_int 1)))
9155 (const_int 0)))
9156 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9157 "TARGET_ARM"
9158 [(set (match_dup 4)
9159 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9160 (match_dup 0)))
9161 (set (reg:CC_NOOV CC_REGNUM)
9162 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9163 (const_int 0)))]
9164 "")
25f905c2 9165;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9166
f7fbdd4a 9167(define_insn "*negscc"
9c08d1fa 9168 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9169 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9170 [(match_operand:SI 1 "s_register_operand" "r")
9171 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9172 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9173 "TARGET_ARM"
9c08d1fa 9174 "*
2ca2ec2e 9175 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9176 return \"mov\\t%0, %1, asr #31\";
9177
9c08d1fa 9178 if (GET_CODE (operands[3]) == NE)
e2348bcb 9179 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9180
e2348bcb 9181 output_asm_insn (\"cmp\\t%1, %2\", operands);
9182 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9183 return \"mvn%d3\\t%0, #0\";
215b30b3 9184 "
8fa3ba89 9185 [(set_attr "conds" "clob")
9186 (set_attr "length" "12")]
9187)
9c08d1fa 9188
9189(define_insn "movcond"
9190 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9191 (if_then_else:SI
8fa3ba89 9192 (match_operator 5 "arm_comparison_operator"
5565501b 9193 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9194 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9195 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9196 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9197 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9198 "TARGET_ARM"
9c08d1fa 9199 "*
9200 if (GET_CODE (operands[5]) == LT
9201 && (operands[4] == const0_rtx))
9202 {
5565501b 9203 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9204 {
9c08d1fa 9205 if (operands[2] == const0_rtx)
e2348bcb 9206 return \"and\\t%0, %1, %3, asr #31\";
9207 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9208 }
9209 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9210 {
9c08d1fa 9211 if (operands[1] == const0_rtx)
e2348bcb 9212 return \"bic\\t%0, %2, %3, asr #31\";
9213 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9214 }
9215 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9216 are constants. */
9c08d1fa 9217 }
e2348bcb 9218
9c08d1fa 9219 if (GET_CODE (operands[5]) == GE
9220 && (operands[4] == const0_rtx))
9221 {
9222 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9223 {
9c08d1fa 9224 if (operands[2] == const0_rtx)
e2348bcb 9225 return \"bic\\t%0, %1, %3, asr #31\";
9226 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9227 }
9228 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9229 {
9c08d1fa 9230 if (operands[1] == const0_rtx)
e2348bcb 9231 return \"and\\t%0, %2, %3, asr #31\";
9232 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9233 }
9234 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9235 are constants. */
9c08d1fa 9236 }
9237 if (GET_CODE (operands[4]) == CONST_INT
9238 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9239 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9240 else
e2348bcb 9241 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9242 if (which_alternative != 0)
e2348bcb 9243 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9244 if (which_alternative != 1)
e2348bcb 9245 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9246 return \"\";
215b30b3 9247 "
8fa3ba89 9248 [(set_attr "conds" "clob")
9249 (set_attr "length" "8,8,12")]
9250)
9c08d1fa 9251
25f905c2 9252;; ??? The patterns below need checking for Thumb-2 usefulness.
9253
8a18b90c 9254(define_insn "*ifcompare_plus_move"
9255 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9256 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9257 [(match_operand:SI 4 "s_register_operand" "r,r")
9258 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9259 (plus:SI
9260 (match_operand:SI 2 "s_register_operand" "r,r")
9261 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9262 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9263 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9264 "TARGET_ARM"
8a18b90c 9265 "#"
8fa3ba89 9266 [(set_attr "conds" "clob")
9267 (set_attr "length" "8,12")]
9268)
8a18b90c 9269
9270(define_insn "*if_plus_move"
129a2fe4 9271 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9272 (if_then_else:SI
8fa3ba89 9273 (match_operator 4 "arm_comparison_operator"
8a18b90c 9274 [(match_operand 5 "cc_register" "") (const_int 0)])
9275 (plus:SI
129a2fe4 9276 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9277 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9278 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9279 "TARGET_ARM"
8a18b90c 9280 "@
9281 add%d4\\t%0, %2, %3
9282 sub%d4\\t%0, %2, #%n3
9283 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9284 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9285 [(set_attr "conds" "use")
9286 (set_attr "length" "4,4,8,8")
9287 (set_attr "type" "*,*,*,*")]
9288)
8a18b90c 9289
9290(define_insn "*ifcompare_move_plus"
5565501b 9291 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9292 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9293 [(match_operand:SI 4 "s_register_operand" "r,r")
9294 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9295 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9296 (plus:SI
9297 (match_operand:SI 2 "s_register_operand" "r,r")
9298 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9299 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9300 "TARGET_ARM"
8a18b90c 9301 "#"
8fa3ba89 9302 [(set_attr "conds" "clob")
9303 (set_attr "length" "8,12")]
9304)
8a18b90c 9305
9306(define_insn "*if_move_plus"
129a2fe4 9307 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9308 (if_then_else:SI
8fa3ba89 9309 (match_operator 4 "arm_comparison_operator"
8a18b90c 9310 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9311 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9312 (plus:SI
129a2fe4 9313 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9314 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9315 "TARGET_ARM"
8a18b90c 9316 "@
9317 add%D4\\t%0, %2, %3
9318 sub%D4\\t%0, %2, #%n3
9319 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9320 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9321 [(set_attr "conds" "use")
9322 (set_attr "length" "4,4,8,8")
9323 (set_attr "type" "*,*,*,*")]
9324)
8a18b90c 9325
9326(define_insn "*ifcompare_arith_arith"
9327 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9328 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9329 [(match_operand:SI 5 "s_register_operand" "r")
9330 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9331 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9332 [(match_operand:SI 1 "s_register_operand" "r")
9333 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9334 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9335 [(match_operand:SI 3 "s_register_operand" "r")
9336 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9337 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9338 "TARGET_ARM"
8a18b90c 9339 "#"
8fa3ba89 9340 [(set_attr "conds" "clob")
9341 (set_attr "length" "12")]
9342)
9c08d1fa 9343
8a18b90c 9344(define_insn "*if_arith_arith"
9345 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9346 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9347 [(match_operand 8 "cc_register" "") (const_int 0)])
9348 (match_operator:SI 6 "shiftable_operator"
9349 [(match_operand:SI 1 "s_register_operand" "r")
9350 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9351 (match_operator:SI 7 "shiftable_operator"
9352 [(match_operand:SI 3 "s_register_operand" "r")
9353 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9354 "TARGET_ARM"
8a18b90c 9355 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9356 [(set_attr "conds" "use")
9357 (set_attr "length" "8")]
9358)
8a18b90c 9359
f7fbdd4a 9360(define_insn "*ifcompare_arith_move"
9c08d1fa 9361 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9362 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9363 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9364 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9365 (match_operator:SI 7 "shiftable_operator"
9366 [(match_operand:SI 4 "s_register_operand" "r,r")
9367 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9368 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9369 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9370 "TARGET_ARM"
9c08d1fa 9371 "*
9c08d1fa 9372 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9373 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9374 everything is in registers then we can do this in two instructions. */
9c08d1fa 9375 if (operands[3] == const0_rtx
9376 && GET_CODE (operands[7]) != AND
9377 && GET_CODE (operands[5]) == REG
9378 && GET_CODE (operands[1]) == REG
9379 && REGNO (operands[1]) == REGNO (operands[4])
9380 && REGNO (operands[4]) != REGNO (operands[0]))
9381 {
9382 if (GET_CODE (operands[6]) == LT)
40dbec34 9383 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9384 else if (GET_CODE (operands[6]) == GE)
40dbec34 9385 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9386 }
9387 if (GET_CODE (operands[3]) == CONST_INT
9388 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9389 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9390 else
e2348bcb 9391 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9392 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9393 if (which_alternative != 0)
129a2fe4 9394 return \"mov%D6\\t%0, %1\";
9c08d1fa 9395 return \"\";
215b30b3 9396 "
8fa3ba89 9397 [(set_attr "conds" "clob")
9398 (set_attr "length" "8,12")]
9399)
9c08d1fa 9400
8a18b90c 9401(define_insn "*if_arith_move"
129a2fe4 9402 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9403 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9404 [(match_operand 6 "cc_register" "") (const_int 0)])
9405 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9406 [(match_operand:SI 2 "s_register_operand" "r,r")
9407 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9408 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9409 "TARGET_ARM"
8a18b90c 9410 "@
9411 %I5%d4\\t%0, %2, %3
129a2fe4 9412 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9413 [(set_attr "conds" "use")
9414 (set_attr "length" "4,8")
9415 (set_attr "type" "*,*")]
9416)
8a18b90c 9417
f7fbdd4a 9418(define_insn "*ifcompare_move_arith"
9c08d1fa 9419 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9420 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9421 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9422 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9423 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9424 (match_operator:SI 7 "shiftable_operator"
9425 [(match_operand:SI 2 "s_register_operand" "r,r")
9426 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9427 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9428 "TARGET_ARM"
9c08d1fa 9429 "*
9c08d1fa 9430 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9431 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9432 everything is in registers then we can do this in two instructions */
9433 if (operands[5] == const0_rtx
9434 && GET_CODE (operands[7]) != AND
9435 && GET_CODE (operands[3]) == REG
9436 && GET_CODE (operands[1]) == REG
9437 && REGNO (operands[1]) == REGNO (operands[2])
9438 && REGNO (operands[2]) != REGNO (operands[0]))
9439 {
9440 if (GET_CODE (operands[6]) == GE)
40dbec34 9441 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9442 else if (GET_CODE (operands[6]) == LT)
40dbec34 9443 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9444 }
40dbec34 9445
9c08d1fa 9446 if (GET_CODE (operands[5]) == CONST_INT
9447 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9448 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9449 else
e2348bcb 9450 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9451
9c08d1fa 9452 if (which_alternative != 0)
129a2fe4 9453 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9454 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9455 "
8fa3ba89 9456 [(set_attr "conds" "clob")
9457 (set_attr "length" "8,12")]
9458)
9c08d1fa 9459
8a18b90c 9460(define_insn "*if_move_arith"
129a2fe4 9461 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9462 (if_then_else:SI
8fa3ba89 9463 (match_operator 4 "arm_comparison_operator"
8a18b90c 9464 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9465 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9466 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9467 [(match_operand:SI 2 "s_register_operand" "r,r")
9468 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9469 "TARGET_ARM"
8a18b90c 9470 "@
9471 %I5%D4\\t%0, %2, %3
129a2fe4 9472 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9473 [(set_attr "conds" "use")
9474 (set_attr "length" "4,8")
9475 (set_attr "type" "*,*")]
9476)
8a18b90c 9477
9478(define_insn "*ifcompare_move_not"
9c08d1fa 9479 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9480 (if_then_else:SI
8fa3ba89 9481 (match_operator 5 "arm_comparison_operator"
8a18b90c 9482 [(match_operand:SI 3 "s_register_operand" "r,r")
9483 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9484 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9485 (not:SI
9486 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9487 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9488 "TARGET_ARM"
8a18b90c 9489 "#"
8fa3ba89 9490 [(set_attr "conds" "clob")
9491 (set_attr "length" "8,12")]
9492)
9c08d1fa 9493
8a18b90c 9494(define_insn "*if_move_not"
9495 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9496 (if_then_else:SI
8fa3ba89 9497 (match_operator 4 "arm_comparison_operator"
8a18b90c 9498 [(match_operand 3 "cc_register" "") (const_int 0)])
9499 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9500 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9501 "TARGET_ARM"
8a18b90c 9502 "@
9503 mvn%D4\\t%0, %2
9504 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9505 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9506 [(set_attr "conds" "use")
d2a518d1 9507 (set_attr "insn" "mvn")
8fa3ba89 9508 (set_attr "length" "4,8,8")]
9509)
8a18b90c 9510
9511(define_insn "*ifcompare_not_move"
9c08d1fa 9512 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9513 (if_then_else:SI
8fa3ba89 9514 (match_operator 5 "arm_comparison_operator"
8a18b90c 9515 [(match_operand:SI 3 "s_register_operand" "r,r")
9516 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9517 (not:SI
9518 (match_operand:SI 2 "s_register_operand" "r,r"))
9519 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9520 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9521 "TARGET_ARM"
8a18b90c 9522 "#"
8fa3ba89 9523 [(set_attr "conds" "clob")
9524 (set_attr "length" "8,12")]
9525)
9c08d1fa 9526
8a18b90c 9527(define_insn "*if_not_move"
9528 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9529 (if_then_else:SI
8fa3ba89 9530 (match_operator 4 "arm_comparison_operator"
8a18b90c 9531 [(match_operand 3 "cc_register" "") (const_int 0)])
9532 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9533 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9534 "TARGET_ARM"
8a18b90c 9535 "@
9536 mvn%d4\\t%0, %2
9537 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9538 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9539 [(set_attr "conds" "use")
d2a518d1 9540 (set_attr "insn" "mvn")
8fa3ba89 9541 (set_attr "length" "4,8,8")]
9542)
8a18b90c 9543
9544(define_insn "*ifcompare_shift_move"
9c08d1fa 9545 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9546 (if_then_else:SI
8fa3ba89 9547 (match_operator 6 "arm_comparison_operator"
8a18b90c 9548 [(match_operand:SI 4 "s_register_operand" "r,r")
9549 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9550 (match_operator:SI 7 "shift_operator"
9551 [(match_operand:SI 2 "s_register_operand" "r,r")
9552 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9553 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9554 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9555 "TARGET_ARM"
9c08d1fa 9556 "#"
8fa3ba89 9557 [(set_attr "conds" "clob")
9558 (set_attr "length" "8,12")]
9559)
9c08d1fa 9560
8a18b90c 9561(define_insn "*if_shift_move"
9562 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9563 (if_then_else:SI
8fa3ba89 9564 (match_operator 5 "arm_comparison_operator"
8a18b90c 9565 [(match_operand 6 "cc_register" "") (const_int 0)])
9566 (match_operator:SI 4 "shift_operator"
9567 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9568 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9569 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9570 "TARGET_ARM"
5565501b 9571 "@
8a18b90c 9572 mov%d5\\t%0, %2%S4
9573 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9574 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9575 [(set_attr "conds" "use")
331beb1a 9576 (set_attr "shift" "2")
a2cd141b 9577 (set_attr "length" "4,8,8")
d2a518d1 9578 (set_attr "insn" "mov")
a2cd141b 9579 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9580 (const_string "alu_shift")
9581 (const_string "alu_shift_reg")))]
8fa3ba89 9582)
5565501b 9583
8a18b90c 9584(define_insn "*ifcompare_move_shift"
9585 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9586 (if_then_else:SI
8fa3ba89 9587 (match_operator 6 "arm_comparison_operator"
8a18b90c 9588 [(match_operand:SI 4 "s_register_operand" "r,r")
9589 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9590 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9591 (match_operator:SI 7 "shift_operator"
8a18b90c 9592 [(match_operand:SI 2 "s_register_operand" "r,r")
9593 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9594 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9595 "TARGET_ARM"
8a18b90c 9596 "#"
8fa3ba89 9597 [(set_attr "conds" "clob")
9598 (set_attr "length" "8,12")]
9599)
5565501b 9600
8a18b90c 9601(define_insn "*if_move_shift"
9602 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9603 (if_then_else:SI
8fa3ba89 9604 (match_operator 5 "arm_comparison_operator"
8a18b90c 9605 [(match_operand 6 "cc_register" "") (const_int 0)])
9606 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9607 (match_operator:SI 4 "shift_operator"
9608 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9609 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9610 "TARGET_ARM"
5565501b 9611 "@
8a18b90c 9612 mov%D5\\t%0, %2%S4
9613 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9614 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9615 [(set_attr "conds" "use")
331beb1a 9616 (set_attr "shift" "2")
a2cd141b 9617 (set_attr "length" "4,8,8")
d2a518d1 9618 (set_attr "insn" "mov")
a2cd141b 9619 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9620 (const_string "alu_shift")
9621 (const_string "alu_shift_reg")))]
8fa3ba89 9622)
9c08d1fa 9623
f7fbdd4a 9624(define_insn "*ifcompare_shift_shift"
8a18b90c 9625 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9626 (if_then_else:SI
8fa3ba89 9627 (match_operator 7 "arm_comparison_operator"
8a18b90c 9628 [(match_operand:SI 5 "s_register_operand" "r")
9629 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9630 (match_operator:SI 8 "shift_operator"
8a18b90c 9631 [(match_operand:SI 1 "s_register_operand" "r")
9632 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9633 (match_operator:SI 9 "shift_operator"
8a18b90c 9634 [(match_operand:SI 3 "s_register_operand" "r")
9635 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9636 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9637 "TARGET_ARM"
8a18b90c 9638 "#"
8fa3ba89 9639 [(set_attr "conds" "clob")
9640 (set_attr "length" "12")]
9641)
9c08d1fa 9642
8a18b90c 9643(define_insn "*if_shift_shift"
9644 [(set (match_operand:SI 0 "s_register_operand" "=r")
9645 (if_then_else:SI
8fa3ba89 9646 (match_operator 5 "arm_comparison_operator"
8a18b90c 9647 [(match_operand 8 "cc_register" "") (const_int 0)])
9648 (match_operator:SI 6 "shift_operator"
9649 [(match_operand:SI 1 "s_register_operand" "r")
9650 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9651 (match_operator:SI 7 "shift_operator"
9652 [(match_operand:SI 3 "s_register_operand" "r")
9653 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9654 "TARGET_ARM"
8a18b90c 9655 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9656 [(set_attr "conds" "use")
331beb1a 9657 (set_attr "shift" "1")
a2cd141b 9658 (set_attr "length" "8")
d2a518d1 9659 (set_attr "insn" "mov")
a2cd141b 9660 (set (attr "type") (if_then_else
9661 (and (match_operand 2 "const_int_operand" "")
9662 (match_operand 4 "const_int_operand" ""))
9663 (const_string "alu_shift")
9664 (const_string "alu_shift_reg")))]
8fa3ba89 9665)
8a18b90c 9666
f7fbdd4a 9667(define_insn "*ifcompare_not_arith"
8a18b90c 9668 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9669 (if_then_else:SI
8fa3ba89 9670 (match_operator 6 "arm_comparison_operator"
8a18b90c 9671 [(match_operand:SI 4 "s_register_operand" "r")
9672 (match_operand:SI 5 "arm_add_operand" "rIL")])
9673 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9674 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9675 [(match_operand:SI 2 "s_register_operand" "r")
9676 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9677 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9678 "TARGET_ARM"
8a18b90c 9679 "#"
8fa3ba89 9680 [(set_attr "conds" "clob")
9681 (set_attr "length" "12")]
9682)
9c08d1fa 9683
8a18b90c 9684(define_insn "*if_not_arith"
9685 [(set (match_operand:SI 0 "s_register_operand" "=r")
9686 (if_then_else:SI
8fa3ba89 9687 (match_operator 5 "arm_comparison_operator"
8a18b90c 9688 [(match_operand 4 "cc_register" "") (const_int 0)])
9689 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9690 (match_operator:SI 6 "shiftable_operator"
9691 [(match_operand:SI 2 "s_register_operand" "r")
9692 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9693 "TARGET_ARM"
8a18b90c 9694 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9695 [(set_attr "conds" "use")
d2a518d1 9696 (set_attr "insn" "mvn")
8fa3ba89 9697 (set_attr "length" "8")]
9698)
8a18b90c 9699
9700(define_insn "*ifcompare_arith_not"
9701 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9702 (if_then_else:SI
8fa3ba89 9703 (match_operator 6 "arm_comparison_operator"
8a18b90c 9704 [(match_operand:SI 4 "s_register_operand" "r")
9705 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9706 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9707 [(match_operand:SI 2 "s_register_operand" "r")
9708 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9709 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9710 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9711 "TARGET_ARM"
8a18b90c 9712 "#"
8fa3ba89 9713 [(set_attr "conds" "clob")
9714 (set_attr "length" "12")]
9715)
9c08d1fa 9716
8a18b90c 9717(define_insn "*if_arith_not"
9718 [(set (match_operand:SI 0 "s_register_operand" "=r")
9719 (if_then_else:SI
8fa3ba89 9720 (match_operator 5 "arm_comparison_operator"
8a18b90c 9721 [(match_operand 4 "cc_register" "") (const_int 0)])
9722 (match_operator:SI 6 "shiftable_operator"
9723 [(match_operand:SI 2 "s_register_operand" "r")
9724 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9725 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9726 "TARGET_ARM"
8a18b90c 9727 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9728 [(set_attr "conds" "use")
d2a518d1 9729 (set_attr "insn" "mvn")
8fa3ba89 9730 (set_attr "length" "8")]
9731)
8a18b90c 9732
f7fbdd4a 9733(define_insn "*ifcompare_neg_move"
8a18b90c 9734 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9735 (if_then_else:SI
8fa3ba89 9736 (match_operator 5 "arm_comparison_operator"
8a18b90c 9737 [(match_operand:SI 3 "s_register_operand" "r,r")
9738 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9739 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9740 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9741 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9742 "TARGET_ARM"
8a18b90c 9743 "#"
8fa3ba89 9744 [(set_attr "conds" "clob")
9745 (set_attr "length" "8,12")]
9746)
8a18b90c 9747
9748(define_insn "*if_neg_move"
9749 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9750 (if_then_else:SI
8fa3ba89 9751 (match_operator 4 "arm_comparison_operator"
8a18b90c 9752 [(match_operand 3 "cc_register" "") (const_int 0)])
9753 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9754 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9755 "TARGET_ARM"
8a18b90c 9756 "@
9757 rsb%d4\\t%0, %2, #0
9758 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9759 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9760 [(set_attr "conds" "use")
9761 (set_attr "length" "4,8,8")]
9762)
9c08d1fa 9763
f7fbdd4a 9764(define_insn "*ifcompare_move_neg"
8a18b90c 9765 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9766 (if_then_else:SI
8fa3ba89 9767 (match_operator 5 "arm_comparison_operator"
8a18b90c 9768 [(match_operand:SI 3 "s_register_operand" "r,r")
9769 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9770 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9771 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9772 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9773 "TARGET_ARM"
8a18b90c 9774 "#"
8fa3ba89 9775 [(set_attr "conds" "clob")
9776 (set_attr "length" "8,12")]
9777)
8a18b90c 9778
9779(define_insn "*if_move_neg"
9780 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9781 (if_then_else:SI
8fa3ba89 9782 (match_operator 4 "arm_comparison_operator"
8a18b90c 9783 [(match_operand 3 "cc_register" "") (const_int 0)])
9784 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9785 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9786 "TARGET_ARM"
8a18b90c 9787 "@
9788 rsb%D4\\t%0, %2, #0
9789 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9790 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9791 [(set_attr "conds" "use")
9792 (set_attr "length" "4,8,8")]
9793)
9c08d1fa 9794
f7fbdd4a 9795(define_insn "*arith_adjacentmem"
9c08d1fa 9796 [(set (match_operand:SI 0 "s_register_operand" "=r")
9797 (match_operator:SI 1 "shiftable_operator"
9798 [(match_operand:SI 2 "memory_operand" "m")
9799 (match_operand:SI 3 "memory_operand" "m")]))
9800 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9801 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9802 "*
215b30b3 9803 {
9804 rtx ldm[3];
9805 rtx arith[4];
94dee231 9806 rtx base_reg;
9807 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9808
215b30b3 9809 if (REGNO (operands[0]) > REGNO (operands[4]))
9810 {
9811 ldm[1] = operands[4];
9812 ldm[2] = operands[0];
9813 }
9814 else
9815 {
9816 ldm[1] = operands[0];
9817 ldm[2] = operands[4];
9818 }
94dee231 9819
9820 base_reg = XEXP (operands[2], 0);
9821
9822 if (!REG_P (base_reg))
9823 {
9824 val1 = INTVAL (XEXP (base_reg, 1));
9825 base_reg = XEXP (base_reg, 0);
9826 }
9827
9828 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9829 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9830
215b30b3 9831 arith[0] = operands[0];
9832 arith[3] = operands[1];
94dee231 9833
215b30b3 9834 if (val1 < val2)
9835 {
9836 arith[1] = ldm[1];
9837 arith[2] = ldm[2];
9838 }
9839 else
9840 {
9841 arith[1] = ldm[2];
9842 arith[2] = ldm[1];
9843 }
94dee231 9844
9845 ldm[0] = base_reg;
9846 if (val1 !=0 && val2 != 0)
215b30b3 9847 {
cdb1295a 9848 rtx ops[3];
9849
94dee231 9850 if (val1 == 4 || val2 == 4)
9851 /* Other val must be 8, since we know they are adjacent and neither
9852 is zero. */
25f905c2 9853 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 9854 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 9855 {
94dee231 9856 ldm[0] = ops[0] = operands[4];
9857 ops[1] = base_reg;
9858 ops[2] = GEN_INT (val1);
9859 output_add_immediate (ops);
9860 if (val1 < val2)
25f905c2 9861 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 9862 else
25f905c2 9863 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 9864 }
cdb1295a 9865 else
9866 {
9867 /* Offset is out of range for a single add, so use two ldr. */
9868 ops[0] = ldm[1];
9869 ops[1] = base_reg;
9870 ops[2] = GEN_INT (val1);
9871 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9872 ops[0] = ldm[2];
9873 ops[2] = GEN_INT (val2);
9874 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9875 }
215b30b3 9876 }
94dee231 9877 else if (val1 != 0)
215b30b3 9878 {
215b30b3 9879 if (val1 < val2)
25f905c2 9880 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9881 else
25f905c2 9882 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9883 }
9884 else
9885 {
215b30b3 9886 if (val1 < val2)
25f905c2 9887 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9888 else
25f905c2 9889 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9890 }
9891 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9892 return \"\";
9893 }"
9894 [(set_attr "length" "12")
9895 (set_attr "predicable" "yes")
a2cd141b 9896 (set_attr "type" "load1")]
215b30b3 9897)
9c08d1fa 9898
9c08d1fa 9899; This pattern is never tried by combine, so do it as a peephole
9900
a0f94409 9901(define_peephole2
372575c7 9902 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9903 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9904 (set (reg:CC CC_REGNUM)
aea4c774 9905 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9906 "TARGET_ARM"
a0f94409 9907 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9908 (set (match_dup 0) (match_dup 1))])]
9909 ""
0d66636f 9910)
9c08d1fa 9911
9c08d1fa 9912(define_split
9913 [(set (match_operand:SI 0 "s_register_operand" "")
9914 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9915 (const_int 0))
8fa3ba89 9916 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9917 [(match_operand:SI 3 "s_register_operand" "")
9918 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9919 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9920 "TARGET_ARM"
9c08d1fa 9921 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9922 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9923 (match_dup 5)))]
215b30b3 9924 ""
9925)
9c08d1fa 9926
aea4c774 9927;; This split can be used because CC_Z mode implies that the following
9928;; branch will be an equality, or an unsigned inequality, so the sign
9929;; extension is not needed.
9c08d1fa 9930
aea4c774 9931(define_split
bd5b4116 9932 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9933 (compare:CC_Z
9934 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9935 (const_int 24))
aea4c774 9936 (match_operand 1 "const_int_operand" "")))
9937 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9938 "TARGET_ARM
9939 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9940 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9941 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9942 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9943 "
9c08d1fa 9944 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9945 "
9946)
25f905c2 9947;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 9948
87b22bf7 9949(define_expand "prologue"
9950 [(clobber (const_int 0))]
cffb2a26 9951 "TARGET_EITHER"
25f905c2 9952 "if (TARGET_32BIT)
cffb2a26 9953 arm_expand_prologue ();
9954 else
25f905c2 9955 thumb1_expand_prologue ();
87b22bf7 9956 DONE;
cffb2a26 9957 "
9958)
87b22bf7 9959
56d27660 9960(define_expand "epilogue"
4c44712e 9961 [(clobber (const_int 0))]
cffb2a26 9962 "TARGET_EITHER"
56d27660 9963 "
18d50ae6 9964 if (crtl->calls_eh_return)
4c44712e 9965 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 9966 if (TARGET_THUMB1)
9967 thumb1_expand_epilogue ();
cffb2a26 9968 else if (USE_RETURN_INSN (FALSE))
56d27660 9969 {
9970 emit_jump_insn (gen_return ());
9971 DONE;
9972 }
cffb2a26 9973 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9974 gen_rtvec (1,
9975 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9976 VUNSPEC_EPILOGUE));
cffb2a26 9977 DONE;
9978 "
9979)
56d27660 9980
ef5651d0 9981;; Note - although unspec_volatile's USE all hard registers,
9982;; USEs are ignored after relaod has completed. Thus we need
9983;; to add an unspec of the link register to ensure that flow
9984;; does not think that it is unused by the sibcall branch that
9985;; will replace the standard function epilogue.
1c494086 9986(define_insn "sibcall_epilogue"
ef5651d0 9987 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9988 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 9989 "TARGET_32BIT"
1c494086 9990 "*
ffc9d00c 9991 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9992 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9993 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9994 "
9995;; Length is absolute worst case
9996 [(set_attr "length" "44")
defc47cf 9997 (set_attr "type" "block")
9998 ;; We don't clobber the conditions, but the potential length of this
9999 ;; operation is sufficient to make conditionalizing the sequence
10000 ;; unlikely to be profitable.
10001 (set_attr "conds" "clob")]
1c494086 10002)
10003
cffb2a26 10004(define_insn "*epilogue_insns"
e1159bbe 10005 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10006 "TARGET_EITHER"
56d27660 10007 "*
25f905c2 10008 if (TARGET_32BIT)
ffc9d00c 10009 return arm_output_epilogue (NULL);
25f905c2 10010 else /* TARGET_THUMB1 */
cffb2a26 10011 return thumb_unexpanded_epilogue ();
10012 "
215b30b3 10013 ; Length is absolute worst case
cffb2a26 10014 [(set_attr "length" "44")
defc47cf 10015 (set_attr "type" "block")
10016 ;; We don't clobber the conditions, but the potential length of this
10017 ;; operation is sufficient to make conditionalizing the sequence
10018 ;; unlikely to be profitable.
10019 (set_attr "conds" "clob")]
cffb2a26 10020)
10021
10022(define_expand "eh_epilogue"
7db9af5d 10023 [(use (match_operand:SI 0 "register_operand" ""))
10024 (use (match_operand:SI 1 "register_operand" ""))
10025 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10026 "TARGET_EITHER"
10027 "
215b30b3 10028 {
10029 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10030 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10031 {
10032 rtx ra = gen_rtx_REG (Pmode, 2);
10033
10034 emit_move_insn (ra, operands[2]);
10035 operands[2] = ra;
10036 }
5cf3595a 10037 /* This is a hack -- we may have crystalized the function type too
10038 early. */
10039 cfun->machine->func_type = 0;
215b30b3 10040 }"
10041)
56d27660 10042
9c08d1fa 10043;; This split is only used during output to reduce the number of patterns
10044;; that need assembler instructions adding to them. We allowed the setting
10045;; of the conditions to be implicit during rtl generation so that
10046;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10047;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10048;; up again here.
10049
25f905c2 10050;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10051;; conditional execution sufficient?
10052
9c08d1fa 10053(define_split
10054 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10055 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10056 [(match_operand 2 "" "") (match_operand 3 "" "")])
10057 (match_dup 0)
10058 (match_operand 4 "" "")))
bd5b4116 10059 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10060 "TARGET_ARM && reload_completed"
8fa3ba89 10061 [(set (match_dup 5) (match_dup 6))
10062 (cond_exec (match_dup 7)
10063 (set (match_dup 0) (match_dup 4)))]
10064 "
10065 {
10066 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10067 operands[2], operands[3]);
10068 enum rtx_code rc = GET_CODE (operands[1]);
10069
bd5b4116 10070 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10071 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10072 if (mode == CCFPmode || mode == CCFPEmode)
10073 rc = reverse_condition_maybe_unordered (rc);
10074 else
10075 rc = reverse_condition (rc);
10076
10077 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10078 }"
10079)
10080
10081(define_split
10082 [(set (match_operand:SI 0 "s_register_operand" "")
10083 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10084 [(match_operand 2 "" "") (match_operand 3 "" "")])
10085 (match_operand 4 "" "")
10086 (match_dup 0)))
bd5b4116 10087 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10088 "TARGET_ARM && reload_completed"
8fa3ba89 10089 [(set (match_dup 5) (match_dup 6))
10090 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10091 (set (match_dup 0) (match_dup 4)))]
10092 "
10093 {
10094 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10095 operands[2], operands[3]);
10096
bd5b4116 10097 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10098 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10099 }"
10100)
10101
10102(define_split
10103 [(set (match_operand:SI 0 "s_register_operand" "")
10104 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10105 [(match_operand 2 "" "") (match_operand 3 "" "")])
10106 (match_operand 4 "" "")
10107 (match_operand 5 "" "")))
bd5b4116 10108 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10109 "TARGET_ARM && reload_completed"
8fa3ba89 10110 [(set (match_dup 6) (match_dup 7))
10111 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10112 (set (match_dup 0) (match_dup 4)))
10113 (cond_exec (match_dup 8)
10114 (set (match_dup 0) (match_dup 5)))]
10115 "
10116 {
10117 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10118 operands[2], operands[3]);
10119 enum rtx_code rc = GET_CODE (operands[1]);
10120
bd5b4116 10121 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10122 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10123 if (mode == CCFPmode || mode == CCFPEmode)
10124 rc = reverse_condition_maybe_unordered (rc);
10125 else
10126 rc = reverse_condition (rc);
10127
10128 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10129 }"
10130)
10131
cffb2a26 10132(define_split
10133 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10134 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10135 [(match_operand:SI 2 "s_register_operand" "")
10136 (match_operand:SI 3 "arm_add_operand" "")])
10137 (match_operand:SI 4 "arm_rhs_operand" "")
10138 (not:SI
10139 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10140 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10141 "TARGET_ARM && reload_completed"
cffb2a26 10142 [(set (match_dup 6) (match_dup 7))
f6c53574 10143 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10144 (set (match_dup 0) (match_dup 4)))
10145 (cond_exec (match_dup 8)
10146 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10147 "
215b30b3 10148 {
10149 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10150 operands[2], operands[3]);
f6c53574 10151 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10152
bd5b4116 10153 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10154 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10155 if (mode == CCFPmode || mode == CCFPEmode)
10156 rc = reverse_condition_maybe_unordered (rc);
10157 else
10158 rc = reverse_condition (rc);
10159
10160 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10161 }"
10162)
cffb2a26 10163
10164(define_insn "*cond_move_not"
10165 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10166 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10167 [(match_operand 3 "cc_register" "") (const_int 0)])
10168 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10169 (not:SI
10170 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10171 "TARGET_ARM"
10172 "@
10173 mvn%D4\\t%0, %2
10174 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10175 [(set_attr "conds" "use")
d2a518d1 10176 (set_attr "insn" "mvn")
0d66636f 10177 (set_attr "length" "4,8")]
10178)
cffb2a26 10179
9c08d1fa 10180;; The next two patterns occur when an AND operation is followed by a
10181;; scc insn sequence
10182
f7fbdd4a 10183(define_insn "*sign_extract_onebit"
9c08d1fa 10184 [(set (match_operand:SI 0 "s_register_operand" "=r")
10185 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10186 (const_int 1)
ed750274 10187 (match_operand:SI 2 "const_int_operand" "n")))
10188 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10189 "TARGET_ARM"
9c08d1fa 10190 "*
0d66636f 10191 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10192 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10193 return \"mvnne\\t%0, #0\";
10194 "
10195 [(set_attr "conds" "clob")
10196 (set_attr "length" "8")]
10197)
9c08d1fa 10198
f7fbdd4a 10199(define_insn "*not_signextract_onebit"
9c08d1fa 10200 [(set (match_operand:SI 0 "s_register_operand" "=r")
10201 (not:SI
10202 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10203 (const_int 1)
ed750274 10204 (match_operand:SI 2 "const_int_operand" "n"))))
10205 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10206 "TARGET_ARM"
9c08d1fa 10207 "*
0d66636f 10208 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10209 output_asm_insn (\"tst\\t%1, %2\", operands);
10210 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10211 return \"movne\\t%0, #0\";
10212 "
10213 [(set_attr "conds" "clob")
10214 (set_attr "length" "12")]
10215)
25f905c2 10216;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10217
0d66636f 10218;; Push multiple registers to the stack. Registers are in parallel (use ...)
10219;; expressions. For simplicity, the first register is also in the unspec
10220;; part.
f7fbdd4a 10221(define_insn "*push_multi"
87b22bf7 10222 [(match_parallel 2 "multi_register_push"
10223 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10224 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10225 UNSPEC_PUSH_MULT))])]
25f905c2 10226 "TARGET_32BIT"
87b22bf7 10227 "*
215b30b3 10228 {
10229 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10230
215b30b3 10231 /* For the StrongARM at least it is faster to
25f905c2 10232 use STR to store only a single register.
542d5028 10233 In Thumb mode always use push, and the assembler will pick
10234 something appropriate. */
25f905c2 10235 if (num_saves == 1 && TARGET_ARM)
215b30b3 10236 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10237 else
10238 {
10239 int i;
10240 char pattern[100];
ed593f11 10241
25f905c2 10242 if (TARGET_ARM)
10243 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10244 else
10245 strcpy (pattern, \"push\\t{%1\");
215b30b3 10246
6079f055 10247 for (i = 1; i < num_saves; i++)
215b30b3 10248 {
10249 strcat (pattern, \", %|\");
10250 strcat (pattern,
10251 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10252 }
10253
10254 strcat (pattern, \"}\");
10255 output_asm_insn (pattern, operands);
10256 }
10257
10258 return \"\";
10259 }"
10260 [(set_attr "type" "store4")]
10261)
f7fbdd4a 10262
4c58c898 10263(define_insn "stack_tie"
10264 [(set (mem:BLK (scratch))
aaa37ad6 10265 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10266 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10267 UNSPEC_PRLG_STK))]
10268 ""
10269 ""
10270 [(set_attr "length" "0")]
10271)
10272
3398e91d 10273;; Similarly for the floating point registers
7b1d2fc4 10274(define_insn "*push_fp_multi"
10275 [(match_parallel 2 "multi_register_push"
10276 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10277 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10278 UNSPEC_PUSH_MULT))])]
25f905c2 10279 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10280 "*
215b30b3 10281 {
10282 char pattern[100];
7b1d2fc4 10283
215b30b3 10284 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10285 output_asm_insn (pattern, operands);
10286 return \"\";
10287 }"
013b9671 10288 [(set_attr "type" "f_fpa_store")]
215b30b3 10289)
7b1d2fc4 10290
f7fbdd4a 10291;; Special patterns for dealing with the constant pool
10292
cffb2a26 10293(define_insn "align_4"
e1159bbe 10294 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10295 "TARGET_EITHER"
f7fbdd4a 10296 "*
cffb2a26 10297 assemble_align (32);
f7fbdd4a 10298 return \"\";
cffb2a26 10299 "
10300)
f7fbdd4a 10301
755eb2b4 10302(define_insn "align_8"
10303 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10304 "TARGET_EITHER"
755eb2b4 10305 "*
10306 assemble_align (64);
10307 return \"\";
10308 "
10309)
10310
cffb2a26 10311(define_insn "consttable_end"
e1159bbe 10312 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10313 "TARGET_EITHER"
f7fbdd4a 10314 "*
cffb2a26 10315 making_const_table = FALSE;
f7fbdd4a 10316 return \"\";
cffb2a26 10317 "
10318)
f7fbdd4a 10319
cffb2a26 10320(define_insn "consttable_1"
e1159bbe 10321 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10322 "TARGET_THUMB1"
f7fbdd4a 10323 "*
cffb2a26 10324 making_const_table = TRUE;
09d688ff 10325 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10326 assemble_zeros (3);
f7fbdd4a 10327 return \"\";
cffb2a26 10328 "
10329 [(set_attr "length" "4")]
10330)
f7fbdd4a 10331
cffb2a26 10332(define_insn "consttable_2"
e1159bbe 10333 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10334 "TARGET_THUMB1"
f7fbdd4a 10335 "*
cffb2a26 10336 making_const_table = TRUE;
9b8516be 10337 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10338 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10339 assemble_zeros (2);
f7fbdd4a 10340 return \"\";
cffb2a26 10341 "
10342 [(set_attr "length" "4")]
10343)
10344
10345(define_insn "consttable_4"
e1159bbe 10346 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10347 "TARGET_EITHER"
10348 "*
10349 {
9b8516be 10350 rtx x = operands[0];
cffb2a26 10351 making_const_table = TRUE;
9b8516be 10352 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10353 {
10354 case MODE_FLOAT:
9b8516be 10355 if (GET_MODE (x) == HFmode)
10356 arm_emit_fp16_const (x);
10357 else
10358 {
10359 REAL_VALUE_TYPE r;
10360 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10361 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10362 }
10363 break;
cffb2a26 10364 default:
7b04c5d5 10365 /* XXX: Sometimes gcc does something really dumb and ends up with
10366 a HIGH in a constant pool entry, usually because it's trying to
10367 load into a VFP register. We know this will always be used in
10368 combination with a LO_SUM which ignores the high bits, so just
10369 strip off the HIGH. */
10370 if (GET_CODE (x) == HIGH)
10371 x = XEXP (x, 0);
9b8516be 10372 assemble_integer (x, 4, BITS_PER_WORD, 1);
10373 mark_symbol_refs_as_used (x);
cffb2a26 10374 break;
10375 }
10376 return \"\";
10377 }"
10378 [(set_attr "length" "4")]
10379)
10380
10381(define_insn "consttable_8"
e1159bbe 10382 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10383 "TARGET_EITHER"
10384 "*
10385 {
10386 making_const_table = TRUE;
10387 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10388 {
10389 case MODE_FLOAT:
10390 {
badfe841 10391 REAL_VALUE_TYPE r;
10392 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10393 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10394 break;
10395 }
10396 default:
09d688ff 10397 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10398 break;
10399 }
10400 return \"\";
10401 }"
10402 [(set_attr "length" "8")]
10403)
10404
d98a3884 10405(define_insn "consttable_16"
10406 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10407 "TARGET_EITHER"
10408 "*
10409 {
10410 making_const_table = TRUE;
10411 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10412 {
10413 case MODE_FLOAT:
10414 {
10415 REAL_VALUE_TYPE r;
10416 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10417 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10418 break;
10419 }
10420 default:
10421 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10422 break;
10423 }
10424 return \"\";
10425 }"
10426 [(set_attr "length" "16")]
10427)
10428
cffb2a26 10429;; Miscellaneous Thumb patterns
10430
fd957ef3 10431(define_expand "tablejump"
7db9af5d 10432 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10433 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10434 "TARGET_THUMB1"
fd957ef3 10435 "
10436 if (flag_pic)
10437 {
10438 /* Hopefully, CSE will eliminate this copy. */
10439 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10440 rtx reg2 = gen_reg_rtx (SImode);
10441
10442 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10443 operands[0] = reg2;
10444 }
10445 "
10446)
10447
f1039640 10448;; NB never uses BX.
25f905c2 10449(define_insn "*thumb1_tablejump"
cffb2a26 10450 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10451 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10452 "TARGET_THUMB1"
fd957ef3 10453 "mov\\t%|pc, %0"
cffb2a26 10454 [(set_attr "length" "2")]
10455)
0d66636f 10456
331beb1a 10457;; V5 Instructions,
10458
8f4be2be 10459(define_insn "clzsi2"
10460 [(set (match_operand:SI 0 "s_register_operand" "=r")
10461 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10462 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10463 "clz%?\\t%0, %1"
bcaec148 10464 [(set_attr "predicable" "yes")
10465 (set_attr "insn" "clz")])
331beb1a 10466
099ad98b 10467(define_insn "rbitsi2"
10468 [(set (match_operand:SI 0 "s_register_operand" "=r")
10469 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10470 "TARGET_32BIT && arm_arch_thumb2"
10471 "rbit%?\\t%0, %1"
10472 [(set_attr "predicable" "yes")
10473 (set_attr "insn" "clz")])
10474
10475(define_expand "ctzsi2"
10476 [(set (match_operand:SI 0 "s_register_operand" "")
10477 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10478 "TARGET_32BIT && arm_arch_thumb2"
10479 "
30191172 10480 {
10481 rtx tmp = gen_reg_rtx (SImode);
10482 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10483 emit_insn (gen_clzsi2 (operands[0], tmp));
10484 }
099ad98b 10485 DONE;
10486 "
10487)
10488
e1159bbe 10489;; V5E instructions.
331beb1a 10490
10491(define_insn "prefetch"
f4e79814 10492 [(prefetch (match_operand:SI 0 "address_operand" "p")
10493 (match_operand:SI 1 "" "")
10494 (match_operand:SI 2 "" ""))]
25f905c2 10495 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10496 "pld\\t%a0")
331beb1a 10497
0d66636f 10498;; General predication pattern
10499
10500(define_cond_exec
10501 [(match_operator 0 "arm_comparison_operator"
10502 [(match_operand 1 "cc_register" "")
10503 (const_int 0)])]
25f905c2 10504 "TARGET_32BIT"
0d66636f 10505 ""
10506)
10507
063a05c7 10508(define_insn "prologue_use"
10509 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10510 ""
10511 "%@ %0 needed for prologue"
02cfc9c9 10512 [(set_attr "length" "0")]
063a05c7 10513)
7db9af5d 10514
4c44712e 10515
10516;; Patterns for exception handling
10517
10518(define_expand "eh_return"
10519 [(use (match_operand 0 "general_operand" ""))]
10520 "TARGET_EITHER"
10521 "
10522 {
25f905c2 10523 if (TARGET_32BIT)
4c44712e 10524 emit_insn (gen_arm_eh_return (operands[0]));
10525 else
10526 emit_insn (gen_thumb_eh_return (operands[0]));
10527 DONE;
10528 }"
10529)
10530
10531;; We can't expand this before we know where the link register is stored.
10532(define_insn_and_split "arm_eh_return"
10533 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10534 VUNSPEC_EH_RETURN)
10535 (clobber (match_scratch:SI 1 "=&r"))]
10536 "TARGET_ARM"
10537 "#"
10538 "&& reload_completed"
10539 [(const_int 0)]
10540 "
10541 {
10542 arm_set_return_address (operands[0], operands[1]);
10543 DONE;
10544 }"
10545)
10546
10547(define_insn_and_split "thumb_eh_return"
10548 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10549 VUNSPEC_EH_RETURN)
10550 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10551 "TARGET_THUMB1"
4c44712e 10552 "#"
10553 "&& reload_completed"
10554 [(const_int 0)]
10555 "
10556 {
10557 thumb_set_return_address (operands[0], operands[1]);
10558 DONE;
10559 }"
10560)
10561
f655717d 10562\f
10563;; TLS support
10564
10565(define_insn "load_tp_hard"
10566 [(set (match_operand:SI 0 "register_operand" "=r")
10567 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10568 "TARGET_HARD_TP"
10569 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10570 [(set_attr "predicable" "yes")]
10571)
10572
10573;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10574(define_insn "load_tp_soft"
10575 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10576 (clobber (reg:SI LR_REGNUM))
10577 (clobber (reg:SI IP_REGNUM))
10578 (clobber (reg:CC CC_REGNUM))]
10579 "TARGET_SOFT_TP"
10580 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10581 [(set_attr "conds" "clob")]
10582)
10583
aabe09ac 10584;; We only care about the lower 16 bits of the constant
10585;; being inserted into the upper 16 bits of the register.
eca5c984 10586(define_insn "*arm_movtas_ze"
10587 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10588 (const_int 16)
10589 (const_int 16))
10590 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10591 "arm_arch_thumb2"
aabe09ac 10592 "movt%?\t%0, %L1"
eca5c984 10593 [(set_attr "predicable" "yes")
10594 (set_attr "length" "4")]
10595)
10596
c0fc3696 10597(define_insn "*arm_rev"
ff82f757 10598 [(set (match_operand:SI 0 "s_register_operand" "=r")
10599 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 10600 "TARGET_32BIT && arm_arch6"
10601 "rev%?\t%0, %1"
10602 [(set_attr "predicable" "yes")
10603 (set_attr "length" "4")]
10604)
10605
10606(define_insn "*thumb1_rev"
10607 [(set (match_operand:SI 0 "s_register_operand" "=l")
10608 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10609 "TARGET_THUMB1 && arm_arch6"
10610 "rev\t%0, %1"
10611 [(set_attr "length" "2")]
ff82f757 10612)
10613
10614(define_expand "arm_legacy_rev"
10615 [(set (match_operand:SI 2 "s_register_operand" "")
10616 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10617 (const_int 16))
10618 (match_dup 1)))
10619 (set (match_dup 2)
10620 (lshiftrt:SI (match_dup 2)
10621 (const_int 8)))
10622 (set (match_operand:SI 3 "s_register_operand" "")
10623 (rotatert:SI (match_dup 1)
10624 (const_int 8)))
10625 (set (match_dup 2)
10626 (and:SI (match_dup 2)
10627 (const_int -65281)))
10628 (set (match_operand:SI 0 "s_register_operand" "")
10629 (xor:SI (match_dup 3)
10630 (match_dup 2)))]
10631 "TARGET_32BIT"
10632 ""
10633)
10634
10635;; Reuse temporaries to keep register pressure down.
10636(define_expand "thumb_legacy_rev"
10637 [(set (match_operand:SI 2 "s_register_operand" "")
10638 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10639 (const_int 24)))
10640 (set (match_operand:SI 3 "s_register_operand" "")
10641 (lshiftrt:SI (match_dup 1)
10642 (const_int 24)))
10643 (set (match_dup 3)
10644 (ior:SI (match_dup 3)
10645 (match_dup 2)))
10646 (set (match_operand:SI 4 "s_register_operand" "")
10647 (const_int 16))
10648 (set (match_operand:SI 5 "s_register_operand" "")
10649 (rotatert:SI (match_dup 1)
10650 (match_dup 4)))
10651 (set (match_dup 2)
10652 (ashift:SI (match_dup 5)
10653 (const_int 24)))
10654 (set (match_dup 5)
10655 (lshiftrt:SI (match_dup 5)
10656 (const_int 24)))
10657 (set (match_dup 5)
10658 (ior:SI (match_dup 5)
10659 (match_dup 2)))
10660 (set (match_dup 5)
10661 (rotatert:SI (match_dup 5)
10662 (match_dup 4)))
10663 (set (match_operand:SI 0 "s_register_operand" "")
10664 (ior:SI (match_dup 5)
10665 (match_dup 3)))]
10666 "TARGET_THUMB"
10667 ""
10668)
10669
10670(define_expand "bswapsi2"
10671 [(set (match_operand:SI 0 "s_register_operand" "=r")
10672 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10673"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10674"
8d1af482 10675 if (!arm_arch6)
10676 {
10677 rtx op2 = gen_reg_rtx (SImode);
10678 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10679
8d1af482 10680 if (TARGET_THUMB)
10681 {
10682 rtx op4 = gen_reg_rtx (SImode);
10683 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10684
8d1af482 10685 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10686 op2, op3, op4, op5));
10687 }
10688 else
10689 {
10690 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10691 op2, op3));
10692 }
ff82f757 10693
8d1af482 10694 DONE;
10695 }
ff82f757 10696 "
10697)
10698
320ea44d 10699;; Load the load/store multiple patterns
10700(include "ldmstm.md")
7db9af5d 10701;; Load the FPA co-processor patterns
10702(include "fpa.md")
10703;; Load the Maverick co-processor patterns
10704(include "cirrus.md")
d98a3884 10705;; Vector bits common to IWMMXT and Neon
10706(include "vec-common.md")
755eb2b4 10707;; Load the Intel Wireless Multimedia Extension patterns
10708(include "iwmmxt.md")
a2cd141b 10709;; Load the VFP co-processor patterns
10710(include "vfp.md")
25f905c2 10711;; Thumb-2 patterns
10712(include "thumb2.md")
d98a3884 10713;; Neon patterns
10714(include "neon.md")
06df6b17 10715;; Synchronization Primitives
10716(include "sync.md")