]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Reindented comment
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
7cf0dbf3 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
934a1e72 4;; Free Software Foundation, Inc.
b11cae9e 5;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 6;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 7;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 8
acf6ed70 9;; This file is part of GCC.
b11cae9e 10
acf6ed70 11;; GCC is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published
038d1e19 13;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 14;; option) any later version.
b11cae9e 15
acf6ed70 16;; GCC is distributed in the hope that it will be useful, but WITHOUT
17;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19;; License for more details.
b11cae9e 20
21;; You should have received a copy of the GNU General Public License
038d1e19 22;; along with GCC; see the file COPYING3. If not see
23;; <http://www.gnu.org/licenses/>.
b11cae9e 24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
9c08d1fa 27\f
e1159bbe 28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
ccd90aaa 33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
e1159bbe 35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
ccd90aaa 39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
e1159bbe 51
9c08d1fa 52;; UNSPEC Usage:
8a18b90c 53;; Note: sin and cos are no-longer used.
d98a3884 54;; Unspec constants for Neon are defined in neon.md.
e1159bbe 55
56(define_constants
57 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
58 ; operand 0 is the result,
59 ; operand 1 the parameter.
60 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
61 ; operand 0 is the result,
62 ; operand 1 the parameter.
63 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
64 ; operand 0 is the first register,
65 ; subsequent registers are in parallel (use ...)
66 ; expressions.
67 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
68 ; usage, that is, we will add the pic_register
69 ; value to it before trying to dereference it.
c0c1fba5 70 (UNSPEC_PIC_BASE 4) ; Add PC and all but the last operand together,
71 ; The last operand is the number of a PIC_LABEL
72 ; that points at the containing instruction.
2c96dc5a 73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
e1159bbe 74 ; being scheduled before the stack adjustment insn.
063a05c7 75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
79 ; register to "use".
68121397 80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
8d232dc7 81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
f655717d 93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
6cdcb15c 94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95 ; instruction stream.
2c2d2f40 96 (UNSPEC_STACK_ALIGN 22) ; Doubleword aligned stack pointer. Used to
25f905c2 97 ; generate correct unwind information.
2c2d2f40 98 (UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
bac7fc85 99 ; correctly for PIC usage.
c0c1fba5 100 (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
101 ; a given symbolic address.
e6ac8414 102 (UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
099ad98b 103 (UNSPEC_RBIT 26) ; rbit operation.
825ae2ed 104 (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
105 ; another symbolic address.
06df6b17 106 (UNSPEC_MEMORY_BARRIER 28) ; Represent a memory barrier.
e1159bbe 107 ]
108)
109
215b30b3 110;; UNSPEC_VOLATILE Usage:
e1159bbe 111
112(define_constants
113 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
114 ; insn in the code.
115 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
116 ; instruction epilogue sequence that isn't expanded
117 ; into normal RTL. Used for both normal and sibcall
118 ; epilogues.
119 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
120 ; for inlined constants.
121 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
122 ; table.
123 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
124 ; an 8-bit object.
125 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
126 ; a 16-bit object.
127 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
128 ; a 32-bit object.
129 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
130 ; a 64-bit object.
d98a3884 131 (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
132 ; a 128-bit object.
133 (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
134 (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
135 (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
136 (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
137 (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
138 (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 139 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 140 ; handling.
06df6b17 141 (VUNSPEC_SYNC_COMPARE_AND_SWAP 21) ; Represent an atomic compare swap.
142 (VUNSPEC_SYNC_LOCK 22) ; Represent a sync_lock_test_and_set.
143 (VUNSPEC_SYNC_OP 23) ; Represent a sync_<op>
144 (VUNSPEC_SYNC_NEW_OP 24) ; Represent a sync_new_<op>
145 (VUNSPEC_SYNC_OLD_OP 25) ; Represent a sync_old_<op>
e1159bbe 146 ]
147)
b11cae9e 148\f
e1159bbe 149;;---------------------------------------------------------------------------
9c08d1fa 150;; Attributes
151
215b30b3 152; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
153; generating ARM code. This is used to control the length of some insn
154; patterns that share the same RTL in both ARM and Thumb code.
1c494086 155(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 156
ef51b8e1 157; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
158(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
159
747b7458 160; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
161(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
162
331beb1a 163;; Operand number of an input operand that is shifted. Zero if the
164;; given instruction does not shift one of its input operands.
331beb1a 165(define_attr "shift" "" (const_int 0))
166
3d91c5d6 167; Floating Point Unit. If we only have floating point emulation, then there
168; is no point in scheduling the floating point insns. (Well, for best
169; performance we should try and group them together).
4fea7d65 170(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 171 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 172
06df6b17 173(define_attr "sync_result" "none,0,1,2,3,4,5" (const_string "none"))
174(define_attr "sync_memory" "none,0,1,2,3,4,5" (const_string "none"))
175(define_attr "sync_required_value" "none,0,1,2,3,4,5" (const_string "none"))
176(define_attr "sync_new_value" "none,0,1,2,3,4,5" (const_string "none"))
177(define_attr "sync_t1" "none,0,1,2,3,4,5" (const_string "none"))
178(define_attr "sync_t2" "none,0,1,2,3,4,5" (const_string "none"))
179(define_attr "sync_release_barrier" "yes,no" (const_string "yes"))
180(define_attr "sync_op" "none,add,sub,ior,xor,and,nand"
181 (const_string "none"))
182
094e994f 183; LENGTH of an instruction (in bytes)
06df6b17 184(define_attr "length" ""
185 (cond [(not (eq_attr "sync_memory" "none"))
186 (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
187 ] (const_int 4)))
9c08d1fa 188
d5d4dc8d 189; The architecture which supports the instruction (or alternative).
190; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
191; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
192; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
193; arm_arch6. This attribute is used to compute attribute "enabled",
194; use type "any" to enable an alternative in all cases.
195(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6"
196 (const_string "any"))
197
198(define_attr "arch_enabled" "no,yes"
199 (cond [(eq_attr "arch" "any")
200 (const_string "yes")
201
202 (and (eq_attr "arch" "a")
203 (ne (symbol_ref "TARGET_ARM") (const_int 0)))
204 (const_string "yes")
205
206 (and (eq_attr "arch" "t")
207 (ne (symbol_ref "TARGET_THUMB") (const_int 0)))
208 (const_string "yes")
209
210 (and (eq_attr "arch" "t1")
211 (ne (symbol_ref "TARGET_THUMB1") (const_int 0)))
212 (const_string "yes")
213
214 (and (eq_attr "arch" "t2")
215 (ne (symbol_ref "TARGET_THUMB2") (const_int 0)))
216 (const_string "yes")
217
218 (and (eq_attr "arch" "32")
219 (ne (symbol_ref "TARGET_32BIT") (const_int 0)))
220 (const_string "yes")
221
222 (and (eq_attr "arch" "v6")
223 (ne (symbol_ref "(TARGET_32BIT && arm_arch6)") (const_int 0)))
224 (const_string "yes")
225
226 (and (eq_attr "arch" "nov6")
227 (ne (symbol_ref "(TARGET_32BIT && !arm_arch6)") (const_int 0)))
228 (const_string "yes")]
229 (const_string "no")))
230
231; Allows an insn to disable certain alternatives for reasons other than
232; arch support.
233(define_attr "insn_enabled" "no,yes"
234 (const_string "yes"))
235
236; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 237 (define_attr "enabled" "no,yes"
238 (if_then_else (eq_attr "insn_enabled" "yes")
239 (if_then_else (eq_attr "arch_enabled" "yes")
240 (const_string "yes")
241 (const_string "no"))
242 (const_string "no")))
d5d4dc8d 243
56d27660 244; POOL_RANGE is how far away from a constant pool entry that this insn
245; can be placed. If the distance is zero, then this insn will never
246; reference the pool.
cffb2a26 247; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
248; before its address.
cde1623a 249(define_attr "arm_pool_range" "" (const_int 0))
250(define_attr "thumb2_pool_range" "" (const_int 0))
251(define_attr "arm_neg_pool_range" "" (const_int 0))
252(define_attr "thumb2_neg_pool_range" "" (const_int 0))
253
254(define_attr "pool_range" ""
255 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
256 (attr "arm_pool_range")))
257(define_attr "neg_pool_range" ""
258 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
259 (attr "arm_neg_pool_range")))
56d27660 260
215b30b3 261; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 262; If such an insn references the pool, then we have no way of knowing how,
263; so use the most conservative value for pool_range.
9c08d1fa 264(define_asm_attributes
4d7a8451 265 [(set_attr "conds" "clob")
266 (set_attr "length" "4")
267 (set_attr "pool_range" "250")])
9c08d1fa 268
a2cd141b 269;; The instruction used to implement a particular pattern. This
270;; information is used by pipeline descriptions to provide accurate
271;; scheduling information.
272
273(define_attr "insn"
934a1e72 274 "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other"
a2cd141b 275 (const_string "other"))
276
9c08d1fa 277; TYPE attribute is used to detect floating point instructions which, if
278; running on a co-processor can run in parallel with other, basic instructions
279; If write-buffer scheduling is enabled then it can also be used in the
280; scheduling of writes.
281
282; Classification of each insn
607978a1 283; Note: vfp.md has different meanings for some of these, and some further
284; types as well. See that file for details.
a2cd141b 285; alu any alu instruction that doesn't hit memory or fp
286; regs or have a shifted source operand
287; alu_shift any data instruction that doesn't hit memory or fp
288; regs, but has a source operand shifted by a constant
289; alu_shift_reg any data instruction that doesn't hit memory or fp
290; regs, but has a source operand shifted by a register value
f7fbdd4a 291; mult a multiply instruction
9c08d1fa 292; block blockage insn, this blocks all functional units
293; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 294; fdivd DFmode floating point division
295; fdivs SFmode floating point division
296; fmul Floating point multiply
297; ffmul Fast floating point multiply
298; farith Floating point arithmetic (4 cycle)
299; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 300; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 301; even on a machine with an fpa.
9c08d1fa 302; f_load a floating point load from memory
303; f_store a floating point store to memory
9aff9709 304; f_load[sd] single/double load from memory
305; f_store[sd] single/double store to memory
c0e1af52 306; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 307; f_mem_r a transfer of a floating point register to a real reg via mem
308; r_mem_f the reverse of f_mem_r
309; f_2_r fast transfer float to arm (no memory needed)
310; r_2_f fast transfer arm to float
c0e1af52 311; f_cvt convert floating<->integral
a2cd141b 312; branch a branch
9c08d1fa 313; call a subroutine call
a2cd141b 314; load_byte load byte(s) from memory to arm registers
315; load1 load 1 word from memory to arm registers
316; load2 load 2 words from memory to arm registers
317; load3 load 3 words from memory to arm registers
318; load4 load 4 words from memory to arm registers
319; store store 1 word to memory from arm registers
9c08d1fa 320; store2 store 2 words
321; store3 store 3 words
a2cd141b 322; store4 store 4 (or more) words
2c6c7d8b 323; Additions for Cirrus Maverick co-processor:
324; mav_farith Floating point arithmetic (4 cycle)
325; mav_dmult Double multiplies (7 cycle)
9c08d1fa 326;
bcaec148 327
9c08d1fa 328(define_attr "type"
e3879fd0 329 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
a2cd141b 330 (if_then_else
331 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
332 (const_string "mult")
333 (const_string "alu")))
9c08d1fa 334
9888ad6d 335; Load scheduling, set from the arm_ld_sched variable
457275b6 336; initialized by arm_override_options()
9888ad6d 337(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 338
c52acdd2 339;; Classification of NEON instructions for scheduling purposes.
340;; Do not set this attribute and the "type" attribute together in
341;; any one instruction pattern.
342(define_attr "neon_type"
343 "neon_int_1,\
344 neon_int_2,\
345 neon_int_3,\
346 neon_int_4,\
347 neon_int_5,\
348 neon_vqneg_vqabs,\
349 neon_vmov,\
350 neon_vaba,\
351 neon_vsma,\
352 neon_vaba_qqq,\
353 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
354 neon_mul_qqq_8_16_32_ddd_32,\
355 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
356 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
357 neon_mla_qqq_8_16,\
358 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
359 neon_mla_qqq_32_qqd_32_scalar,\
360 neon_mul_ddd_16_scalar_32_16_long_scalar,\
361 neon_mul_qqd_32_scalar,\
362 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
363 neon_shift_1,\
364 neon_shift_2,\
365 neon_shift_3,\
366 neon_vshl_ddd,\
367 neon_vqshl_vrshl_vqrshl_qqq,\
368 neon_vsra_vrsra,\
369 neon_fp_vadd_ddd_vabs_dd,\
370 neon_fp_vadd_qqq_vabs_qq,\
371 neon_fp_vsum,\
372 neon_fp_vmul_ddd,\
373 neon_fp_vmul_qqd,\
374 neon_fp_vmla_ddd,\
375 neon_fp_vmla_qqq,\
376 neon_fp_vmla_ddd_scalar,\
377 neon_fp_vmla_qqq_scalar,\
378 neon_fp_vrecps_vrsqrts_ddd,\
379 neon_fp_vrecps_vrsqrts_qqq,\
380 neon_bp_simple,\
381 neon_bp_2cycle,\
382 neon_bp_3cycle,\
383 neon_ldr,\
384 neon_str,\
385 neon_vld1_1_2_regs,\
386 neon_vld1_3_4_regs,\
387 neon_vld2_2_regs_vld1_vld2_all_lanes,\
388 neon_vld2_4_regs,\
389 neon_vld3_vld4,\
390 neon_vst1_1_2_regs_vst2_2_regs,\
391 neon_vst1_3_4_regs,\
392 neon_vst2_4_regs_vst3_vst4,\
393 neon_vst3_vst4,\
394 neon_vld1_vld2_lane,\
395 neon_vld3_vld4_lane,\
396 neon_vst1_vst2_lane,\
397 neon_vst3_vst4_lane,\
398 neon_vld3_vld4_all_lanes,\
399 neon_mcr,\
400 neon_mcr_2_mcrr,\
401 neon_mrc,\
402 neon_mrrc,\
403 neon_ldm_2,\
404 neon_stm_2,\
405 none"
406 (const_string "none"))
407
f7fbdd4a 408; condition codes: this one is used by final_prescan_insn to speed up
409; conditionalizing instructions. It saves having to scan the rtl to see if
410; it uses or alters the condition codes.
215b30b3 411;
f7fbdd4a 412; USE means that the condition codes are used by the insn in the process of
215b30b3 413; outputting code, this means (at present) that we can't use the insn in
414; inlined branches
415;
f7fbdd4a 416; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 417; well defined manner.
418;
f7fbdd4a 419; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 420; they are altered at all
421;
c52acdd2 422; UNCONDITIONAL means the instions can not be conditionally executed.
423;
f7fbdd4a 424; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 425; output of this insn
f7fbdd4a 426
b0694be0 427(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 428 (if_then_else
429 (ior (eq_attr "is_thumb1" "yes")
430 (eq_attr "type" "call"))
c1a66faf 431 (const_string "clob")
c52acdd2 432 (if_then_else (eq_attr "neon_type" "none")
433 (const_string "nocond")
434 (const_string "unconditional"))))
f7fbdd4a 435
215b30b3 436; Predicable means that the insn can be conditionally executed based on
437; an automatically added predicate (additional patterns are generated by
438; gen...). We default to 'no' because no Thumb patterns match this rule
439; and not all ARM patterns do.
0d66636f 440(define_attr "predicable" "no,yes" (const_string "no"))
441
129a2fe4 442; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
443; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 444; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 445; affect the schedule).
74a71f7d 446(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 447
215b30b3 448; WRITE_CONFLICT implies that a read following an unrelated write is likely
449; to stall the processor. Used with model_wbuf above.
9c08d1fa 450(define_attr "write_conflict" "no,yes"
451 (if_then_else (eq_attr "type"
a2cd141b 452 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 453 (const_string "yes")
454 (const_string "no")))
455
215b30b3 456; Classify the insns into those that take one cycle and those that take more
457; than one on the main cpu execution unit.
f7fbdd4a 458(define_attr "core_cycles" "single,multi"
459 (if_then_else (eq_attr "type"
a2cd141b 460 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 461 (const_string "single")
462 (const_string "multi")))
463
cffb2a26 464;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 465;; distant label. Only applicable to Thumb code.
cffb2a26 466(define_attr "far_jump" "yes,no" (const_string "no"))
467
d51f92df 468
25f905c2 469;; The number of machine instructions this pattern expands to.
470;; Used for Thumb-2 conditional execution.
471(define_attr "ce_count" "" (const_int 1))
472
d51f92df 473;;---------------------------------------------------------------------------
fd781bb2 474;; Mode iterators
d51f92df 475
3de0dec6 476(include "iterators.md")
03770691 477
d51f92df 478;;---------------------------------------------------------------------------
479;; Predicates
480
9c9db025 481(include "predicates.md")
234f6557 482(include "constraints.md")
9c9db025 483
a2cd141b 484;;---------------------------------------------------------------------------
485;; Pipeline descriptions
215b30b3 486
06469f9e 487;; Processor type. This is created automatically from arm-cores.def.
488(include "arm-tune.md")
331beb1a 489
e3879fd0 490(define_attr "tune_cortexr4" "yes,no"
491 (const (if_then_else
492 (eq_attr "tune" "cortexr4,cortexr4f")
493 (const_string "yes")
494 (const_string "no"))))
495
a2cd141b 496;; True if the generic scheduling description should be used.
497
498(define_attr "generic_sched" "yes,no"
4d5cb40d 499 (const (if_then_else
3f1e069f 500 (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9")
e3879fd0 501 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 502 (const_string "no")
503 (const_string "yes"))))
504
c0e1af52 505(define_attr "generic_vfp" "yes,no"
506 (const (if_then_else
507 (and (eq_attr "fpu" "vfp")
3f1e069f 508 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9")
e3879fd0 509 (eq_attr "tune_cortexr4" "no"))
c0e1af52 510 (const_string "yes")
511 (const_string "no"))))
512
a2cd141b 513(include "arm-generic.md")
514(include "arm926ejs.md")
c0e1af52 515(include "arm1020e.md")
a2cd141b 516(include "arm1026ejs.md")
517(include "arm1136jfs.md")
3f1e069f 518(include "cortex-a5.md")
bcaec148 519(include "cortex-a8.md")
036068af 520(include "cortex-a9.md")
934a1e72 521(include "cortex-r4.md")
e3879fd0 522(include "cortex-r4f.md")
55e3ada8 523(include "vfp11.md")
3586df96 524
9c08d1fa 525\f
215b30b3 526;;---------------------------------------------------------------------------
e1159bbe 527;; Insn patterns
528;;
a0f94409 529;; Addition insns.
215b30b3 530
9c08d1fa 531;; Note: For DImode insns, there is normally no reason why operands should
532;; not be in the same register, what we don't want is for something being
533;; written to partially overlap something that is an input.
7d57ec45 534;; Cirrus 64bit additions should not be split because we have a native
535;; 64bit addition instructions.
9c08d1fa 536
cffb2a26 537(define_expand "adddi3"
538 [(parallel
215b30b3 539 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 540 (plus:DI (match_operand:DI 1 "s_register_operand" "")
541 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 542 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 543 "TARGET_EITHER"
544 "
a2cd141b 545 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 546 {
547 if (!cirrus_fp_register (operands[0], DImode))
548 operands[0] = force_reg (DImode, operands[0]);
549 if (!cirrus_fp_register (operands[1], DImode))
550 operands[1] = force_reg (DImode, operands[1]);
551 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
552 DONE;
553 }
554
25f905c2 555 if (TARGET_THUMB1)
cffb2a26 556 {
557 if (GET_CODE (operands[1]) != REG)
bc5a93af 558 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 559 if (GET_CODE (operands[2]) != REG)
bc5a93af 560 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 561 }
562 "
563)
564
25f905c2 565(define_insn "*thumb1_adddi3"
cffb2a26 566 [(set (match_operand:DI 0 "register_operand" "=l")
567 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 568 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 569 (clobber (reg:CC CC_REGNUM))
cffb2a26 570 ]
25f905c2 571 "TARGET_THUMB1"
cffb2a26 572 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
573 [(set_attr "length" "4")]
574)
575
a0f94409 576(define_insn_and_split "*arm_adddi3"
cffb2a26 577 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 578 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
579 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 580 (clobber (reg:CC CC_REGNUM))]
94829feb 581 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 582 "#"
94829feb 583 "TARGET_32BIT && reload_completed
584 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 585 [(parallel [(set (reg:CC_C CC_REGNUM)
586 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
587 (match_dup 1)))
588 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 589 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
590 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 591 "
592 {
593 operands[3] = gen_highpart (SImode, operands[0]);
594 operands[0] = gen_lowpart (SImode, operands[0]);
595 operands[4] = gen_highpart (SImode, operands[1]);
596 operands[1] = gen_lowpart (SImode, operands[1]);
597 operands[5] = gen_highpart (SImode, operands[2]);
598 operands[2] = gen_lowpart (SImode, operands[2]);
599 }"
cffb2a26 600 [(set_attr "conds" "clob")
601 (set_attr "length" "8")]
602)
9c08d1fa 603
a0f94409 604(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 605 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
606 (plus:DI (sign_extend:DI
97499065 607 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 608 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 609 (clobber (reg:CC CC_REGNUM))]
25f905c2 610 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 611 "#"
25f905c2 612 "TARGET_32BIT && reload_completed"
a0f94409 613 [(parallel [(set (reg:CC_C CC_REGNUM)
614 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
615 (match_dup 1)))
616 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 617 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 618 (const_int 31))
080c0b9a 619 (match_dup 4))
620 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 621 "
622 {
623 operands[3] = gen_highpart (SImode, operands[0]);
624 operands[0] = gen_lowpart (SImode, operands[0]);
625 operands[4] = gen_highpart (SImode, operands[1]);
626 operands[1] = gen_lowpart (SImode, operands[1]);
627 operands[2] = gen_lowpart (SImode, operands[2]);
628 }"
215b30b3 629 [(set_attr "conds" "clob")
630 (set_attr "length" "8")]
631)
9c08d1fa 632
a0f94409 633(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 634 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
635 (plus:DI (zero_extend:DI
97499065 636 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 637 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 638 (clobber (reg:CC CC_REGNUM))]
25f905c2 639 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 640 "#"
25f905c2 641 "TARGET_32BIT && reload_completed"
a0f94409 642 [(parallel [(set (reg:CC_C CC_REGNUM)
643 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
644 (match_dup 1)))
645 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 646 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
647 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 648 "
649 {
650 operands[3] = gen_highpart (SImode, operands[0]);
651 operands[0] = gen_lowpart (SImode, operands[0]);
652 operands[4] = gen_highpart (SImode, operands[1]);
653 operands[1] = gen_lowpart (SImode, operands[1]);
654 operands[2] = gen_lowpart (SImode, operands[2]);
655 }"
cffb2a26 656 [(set_attr "conds" "clob")
657 (set_attr "length" "8")]
658)
b11cae9e 659
87b22bf7 660(define_expand "addsi3"
cffb2a26 661 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 662 (plus:SI (match_operand:SI 1 "s_register_operand" "")
663 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 664 "TARGET_EITHER"
87b22bf7 665 "
25f905c2 666 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 667 {
96f57e36 668 arm_split_constant (PLUS, SImode, NULL_RTX,
669 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 670 optimize && can_create_pseudo_p ());
87b22bf7 671 DONE;
672 }
cffb2a26 673 "
674)
87b22bf7 675
5bd751ff 676; If there is a scratch available, this will be faster than synthesizing the
a0f94409 677; addition.
678(define_peephole2
679 [(match_scratch:SI 3 "r")
372575c7 680 (set (match_operand:SI 0 "arm_general_register_operand" "")
681 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 682 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 683 "TARGET_32BIT &&
a0f94409 684 !(const_ok_for_arm (INTVAL (operands[2]))
685 || const_ok_for_arm (-INTVAL (operands[2])))
686 && const_ok_for_arm (~INTVAL (operands[2]))"
687 [(set (match_dup 3) (match_dup 2))
688 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
689 ""
690)
87b22bf7 691
2f02c19f 692;; The r/r/k alternative is required when reloading the address
693;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
694;; put the duplicated register first, and not try the commutative version.
a0f94409 695(define_insn_and_split "*arm_addsi3"
bccb5444 696 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k,r")
697 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
698 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
25f905c2 699 "TARGET_32BIT"
5565501b 700 "@
701 add%?\\t%0, %1, %2
aaa37ad6 702 add%?\\t%0, %1, %2
2f02c19f 703 add%?\\t%0, %2, %1
aaa37ad6 704 sub%?\\t%0, %1, #%n2
87b22bf7 705 sub%?\\t%0, %1, #%n2
706 #"
a3ffc315 707 "TARGET_32BIT
708 && GET_CODE (operands[2]) == CONST_INT
a0f94409 709 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 710 || const_ok_for_arm (-INTVAL (operands[2])))
711 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 712 [(clobber (const_int 0))]
713 "
96f57e36 714 arm_split_constant (PLUS, SImode, curr_insn,
715 INTVAL (operands[2]), operands[0],
a0f94409 716 operands[1], 0);
717 DONE;
718 "
2f02c19f 719 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 720 (set_attr "predicable" "yes")]
cffb2a26 721)
722
0bdb6455 723(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 724 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
725 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
726 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 727 "TARGET_THUMB1"
cffb2a26 728 "*
0d66636f 729 static const char * const asms[] =
cffb2a26 730 {
731 \"add\\t%0, %0, %2\",
732 \"sub\\t%0, %0, #%n2\",
733 \"add\\t%0, %1, %2\",
734 \"add\\t%0, %0, %2\",
735 \"add\\t%0, %0, %2\",
736 \"add\\t%0, %1, %2\",
0bdb6455 737 \"add\\t%0, %1, %2\",
738 \"#\",
bf7bc2f6 739 \"#\",
0bdb6455 740 \"#\"
cffb2a26 741 };
742 if ((which_alternative == 2 || which_alternative == 6)
743 && GET_CODE (operands[2]) == CONST_INT
744 && INTVAL (operands[2]) < 0)
745 return \"sub\\t%0, %1, #%n2\";
746 return asms[which_alternative];
747 "
0bdb6455 748 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 749 && ((operands[1] != stack_pointer_rtx
750 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
751 || (operands[1] == stack_pointer_rtx
752 && INTVAL (operands[2]) > 1020))"
0bdb6455 753 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
754 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
755 {
756 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 757 if (operands[1] == stack_pointer_rtx)
758 offset -= 1020;
759 else
760 {
761 if (offset > 255)
762 offset = 255;
763 else if (offset < -255)
764 offset = -255;
765 }
0bdb6455 766 operands[3] = GEN_INT (offset);
767 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
768 }
bf7bc2f6 769 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 770)
771
772;; Reloading and elimination of the frame pointer can
773;; sometimes cause this optimization to be missed.
a0f94409 774(define_peephole2
372575c7 775 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 776 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 777 (set (match_dup 0)
372575c7 778 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 779 "TARGET_THUMB1
cffb2a26 780 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
781 && (INTVAL (operands[1]) & 3) == 0"
372575c7 782 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 783 ""
cffb2a26 784)
b11cae9e 785
f7fbdd4a 786(define_insn "*addsi3_compare0"
bd5b4116 787 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 788 (compare:CC_NOOV
215b30b3 789 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
790 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 791 (const_int 0)))
792 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 793 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 794 "TARGET_ARM"
5565501b 795 "@
25f905c2 796 add%.\\t%0, %1, %2
797 sub%.\\t%0, %1, #%n2"
cffb2a26 798 [(set_attr "conds" "set")]
799)
9c08d1fa 800
aea4c774 801(define_insn "*addsi3_compare0_scratch"
bd5b4116 802 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 803 (compare:CC_NOOV
215b30b3 804 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
805 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 806 (const_int 0)))]
ec792a7b 807 "TARGET_ARM"
cffb2a26 808 "@
809 cmn%?\\t%0, %1
810 cmp%?\\t%0, #%n1"
0d66636f 811 [(set_attr "conds" "set")]
812)
cffb2a26 813
aed179ae 814(define_insn "*compare_negsi_si"
815 [(set (reg:CC_Z CC_REGNUM)
816 (compare:CC_Z
817 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
818 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 819 "TARGET_32BIT"
aed179ae 820 "cmn%?\\t%1, %0"
0d66636f 821 [(set_attr "conds" "set")]
822)
aea4c774 823
203c488f 824;; This is the canonicalization of addsi3_compare0_for_combiner when the
825;; addend is a constant.
826(define_insn "*cmpsi2_addneg"
827 [(set (reg:CC CC_REGNUM)
828 (compare:CC
829 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 830 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 831 (set (match_operand:SI 0 "s_register_operand" "=r,r")
832 (plus:SI (match_dup 1)
2a977b78 833 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 834 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 835 "@
2a977b78 836 add%.\\t%0, %1, %3
837 sub%.\\t%0, %1, #%n3"
203c488f 838 [(set_attr "conds" "set")]
839)
840
841;; Convert the sequence
842;; sub rd, rn, #1
843;; cmn rd, #1 (equivalent to cmp rd, #-1)
844;; bne dest
845;; into
846;; subs rd, rn, #1
847;; bcs dest ((unsigned)rn >= 1)
848;; similarly for the beq variant using bcc.
849;; This is a common looping idiom (while (n--))
850(define_peephole2
372575c7 851 [(set (match_operand:SI 0 "arm_general_register_operand" "")
852 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 853 (const_int -1)))
854 (set (match_operand 2 "cc_register" "")
855 (compare (match_dup 0) (const_int -1)))
856 (set (pc)
857 (if_then_else (match_operator 3 "equality_operator"
858 [(match_dup 2) (const_int 0)])
859 (match_operand 4 "" "")
860 (match_operand 5 "" "")))]
25f905c2 861 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 862 [(parallel[
863 (set (match_dup 2)
864 (compare:CC
865 (match_dup 1) (const_int 1)))
866 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
867 (set (pc)
868 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
869 (match_dup 4)
870 (match_dup 5)))]
871 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
872 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
873 ? GEU : LTU),
874 VOIDmode,
875 operands[2], const0_rtx);"
876)
877
ebcc79bc 878;; The next four insns work because they compare the result with one of
879;; the operands, and we know that the use of the condition code is
880;; either GEU or LTU, so we can use the carry flag from the addition
881;; instead of doing the compare a second time.
882(define_insn "*addsi3_compare_op1"
bd5b4116 883 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 884 (compare:CC_C
885 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
886 (match_operand:SI 2 "arm_add_operand" "rI,L"))
887 (match_dup 1)))
888 (set (match_operand:SI 0 "s_register_operand" "=r,r")
889 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 890 "TARGET_32BIT"
ebcc79bc 891 "@
25f905c2 892 add%.\\t%0, %1, %2
893 sub%.\\t%0, %1, #%n2"
0d66636f 894 [(set_attr "conds" "set")]
895)
ebcc79bc 896
897(define_insn "*addsi3_compare_op2"
bd5b4116 898 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 899 (compare:CC_C
900 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
901 (match_operand:SI 2 "arm_add_operand" "rI,L"))
902 (match_dup 2)))
5565501b 903 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 904 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 905 "TARGET_32BIT"
5565501b 906 "@
25f905c2 907 add%.\\t%0, %1, %2
908 sub%.\\t%0, %1, #%n2"
0d66636f 909 [(set_attr "conds" "set")]
910)
9c08d1fa 911
ebcc79bc 912(define_insn "*compare_addsi2_op0"
bd5b4116 913 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 914 (compare:CC_C
915 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
916 (match_operand:SI 1 "arm_add_operand" "rI,L"))
917 (match_dup 0)))]
25f905c2 918 "TARGET_32BIT"
ebcc79bc 919 "@
920 cmn%?\\t%0, %1
921 cmp%?\\t%0, #%n1"
0d66636f 922 [(set_attr "conds" "set")]
923)
ebcc79bc 924
925(define_insn "*compare_addsi2_op1"
bd5b4116 926 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 927 (compare:CC_C
928 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
929 (match_operand:SI 1 "arm_add_operand" "rI,L"))
930 (match_dup 1)))]
25f905c2 931 "TARGET_32BIT"
ebcc79bc 932 "@
933 cmn%?\\t%0, %1
934 cmp%?\\t%0, #%n1"
0d66636f 935 [(set_attr "conds" "set")]
936)
ebcc79bc 937
080c0b9a 938(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 939 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 940 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 941 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 942 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 943 "TARGET_32BIT"
ebcc79bc 944 "adc%?\\t%0, %1, %2"
cffb2a26 945 [(set_attr "conds" "use")]
946)
ebcc79bc 947
080c0b9a 948(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 949 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 950 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
951 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 952 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 953 "TARGET_32BIT"
ebcc79bc 954 "adc%?\\t%0, %1, %2"
0d66636f 955 [(set_attr "conds" "use")]
956)
ebcc79bc 957
080c0b9a 958(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 959 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 960 (plus:SI (plus:SI
961 (match_operator:SI 2 "shift_operator"
962 [(match_operand:SI 3 "s_register_operand" "r")
963 (match_operand:SI 4 "reg_or_int_operand" "rM")])
964 (match_operand:SI 1 "s_register_operand" "r"))
965 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 966 "TARGET_32BIT"
080c0b9a 967 "adc%?\\t%0, %1, %3%S2"
968 [(set_attr "conds" "use")
969 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
970 (const_string "alu_shift")
971 (const_string "alu_shift_reg")))]
cffb2a26 972)
ebcc79bc 973
25f905c2 974(define_expand "incscc"
975 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
976 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
977 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
978 (match_operand:SI 1 "s_register_operand" "0,?r")))]
979 "TARGET_32BIT"
980 ""
981)
982
983(define_insn "*arm_incscc"
9c08d1fa 984 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 985 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 986 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 987 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 988 "TARGET_ARM"
5565501b 989 "@
990 add%d2\\t%0, %1, #1
991 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 992 [(set_attr "conds" "use")
215b30b3 993 (set_attr "length" "4,8")]
994)
9c08d1fa 995
d795fb69 996; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
997(define_split
998 [(set (match_operand:SI 0 "s_register_operand" "")
999 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1000 (match_operand:SI 2 "s_register_operand" ""))
1001 (const_int -1)))
1002 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1003 "TARGET_32BIT"
d795fb69 1004 [(set (match_dup 3) (match_dup 1))
1005 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1006 "
1007 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1008")
1009
604f3a0a 1010(define_expand "addsf3"
1011 [(set (match_operand:SF 0 "s_register_operand" "")
1012 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1013 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 1014 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1015 "
a2cd141b 1016 if (TARGET_MAVERICK
604f3a0a 1017 && !cirrus_fp_register (operands[2], SFmode))
1018 operands[2] = force_reg (SFmode, operands[2]);
1019")
1020
604f3a0a 1021(define_expand "adddf3"
1022 [(set (match_operand:DF 0 "s_register_operand" "")
1023 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1024 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1025 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1026 "
a2cd141b 1027 if (TARGET_MAVERICK
604f3a0a 1028 && !cirrus_fp_register (operands[2], DFmode))
1029 operands[2] = force_reg (DFmode, operands[2]);
1030")
1031
cffb2a26 1032(define_expand "subdi3"
1033 [(parallel
1034 [(set (match_operand:DI 0 "s_register_operand" "")
1035 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1036 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1037 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1038 "TARGET_EITHER"
1039 "
a2cd141b 1040 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1041 && TARGET_32BIT
7d57ec45 1042 && cirrus_fp_register (operands[0], DImode)
1043 && cirrus_fp_register (operands[1], DImode))
1044 {
1045 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1046 DONE;
1047 }
1048
25f905c2 1049 if (TARGET_THUMB1)
cffb2a26 1050 {
1051 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1052 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1053 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1054 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1055 }
1056 "
1057)
1058
1059(define_insn "*arm_subdi3"
1060 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1061 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1062 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1063 (clobber (reg:CC CC_REGNUM))]
94829feb 1064 "TARGET_32BIT && !TARGET_NEON"
97499065 1065 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1066 [(set_attr "conds" "clob")
1067 (set_attr "length" "8")]
1068)
1069
1070(define_insn "*thumb_subdi3"
1071 [(set (match_operand:DI 0 "register_operand" "=l")
1072 (minus:DI (match_operand:DI 1 "register_operand" "0")
1073 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1074 (clobber (reg:CC CC_REGNUM))]
25f905c2 1075 "TARGET_THUMB1"
cffb2a26 1076 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1077 [(set_attr "length" "4")]
1078)
9c08d1fa 1079
f7fbdd4a 1080(define_insn "*subdi_di_zesidi"
cffb2a26 1081 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1082 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1083 (zero_extend:DI
cffb2a26 1084 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1085 (clobber (reg:CC CC_REGNUM))]
25f905c2 1086 "TARGET_32BIT"
97499065 1087 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1088 [(set_attr "conds" "clob")
1089 (set_attr "length" "8")]
1090)
9c08d1fa 1091
f7fbdd4a 1092(define_insn "*subdi_di_sesidi"
cffb2a26 1093 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1094 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1095 (sign_extend:DI
cffb2a26 1096 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1097 (clobber (reg:CC CC_REGNUM))]
25f905c2 1098 "TARGET_32BIT"
97499065 1099 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1100 [(set_attr "conds" "clob")
1101 (set_attr "length" "8")]
1102)
9c08d1fa 1103
f7fbdd4a 1104(define_insn "*subdi_zesidi_di"
cffb2a26 1105 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1106 (minus:DI (zero_extend:DI
cffb2a26 1107 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1108 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1109 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1110 "TARGET_ARM"
97499065 1111 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1112 [(set_attr "conds" "clob")
1113 (set_attr "length" "8")]
1114)
9c08d1fa 1115
f7fbdd4a 1116(define_insn "*subdi_sesidi_di"
cffb2a26 1117 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1118 (minus:DI (sign_extend:DI
cffb2a26 1119 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1120 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1121 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1122 "TARGET_ARM"
97499065 1123 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1124 [(set_attr "conds" "clob")
1125 (set_attr "length" "8")]
1126)
9c08d1fa 1127
f7fbdd4a 1128(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1129 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1130 (minus:DI (zero_extend:DI
cffb2a26 1131 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1132 (zero_extend:DI
cffb2a26 1133 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1134 (clobber (reg:CC CC_REGNUM))]
25f905c2 1135 "TARGET_32BIT"
1136 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1137 [(set_attr "conds" "clob")
1138 (set_attr "length" "8")]
1139)
b11cae9e 1140
87b22bf7 1141(define_expand "subsi3"
cffb2a26 1142 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1143 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1144 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1145 "TARGET_EITHER"
87b22bf7 1146 "
1147 if (GET_CODE (operands[1]) == CONST_INT)
1148 {
25f905c2 1149 if (TARGET_32BIT)
cffb2a26 1150 {
96f57e36 1151 arm_split_constant (MINUS, SImode, NULL_RTX,
1152 INTVAL (operands[1]), operands[0],
e1ba4a27 1153 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1154 DONE;
1155 }
25f905c2 1156 else /* TARGET_THUMB1 */
cffb2a26 1157 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1158 }
cffb2a26 1159 "
1160)
87b22bf7 1161
747b7458 1162(define_insn "thumb1_subsi3_insn"
cffb2a26 1163 [(set (match_operand:SI 0 "register_operand" "=l")
1164 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1165 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1166 "TARGET_THUMB1"
cffb2a26 1167 "sub\\t%0, %1, %2"
747b7458 1168 [(set_attr "length" "2")
1169 (set_attr "conds" "set")])
cffb2a26 1170
25f905c2 1171; ??? Check Thumb-2 split length
a0f94409 1172(define_insn_and_split "*arm_subsi3_insn"
080c0b9a 1173 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
bccb5444 1174 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1175 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
25f905c2 1176 "TARGET_32BIT"
e2348bcb 1177 "@
87b22bf7 1178 rsb%?\\t%0, %2, %1
aaa37ad6 1179 sub%?\\t%0, %1, %2
080c0b9a 1180 sub%?\\t%0, %1, %2
1181 #
87b22bf7 1182 #"
080c0b9a 1183 "&& ((GET_CODE (operands[1]) == CONST_INT
1184 && !const_ok_for_arm (INTVAL (operands[1])))
1185 || (GET_CODE (operands[2]) == CONST_INT
1186 && !const_ok_for_arm (INTVAL (operands[2]))))"
87b22bf7 1187 [(clobber (const_int 0))]
1188 "
96f57e36 1189 arm_split_constant (MINUS, SImode, curr_insn,
1190 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1191 DONE;
cffb2a26 1192 "
080c0b9a 1193 [(set_attr "length" "4,4,4,16,16")
a0f94409 1194 (set_attr "predicable" "yes")]
1195)
1196
1197(define_peephole2
1198 [(match_scratch:SI 3 "r")
372575c7 1199 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1200 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1201 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1202 "TARGET_32BIT
a0f94409 1203 && !const_ok_for_arm (INTVAL (operands[1]))
1204 && const_ok_for_arm (~INTVAL (operands[1]))"
1205 [(set (match_dup 3) (match_dup 1))
1206 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1207 ""
cffb2a26 1208)
b11cae9e 1209
f7fbdd4a 1210(define_insn "*subsi3_compare0"
bd5b4116 1211 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1212 (compare:CC_NOOV
1213 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1214 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1215 (const_int 0)))
9c08d1fa 1216 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1217 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1218 "TARGET_32BIT"
e2348bcb 1219 "@
25f905c2 1220 sub%.\\t%0, %1, %2
1221 rsb%.\\t%0, %2, %1"
cffb2a26 1222 [(set_attr "conds" "set")]
1223)
9c08d1fa 1224
080c0b9a 1225(define_insn "*subsi3_compare"
1226 [(set (reg:CC CC_REGNUM)
1227 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1228 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1229 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1230 (minus:SI (match_dup 1) (match_dup 2)))]
1231 "TARGET_32BIT"
1232 "@
1233 sub%.\\t%0, %1, %2
1234 rsb%.\\t%0, %2, %1"
1235 [(set_attr "conds" "set")]
1236)
1237
25f905c2 1238(define_expand "decscc"
1239 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1240 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1241 (match_operator:SI 2 "arm_comparison_operator"
1242 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1243 "TARGET_32BIT"
1244 ""
1245)
1246
1247(define_insn "*arm_decscc"
cffb2a26 1248 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1249 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1250 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1251 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1252 "TARGET_ARM"
e2348bcb 1253 "@
215b30b3 1254 sub%d2\\t%0, %1, #1
1255 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1256 [(set_attr "conds" "use")
1257 (set_attr "length" "*,8")]
1258)
9c08d1fa 1259
604f3a0a 1260(define_expand "subsf3"
1261 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1262 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1263 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1264 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1265 "
a2cd141b 1266 if (TARGET_MAVERICK)
604f3a0a 1267 {
1268 if (!cirrus_fp_register (operands[1], SFmode))
1269 operands[1] = force_reg (SFmode, operands[1]);
1270 if (!cirrus_fp_register (operands[2], SFmode))
1271 operands[2] = force_reg (SFmode, operands[2]);
1272 }
1273")
1274
604f3a0a 1275(define_expand "subdf3"
1276 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1277 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1278 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1279 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1280 "
a2cd141b 1281 if (TARGET_MAVERICK)
604f3a0a 1282 {
1283 if (!cirrus_fp_register (operands[1], DFmode))
1284 operands[1] = force_reg (DFmode, operands[1]);
1285 if (!cirrus_fp_register (operands[2], DFmode))
1286 operands[2] = force_reg (DFmode, operands[2]);
1287 }
1288")
1289
b11cae9e 1290\f
1291;; Multiplication insns
1292
cffb2a26 1293(define_expand "mulsi3"
1294 [(set (match_operand:SI 0 "s_register_operand" "")
1295 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1296 (match_operand:SI 1 "s_register_operand" "")))]
1297 "TARGET_EITHER"
1298 ""
1299)
1300
9c08d1fa 1301;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1302(define_insn "*arm_mulsi3"
1303 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1304 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1305 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1306 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1307 "mul%?\\t%0, %2, %1"
a2cd141b 1308 [(set_attr "insn" "mul")
0d66636f 1309 (set_attr "predicable" "yes")]
cffb2a26 1310)
1311
58d7d654 1312(define_insn "*arm_mulsi3_v6"
1313 [(set (match_operand:SI 0 "s_register_operand" "=r")
1314 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1315 (match_operand:SI 2 "s_register_operand" "r")))]
1316 "TARGET_32BIT && arm_arch6"
1317 "mul%?\\t%0, %1, %2"
1318 [(set_attr "insn" "mul")
1319 (set_attr "predicable" "yes")]
1320)
1321
215b30b3 1322; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1323; 1 and 2; are the same, because reload will make operand 0 match
1324; operand 1 without realizing that this conflicts with operand 2. We fix
1325; this by adding another alternative to match this case, and then `reload'
1326; it ourselves. This alternative must come first.
cffb2a26 1327(define_insn "*thumb_mulsi3"
1328 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1329 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1330 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1331 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1332 "*
1333 if (which_alternative < 2)
20c4e896 1334 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1335 else
20c4e896 1336 return \"mul\\t%0, %2\";
cffb2a26 1337 "
1338 [(set_attr "length" "4,4,2")
a2cd141b 1339 (set_attr "insn" "mul")]
cffb2a26 1340)
b11cae9e 1341
58d7d654 1342(define_insn "*thumb_mulsi3_v6"
1343 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1344 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1345 (match_operand:SI 2 "register_operand" "l,0,0")))]
1346 "TARGET_THUMB1 && arm_arch6"
1347 "@
1490694c 1348 mul\\t%0, %2
1349 mul\\t%0, %1
58d7d654 1350 mul\\t%0, %1"
1351 [(set_attr "length" "2")
1352 (set_attr "insn" "mul")]
1353)
1354
f7fbdd4a 1355(define_insn "*mulsi3_compare0"
bd5b4116 1356 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1357 (compare:CC_NOOV (mult:SI
1358 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1359 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1360 (const_int 0)))
1361 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1362 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1363 "TARGET_ARM && !arm_arch6"
1364 "mul%.\\t%0, %2, %1"
1365 [(set_attr "conds" "set")
1366 (set_attr "insn" "muls")]
1367)
1368
1369(define_insn "*mulsi3_compare0_v6"
1370 [(set (reg:CC_NOOV CC_REGNUM)
1371 (compare:CC_NOOV (mult:SI
1372 (match_operand:SI 2 "s_register_operand" "r")
1373 (match_operand:SI 1 "s_register_operand" "r"))
1374 (const_int 0)))
1375 (set (match_operand:SI 0 "s_register_operand" "=r")
1376 (mult:SI (match_dup 2) (match_dup 1)))]
1377 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1378 "mul%.\\t%0, %2, %1"
cffb2a26 1379 [(set_attr "conds" "set")
a2cd141b 1380 (set_attr "insn" "muls")]
cffb2a26 1381)
9c08d1fa 1382
f7fbdd4a 1383(define_insn "*mulsi_compare0_scratch"
bd5b4116 1384 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1385 (compare:CC_NOOV (mult:SI
1386 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1387 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1388 (const_int 0)))
1389 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1390 "TARGET_ARM && !arm_arch6"
1391 "mul%.\\t%0, %2, %1"
1392 [(set_attr "conds" "set")
1393 (set_attr "insn" "muls")]
1394)
1395
1396(define_insn "*mulsi_compare0_scratch_v6"
1397 [(set (reg:CC_NOOV CC_REGNUM)
1398 (compare:CC_NOOV (mult:SI
1399 (match_operand:SI 2 "s_register_operand" "r")
1400 (match_operand:SI 1 "s_register_operand" "r"))
1401 (const_int 0)))
1402 (clobber (match_scratch:SI 0 "=r"))]
1403 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1404 "mul%.\\t%0, %2, %1"
cffb2a26 1405 [(set_attr "conds" "set")
a2cd141b 1406 (set_attr "insn" "muls")]
cffb2a26 1407)
9c08d1fa 1408
b11cae9e 1409;; Unnamed templates to match MLA instruction.
1410
f7fbdd4a 1411(define_insn "*mulsi3addsi"
9c08d1fa 1412 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1413 (plus:SI
9c08d1fa 1414 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1415 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1416 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1417 "TARGET_32BIT && !arm_arch6"
1418 "mla%?\\t%0, %2, %1, %3"
1419 [(set_attr "insn" "mla")
1420 (set_attr "predicable" "yes")]
1421)
1422
1423(define_insn "*mulsi3addsi_v6"
1424 [(set (match_operand:SI 0 "s_register_operand" "=r")
1425 (plus:SI
1426 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1427 (match_operand:SI 1 "s_register_operand" "r"))
1428 (match_operand:SI 3 "s_register_operand" "r")))]
1429 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1430 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1431 [(set_attr "insn" "mla")
0d66636f 1432 (set_attr "predicable" "yes")]
1433)
b11cae9e 1434
f7fbdd4a 1435(define_insn "*mulsi3addsi_compare0"
bd5b4116 1436 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1437 (compare:CC_NOOV
1438 (plus:SI (mult:SI
1439 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1440 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1441 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1442 (const_int 0)))
9c08d1fa 1443 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1444 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1445 (match_dup 3)))]
58d7d654 1446 "TARGET_ARM && arm_arch6"
1447 "mla%.\\t%0, %2, %1, %3"
1448 [(set_attr "conds" "set")
1449 (set_attr "insn" "mlas")]
1450)
1451
1452(define_insn "*mulsi3addsi_compare0_v6"
1453 [(set (reg:CC_NOOV CC_REGNUM)
1454 (compare:CC_NOOV
1455 (plus:SI (mult:SI
1456 (match_operand:SI 2 "s_register_operand" "r")
1457 (match_operand:SI 1 "s_register_operand" "r"))
1458 (match_operand:SI 3 "s_register_operand" "r"))
1459 (const_int 0)))
1460 (set (match_operand:SI 0 "s_register_operand" "=r")
1461 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1462 (match_dup 3)))]
1463 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1464 "mla%.\\t%0, %2, %1, %3"
0d66636f 1465 [(set_attr "conds" "set")
a2cd141b 1466 (set_attr "insn" "mlas")]
0d66636f 1467)
9c08d1fa 1468
f7fbdd4a 1469(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1470 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1471 (compare:CC_NOOV
1472 (plus:SI (mult:SI
1473 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1474 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1475 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1476 (const_int 0)))
9c08d1fa 1477 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1478 "TARGET_ARM && !arm_arch6"
1479 "mla%.\\t%0, %2, %1, %3"
1480 [(set_attr "conds" "set")
1481 (set_attr "insn" "mlas")]
1482)
1483
1484(define_insn "*mulsi3addsi_compare0_scratch_v6"
1485 [(set (reg:CC_NOOV CC_REGNUM)
1486 (compare:CC_NOOV
1487 (plus:SI (mult:SI
1488 (match_operand:SI 2 "s_register_operand" "r")
1489 (match_operand:SI 1 "s_register_operand" "r"))
1490 (match_operand:SI 3 "s_register_operand" "r"))
1491 (const_int 0)))
1492 (clobber (match_scratch:SI 0 "=r"))]
1493 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1494 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1495 [(set_attr "conds" "set")
a2cd141b 1496 (set_attr "insn" "mlas")]
cffb2a26 1497)
f7fbdd4a 1498
89545238 1499(define_insn "*mulsi3subsi"
1500 [(set (match_operand:SI 0 "s_register_operand" "=r")
1501 (minus:SI
1502 (match_operand:SI 3 "s_register_operand" "r")
1503 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1504 (match_operand:SI 1 "s_register_operand" "r"))))]
1505 "TARGET_32BIT && arm_arch_thumb2"
1506 "mls%?\\t%0, %2, %1, %3"
1507 [(set_attr "insn" "mla")
1508 (set_attr "predicable" "yes")]
1509)
1510
5cdca009 1511(define_expand "maddsidi4"
1512 [(set (match_operand:DI 0 "s_register_operand" "")
1513 (plus:DI
1514 (mult:DI
1515 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1516 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1517 (match_operand:DI 3 "s_register_operand" "")))]
1518 "TARGET_32BIT && arm_arch3m"
1519 "")
82b85d08 1520
1521(define_insn "*mulsidi3adddi"
fe8dbf85 1522 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1523 (plus:DI
215b30b3 1524 (mult:DI
fe8dbf85 1525 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1526 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1527 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1528 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1529 "smlal%?\\t%Q0, %R0, %3, %2"
1530 [(set_attr "insn" "smlal")
1531 (set_attr "predicable" "yes")]
1532)
1533
1534(define_insn "*mulsidi3adddi_v6"
1535 [(set (match_operand:DI 0 "s_register_operand" "=r")
1536 (plus:DI
1537 (mult:DI
1538 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1539 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1540 (match_operand:DI 1 "s_register_operand" "0")))]
1541 "TARGET_32BIT && arm_arch6"
fe8dbf85 1542 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1543 [(set_attr "insn" "smlal")
0d66636f 1544 (set_attr "predicable" "yes")]
1545)
82b85d08 1546
957788b0 1547;; 32x32->64 widening multiply.
1548;; As with mulsi3, the only difference between the v3-5 and v6+
1549;; versions of these patterns is the requirement that the output not
1550;; overlap the inputs, but that still means we have to have a named
1551;; expander and two different starred insns.
1552
1553(define_expand "mulsidi3"
1554 [(set (match_operand:DI 0 "s_register_operand" "")
1555 (mult:DI
1556 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1557 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1558 "TARGET_32BIT && arm_arch3m"
1559 ""
1560)
1561
1562(define_insn "*mulsidi3_nov6"
f7fbdd4a 1563 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1564 (mult:DI
1565 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1566 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1567 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1568 "smull%?\\t%Q0, %R0, %1, %2"
1569 [(set_attr "insn" "smull")
1570 (set_attr "predicable" "yes")]
1571)
1572
957788b0 1573(define_insn "*mulsidi3_v6"
58d7d654 1574 [(set (match_operand:DI 0 "s_register_operand" "=r")
1575 (mult:DI
1576 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1577 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1578 "TARGET_32BIT && arm_arch6"
97499065 1579 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1580 [(set_attr "insn" "smull")
0d66636f 1581 (set_attr "predicable" "yes")]
1582)
f7fbdd4a 1583
957788b0 1584(define_expand "umulsidi3"
1585 [(set (match_operand:DI 0 "s_register_operand" "")
1586 (mult:DI
1587 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1588 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1589 "TARGET_32BIT && arm_arch3m"
1590 ""
1591)
1592
1593(define_insn "*umulsidi3_nov6"
f7fbdd4a 1594 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1595 (mult:DI
1596 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1597 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1598 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1599 "umull%?\\t%Q0, %R0, %1, %2"
1600 [(set_attr "insn" "umull")
1601 (set_attr "predicable" "yes")]
1602)
1603
957788b0 1604(define_insn "*umulsidi3_v6"
58d7d654 1605 [(set (match_operand:DI 0 "s_register_operand" "=r")
1606 (mult:DI
1607 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1608 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1609 "TARGET_32BIT && arm_arch6"
97499065 1610 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1611 [(set_attr "insn" "umull")
0d66636f 1612 (set_attr "predicable" "yes")]
1613)
b11cae9e 1614
5cdca009 1615(define_expand "umaddsidi4"
1616 [(set (match_operand:DI 0 "s_register_operand" "")
1617 (plus:DI
1618 (mult:DI
1619 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1620 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1621 (match_operand:DI 3 "s_register_operand" "")))]
1622 "TARGET_32BIT && arm_arch3m"
1623 "")
82b85d08 1624
1625(define_insn "*umulsidi3adddi"
8ead09f9 1626 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1627 (plus:DI
215b30b3 1628 (mult:DI
fe8dbf85 1629 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1630 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1631 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1632 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1633 "umlal%?\\t%Q0, %R0, %3, %2"
1634 [(set_attr "insn" "umlal")
1635 (set_attr "predicable" "yes")]
1636)
1637
1638(define_insn "*umulsidi3adddi_v6"
1639 [(set (match_operand:DI 0 "s_register_operand" "=r")
1640 (plus:DI
1641 (mult:DI
1642 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1643 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1644 (match_operand:DI 1 "s_register_operand" "0")))]
1645 "TARGET_32BIT && arm_arch6"
fe8dbf85 1646 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1647 [(set_attr "insn" "umlal")
0d66636f 1648 (set_attr "predicable" "yes")]
1649)
82b85d08 1650
957788b0 1651(define_expand "smulsi3_highpart"
1652 [(parallel
1653 [(set (match_operand:SI 0 "s_register_operand" "")
1654 (truncate:SI
1655 (lshiftrt:DI
1656 (mult:DI
1657 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1658 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1659 (const_int 32))))
1660 (clobber (match_scratch:SI 3 ""))])]
1661 "TARGET_32BIT && arm_arch3m"
1662 ""
1663)
1664
1665(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1666 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1667 (truncate:SI
1668 (lshiftrt:DI
215b30b3 1669 (mult:DI
e5fea38e 1670 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1671 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1672 (const_int 32))))
1673 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1674 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1675 "smull%?\\t%3, %0, %2, %1"
1676 [(set_attr "insn" "smull")
1677 (set_attr "predicable" "yes")]
1678)
1679
957788b0 1680(define_insn "*smulsi3_highpart_v6"
58d7d654 1681 [(set (match_operand:SI 0 "s_register_operand" "=r")
1682 (truncate:SI
1683 (lshiftrt:DI
1684 (mult:DI
1685 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1686 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1687 (const_int 32))))
1688 (clobber (match_scratch:SI 3 "=r"))]
1689 "TARGET_32BIT && arm_arch6"
f082f1c4 1690 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1691 [(set_attr "insn" "smull")
0d66636f 1692 (set_attr "predicable" "yes")]
cffb2a26 1693)
f082f1c4 1694
957788b0 1695(define_expand "umulsi3_highpart"
1696 [(parallel
1697 [(set (match_operand:SI 0 "s_register_operand" "")
1698 (truncate:SI
1699 (lshiftrt:DI
1700 (mult:DI
1701 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1702 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1703 (const_int 32))))
1704 (clobber (match_scratch:SI 3 ""))])]
1705 "TARGET_32BIT && arm_arch3m"
1706 ""
1707)
1708
1709(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1710 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1711 (truncate:SI
1712 (lshiftrt:DI
215b30b3 1713 (mult:DI
e5fea38e 1714 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1715 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1716 (const_int 32))))
1717 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1718 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1719 "umull%?\\t%3, %0, %2, %1"
1720 [(set_attr "insn" "umull")
1721 (set_attr "predicable" "yes")]
1722)
1723
957788b0 1724(define_insn "*umulsi3_highpart_v6"
58d7d654 1725 [(set (match_operand:SI 0 "s_register_operand" "=r")
1726 (truncate:SI
1727 (lshiftrt:DI
1728 (mult:DI
1729 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1730 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1731 (const_int 32))))
1732 (clobber (match_scratch:SI 3 "=r"))]
1733 "TARGET_32BIT && arm_arch6"
f082f1c4 1734 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1735 [(set_attr "insn" "umull")
0d66636f 1736 (set_attr "predicable" "yes")]
cffb2a26 1737)
f082f1c4 1738
331beb1a 1739(define_insn "mulhisi3"
1740 [(set (match_operand:SI 0 "s_register_operand" "=r")
1741 (mult:SI (sign_extend:SI
1742 (match_operand:HI 1 "s_register_operand" "%r"))
1743 (sign_extend:SI
1744 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1745 "TARGET_DSP_MULTIPLY"
61a2d04c 1746 "smulbb%?\\t%0, %1, %2"
a2cd141b 1747 [(set_attr "insn" "smulxy")
fec538d9 1748 (set_attr "predicable" "yes")]
1749)
1750
1751(define_insn "*mulhisi3tb"
1752 [(set (match_operand:SI 0 "s_register_operand" "=r")
1753 (mult:SI (ashiftrt:SI
1754 (match_operand:SI 1 "s_register_operand" "r")
1755 (const_int 16))
1756 (sign_extend:SI
1757 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1758 "TARGET_DSP_MULTIPLY"
fec538d9 1759 "smultb%?\\t%0, %1, %2"
a2cd141b 1760 [(set_attr "insn" "smulxy")
fec538d9 1761 (set_attr "predicable" "yes")]
1762)
1763
1764(define_insn "*mulhisi3bt"
1765 [(set (match_operand:SI 0 "s_register_operand" "=r")
1766 (mult:SI (sign_extend:SI
1767 (match_operand:HI 1 "s_register_operand" "r"))
1768 (ashiftrt:SI
1769 (match_operand:SI 2 "s_register_operand" "r")
1770 (const_int 16))))]
25f905c2 1771 "TARGET_DSP_MULTIPLY"
fec538d9 1772 "smulbt%?\\t%0, %1, %2"
a2cd141b 1773 [(set_attr "insn" "smulxy")
fec538d9 1774 (set_attr "predicable" "yes")]
1775)
1776
1777(define_insn "*mulhisi3tt"
1778 [(set (match_operand:SI 0 "s_register_operand" "=r")
1779 (mult:SI (ashiftrt:SI
1780 (match_operand:SI 1 "s_register_operand" "r")
1781 (const_int 16))
1782 (ashiftrt:SI
1783 (match_operand:SI 2 "s_register_operand" "r")
1784 (const_int 16))))]
25f905c2 1785 "TARGET_DSP_MULTIPLY"
fec538d9 1786 "smultt%?\\t%0, %1, %2"
a2cd141b 1787 [(set_attr "insn" "smulxy")
fec538d9 1788 (set_attr "predicable" "yes")]
331beb1a 1789)
1790
5cdca009 1791(define_insn "maddhisi4"
331beb1a 1792 [(set (match_operand:SI 0 "s_register_operand" "=r")
5cdca009 1793 (plus:SI (match_operand:SI 3 "s_register_operand" "r")
331beb1a 1794 (mult:SI (sign_extend:SI
5cdca009 1795 (match_operand:HI 1 "s_register_operand" "%r"))
331beb1a 1796 (sign_extend:SI
5cdca009 1797 (match_operand:HI 2 "s_register_operand" "r")))))]
25f905c2 1798 "TARGET_DSP_MULTIPLY"
5cdca009 1799 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1800 [(set_attr "insn" "smlaxy")
fec538d9 1801 (set_attr "predicable" "yes")]
331beb1a 1802)
1803
5cdca009 1804(define_insn "*maddhidi4"
331beb1a 1805 [(set (match_operand:DI 0 "s_register_operand" "=r")
1806 (plus:DI
5cdca009 1807 (match_operand:DI 3 "s_register_operand" "0")
331beb1a 1808 (mult:DI (sign_extend:DI
5cdca009 1809 (match_operand:HI 1 "s_register_operand" "%r"))
331beb1a 1810 (sign_extend:DI
5cdca009 1811 (match_operand:HI 2 "s_register_operand" "r")))))]
25f905c2 1812 "TARGET_DSP_MULTIPLY"
5cdca009 1813 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1814 [(set_attr "insn" "smlalxy")
fec538d9 1815 (set_attr "predicable" "yes")])
331beb1a 1816
604f3a0a 1817(define_expand "mulsf3"
1818 [(set (match_operand:SF 0 "s_register_operand" "")
1819 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1820 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1821 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1822 "
a2cd141b 1823 if (TARGET_MAVERICK
604f3a0a 1824 && !cirrus_fp_register (operands[2], SFmode))
1825 operands[2] = force_reg (SFmode, operands[2]);
1826")
1827
604f3a0a 1828(define_expand "muldf3"
1829 [(set (match_operand:DF 0 "s_register_operand" "")
1830 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1831 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1832 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1833 "
a2cd141b 1834 if (TARGET_MAVERICK
604f3a0a 1835 && !cirrus_fp_register (operands[2], DFmode))
1836 operands[2] = force_reg (DFmode, operands[2]);
1837")
b11cae9e 1838\f
1839;; Division insns
1840
7db9af5d 1841(define_expand "divsf3"
1842 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1843 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1844 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1845 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1846 "")
9c08d1fa 1847
7db9af5d 1848(define_expand "divdf3"
1849 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1850 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1851 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1852 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1853 "")
b11cae9e 1854\f
1855;; Modulo insns
1856
7db9af5d 1857(define_expand "modsf3"
1858 [(set (match_operand:SF 0 "s_register_operand" "")
1859 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1860 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1861 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1862 "")
9c08d1fa 1863
7db9af5d 1864(define_expand "moddf3"
1865 [(set (match_operand:DF 0 "s_register_operand" "")
1866 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1867 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1868 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1869 "")
b11cae9e 1870\f
1871;; Boolean and,ior,xor insns
1872
f6ebffac 1873;; Split up double word logical operations
1874
1875;; Split up simple DImode logical operations. Simply perform the logical
1876;; operation on the upper and lower halves of the registers.
1877(define_split
1878 [(set (match_operand:DI 0 "s_register_operand" "")
1879 (match_operator:DI 6 "logical_binary_operator"
1880 [(match_operand:DI 1 "s_register_operand" "")
1881 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1882 "TARGET_32BIT && reload_completed
e2669ea7 1883 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1884 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1885 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1886 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1887 "
215b30b3 1888 {
1889 operands[3] = gen_highpart (SImode, operands[0]);
1890 operands[0] = gen_lowpart (SImode, operands[0]);
1891 operands[4] = gen_highpart (SImode, operands[1]);
1892 operands[1] = gen_lowpart (SImode, operands[1]);
1893 operands[5] = gen_highpart (SImode, operands[2]);
1894 operands[2] = gen_lowpart (SImode, operands[2]);
1895 }"
1896)
f6ebffac 1897
f6ebffac 1898(define_split
1899 [(set (match_operand:DI 0 "s_register_operand" "")
1900 (match_operator:DI 6 "logical_binary_operator"
1901 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1902 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1903 "TARGET_32BIT && reload_completed"
f6ebffac 1904 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1905 (set (match_dup 3) (match_op_dup:SI 6
1906 [(ashiftrt:SI (match_dup 2) (const_int 31))
1907 (match_dup 4)]))]
1908 "
215b30b3 1909 {
1910 operands[3] = gen_highpart (SImode, operands[0]);
1911 operands[0] = gen_lowpart (SImode, operands[0]);
1912 operands[4] = gen_highpart (SImode, operands[1]);
1913 operands[1] = gen_lowpart (SImode, operands[1]);
1914 operands[5] = gen_highpart (SImode, operands[2]);
1915 operands[2] = gen_lowpart (SImode, operands[2]);
1916 }"
1917)
f6ebffac 1918
f6ebffac 1919;; The zero extend of operand 2 means we can just copy the high part of
1920;; operand1 into operand0.
1921(define_split
1922 [(set (match_operand:DI 0 "s_register_operand" "")
1923 (ior:DI
1924 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1925 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1926 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1927 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1928 (set (match_dup 3) (match_dup 4))]
1929 "
215b30b3 1930 {
1931 operands[4] = gen_highpart (SImode, operands[1]);
1932 operands[3] = gen_highpart (SImode, operands[0]);
1933 operands[0] = gen_lowpart (SImode, operands[0]);
1934 operands[1] = gen_lowpart (SImode, operands[1]);
1935 }"
1936)
f6ebffac 1937
1938;; The zero extend of operand 2 means we can just copy the high part of
1939;; operand1 into operand0.
1940(define_split
1941 [(set (match_operand:DI 0 "s_register_operand" "")
1942 (xor:DI
1943 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1944 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1945 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1946 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1947 (set (match_dup 3) (match_dup 4))]
1948 "
215b30b3 1949 {
1950 operands[4] = gen_highpart (SImode, operands[1]);
1951 operands[3] = gen_highpart (SImode, operands[0]);
1952 operands[0] = gen_lowpart (SImode, operands[0]);
1953 operands[1] = gen_lowpart (SImode, operands[1]);
1954 }"
1955)
f6ebffac 1956
e2669ea7 1957(define_expand "anddi3"
1958 [(set (match_operand:DI 0 "s_register_operand" "")
1959 (and:DI (match_operand:DI 1 "s_register_operand" "")
1960 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1961 "TARGET_32BIT"
1962 ""
1963)
1964
1965(define_insn "*anddi3_insn"
cffb2a26 1966 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1967 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1968 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 1969 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 1970 "#"
215b30b3 1971 [(set_attr "length" "8")]
1972)
b11cae9e 1973
a0f94409 1974(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1975 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1976 (and:DI (zero_extend:DI
1977 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1978 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1979 "TARGET_32BIT"
f6ebffac 1980 "#"
25f905c2 1981 "TARGET_32BIT && reload_completed"
a0f94409 1982 ; The zero extend of operand 2 clears the high word of the output
1983 ; operand.
1984 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1985 (set (match_dup 3) (const_int 0))]
1986 "
1987 {
1988 operands[3] = gen_highpart (SImode, operands[0]);
1989 operands[0] = gen_lowpart (SImode, operands[0]);
1990 operands[1] = gen_lowpart (SImode, operands[1]);
1991 }"
215b30b3 1992 [(set_attr "length" "8")]
1993)
b11cae9e 1994
f7fbdd4a 1995(define_insn "*anddi_sesdi_di"
cffb2a26 1996 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1997 (and:DI (sign_extend:DI
1998 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1999 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2000 "TARGET_32BIT"
f6ebffac 2001 "#"
cffb2a26 2002 [(set_attr "length" "8")]
2003)
b11cae9e 2004
87b22bf7 2005(define_expand "andsi3"
cffb2a26 2006 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2007 (and:SI (match_operand:SI 1 "s_register_operand" "")
2008 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2009 "TARGET_EITHER"
87b22bf7 2010 "
25f905c2 2011 if (TARGET_32BIT)
87b22bf7 2012 {
cffb2a26 2013 if (GET_CODE (operands[2]) == CONST_INT)
2014 {
47b5b27b 2015 if (INTVAL (operands[2]) == 255 && arm_arch6)
2016 {
2017 operands[1] = convert_to_mode (QImode, operands[1], 1);
2018 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2019 operands[1]));
2020 }
2021 else
2022 arm_split_constant (AND, SImode, NULL_RTX,
2023 INTVAL (operands[2]), operands[0],
2024 operands[1],
2025 optimize && can_create_pseudo_p ());
615caa51 2026
cffb2a26 2027 DONE;
2028 }
87b22bf7 2029 }
25f905c2 2030 else /* TARGET_THUMB1 */
cffb2a26 2031 {
2032 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2033 {
2034 rtx tmp = force_reg (SImode, operands[2]);
2035 if (rtx_equal_p (operands[0], operands[1]))
2036 operands[2] = tmp;
2037 else
2038 {
2039 operands[2] = operands[1];
2040 operands[1] = tmp;
2041 }
2042 }
cffb2a26 2043 else
2044 {
2045 int i;
2046
215b30b3 2047 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2048 {
215b30b3 2049 operands[2] = force_reg (SImode,
2050 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2051
747b7458 2052 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2053
2054 DONE;
2055 }
87b22bf7 2056
cffb2a26 2057 for (i = 9; i <= 31; i++)
2058 {
2059 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2060 {
2061 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2062 const0_rtx));
2063 DONE;
2064 }
215b30b3 2065 else if ((((HOST_WIDE_INT) 1) << i) - 1
2066 == ~INTVAL (operands[2]))
cffb2a26 2067 {
2068 rtx shift = GEN_INT (i);
2069 rtx reg = gen_reg_rtx (SImode);
2070
2071 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2072 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2073
2074 DONE;
2075 }
2076 }
2077
2078 operands[2] = force_reg (SImode, operands[2]);
2079 }
215b30b3 2080 }
2081 "
cffb2a26 2082)
2083
25f905c2 2084; ??? Check split length for Thumb-2
a0f94409 2085(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2086 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2087 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2088 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2089 "TARGET_32BIT"
5565501b 2090 "@
2091 and%?\\t%0, %1, %2
87b22bf7 2092 bic%?\\t%0, %1, #%B2
2093 #"
25f905c2 2094 "TARGET_32BIT
a0f94409 2095 && GET_CODE (operands[2]) == CONST_INT
2096 && !(const_ok_for_arm (INTVAL (operands[2]))
2097 || const_ok_for_arm (~INTVAL (operands[2])))"
2098 [(clobber (const_int 0))]
2099 "
96f57e36 2100 arm_split_constant (AND, SImode, curr_insn,
2101 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2102 DONE;
2103 "
0d66636f 2104 [(set_attr "length" "4,4,16")
2105 (set_attr "predicable" "yes")]
cffb2a26 2106)
2107
25f905c2 2108(define_insn "*thumb1_andsi3_insn"
cffb2a26 2109 [(set (match_operand:SI 0 "register_operand" "=l")
2110 (and:SI (match_operand:SI 1 "register_operand" "%0")
2111 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2112 "TARGET_THUMB1"
747b7458 2113 "and\\t%0, %2"
2114 [(set_attr "length" "2")
2115 (set_attr "conds" "set")])
87b22bf7 2116
f7fbdd4a 2117(define_insn "*andsi3_compare0"
bd5b4116 2118 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2119 (compare:CC_NOOV
2120 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2121 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2122 (const_int 0)))
cffb2a26 2123 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2124 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2125 "TARGET_32BIT"
5565501b 2126 "@
25f905c2 2127 and%.\\t%0, %1, %2
2128 bic%.\\t%0, %1, #%B2"
cffb2a26 2129 [(set_attr "conds" "set")]
2130)
9c08d1fa 2131
f7fbdd4a 2132(define_insn "*andsi3_compare0_scratch"
bd5b4116 2133 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2134 (compare:CC_NOOV
2135 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2136 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2137 (const_int 0)))
dd193d7c 2138 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2139 "TARGET_32BIT"
5565501b 2140 "@
2141 tst%?\\t%0, %1
25f905c2 2142 bic%.\\t%2, %0, #%B1"
0d66636f 2143 [(set_attr "conds" "set")]
2144)
9c08d1fa 2145
f7fbdd4a 2146(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2147 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2148 (compare:CC_NOOV (zero_extract:SI
2149 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2150 (match_operand 1 "const_int_operand" "n")
2151 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2152 (const_int 0)))]
25f905c2 2153 "TARGET_32BIT
cffb2a26 2154 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2155 && INTVAL (operands[1]) > 0
2156 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2157 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2158 "*
5c49a439 2159 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2160 << INTVAL (operands[2]));
40dbec34 2161 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2162 return \"\";
0d66636f 2163 "
2164 [(set_attr "conds" "set")]
2165)
9c08d1fa 2166
f4462328 2167(define_insn_and_split "*ne_zeroextractsi"
c4034607 2168 [(set (match_operand:SI 0 "s_register_operand" "=r")
2169 (ne:SI (zero_extract:SI
2170 (match_operand:SI 1 "s_register_operand" "r")
2171 (match_operand:SI 2 "const_int_operand" "n")
2172 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2173 (const_int 0)))
2174 (clobber (reg:CC CC_REGNUM))]
25f905c2 2175 "TARGET_32BIT
cffb2a26 2176 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2177 && INTVAL (operands[2]) > 0
2178 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2179 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2180 "#"
25f905c2 2181 "TARGET_32BIT
f4462328 2182 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2183 && INTVAL (operands[2]) > 0
2184 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2185 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2186 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2187 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2188 (const_int 0)))
2189 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2190 (set (match_dup 0)
2191 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2192 (match_dup 0) (const_int 1)))]
2193 "
2194 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2195 << INTVAL (operands[3]));
2196 "
2197 [(set_attr "conds" "clob")
25f905c2 2198 (set (attr "length")
2199 (if_then_else (eq_attr "is_thumb" "yes")
2200 (const_int 12)
2201 (const_int 8)))]
f4462328 2202)
2203
2204(define_insn_and_split "*ne_zeroextractsi_shifted"
2205 [(set (match_operand:SI 0 "s_register_operand" "=r")
2206 (ne:SI (zero_extract:SI
2207 (match_operand:SI 1 "s_register_operand" "r")
2208 (match_operand:SI 2 "const_int_operand" "n")
2209 (const_int 0))
2210 (const_int 0)))
2211 (clobber (reg:CC CC_REGNUM))]
2212 "TARGET_ARM"
2213 "#"
2214 "TARGET_ARM"
2215 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2216 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2217 (const_int 0)))
2218 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2219 (set (match_dup 0)
2220 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2221 (match_dup 0) (const_int 1)))]
2222 "
2223 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2224 "
2225 [(set_attr "conds" "clob")
2226 (set_attr "length" "8")]
2227)
2228
2229(define_insn_and_split "*ite_ne_zeroextractsi"
2230 [(set (match_operand:SI 0 "s_register_operand" "=r")
2231 (if_then_else:SI (ne (zero_extract:SI
2232 (match_operand:SI 1 "s_register_operand" "r")
2233 (match_operand:SI 2 "const_int_operand" "n")
2234 (match_operand:SI 3 "const_int_operand" "n"))
2235 (const_int 0))
2236 (match_operand:SI 4 "arm_not_operand" "rIK")
2237 (const_int 0)))
2238 (clobber (reg:CC CC_REGNUM))]
2239 "TARGET_ARM
2240 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2241 && INTVAL (operands[2]) > 0
2242 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2243 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2244 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2245 "#"
2246 "TARGET_ARM
2247 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2248 && INTVAL (operands[2]) > 0
2249 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2250 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2251 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2252 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2253 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2254 (const_int 0)))
2255 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2256 (set (match_dup 0)
2257 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2258 (match_dup 0) (match_dup 4)))]
2259 "
c4034607 2260 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2261 << INTVAL (operands[3]));
2262 "
2263 [(set_attr "conds" "clob")
2264 (set_attr "length" "8")]
2265)
2266
2267(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2268 [(set (match_operand:SI 0 "s_register_operand" "=r")
2269 (if_then_else:SI (ne (zero_extract:SI
2270 (match_operand:SI 1 "s_register_operand" "r")
2271 (match_operand:SI 2 "const_int_operand" "n")
2272 (const_int 0))
2273 (const_int 0))
2274 (match_operand:SI 3 "arm_not_operand" "rIK")
2275 (const_int 0)))
2276 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2277 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2278 "#"
f8d7bf2f 2279 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2280 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2281 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2282 (const_int 0)))
2283 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2284 (set (match_dup 0)
2285 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2286 (match_dup 0) (match_dup 3)))]
2287 "
2288 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2289 "
2290 [(set_attr "conds" "clob")
215b30b3 2291 (set_attr "length" "8")]
2292)
9c08d1fa 2293
58d6528b 2294(define_split
2295 [(set (match_operand:SI 0 "s_register_operand" "")
2296 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2297 (match_operand:SI 2 "const_int_operand" "")
2298 (match_operand:SI 3 "const_int_operand" "")))
2299 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2300 "TARGET_THUMB1"
58d6528b 2301 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2302 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2303 "{
2304 HOST_WIDE_INT temp = INTVAL (operands[2]);
2305
2306 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2307 operands[3] = GEN_INT (32 - temp);
2308 }"
2309)
2310
25f905c2 2311;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2312(define_split
2313 [(set (match_operand:SI 0 "s_register_operand" "")
2314 (match_operator:SI 1 "shiftable_operator"
2315 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2316 (match_operand:SI 3 "const_int_operand" "")
2317 (match_operand:SI 4 "const_int_operand" ""))
2318 (match_operand:SI 5 "s_register_operand" "")]))
2319 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2320 "TARGET_ARM"
2321 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2322 (set (match_dup 0)
2323 (match_op_dup 1
2324 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2325 (match_dup 5)]))]
2326 "{
2327 HOST_WIDE_INT temp = INTVAL (operands[3]);
2328
2329 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2330 operands[4] = GEN_INT (32 - temp);
2331 }"
2332)
2333
58d6528b 2334(define_split
2335 [(set (match_operand:SI 0 "s_register_operand" "")
2336 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2337 (match_operand:SI 2 "const_int_operand" "")
2338 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2339 "TARGET_THUMB1"
58d6528b 2340 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2341 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2342 "{
2343 HOST_WIDE_INT temp = INTVAL (operands[2]);
2344
2345 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2346 operands[3] = GEN_INT (32 - temp);
2347 }"
2348)
2349
d7863cfe 2350(define_split
2351 [(set (match_operand:SI 0 "s_register_operand" "")
2352 (match_operator:SI 1 "shiftable_operator"
2353 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2354 (match_operand:SI 3 "const_int_operand" "")
2355 (match_operand:SI 4 "const_int_operand" ""))
2356 (match_operand:SI 5 "s_register_operand" "")]))
2357 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2358 "TARGET_ARM"
2359 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2360 (set (match_dup 0)
2361 (match_op_dup 1
2362 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2363 (match_dup 5)]))]
2364 "{
2365 HOST_WIDE_INT temp = INTVAL (operands[3]);
2366
2367 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2368 operands[4] = GEN_INT (32 - temp);
2369 }"
2370)
2371
a42059fd 2372;;; ??? This pattern is bogus. If operand3 has bits outside the range
2373;;; represented by the bitfield, then this will produce incorrect results.
2374;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2375;;; which have a real bit-field insert instruction, the truncation happens
2376;;; in the bit-field insert instruction itself. Since arm does not have a
2377;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2378;;; the value before we insert. This loses some of the advantage of having
2379;;; this insv pattern, so this pattern needs to be reevalutated.
2380
8a18b90c 2381(define_expand "insv"
2382 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2383 (match_operand:SI 1 "general_operand" "")
2384 (match_operand:SI 2 "general_operand" ""))
19335226 2385 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2386 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2387 "
215b30b3 2388 {
2389 int start_bit = INTVAL (operands[2]);
2390 int width = INTVAL (operands[1]);
2391 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2392 rtx target, subtarget;
2393
8b054d5a 2394 if (arm_arch_thumb2)
2395 {
2396 bool use_bfi = TRUE;
2397
2398 if (GET_CODE (operands[3]) == CONST_INT)
2399 {
2400 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2401
2402 if (val == 0)
2403 {
2404 emit_insn (gen_insv_zero (operands[0], operands[1],
2405 operands[2]));
2406 DONE;
2407 }
2408
2409 /* See if the set can be done with a single orr instruction. */
2410 if (val == mask && const_ok_for_arm (val << start_bit))
2411 use_bfi = FALSE;
2412 }
2413
2414 if (use_bfi)
2415 {
2416 if (GET_CODE (operands[3]) != REG)
2417 operands[3] = force_reg (SImode, operands[3]);
2418
2419 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2420 operands[3]));
2421 DONE;
2422 }
2423 }
2424
3f8fde42 2425 target = copy_rtx (operands[0]);
215b30b3 2426 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2427 subreg as the final target. */
2428 if (GET_CODE (target) == SUBREG)
2429 {
2430 subtarget = gen_reg_rtx (SImode);
2431 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2432 < GET_MODE_SIZE (SImode))
2433 target = SUBREG_REG (target);
2434 }
2435 else
2436 subtarget = target;
8a18b90c 2437
215b30b3 2438 if (GET_CODE (operands[3]) == CONST_INT)
2439 {
2440 /* Since we are inserting a known constant, we may be able to
2441 reduce the number of bits that we have to clear so that
2442 the mask becomes simple. */
2443 /* ??? This code does not check to see if the new mask is actually
2444 simpler. It may not be. */
2445 rtx op1 = gen_reg_rtx (SImode);
2446 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2447 start of this pattern. */
2448 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2449 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2450
c5b3a71b 2451 emit_insn (gen_andsi3 (op1, operands[0],
2452 gen_int_mode (~mask2, SImode)));
215b30b3 2453 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2454 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2455 }
2456 else if (start_bit == 0
2457 && !(const_ok_for_arm (mask)
2458 || const_ok_for_arm (~mask)))
2459 {
2460 /* A Trick, since we are setting the bottom bits in the word,
2461 we can shift operand[3] up, operand[0] down, OR them together
2462 and rotate the result back again. This takes 3 insns, and
5910bb95 2463 the third might be mergeable into another op. */
215b30b3 2464 /* The shift up copes with the possibility that operand[3] is
2465 wider than the bitfield. */
2466 rtx op0 = gen_reg_rtx (SImode);
2467 rtx op1 = gen_reg_rtx (SImode);
2468
2469 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2470 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2471 emit_insn (gen_iorsi3 (op1, op1, op0));
2472 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2473 }
2474 else if ((width + start_bit == 32)
2475 && !(const_ok_for_arm (mask)
2476 || const_ok_for_arm (~mask)))
2477 {
2478 /* Similar trick, but slightly less efficient. */
8a18b90c 2479
215b30b3 2480 rtx op0 = gen_reg_rtx (SImode);
2481 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2482
215b30b3 2483 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2484 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2485 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2486 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2487 }
2488 else
2489 {
c5b3a71b 2490 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2491 rtx op1 = gen_reg_rtx (SImode);
2492 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2493
215b30b3 2494 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2495 {
2496 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2497
215b30b3 2498 emit_insn (gen_movsi (tmp, op0));
2499 op0 = tmp;
2500 }
8a18b90c 2501
215b30b3 2502 /* Mask out any bits in operand[3] that are not needed. */
2503 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2504
215b30b3 2505 if (GET_CODE (op0) == CONST_INT
2506 && (const_ok_for_arm (mask << start_bit)
2507 || const_ok_for_arm (~(mask << start_bit))))
2508 {
c5b3a71b 2509 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2510 emit_insn (gen_andsi3 (op2, operands[0], op0));
2511 }
2512 else
2513 {
2514 if (GET_CODE (op0) == CONST_INT)
2515 {
2516 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2517
215b30b3 2518 emit_insn (gen_movsi (tmp, op0));
2519 op0 = tmp;
2520 }
2521
2522 if (start_bit != 0)
2523 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2524
215b30b3 2525 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2526 }
8a18b90c 2527
215b30b3 2528 if (start_bit != 0)
2529 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2530
215b30b3 2531 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2532 }
f082f1c4 2533
215b30b3 2534 if (subtarget != target)
2535 {
2536 /* If TARGET is still a SUBREG, then it must be wider than a word,
2537 so we must be careful only to set the subword we were asked to. */
2538 if (GET_CODE (target) == SUBREG)
2539 emit_move_insn (target, subtarget);
2540 else
2541 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2542 }
8a18b90c 2543
215b30b3 2544 DONE;
2545 }"
2546)
8a18b90c 2547
8b054d5a 2548(define_insn "insv_zero"
2549 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2550 (match_operand:SI 1 "const_int_operand" "M")
2551 (match_operand:SI 2 "const_int_operand" "M"))
2552 (const_int 0))]
2553 "arm_arch_thumb2"
2554 "bfc%?\t%0, %2, %1"
2555 [(set_attr "length" "4")
2556 (set_attr "predicable" "yes")]
2557)
2558
2559(define_insn "insv_t2"
2560 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2561 (match_operand:SI 1 "const_int_operand" "M")
2562 (match_operand:SI 2 "const_int_operand" "M"))
2563 (match_operand:SI 3 "s_register_operand" "r"))]
2564 "arm_arch_thumb2"
2565 "bfi%?\t%0, %3, %2, %1"
2566 [(set_attr "length" "4")
2567 (set_attr "predicable" "yes")]
2568)
2569
215b30b3 2570; constants for op 2 will never be given to these patterns.
a0f94409 2571(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2572 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2573 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2574 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2575 "TARGET_32BIT"
f6ebffac 2576 "#"
e2669ea7 2577 "TARGET_32BIT && reload_completed
2578 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2579 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2580 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2581 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2582 "
2583 {
2584 operands[3] = gen_highpart (SImode, operands[0]);
2585 operands[0] = gen_lowpart (SImode, operands[0]);
2586 operands[4] = gen_highpart (SImode, operands[1]);
2587 operands[1] = gen_lowpart (SImode, operands[1]);
2588 operands[5] = gen_highpart (SImode, operands[2]);
2589 operands[2] = gen_lowpart (SImode, operands[2]);
2590 }"
0d66636f 2591 [(set_attr "length" "8")
2592 (set_attr "predicable" "yes")]
2593)
9c08d1fa 2594
a0f94409 2595(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2596 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2597 (and:DI (not:DI (zero_extend:DI
2598 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2599 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2600 "TARGET_32BIT"
e2348bcb 2601 "@
97499065 2602 bic%?\\t%Q0, %Q1, %2
f6ebffac 2603 #"
a0f94409 2604 ; (not (zero_extend ...)) allows us to just copy the high word from
2605 ; operand1 to operand0.
25f905c2 2606 "TARGET_32BIT
a0f94409 2607 && reload_completed
2608 && operands[0] != operands[1]"
5a097f7d 2609 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2610 (set (match_dup 3) (match_dup 4))]
2611 "
2612 {
2613 operands[3] = gen_highpart (SImode, operands[0]);
2614 operands[0] = gen_lowpart (SImode, operands[0]);
2615 operands[4] = gen_highpart (SImode, operands[1]);
2616 operands[1] = gen_lowpart (SImode, operands[1]);
2617 }"
0d66636f 2618 [(set_attr "length" "4,8")
2619 (set_attr "predicable" "yes")]
2620)
9c08d1fa 2621
a0f94409 2622(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2623 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2624 (and:DI (not:DI (sign_extend:DI
2625 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2626 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2627 "TARGET_32BIT"
f6ebffac 2628 "#"
25f905c2 2629 "TARGET_32BIT && reload_completed"
5a097f7d 2630 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2631 (set (match_dup 3) (and:SI (not:SI
2632 (ashiftrt:SI (match_dup 2) (const_int 31)))
2633 (match_dup 4)))]
2634 "
2635 {
2636 operands[3] = gen_highpart (SImode, operands[0]);
2637 operands[0] = gen_lowpart (SImode, operands[0]);
2638 operands[4] = gen_highpart (SImode, operands[1]);
2639 operands[1] = gen_lowpart (SImode, operands[1]);
2640 }"
0d66636f 2641 [(set_attr "length" "8")
2642 (set_attr "predicable" "yes")]
2643)
9c08d1fa 2644
8a18b90c 2645(define_insn "andsi_notsi_si"
9c08d1fa 2646 [(set (match_operand:SI 0 "s_register_operand" "=r")
2647 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2648 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2649 "TARGET_32BIT"
0d66636f 2650 "bic%?\\t%0, %1, %2"
2651 [(set_attr "predicable" "yes")]
2652)
b11cae9e 2653
747b7458 2654(define_insn "thumb1_bicsi3"
cffb2a26 2655 [(set (match_operand:SI 0 "register_operand" "=l")
2656 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2657 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2658 "TARGET_THUMB1"
747b7458 2659 "bic\\t%0, %1"
2660 [(set_attr "length" "2")
2661 (set_attr "conds" "set")])
cffb2a26 2662
8a18b90c 2663(define_insn "andsi_not_shiftsi_si"
a2cd141b 2664 [(set (match_operand:SI 0 "s_register_operand" "=r")
2665 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2666 [(match_operand:SI 2 "s_register_operand" "r")
2667 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2668 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2669 "TARGET_ARM"
6c4c2133 2670 "bic%?\\t%0, %1, %2%S4"
344495ea 2671 [(set_attr "predicable" "yes")
331beb1a 2672 (set_attr "shift" "2")
a2cd141b 2673 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2674 (const_string "alu_shift")
2675 (const_string "alu_shift_reg")))]
6c4c2133 2676)
8a18b90c 2677
f7fbdd4a 2678(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2679 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2680 (compare:CC_NOOV
2681 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2682 (match_operand:SI 1 "s_register_operand" "r"))
2683 (const_int 0)))
9c08d1fa 2684 (set (match_operand:SI 0 "s_register_operand" "=r")
2685 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2686 "TARGET_32BIT"
2687 "bic%.\\t%0, %1, %2"
0d66636f 2688 [(set_attr "conds" "set")]
2689)
9c08d1fa 2690
f7fbdd4a 2691(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2692 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2693 (compare:CC_NOOV
2694 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2695 (match_operand:SI 1 "s_register_operand" "r"))
2696 (const_int 0)))
9c08d1fa 2697 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2698 "TARGET_32BIT"
2699 "bic%.\\t%0, %1, %2"
0d66636f 2700 [(set_attr "conds" "set")]
2701)
9c08d1fa 2702
e2669ea7 2703(define_expand "iordi3"
2704 [(set (match_operand:DI 0 "s_register_operand" "")
2705 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2706 (match_operand:DI 2 "neon_logic_op2" "")))]
2707 "TARGET_32BIT"
2708 ""
2709)
2710
2711(define_insn "*iordi3_insn"
cffb2a26 2712 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2713 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2714 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2715 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2716 "#"
0d66636f 2717 [(set_attr "length" "8")
2718 (set_attr "predicable" "yes")]
cffb2a26 2719)
9c08d1fa 2720
f7fbdd4a 2721(define_insn "*iordi_zesidi_di"
9c08d1fa 2722 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2723 (ior:DI (zero_extend:DI
2724 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2725 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2726 "TARGET_32BIT"
e2348bcb 2727 "@
97499065 2728 orr%?\\t%Q0, %Q1, %2
f6ebffac 2729 #"
0d66636f 2730 [(set_attr "length" "4,8")
2731 (set_attr "predicable" "yes")]
cffb2a26 2732)
9c08d1fa 2733
f7fbdd4a 2734(define_insn "*iordi_sesidi_di"
9c08d1fa 2735 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2736 (ior:DI (sign_extend:DI
2737 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2738 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2739 "TARGET_32BIT"
f6ebffac 2740 "#"
0d66636f 2741 [(set_attr "length" "8")
2742 (set_attr "predicable" "yes")]
cffb2a26 2743)
9c08d1fa 2744
87b22bf7 2745(define_expand "iorsi3"
cffb2a26 2746 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2747 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2748 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2749 "TARGET_EITHER"
87b22bf7 2750 "
2751 if (GET_CODE (operands[2]) == CONST_INT)
2752 {
25f905c2 2753 if (TARGET_32BIT)
cffb2a26 2754 {
96f57e36 2755 arm_split_constant (IOR, SImode, NULL_RTX,
2756 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2757 optimize && can_create_pseudo_p ());
cffb2a26 2758 DONE;
2759 }
25f905c2 2760 else /* TARGET_THUMB1 */
923ffadb 2761 {
2762 rtx tmp = force_reg (SImode, operands[2]);
2763 if (rtx_equal_p (operands[0], operands[1]))
2764 operands[2] = tmp;
2765 else
2766 {
2767 operands[2] = operands[1];
2768 operands[1] = tmp;
2769 }
2770 }
87b22bf7 2771 }
cffb2a26 2772 "
2773)
87b22bf7 2774
d5d4dc8d 2775(define_insn_and_split "*iorsi3_insn"
2776 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2777 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2778 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2779 "TARGET_32BIT"
87b22bf7 2780 "@
2781 orr%?\\t%0, %1, %2
d5d4dc8d 2782 orn%?\\t%0, %1, #%B2
87b22bf7 2783 #"
d5d4dc8d 2784 "TARGET_32BIT
a0f94409 2785 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2786 && !(const_ok_for_arm (INTVAL (operands[2]))
2787 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2788 [(clobber (const_int 0))]
d5d4dc8d 2789{
96f57e36 2790 arm_split_constant (IOR, SImode, curr_insn,
2791 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2792 DONE;
d5d4dc8d 2793}
2794 [(set_attr "length" "4,4,16")
2795 (set_attr "arch" "32,t2,32")
2796 (set_attr "predicable" "yes")])
cffb2a26 2797
747b7458 2798(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2799 [(set (match_operand:SI 0 "register_operand" "=l")
2800 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2801 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2802 "TARGET_THUMB1"
747b7458 2803 "orr\\t%0, %2"
2804 [(set_attr "length" "2")
2805 (set_attr "conds" "set")])
9c08d1fa 2806
a0f94409 2807(define_peephole2
2808 [(match_scratch:SI 3 "r")
372575c7 2809 (set (match_operand:SI 0 "arm_general_register_operand" "")
2810 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2811 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2812 "TARGET_ARM
a0f94409 2813 && !const_ok_for_arm (INTVAL (operands[2]))
2814 && const_ok_for_arm (~INTVAL (operands[2]))"
2815 [(set (match_dup 3) (match_dup 2))
2816 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2817 ""
215b30b3 2818)
a0f94409 2819
f7fbdd4a 2820(define_insn "*iorsi3_compare0"
bd5b4116 2821 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2822 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2823 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2824 (const_int 0)))
2825 (set (match_operand:SI 0 "s_register_operand" "=r")
2826 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2827 "TARGET_32BIT"
2828 "orr%.\\t%0, %1, %2"
cffb2a26 2829 [(set_attr "conds" "set")]
2830)
9c08d1fa 2831
f7fbdd4a 2832(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2833 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2834 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2835 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2836 (const_int 0)))
2837 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2838 "TARGET_32BIT"
2839 "orr%.\\t%0, %1, %2"
0d66636f 2840 [(set_attr "conds" "set")]
2841)
9c08d1fa 2842
e2669ea7 2843(define_expand "xordi3"
2844 [(set (match_operand:DI 0 "s_register_operand" "")
2845 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2846 (match_operand:DI 2 "s_register_operand" "")))]
2847 "TARGET_32BIT"
2848 ""
2849)
2850
2851(define_insn "*xordi3_insn"
cffb2a26 2852 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2853 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2854 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2855 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2856 "#"
0d66636f 2857 [(set_attr "length" "8")
2858 (set_attr "predicable" "yes")]
cffb2a26 2859)
9c08d1fa 2860
f7fbdd4a 2861(define_insn "*xordi_zesidi_di"
9c08d1fa 2862 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2863 (xor:DI (zero_extend:DI
2864 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2865 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2866 "TARGET_32BIT"
e2348bcb 2867 "@
97499065 2868 eor%?\\t%Q0, %Q1, %2
f6ebffac 2869 #"
0d66636f 2870 [(set_attr "length" "4,8")
2871 (set_attr "predicable" "yes")]
cffb2a26 2872)
9c08d1fa 2873
f7fbdd4a 2874(define_insn "*xordi_sesidi_di"
9c08d1fa 2875 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2876 (xor:DI (sign_extend:DI
2877 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2878 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2879 "TARGET_32BIT"
f6ebffac 2880 "#"
0d66636f 2881 [(set_attr "length" "8")
2882 (set_attr "predicable" "yes")]
cffb2a26 2883)
9c08d1fa 2884
cffb2a26 2885(define_expand "xorsi3"
2886 [(set (match_operand:SI 0 "s_register_operand" "")
2887 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2888 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2889 "TARGET_EITHER"
923ffadb 2890 "if (GET_CODE (operands[2]) == CONST_INT)
2891 {
2892 if (TARGET_32BIT)
2893 {
2894 arm_split_constant (XOR, SImode, NULL_RTX,
2895 INTVAL (operands[2]), operands[0], operands[1],
2896 optimize && can_create_pseudo_p ());
2897 DONE;
2898 }
2899 else /* TARGET_THUMB1 */
2900 {
2901 rtx tmp = force_reg (SImode, operands[2]);
2902 if (rtx_equal_p (operands[0], operands[1]))
2903 operands[2] = tmp;
2904 else
2905 {
2906 operands[2] = operands[1];
2907 operands[1] = tmp;
2908 }
2909 }
2910 }"
cffb2a26 2911)
2912
2913(define_insn "*arm_xorsi3"
2914 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2915 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2916 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2917 "TARGET_32BIT"
cffb2a26 2918 "eor%?\\t%0, %1, %2"
0d66636f 2919 [(set_attr "predicable" "yes")]
cffb2a26 2920)
2921
747b7458 2922(define_insn "*thumb1_xorsi3_insn"
cffb2a26 2923 [(set (match_operand:SI 0 "register_operand" "=l")
2924 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2925 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2926 "TARGET_THUMB1"
747b7458 2927 "eor\\t%0, %2"
2928 [(set_attr "length" "2")
2929 (set_attr "conds" "set")])
9c08d1fa 2930
f7fbdd4a 2931(define_insn "*xorsi3_compare0"
bd5b4116 2932 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2933 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2934 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2935 (const_int 0)))
2936 (set (match_operand:SI 0 "s_register_operand" "=r")
2937 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2938 "TARGET_32BIT"
2939 "eor%.\\t%0, %1, %2"
0d66636f 2940 [(set_attr "conds" "set")]
2941)
9c08d1fa 2942
f7fbdd4a 2943(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2944 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2945 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2946 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2947 (const_int 0)))]
25f905c2 2948 "TARGET_32BIT"
40dbec34 2949 "teq%?\\t%0, %1"
cffb2a26 2950 [(set_attr "conds" "set")]
2951)
9c08d1fa 2952
215b30b3 2953; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2954; (NOT D) we can sometimes merge the final NOT into one of the following
2955; insns.
9c08d1fa 2956
2957(define_split
a058e94a 2958 [(set (match_operand:SI 0 "s_register_operand" "")
2959 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2960 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2961 (match_operand:SI 3 "arm_rhs_operand" "")))
2962 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2963 "TARGET_32BIT"
9c08d1fa 2964 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2965 (not:SI (match_dup 3))))
2966 (set (match_dup 0) (not:SI (match_dup 4)))]
2967 ""
2968)
2969
f7fbdd4a 2970(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2971 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 2972 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 2973 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2974 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2975 "TARGET_32BIT"
40dbec34 2976 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2977 [(set_attr "length" "8")
25f905c2 2978 (set_attr "ce_count" "2")
0d66636f 2979 (set_attr "predicable" "yes")]
cffb2a26 2980)
9c08d1fa 2981
25f905c2 2982; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2983; insns are available?
d7863cfe 2984(define_split
2985 [(set (match_operand:SI 0 "s_register_operand" "")
2986 (match_operator:SI 1 "logical_binary_operator"
2987 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2988 (match_operand:SI 3 "const_int_operand" "")
2989 (match_operand:SI 4 "const_int_operand" ""))
2990 (match_operator:SI 9 "logical_binary_operator"
2991 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2992 (match_operand:SI 6 "const_int_operand" ""))
2993 (match_operand:SI 7 "s_register_operand" "")])]))
2994 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2995 "TARGET_32BIT
d7863cfe 2996 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2997 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2998 [(set (match_dup 8)
2999 (match_op_dup 1
3000 [(ashift:SI (match_dup 2) (match_dup 4))
3001 (match_dup 5)]))
3002 (set (match_dup 0)
3003 (match_op_dup 1
3004 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3005 (match_dup 7)]))]
3006 "
3007 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3008")
3009
3010(define_split
3011 [(set (match_operand:SI 0 "s_register_operand" "")
3012 (match_operator:SI 1 "logical_binary_operator"
3013 [(match_operator:SI 9 "logical_binary_operator"
3014 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3015 (match_operand:SI 6 "const_int_operand" ""))
3016 (match_operand:SI 7 "s_register_operand" "")])
3017 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3018 (match_operand:SI 3 "const_int_operand" "")
3019 (match_operand:SI 4 "const_int_operand" ""))]))
3020 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3021 "TARGET_32BIT
d7863cfe 3022 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3023 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3024 [(set (match_dup 8)
3025 (match_op_dup 1
3026 [(ashift:SI (match_dup 2) (match_dup 4))
3027 (match_dup 5)]))
3028 (set (match_dup 0)
3029 (match_op_dup 1
3030 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3031 (match_dup 7)]))]
3032 "
3033 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3034")
3035
3036(define_split
3037 [(set (match_operand:SI 0 "s_register_operand" "")
3038 (match_operator:SI 1 "logical_binary_operator"
3039 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3040 (match_operand:SI 3 "const_int_operand" "")
3041 (match_operand:SI 4 "const_int_operand" ""))
3042 (match_operator:SI 9 "logical_binary_operator"
3043 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3044 (match_operand:SI 6 "const_int_operand" ""))
3045 (match_operand:SI 7 "s_register_operand" "")])]))
3046 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3047 "TARGET_32BIT
d7863cfe 3048 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3049 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3050 [(set (match_dup 8)
3051 (match_op_dup 1
3052 [(ashift:SI (match_dup 2) (match_dup 4))
3053 (match_dup 5)]))
3054 (set (match_dup 0)
3055 (match_op_dup 1
3056 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3057 (match_dup 7)]))]
3058 "
3059 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3060")
3061
3062(define_split
3063 [(set (match_operand:SI 0 "s_register_operand" "")
3064 (match_operator:SI 1 "logical_binary_operator"
3065 [(match_operator:SI 9 "logical_binary_operator"
3066 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3067 (match_operand:SI 6 "const_int_operand" ""))
3068 (match_operand:SI 7 "s_register_operand" "")])
3069 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3070 (match_operand:SI 3 "const_int_operand" "")
3071 (match_operand:SI 4 "const_int_operand" ""))]))
3072 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3073 "TARGET_32BIT
d7863cfe 3074 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3075 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3076 [(set (match_dup 8)
3077 (match_op_dup 1
3078 [(ashift:SI (match_dup 2) (match_dup 4))
3079 (match_dup 5)]))
3080 (set (match_dup 0)
3081 (match_op_dup 1
3082 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3083 (match_dup 7)]))]
3084 "
3085 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3086")
9c08d1fa 3087\f
3088
3089;; Minimum and maximum insns
3090
8b9dc177 3091(define_expand "smaxsi3"
3092 [(parallel [
3093 (set (match_operand:SI 0 "s_register_operand" "")
3094 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3095 (match_operand:SI 2 "arm_rhs_operand" "")))
3096 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3097 "TARGET_32BIT"
8b9dc177 3098 "
8774928b 3099 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3100 {
3101 /* No need for a clobber of the condition code register here. */
3102 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3103 gen_rtx_SMAX (SImode, operands[1],
3104 operands[2])));
3105 DONE;
3106 }
3107")
3108
3109(define_insn "*smax_0"
3110 [(set (match_operand:SI 0 "s_register_operand" "=r")
3111 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3112 (const_int 0)))]
25f905c2 3113 "TARGET_32BIT"
8b9dc177 3114 "bic%?\\t%0, %1, %1, asr #31"
3115 [(set_attr "predicable" "yes")]
3116)
3117
8774928b 3118(define_insn "*smax_m1"
3119 [(set (match_operand:SI 0 "s_register_operand" "=r")
3120 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3121 (const_int -1)))]
25f905c2 3122 "TARGET_32BIT"
8774928b 3123 "orr%?\\t%0, %1, %1, asr #31"
3124 [(set_attr "predicable" "yes")]
3125)
3126
25f905c2 3127(define_insn "*arm_smax_insn"
8b9dc177 3128 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3129 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3130 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3131 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3132 "TARGET_ARM"
e2348bcb 3133 "@
3134 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3135 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3136 [(set_attr "conds" "clob")
8b9dc177 3137 (set_attr "length" "8,12")]
cffb2a26 3138)
9c08d1fa 3139
8b9dc177 3140(define_expand "sminsi3"
3141 [(parallel [
3142 (set (match_operand:SI 0 "s_register_operand" "")
3143 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3144 (match_operand:SI 2 "arm_rhs_operand" "")))
3145 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3146 "TARGET_32BIT"
8b9dc177 3147 "
3148 if (operands[2] == const0_rtx)
3149 {
3150 /* No need for a clobber of the condition code register here. */
3151 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3152 gen_rtx_SMIN (SImode, operands[1],
3153 operands[2])));
3154 DONE;
3155 }
3156")
3157
3158(define_insn "*smin_0"
3159 [(set (match_operand:SI 0 "s_register_operand" "=r")
3160 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3161 (const_int 0)))]
25f905c2 3162 "TARGET_32BIT"
8b9dc177 3163 "and%?\\t%0, %1, %1, asr #31"
3164 [(set_attr "predicable" "yes")]
3165)
3166
25f905c2 3167(define_insn "*arm_smin_insn"
8b9dc177 3168 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3169 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3170 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3171 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3172 "TARGET_ARM"
e2348bcb 3173 "@
3174 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3175 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3176 [(set_attr "conds" "clob")
8b9dc177 3177 (set_attr "length" "8,12")]
0d66636f 3178)
9c08d1fa 3179
25f905c2 3180(define_expand "umaxsi3"
3181 [(parallel [
3182 (set (match_operand:SI 0 "s_register_operand" "")
3183 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3184 (match_operand:SI 2 "arm_rhs_operand" "")))
3185 (clobber (reg:CC CC_REGNUM))])]
3186 "TARGET_32BIT"
3187 ""
3188)
3189
3190(define_insn "*arm_umaxsi3"
9c08d1fa 3191 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3192 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3193 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3194 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3195 "TARGET_ARM"
e2348bcb 3196 "@
3197 cmp\\t%1, %2\;movcc\\t%0, %2
3198 cmp\\t%1, %2\;movcs\\t%0, %1
3199 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3200 [(set_attr "conds" "clob")
3201 (set_attr "length" "8,8,12")]
3202)
9c08d1fa 3203
25f905c2 3204(define_expand "uminsi3"
3205 [(parallel [
3206 (set (match_operand:SI 0 "s_register_operand" "")
3207 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3208 (match_operand:SI 2 "arm_rhs_operand" "")))
3209 (clobber (reg:CC CC_REGNUM))])]
3210 "TARGET_32BIT"
3211 ""
3212)
3213
3214(define_insn "*arm_uminsi3"
9c08d1fa 3215 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3216 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3217 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3218 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3219 "TARGET_ARM"
e2348bcb 3220 "@
3221 cmp\\t%1, %2\;movcs\\t%0, %2
3222 cmp\\t%1, %2\;movcc\\t%0, %1
3223 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3224 [(set_attr "conds" "clob")
3225 (set_attr "length" "8,8,12")]
3226)
9c08d1fa 3227
8a18b90c 3228(define_insn "*store_minmaxsi"
9c08d1fa 3229 [(set (match_operand:SI 0 "memory_operand" "=m")
3230 (match_operator:SI 3 "minmax_operator"
3231 [(match_operand:SI 1 "s_register_operand" "r")
3232 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3233 (clobber (reg:CC CC_REGNUM))]
25f905c2 3234 "TARGET_32BIT"
9c08d1fa 3235 "*
dc55b8a9 3236 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3237 operands[1], operands[2]);
e2348bcb 3238 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3239 if (TARGET_THUMB2)
3240 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3241 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3242 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3243 return \"\";
0d66636f 3244 "
3245 [(set_attr "conds" "clob")
25f905c2 3246 (set (attr "length")
3247 (if_then_else (eq_attr "is_thumb" "yes")
3248 (const_int 14)
3249 (const_int 12)))
0d66636f 3250 (set_attr "type" "store1")]
3251)
9c08d1fa 3252
8a18b90c 3253; Reject the frame pointer in operand[1], since reloading this after
3254; it has been eliminated can cause carnage.
f7fbdd4a 3255(define_insn "*minmax_arithsi"
9c08d1fa 3256 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3257 (match_operator:SI 4 "shiftable_operator"
3258 [(match_operator:SI 5 "minmax_operator"
3259 [(match_operand:SI 2 "s_register_operand" "r,r")
3260 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3261 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3262 (clobber (reg:CC CC_REGNUM))]
25f905c2 3263 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3264 "*
0d66636f 3265 {
3266 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3267 bool need_else;
3268
3269 if (which_alternative != 0 || operands[3] != const0_rtx
3270 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3271 need_else = true;
3272 else
3273 need_else = false;
0d66636f 3274
dc55b8a9 3275 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3276 operands[2], operands[3]);
0d66636f 3277 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3278 if (TARGET_THUMB2)
3279 {
3280 if (need_else)
3281 output_asm_insn (\"ite\\t%d5\", operands);
3282 else
3283 output_asm_insn (\"it\\t%d5\", operands);
3284 }
0d66636f 3285 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3286 if (need_else)
0d66636f 3287 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3288 return \"\";
215b30b3 3289 }"
0d66636f 3290 [(set_attr "conds" "clob")
25f905c2 3291 (set (attr "length")
3292 (if_then_else (eq_attr "is_thumb" "yes")
3293 (const_int 14)
3294 (const_int 12)))]
0d66636f 3295)
9c08d1fa 3296
b11cae9e 3297\f
3298;; Shift and rotation insns
3299
a2cd141b 3300(define_expand "ashldi3"
3301 [(set (match_operand:DI 0 "s_register_operand" "")
3302 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3303 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3304 "TARGET_32BIT"
a2cd141b 3305 "
3306 if (GET_CODE (operands[2]) == CONST_INT)
3307 {
3308 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3309 {
3310 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3311 DONE;
3312 }
3313 /* Ideally we shouldn't fail here if we could know that operands[1]
3314 ends up already living in an iwmmxt register. Otherwise it's
3315 cheaper to have the alternate code being generated than moving
1d60d981 3316 values to iwmmxt regs and back. */
a2cd141b 3317 FAIL;
3318 }
3319 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3320 FAIL;
3321 "
3322)
3323
3324(define_insn "arm_ashldi3_1bit"
3325 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3326 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3327 (const_int 1)))
3328 (clobber (reg:CC CC_REGNUM))]
25f905c2 3329 "TARGET_32BIT"
a2cd141b 3330 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3331 [(set_attr "conds" "clob")
3332 (set_attr "length" "8")]
3333)
3334
87b22bf7 3335(define_expand "ashlsi3"
cffb2a26 3336 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3337 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3338 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3339 "TARGET_EITHER"
87b22bf7 3340 "
3341 if (GET_CODE (operands[2]) == CONST_INT
3342 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3343 {
3344 emit_insn (gen_movsi (operands[0], const0_rtx));
3345 DONE;
3346 }
cffb2a26 3347 "
3348)
3349
25f905c2 3350(define_insn "*thumb1_ashlsi3"
cffb2a26 3351 [(set (match_operand:SI 0 "register_operand" "=l,l")
3352 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3353 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3354 "TARGET_THUMB1"
cffb2a26 3355 "lsl\\t%0, %1, %2"
747b7458 3356 [(set_attr "length" "2")
3357 (set_attr "conds" "set")])
b11cae9e 3358
a2cd141b 3359(define_expand "ashrdi3"
3360 [(set (match_operand:DI 0 "s_register_operand" "")
3361 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3362 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3363 "TARGET_32BIT"
a2cd141b 3364 "
3365 if (GET_CODE (operands[2]) == CONST_INT)
3366 {
3367 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3368 {
3369 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3370 DONE;
3371 }
3372 /* Ideally we shouldn't fail here if we could know that operands[1]
3373 ends up already living in an iwmmxt register. Otherwise it's
3374 cheaper to have the alternate code being generated than moving
1d60d981 3375 values to iwmmxt regs and back. */
a2cd141b 3376 FAIL;
3377 }
3378 else if (!TARGET_REALLY_IWMMXT)
3379 FAIL;
3380 "
3381)
3382
3383(define_insn "arm_ashrdi3_1bit"
3384 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3385 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3386 (const_int 1)))
3387 (clobber (reg:CC CC_REGNUM))]
25f905c2 3388 "TARGET_32BIT"
a2cd141b 3389 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3390 [(set_attr "conds" "clob")
d2a518d1 3391 (set_attr "insn" "mov")
a2cd141b 3392 (set_attr "length" "8")]
3393)
3394
87b22bf7 3395(define_expand "ashrsi3"
cffb2a26 3396 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3397 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3398 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3399 "TARGET_EITHER"
87b22bf7 3400 "
3401 if (GET_CODE (operands[2]) == CONST_INT
3402 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3403 operands[2] = GEN_INT (31);
cffb2a26 3404 "
3405)
3406
25f905c2 3407(define_insn "*thumb1_ashrsi3"
cffb2a26 3408 [(set (match_operand:SI 0 "register_operand" "=l,l")
3409 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3410 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3411 "TARGET_THUMB1"
cffb2a26 3412 "asr\\t%0, %1, %2"
747b7458 3413 [(set_attr "length" "2")
3414 (set_attr "conds" "set")])
b11cae9e 3415
a2cd141b 3416(define_expand "lshrdi3"
3417 [(set (match_operand:DI 0 "s_register_operand" "")
3418 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3419 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3420 "TARGET_32BIT"
a2cd141b 3421 "
3422 if (GET_CODE (operands[2]) == CONST_INT)
3423 {
3424 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3425 {
3426 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3427 DONE;
3428 }
3429 /* Ideally we shouldn't fail here if we could know that operands[1]
3430 ends up already living in an iwmmxt register. Otherwise it's
3431 cheaper to have the alternate code being generated than moving
1d60d981 3432 values to iwmmxt regs and back. */
a2cd141b 3433 FAIL;
3434 }
3435 else if (!TARGET_REALLY_IWMMXT)
3436 FAIL;
3437 "
3438)
3439
3440(define_insn "arm_lshrdi3_1bit"
3441 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3442 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3443 (const_int 1)))
3444 (clobber (reg:CC CC_REGNUM))]
25f905c2 3445 "TARGET_32BIT"
a2cd141b 3446 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3447 [(set_attr "conds" "clob")
d2a518d1 3448 (set_attr "insn" "mov")
a2cd141b 3449 (set_attr "length" "8")]
3450)
3451
87b22bf7 3452(define_expand "lshrsi3"
cffb2a26 3453 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3454 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3455 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3456 "TARGET_EITHER"
87b22bf7 3457 "
3458 if (GET_CODE (operands[2]) == CONST_INT
3459 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3460 {
3461 emit_insn (gen_movsi (operands[0], const0_rtx));
3462 DONE;
3463 }
cffb2a26 3464 "
3465)
3466
25f905c2 3467(define_insn "*thumb1_lshrsi3"
cffb2a26 3468 [(set (match_operand:SI 0 "register_operand" "=l,l")
3469 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3470 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3471 "TARGET_THUMB1"
cffb2a26 3472 "lsr\\t%0, %1, %2"
747b7458 3473 [(set_attr "length" "2")
3474 (set_attr "conds" "set")])
b11cae9e 3475
87b22bf7 3476(define_expand "rotlsi3"
cffb2a26 3477 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3478 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3479 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3480 "TARGET_32BIT"
87b22bf7 3481 "
3482 if (GET_CODE (operands[2]) == CONST_INT)
3483 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3484 else
b11cae9e 3485 {
87b22bf7 3486 rtx reg = gen_reg_rtx (SImode);
3487 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3488 operands[2] = reg;
b11cae9e 3489 }
cffb2a26 3490 "
3491)
9c08d1fa 3492
87b22bf7 3493(define_expand "rotrsi3"
cffb2a26 3494 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3495 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3496 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3497 "TARGET_EITHER"
87b22bf7 3498 "
25f905c2 3499 if (TARGET_32BIT)
cffb2a26 3500 {
3501 if (GET_CODE (operands[2]) == CONST_INT
3502 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3503 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3504 }
25f905c2 3505 else /* TARGET_THUMB1 */
cffb2a26 3506 {
3507 if (GET_CODE (operands [2]) == CONST_INT)
3508 operands [2] = force_reg (SImode, operands[2]);
3509 }
3510 "
3511)
87b22bf7 3512
25f905c2 3513(define_insn "*thumb1_rotrsi3"
cffb2a26 3514 [(set (match_operand:SI 0 "register_operand" "=l")
3515 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3516 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3517 "TARGET_THUMB1"
cffb2a26 3518 "ror\\t%0, %0, %2"
3519 [(set_attr "length" "2")]
3520)
3521
3522(define_insn "*arm_shiftsi3"
3523 [(set (match_operand:SI 0 "s_register_operand" "=r")
3524 (match_operator:SI 3 "shift_operator"
3525 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3526 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3527 "TARGET_32BIT"
3528 "* return arm_output_shift(operands, 0);"
344495ea 3529 [(set_attr "predicable" "yes")
331beb1a 3530 (set_attr "shift" "1")
a2cd141b 3531 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3532 (const_string "alu_shift")
3533 (const_string "alu_shift_reg")))]
6c4c2133 3534)
87b22bf7 3535
f7fbdd4a 3536(define_insn "*shiftsi3_compare0"
bd5b4116 3537 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3538 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3539 [(match_operand:SI 1 "s_register_operand" "r")
3540 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3541 (const_int 0)))
3542 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3543 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3544 "TARGET_32BIT"
3545 "* return arm_output_shift(operands, 1);"
344495ea 3546 [(set_attr "conds" "set")
331beb1a 3547 (set_attr "shift" "1")
a2cd141b 3548 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3549 (const_string "alu_shift")
3550 (const_string "alu_shift_reg")))]
0d66636f 3551)
9c08d1fa 3552
f7fbdd4a 3553(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3554 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3555 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3556 [(match_operand:SI 1 "s_register_operand" "r")
3557 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3558 (const_int 0)))
3559 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3560 "TARGET_32BIT"
3561 "* return arm_output_shift(operands, 1);"
344495ea 3562 [(set_attr "conds" "set")
a2cd141b 3563 (set_attr "shift" "1")]
0d66636f 3564)
9c08d1fa 3565
d5d4dc8d 3566(define_insn "*not_shiftsi"
3567 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3568 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3569 [(match_operand:SI 1 "s_register_operand" "r,r")
3570 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3571 "TARGET_32BIT"
6c4c2133 3572 "mvn%?\\t%0, %1%S3"
344495ea 3573 [(set_attr "predicable" "yes")
331beb1a 3574 (set_attr "shift" "1")
d2a518d1 3575 (set_attr "insn" "mvn")
d5d4dc8d 3576 (set_attr "arch" "32,a")
3577 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3578
d5d4dc8d 3579(define_insn "*not_shiftsi_compare0"
bd5b4116 3580 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3581 (compare:CC_NOOV
3582 (not:SI (match_operator:SI 3 "shift_operator"
3583 [(match_operand:SI 1 "s_register_operand" "r,r")
3584 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3585 (const_int 0)))
3586 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3587 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3588 "TARGET_32BIT"
25f905c2 3589 "mvn%.\\t%0, %1%S3"
344495ea 3590 [(set_attr "conds" "set")
331beb1a 3591 (set_attr "shift" "1")
d2a518d1 3592 (set_attr "insn" "mvn")
d5d4dc8d 3593 (set_attr "arch" "32,a")
3594 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3595
d5d4dc8d 3596(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3597 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3598 (compare:CC_NOOV
3599 (not:SI (match_operator:SI 3 "shift_operator"
3600 [(match_operand:SI 1 "s_register_operand" "r,r")
3601 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3602 (const_int 0)))
3603 (clobber (match_scratch:SI 0 "=r,r"))]
3604 "TARGET_32BIT"
25f905c2 3605 "mvn%.\\t%0, %1%S3"
344495ea 3606 [(set_attr "conds" "set")
331beb1a 3607 (set_attr "shift" "1")
d2a518d1 3608 (set_attr "insn" "mvn")
d5d4dc8d 3609 (set_attr "arch" "32,a")
3610 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3611
cffb2a26 3612;; We don't really have extzv, but defining this using shifts helps
3613;; to reduce register pressure later on.
3614
3615(define_expand "extzv"
3616 [(set (match_dup 4)
3617 (ashift:SI (match_operand:SI 1 "register_operand" "")
3618 (match_operand:SI 2 "const_int_operand" "")))
3619 (set (match_operand:SI 0 "register_operand" "")
3620 (lshiftrt:SI (match_dup 4)
215b30b3 3621 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3622 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3623 "
3624 {
3625 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3626 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3627
8b054d5a 3628 if (arm_arch_thumb2)
3629 {
3630 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3631 operands[3]));
3632 DONE;
3633 }
3634
cffb2a26 3635 operands[3] = GEN_INT (rshift);
3636
3637 if (lshift == 0)
3638 {
3639 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3640 DONE;
3641 }
3642
3643 operands[2] = GEN_INT (lshift);
3644 operands[4] = gen_reg_rtx (SImode);
215b30b3 3645 }"
cffb2a26 3646)
3647
8b054d5a 3648(define_insn "extv"
3649 [(set (match_operand:SI 0 "s_register_operand" "=r")
3650 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3651 (match_operand:SI 2 "const_int_operand" "M")
3652 (match_operand:SI 3 "const_int_operand" "M")))]
3653 "arm_arch_thumb2"
3654 "sbfx%?\t%0, %1, %3, %2"
3655 [(set_attr "length" "4")
3656 (set_attr "predicable" "yes")]
3657)
3658
3659(define_insn "extzv_t2"
3660 [(set (match_operand:SI 0 "s_register_operand" "=r")
3661 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3662 (match_operand:SI 2 "const_int_operand" "M")
3663 (match_operand:SI 3 "const_int_operand" "M")))]
3664 "arm_arch_thumb2"
3665 "ubfx%?\t%0, %1, %3, %2"
3666 [(set_attr "length" "4")
3667 (set_attr "predicable" "yes")]
3668)
3669
b11cae9e 3670\f
3671;; Unary arithmetic insns
3672
cffb2a26 3673(define_expand "negdi2"
3674 [(parallel
8135a42b 3675 [(set (match_operand:DI 0 "s_register_operand" "")
3676 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3677 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3678 "TARGET_EITHER"
8135a42b 3679 ""
cffb2a26 3680)
3681
3682;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 3683;; The first alternative allows the common case of a *full* overlap.
cffb2a26 3684(define_insn "*arm_negdi2"
3685 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3686 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 3687 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3688 "TARGET_ARM"
97499065 3689 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3690 [(set_attr "conds" "clob")
3691 (set_attr "length" "8")]
3692)
b11cae9e 3693
25f905c2 3694(define_insn "*thumb1_negdi2"
8135a42b 3695 [(set (match_operand:DI 0 "register_operand" "=&l")
3696 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3697 (clobber (reg:CC CC_REGNUM))]
25f905c2 3698 "TARGET_THUMB1"
cffb2a26 3699 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3700 [(set_attr "length" "6")]
3701)
3702
3703(define_expand "negsi2"
3704 [(set (match_operand:SI 0 "s_register_operand" "")
3705 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3706 "TARGET_EITHER"
b11cae9e 3707 ""
cffb2a26 3708)
3709
3710(define_insn "*arm_negsi2"
3711 [(set (match_operand:SI 0 "s_register_operand" "=r")
3712 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3713 "TARGET_32BIT"
cffb2a26 3714 "rsb%?\\t%0, %1, #0"
0d66636f 3715 [(set_attr "predicable" "yes")]
cffb2a26 3716)
3717
25f905c2 3718(define_insn "*thumb1_negsi2"
cffb2a26 3719 [(set (match_operand:SI 0 "register_operand" "=l")
3720 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3721 "TARGET_THUMB1"
cffb2a26 3722 "neg\\t%0, %1"
3723 [(set_attr "length" "2")]
3724)
b11cae9e 3725
604f3a0a 3726(define_expand "negsf2"
3727 [(set (match_operand:SF 0 "s_register_operand" "")
3728 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3729 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3730 ""
3731)
3732
3733(define_expand "negdf2"
3734 [(set (match_operand:DF 0 "s_register_operand" "")
3735 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3736 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3737 "")
3738
9c08d1fa 3739;; abssi2 doesn't really clobber the condition codes if a different register
3740;; is being set. To keep things simple, assume during rtl manipulations that
3741;; it does, but tell the final scan operator the truth. Similarly for
3742;; (neg (abs...))
3743
604f3a0a 3744(define_expand "abssi2"
3745 [(parallel
3746 [(set (match_operand:SI 0 "s_register_operand" "")
3747 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3748 (clobber (match_dup 2))])]
3749 "TARGET_EITHER"
3750 "
25f905c2 3751 if (TARGET_THUMB1)
ba156559 3752 operands[2] = gen_rtx_SCRATCH (SImode);
3753 else
3754 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3755")
604f3a0a 3756
7d57ec45 3757(define_insn "*arm_abssi2"
ba156559 3758 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3759 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3760 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3761 "TARGET_ARM"
e2348bcb 3762 "@
3763 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3764 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3765 [(set_attr "conds" "clob,*")
331beb1a 3766 (set_attr "shift" "1")
0d66636f 3767 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3768 (set_attr "length" "8")]
3769)
9c08d1fa 3770
25f905c2 3771(define_insn_and_split "*thumb1_abssi2"
ba156559 3772 [(set (match_operand:SI 0 "s_register_operand" "=l")
3773 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3774 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3775 "TARGET_THUMB1"
ba156559 3776 "#"
25f905c2 3777 "TARGET_THUMB1 && reload_completed"
ba156559 3778 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3779 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3780 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3781 ""
3782 [(set_attr "length" "6")]
3783)
3784
3785(define_insn "*arm_neg_abssi2"
9c08d1fa 3786 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3787 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3788 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3789 "TARGET_ARM"
e2348bcb 3790 "@
3791 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3792 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3793 [(set_attr "conds" "clob,*")
331beb1a 3794 (set_attr "shift" "1")
0d66636f 3795 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3796 (set_attr "length" "8")]
3797)
b11cae9e 3798
25f905c2 3799(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3800 [(set (match_operand:SI 0 "s_register_operand" "=l")
3801 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3802 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3803 "TARGET_THUMB1"
ba156559 3804 "#"
25f905c2 3805 "TARGET_THUMB1 && reload_completed"
ba156559 3806 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3807 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3808 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3809 ""
3810 [(set_attr "length" "6")]
3811)
3812
604f3a0a 3813(define_expand "abssf2"
3814 [(set (match_operand:SF 0 "s_register_operand" "")
3815 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3816 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3817 "")
3818
604f3a0a 3819(define_expand "absdf2"
3820 [(set (match_operand:DF 0 "s_register_operand" "")
3821 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3822 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3823 "")
3824
7db9af5d 3825(define_expand "sqrtsf2"
3826 [(set (match_operand:SF 0 "s_register_operand" "")
3827 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3828 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3829 "")
9c08d1fa 3830
7db9af5d 3831(define_expand "sqrtdf2"
3832 [(set (match_operand:DF 0 "s_register_operand" "")
3833 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3834 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3835 "")
9c08d1fa 3836
a0f94409 3837(define_insn_and_split "one_cmpldi2"
9c08d1fa 3838 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3839 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3840 "TARGET_32BIT"
f6ebffac 3841 "#"
25f905c2 3842 "TARGET_32BIT && reload_completed"
a0f94409 3843 [(set (match_dup 0) (not:SI (match_dup 1)))
3844 (set (match_dup 2) (not:SI (match_dup 3)))]
3845 "
3846 {
3847 operands[2] = gen_highpart (SImode, operands[0]);
3848 operands[0] = gen_lowpart (SImode, operands[0]);
3849 operands[3] = gen_highpart (SImode, operands[1]);
3850 operands[1] = gen_lowpart (SImode, operands[1]);
3851 }"
0d66636f 3852 [(set_attr "length" "8")
3853 (set_attr "predicable" "yes")]
cffb2a26 3854)
b11cae9e 3855
cffb2a26 3856(define_expand "one_cmplsi2"
3857 [(set (match_operand:SI 0 "s_register_operand" "")
3858 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3859 "TARGET_EITHER"
b11cae9e 3860 ""
cffb2a26 3861)
3862
3863(define_insn "*arm_one_cmplsi2"
3864 [(set (match_operand:SI 0 "s_register_operand" "=r")
3865 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3866 "TARGET_32BIT"
cffb2a26 3867 "mvn%?\\t%0, %1"
d2a518d1 3868 [(set_attr "predicable" "yes")
3869 (set_attr "insn" "mvn")]
cffb2a26 3870)
3871
25f905c2 3872(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3873 [(set (match_operand:SI 0 "register_operand" "=l")
3874 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3875 "TARGET_THUMB1"
cffb2a26 3876 "mvn\\t%0, %1"
d2a518d1 3877 [(set_attr "length" "2")
3878 (set_attr "insn" "mvn")]
cffb2a26 3879)
9c08d1fa 3880
f7fbdd4a 3881(define_insn "*notsi_compare0"
bd5b4116 3882 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3883 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3884 (const_int 0)))
3885 (set (match_operand:SI 0 "s_register_operand" "=r")
3886 (not:SI (match_dup 1)))]
25f905c2 3887 "TARGET_32BIT"
3888 "mvn%.\\t%0, %1"
d2a518d1 3889 [(set_attr "conds" "set")
3890 (set_attr "insn" "mvn")]
cffb2a26 3891)
9c08d1fa 3892
f7fbdd4a 3893(define_insn "*notsi_compare0_scratch"
bd5b4116 3894 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3895 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3896 (const_int 0)))
3897 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3898 "TARGET_32BIT"
3899 "mvn%.\\t%0, %1"
d2a518d1 3900 [(set_attr "conds" "set")
3901 (set_attr "insn" "mvn")]
cffb2a26 3902)
b11cae9e 3903\f
3904;; Fixed <--> Floating conversion insns
3905
9b8516be 3906(define_expand "floatsihf2"
3907 [(set (match_operand:HF 0 "general_operand" "")
3908 (float:HF (match_operand:SI 1 "general_operand" "")))]
3909 "TARGET_EITHER"
3910 "
3911 {
3912 rtx op1 = gen_reg_rtx (SFmode);
3913 expand_float (op1, operands[1], 0);
3914 op1 = convert_to_mode (HFmode, op1, 0);
3915 emit_move_insn (operands[0], op1);
3916 DONE;
3917 }"
3918)
3919
3920(define_expand "floatdihf2"
3921 [(set (match_operand:HF 0 "general_operand" "")
3922 (float:HF (match_operand:DI 1 "general_operand" "")))]
3923 "TARGET_EITHER"
3924 "
3925 {
3926 rtx op1 = gen_reg_rtx (SFmode);
3927 expand_float (op1, operands[1], 0);
3928 op1 = convert_to_mode (HFmode, op1, 0);
3929 emit_move_insn (operands[0], op1);
3930 DONE;
3931 }"
3932)
3933
604f3a0a 3934(define_expand "floatsisf2"
3935 [(set (match_operand:SF 0 "s_register_operand" "")
3936 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3937 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3938 "
a2cd141b 3939 if (TARGET_MAVERICK)
604f3a0a 3940 {
3941 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3942 DONE;
3943 }
3944")
3945
604f3a0a 3946(define_expand "floatsidf2"
3947 [(set (match_operand:DF 0 "s_register_operand" "")
3948 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 3949 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3950 "
a2cd141b 3951 if (TARGET_MAVERICK)
604f3a0a 3952 {
3953 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3954 DONE;
3955 }
3956")
3957
9b8516be 3958(define_expand "fix_trunchfsi2"
3959 [(set (match_operand:SI 0 "general_operand" "")
3960 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3961 "TARGET_EITHER"
3962 "
3963 {
3964 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3965 expand_fix (operands[0], op1, 0);
3966 DONE;
3967 }"
3968)
3969
3970(define_expand "fix_trunchfdi2"
3971 [(set (match_operand:DI 0 "general_operand" "")
3972 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3973 "TARGET_EITHER"
3974 "
3975 {
3976 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3977 expand_fix (operands[0], op1, 0);
3978 DONE;
3979 }"
3980)
3981
604f3a0a 3982(define_expand "fix_truncsfsi2"
3983 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3984 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3985 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3986 "
a2cd141b 3987 if (TARGET_MAVERICK)
604f3a0a 3988 {
3989 if (!cirrus_fp_register (operands[0], SImode))
3990 operands[0] = force_reg (SImode, operands[0]);
3991 if (!cirrus_fp_register (operands[1], SFmode))
3992 operands[1] = force_reg (SFmode, operands[0]);
3993 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3994 DONE;
3995 }
3996")
3997
604f3a0a 3998(define_expand "fix_truncdfsi2"
3999 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4000 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4001 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4002 "
a2cd141b 4003 if (TARGET_MAVERICK)
604f3a0a 4004 {
4005 if (!cirrus_fp_register (operands[1], DFmode))
4006 operands[1] = force_reg (DFmode, operands[0]);
4007 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4008 DONE;
4009 }
4010")
4011
f544c6d2 4012;; Truncation insns
b11cae9e 4013
604f3a0a 4014(define_expand "truncdfsf2"
4015 [(set (match_operand:SF 0 "s_register_operand" "")
4016 (float_truncate:SF
4017 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4018 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4019 ""
4020)
9b8516be 4021
4022/* DFmode -> HFmode conversions have to go through SFmode. */
4023(define_expand "truncdfhf2"
4024 [(set (match_operand:HF 0 "general_operand" "")
4025 (float_truncate:HF
4026 (match_operand:DF 1 "general_operand" "")))]
4027 "TARGET_EITHER"
4028 "
4029 {
4030 rtx op1;
4031 op1 = convert_to_mode (SFmode, operands[1], 0);
4032 op1 = convert_to_mode (HFmode, op1, 0);
4033 emit_move_insn (operands[0], op1);
4034 DONE;
4035 }"
4036)
b11cae9e 4037\f
9c08d1fa 4038;; Zero and sign extension instructions.
b11cae9e 4039
848e66ac 4040(define_insn "zero_extend<mode>di2"
4041 [(set (match_operand:DI 0 "s_register_operand" "=r")
4042 (zero_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))]
4043 "TARGET_32BIT <qhs_zextenddi_cond>"
4044 "#"
4045 [(set_attr "length" "8")
4046 (set_attr "ce_count" "2")
4047 (set_attr "predicable" "yes")]
25f905c2 4048)
4049
848e66ac 4050(define_insn "extend<mode>di2"
9c08d1fa 4051 [(set (match_operand:DI 0 "s_register_operand" "=r")
848e66ac 4052 (sign_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))]
4053 "TARGET_32BIT <qhs_sextenddi_cond>"
4054 "#"
0d66636f 4055 [(set_attr "length" "8")
848e66ac 4056 (set_attr "ce_count" "2")
4057 (set_attr "shift" "1")
0d66636f 4058 (set_attr "predicable" "yes")]
4059)
9c08d1fa 4060
848e66ac 4061;; Splits for all extensions to DImode
4062(define_split
4063 [(set (match_operand:DI 0 "s_register_operand" "")
4064 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4065 "TARGET_32BIT"
848e66ac 4066 [(set (match_dup 0) (match_dup 1))]
4067{
848e66ac 4068 rtx lo_part = gen_lowpart (SImode, operands[0]);
4069 enum machine_mode src_mode = GET_MODE (operands[1]);
4070
4071 if (REG_P (operands[0])
4072 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4073 emit_clobber (operands[0]);
4074 if (!REG_P (lo_part) || src_mode != SImode
4075 || !rtx_equal_p (lo_part, operands[1]))
4076 {
4077 if (src_mode == SImode)
4078 emit_move_insn (lo_part, operands[1]);
4079 else
4080 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4081 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4082 operands[1] = lo_part;
4083 }
4084 operands[0] = gen_highpart (SImode, operands[0]);
4085 operands[1] = const0_rtx;
4086})
9c08d1fa 4087
848e66ac 4088(define_split
25f905c2 4089 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4090 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4091 "TARGET_32BIT"
848e66ac 4092 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4093{
4094 rtx lo_part = gen_lowpart (SImode, operands[0]);
4095 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4096
848e66ac 4097 if (REG_P (operands[0])
4098 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4099 emit_clobber (operands[0]);
4100
4101 if (!REG_P (lo_part) || src_mode != SImode
4102 || !rtx_equal_p (lo_part, operands[1]))
4103 {
4104 if (src_mode == SImode)
4105 emit_move_insn (lo_part, operands[1]);
4106 else
4107 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4108 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4109 operands[1] = lo_part;
4110 }
4111 operands[0] = gen_highpart (SImode, operands[0]);
4112})
9c08d1fa 4113
4114(define_expand "zero_extendhisi2"
ef51b8e1 4115 [(set (match_operand:SI 0 "s_register_operand" "")
4116 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4117 "TARGET_EITHER"
ef51b8e1 4118{
4119 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4120 {
ef51b8e1 4121 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4122 DONE;
25f7a26e 4123 }
ef51b8e1 4124 if (!arm_arch6 && !MEM_P (operands[1]))
4125 {
4126 rtx t = gen_lowpart (SImode, operands[1]);
4127 rtx tmp = gen_reg_rtx (SImode);
4128 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4129 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4130 DONE;
4131 }
4132})
9c08d1fa 4133
ef51b8e1 4134(define_split
4135 [(set (match_operand:SI 0 "register_operand" "")
747b7458 4136 (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
ef51b8e1 4137 "!TARGET_THUMB2 && !arm_arch6"
4138 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4139 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4140{
4141 operands[2] = gen_lowpart (SImode, operands[1]);
4142})
4143
4144(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4145 [(set (match_operand:SI 0 "register_operand" "=l,l")
4146 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4147 "TARGET_THUMB1"
848e66ac 4148{
a2cd141b 4149 rtx mem;
4150
ef51b8e1 4151 if (which_alternative == 0 && arm_arch6)
848e66ac 4152 return "uxth\t%0, %1";
ef51b8e1 4153 if (which_alternative == 0)
848e66ac 4154 return "#";
a2cd141b 4155
4156 mem = XEXP (operands[1], 0);
4157
4158 if (GET_CODE (mem) == CONST)
4159 mem = XEXP (mem, 0);
4160
a2cd141b 4161 if (GET_CODE (mem) == PLUS)
4162 {
4163 rtx a = XEXP (mem, 0);
a2cd141b 4164
4165 /* This can happen due to bugs in reload. */
4166 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4167 {
4168 rtx ops[2];
4169 ops[0] = operands[0];
4170 ops[1] = a;
4171
848e66ac 4172 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4173
4174 XEXP (mem, 0) = operands[0];
4175 }
a2cd141b 4176 }
4177
848e66ac 4178 return "ldrh\t%0, %1";
4179}
ef51b8e1 4180 [(set_attr_alternative "length"
4181 [(if_then_else (eq_attr "is_arch6" "yes")
4182 (const_int 2) (const_int 4))
4183 (const_int 4)])
848e66ac 4184 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4185)
4186
cffb2a26 4187(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4188 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4189 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4190 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4191 "@
4192 #
4193 ldr%(h%)\\t%0, %1"
4194 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4195 (set_attr "predicable" "yes")]
cffb2a26 4196)
f7fbdd4a 4197
a2cd141b 4198(define_insn "*arm_zero_extendhisi2_v6"
4199 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4200 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4201 "TARGET_ARM && arm_arch6"
4202 "@
4203 uxth%?\\t%0, %1
25f905c2 4204 ldr%(h%)\\t%0, %1"
a2cd141b 4205 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4206 (set_attr "predicable" "yes")]
a2cd141b 4207)
4208
4209(define_insn "*arm_zero_extendhisi2addsi"
4210 [(set (match_operand:SI 0 "s_register_operand" "=r")
4211 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4212 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4213 "TARGET_INT_SIMD"
a2cd141b 4214 "uxtah%?\\t%0, %2, %1"
4215 [(set_attr "type" "alu_shift")
4216 (set_attr "predicable" "yes")]
4217)
4218
87b22bf7 4219(define_expand "zero_extendqisi2"
cffb2a26 4220 [(set (match_operand:SI 0 "s_register_operand" "")
4221 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4222 "TARGET_EITHER"
ef51b8e1 4223{
4224 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4225 {
ef51b8e1 4226 emit_insn (gen_andsi3 (operands[0],
4227 gen_lowpart (SImode, operands[1]),
4228 GEN_INT (255)));
4229 DONE;
4230 }
4231 if (!arm_arch6 && !MEM_P (operands[1]))
4232 {
4233 rtx t = gen_lowpart (SImode, operands[1]);
4234 rtx tmp = gen_reg_rtx (SImode);
4235 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4236 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4237 DONE;
4238 }
4239})
cffb2a26 4240
ef51b8e1 4241(define_split
4242 [(set (match_operand:SI 0 "register_operand" "")
4243 (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4244 "!arm_arch6"
4245 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4246 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4247{
4248 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4249 if (TARGET_ARM)
4250 {
4251 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4252 DONE;
4253 }
ef51b8e1 4254})
9c08d1fa 4255
25f905c2 4256(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4257 [(set (match_operand:SI 0 "register_operand" "=l,l")
4258 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4259 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4260 "@
4261 #
4262 ldrb\\t%0, %1"
4263 [(set_attr "length" "4,2")
4264 (set_attr "type" "alu_shift,load_byte")
4265 (set_attr "pool_range" "*,32")]
cffb2a26 4266)
4267
25f905c2 4268(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4269 [(set (match_operand:SI 0 "register_operand" "=l,l")
4270 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4271 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4272 "@
4273 uxtb\\t%0, %1
4274 ldrb\\t%0, %1"
848e66ac 4275 [(set_attr "length" "2")
4276 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4277)
4278
cffb2a26 4279(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4280 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4281 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4282 "TARGET_ARM && !arm_arch6"
ef51b8e1 4283 "@
4284 #
4285 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4286 [(set_attr "length" "8,4")
4287 (set_attr "type" "alu_shift,load_byte")
848e66ac 4288 (set_attr "predicable" "yes")]
cffb2a26 4289)
87b22bf7 4290
a2cd141b 4291(define_insn "*arm_zero_extendqisi2_v6"
4292 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4293 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4294 "TARGET_ARM && arm_arch6"
4295 "@
25f905c2 4296 uxtb%(%)\\t%0, %1
4297 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4298 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4299 (set_attr "predicable" "yes")]
a2cd141b 4300)
4301
4302(define_insn "*arm_zero_extendqisi2addsi"
4303 [(set (match_operand:SI 0 "s_register_operand" "=r")
4304 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4305 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4306 "TARGET_INT_SIMD"
a2cd141b 4307 "uxtab%?\\t%0, %2, %1"
4308 [(set_attr "predicable" "yes")
bcaec148 4309 (set_attr "insn" "xtab")
a2cd141b 4310 (set_attr "type" "alu_shift")]
4311)
4312
87b22bf7 4313(define_split
4314 [(set (match_operand:SI 0 "s_register_operand" "")
4315 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4316 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4317 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4318 [(set (match_dup 2) (match_dup 1))
4319 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4320 ""
4321)
9c08d1fa 4322
8a4d25d6 4323(define_split
4324 [(set (match_operand:SI 0 "s_register_operand" "")
4325 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4326 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4327 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4328 [(set (match_dup 2) (match_dup 1))
4329 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4330 ""
4331)
4332
1c274529 4333
4334(define_split
4335 [(set (match_operand:SI 0 "s_register_operand" "")
4336 (ior_xor:SI (and:SI (ashift:SI
4337 (match_operand:SI 1 "s_register_operand" "")
4338 (match_operand:SI 2 "const_int_operand" ""))
4339 (match_operand:SI 3 "const_int_operand" ""))
4340 (zero_extend:SI
4341 (match_operator 5 "subreg_lowpart_operator"
4342 [(match_operand:SI 4 "s_register_operand" "")]))))]
4343 "TARGET_32BIT
63787642 4344 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4345 == (GET_MODE_MASK (GET_MODE (operands[5]))
4346 & (GET_MODE_MASK (GET_MODE (operands[5]))
4347 << (INTVAL (operands[2])))))"
4348 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4349 (match_dup 4)))
4350 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4351 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4352)
4353
f7fbdd4a 4354(define_insn "*compareqi_eq0"
bd5b4116 4355 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4356 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4357 (const_int 0)))]
25f905c2 4358 "TARGET_32BIT"
87b22bf7 4359 "tst\\t%0, #255"
cffb2a26 4360 [(set_attr "conds" "set")]
4361)
b11cae9e 4362
b11cae9e 4363(define_expand "extendhisi2"
ef51b8e1 4364 [(set (match_operand:SI 0 "s_register_operand" "")
4365 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4366 "TARGET_EITHER"
ef51b8e1 4367{
4368 if (TARGET_THUMB1)
4369 {
4370 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4371 DONE;
4372 }
4373 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4374 {
4375 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4376 DONE;
4377 }
ed29c566 4378
ef51b8e1 4379 if (!arm_arch6 && !MEM_P (operands[1]))
4380 {
4381 rtx t = gen_lowpart (SImode, operands[1]);
4382 rtx tmp = gen_reg_rtx (SImode);
4383 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4384 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4385 DONE;
4386 }
4387})
cffb2a26 4388
ef51b8e1 4389(define_split
4390 [(parallel
4391 [(set (match_operand:SI 0 "register_operand" "")
4392 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4393 (clobber (match_scratch:SI 2 ""))])]
4394 "!arm_arch6"
4395 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4396 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4397{
4398 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4399})
25f7a26e 4400
a2cd141b 4401;; We used to have an early-clobber on the scratch register here.
4402;; However, there's a bug somewhere in reload which means that this
4403;; can be partially ignored during spill allocation if the memory
ed29c566 4404;; address also needs reloading; this causes us to die later on when
a2cd141b 4405;; we try to verify the operands. Fortunately, we don't really need
4406;; the early-clobber: we can always use operand 0 if operand 2
4407;; overlaps the address.
ef51b8e1 4408(define_insn "thumb1_extendhisi2"
a2cd141b 4409 [(set (match_operand:SI 0 "register_operand" "=l,l")
4410 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4411 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4412 "TARGET_THUMB1"
a2cd141b 4413 "*
4414 {
4415 rtx ops[4];
4416 rtx mem;
4417
ef51b8e1 4418 if (which_alternative == 0 && !arm_arch6)
4419 return \"#\";
a2cd141b 4420 if (which_alternative == 0)
4421 return \"sxth\\t%0, %1\";
4422
4423 mem = XEXP (operands[1], 0);
4424
4425 /* This code used to try to use 'V', and fix the address only if it was
4426 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4427 range of QImode offsets, and offsettable_address_p does a QImode
4428 address check. */
4429
4430 if (GET_CODE (mem) == CONST)
4431 mem = XEXP (mem, 0);
4432
4433 if (GET_CODE (mem) == LABEL_REF)
4434 return \"ldr\\t%0, %1\";
4435
4436 if (GET_CODE (mem) == PLUS)
4437 {
4438 rtx a = XEXP (mem, 0);
4439 rtx b = XEXP (mem, 1);
4440
4441 if (GET_CODE (a) == LABEL_REF
4442 && GET_CODE (b) == CONST_INT)
4443 return \"ldr\\t%0, %1\";
4444
4445 if (GET_CODE (b) == REG)
4446 return \"ldrsh\\t%0, %1\";
4447
4448 ops[1] = a;
4449 ops[2] = b;
4450 }
4451 else
4452 {
4453 ops[1] = mem;
4454 ops[2] = const0_rtx;
4455 }
4456
ed29c566 4457 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4458
4459 ops[0] = operands[0];
4460 if (reg_mentioned_p (operands[2], ops[1]))
4461 ops[3] = ops[0];
4462 else
4463 ops[3] = operands[2];
4464 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4465 return \"\";
4466 }"
ef51b8e1 4467 [(set_attr_alternative "length"
4468 [(if_then_else (eq_attr "is_arch6" "yes")
4469 (const_int 2) (const_int 4))
4470 (const_int 4)])
a2cd141b 4471 (set_attr "type" "alu_shift,load_byte")
4472 (set_attr "pool_range" "*,1020")]
4473)
4474
25f905c2 4475;; This pattern will only be used when ldsh is not available
25f7a26e 4476(define_expand "extendhisi2_mem"
eab14235 4477 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4478 (set (match_dup 3)
eab14235 4479 (zero_extend:SI (match_dup 7)))
25f7a26e 4480 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4481 (set (match_operand:SI 0 "" "")
4482 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4483 "TARGET_ARM"
25f7a26e 4484 "
215b30b3 4485 {
4486 rtx mem1, mem2;
4487 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4488
788fcce0 4489 mem1 = change_address (operands[1], QImode, addr);
4490 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4491 operands[0] = gen_lowpart (SImode, operands[0]);
4492 operands[1] = mem1;
4493 operands[2] = gen_reg_rtx (SImode);
4494 operands[3] = gen_reg_rtx (SImode);
4495 operands[6] = gen_reg_rtx (SImode);
4496 operands[7] = mem2;
25f7a26e 4497
215b30b3 4498 if (BYTES_BIG_ENDIAN)
4499 {
4500 operands[4] = operands[2];
4501 operands[5] = operands[3];
4502 }
4503 else
4504 {
4505 operands[4] = operands[3];
4506 operands[5] = operands[2];
4507 }
4508 }"
4509)
b11cae9e 4510
ef51b8e1 4511(define_split
4512 [(set (match_operand:SI 0 "register_operand" "")
4513 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4514 "!arm_arch6"
4515 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4516 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4517{
4518 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4519})
4520
a2cd141b 4521(define_insn "*arm_extendhisi2"
ef51b8e1 4522 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4523 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4524 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4525 "@
4526 #
4527 ldr%(sh%)\\t%0, %1"
4528 [(set_attr "length" "8,4")
4529 (set_attr "type" "alu_shift,load_byte")
0d66636f 4530 (set_attr "predicable" "yes")
ef51b8e1 4531 (set_attr "pool_range" "*,256")
4532 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4533)
f7fbdd4a 4534
25f905c2 4535;; ??? Check Thumb-2 pool range
a2cd141b 4536(define_insn "*arm_extendhisi2_v6"
4537 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4538 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4539 "TARGET_32BIT && arm_arch6"
a2cd141b 4540 "@
4541 sxth%?\\t%0, %1
25f905c2 4542 ldr%(sh%)\\t%0, %1"
a2cd141b 4543 [(set_attr "type" "alu_shift,load_byte")
4544 (set_attr "predicable" "yes")
4545 (set_attr "pool_range" "*,256")
4546 (set_attr "neg_pool_range" "*,244")]
4547)
4548
4549(define_insn "*arm_extendhisi2addsi"
4550 [(set (match_operand:SI 0 "s_register_operand" "=r")
4551 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4552 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4553 "TARGET_INT_SIMD"
a2cd141b 4554 "sxtah%?\\t%0, %2, %1"
4555)
4556
c8f69309 4557(define_expand "extendqihi2"
4558 [(set (match_dup 2)
bed7d9a5 4559 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4560 (const_int 24)))
9c08d1fa 4561 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4562 (ashiftrt:SI (match_dup 2)
4563 (const_int 24)))]
cffb2a26 4564 "TARGET_ARM"
c8f69309 4565 "
215b30b3 4566 {
4567 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4568 {
4569 emit_insn (gen_rtx_SET (VOIDmode,
4570 operands[0],
4571 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4572 DONE;
4573 }
4574 if (!s_register_operand (operands[1], QImode))
4575 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4576 operands[0] = gen_lowpart (SImode, operands[0]);
4577 operands[1] = gen_lowpart (SImode, operands[1]);
4578 operands[2] = gen_reg_rtx (SImode);
4579 }"
4580)
f7fbdd4a 4581
25f905c2 4582(define_insn "*arm_extendqihi_insn"
b4e8a300 4583 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4584 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4585 "TARGET_ARM && arm_arch4"
25f905c2 4586 "ldr%(sb%)\\t%0, %1"
a2cd141b 4587 [(set_attr "type" "load_byte")
0d66636f 4588 (set_attr "predicable" "yes")
cffb2a26 4589 (set_attr "pool_range" "256")
4590 (set_attr "neg_pool_range" "244")]
4591)
3fc2009e 4592
b11cae9e 4593(define_expand "extendqisi2"
ef51b8e1 4594 [(set (match_operand:SI 0 "s_register_operand" "")
4595 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 4596 "TARGET_EITHER"
ef51b8e1 4597{
4598 if (!arm_arch4 && MEM_P (operands[1]))
4599 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4600
ef51b8e1 4601 if (!arm_arch6 && !MEM_P (operands[1]))
4602 {
4603 rtx t = gen_lowpart (SImode, operands[1]);
4604 rtx tmp = gen_reg_rtx (SImode);
4605 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4606 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4607 DONE;
4608 }
4609})
a2cd141b 4610
ef51b8e1 4611(define_split
4612 [(set (match_operand:SI 0 "register_operand" "")
4613 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4614 "!arm_arch6"
4615 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4616 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4617{
4618 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4619})
f7fbdd4a 4620
a2cd141b 4621(define_insn "*arm_extendqisi"
ef51b8e1 4622 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4623 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4624 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4625 "@
4626 #
4627 ldr%(sb%)\\t%0, %1"
4628 [(set_attr "length" "8,4")
4629 (set_attr "type" "alu_shift,load_byte")
0d66636f 4630 (set_attr "predicable" "yes")
ef51b8e1 4631 (set_attr "pool_range" "*,256")
4632 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4633)
3fc2009e 4634
a2cd141b 4635(define_insn "*arm_extendqisi_v6"
4636 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4637 (sign_extend:SI
4638 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4639 "TARGET_ARM && arm_arch6"
b4e8a300 4640 "@
4641 sxtb%?\\t%0, %1
25f905c2 4642 ldr%(sb%)\\t%0, %1"
a2cd141b 4643 [(set_attr "type" "alu_shift,load_byte")
4644 (set_attr "predicable" "yes")
a2cd141b 4645 (set_attr "pool_range" "*,256")
4646 (set_attr "neg_pool_range" "*,244")]
4647)
4648
4649(define_insn "*arm_extendqisi2addsi"
4650 [(set (match_operand:SI 0 "s_register_operand" "=r")
4651 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4652 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4653 "TARGET_INT_SIMD"
a2cd141b 4654 "sxtab%?\\t%0, %2, %1"
4655 [(set_attr "type" "alu_shift")
bcaec148 4656 (set_attr "insn" "xtab")
a2cd141b 4657 (set_attr "predicable" "yes")]
4658)
4659
ef51b8e1 4660(define_split
4661 [(set (match_operand:SI 0 "register_operand" "")
4662 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4663 "TARGET_THUMB1 && reload_completed"
4664 [(set (match_dup 0) (match_dup 2))
4665 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4666{
4667 rtx addr = XEXP (operands[1], 0);
cffb2a26 4668
ef51b8e1 4669 if (GET_CODE (addr) == CONST)
4670 addr = XEXP (addr, 0);
cffb2a26 4671
ef51b8e1 4672 if (GET_CODE (addr) == PLUS
4673 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4674 /* No split necessary. */
4675 FAIL;
4676
4677 if (GET_CODE (addr) == PLUS
4678 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4679 FAIL;
4680
4681 if (reg_overlap_mentioned_p (operands[0], addr))
4682 {
4683 rtx t = gen_lowpart (QImode, operands[0]);
4684 emit_move_insn (t, operands[1]);
4685 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4686 DONE;
4687 }
4688
4689 if (REG_P (addr))
4690 {
4691 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4692 operands[2] = const0_rtx;
4693 }
4694 else if (GET_CODE (addr) != PLUS)
4695 FAIL;
4696 else if (REG_P (XEXP (addr, 0)))
4697 {
4698 operands[2] = XEXP (addr, 1);
4699 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4700 }
4701 else
4702 {
4703 operands[2] = XEXP (addr, 0);
4704 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4705 }
cffb2a26 4706
ef51b8e1 4707 operands[3] = change_address (operands[1], QImode, addr);
4708})
4709
8a3b73a1 4710(define_peephole2
4711 [(set (match_operand:SI 0 "register_operand" "")
4712 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4713 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4714 (set (match_operand:SI 3 "register_operand" "")
4715 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4716 "TARGET_THUMB1
4717 && GET_CODE (XEXP (operands[4], 0)) == PLUS
4718 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4719 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4720 && (peep2_reg_dead_p (3, operands[0])
4721 || rtx_equal_p (operands[0], operands[3]))
4722 && (peep2_reg_dead_p (3, operands[2])
4723 || rtx_equal_p (operands[2], operands[3]))"
4724 [(set (match_dup 2) (match_dup 1))
4725 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4726{
4727 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4728 operands[4] = change_address (operands[4], QImode, addr);
4729})
4730
ef51b8e1 4731(define_insn "thumb1_extendqisi2"
a2cd141b 4732 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4733 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 4734 "TARGET_THUMB1"
4735{
4736 rtx addr;
a2cd141b 4737
ef51b8e1 4738 if (which_alternative == 0 && arm_arch6)
4739 return "sxtb\\t%0, %1";
4740 if (which_alternative == 0)
4741 return "#";
a2cd141b 4742
ef51b8e1 4743 addr = XEXP (operands[1], 0);
4744 if (GET_CODE (addr) == PLUS
4745 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4746 return "ldrsb\\t%0, %1";
a2cd141b 4747
ef51b8e1 4748 return "#";
4749}
4750 [(set_attr_alternative "length"
4751 [(if_then_else (eq_attr "is_arch6" "yes")
4752 (const_int 2) (const_int 4))
4753 (const_int 2)
4754 (if_then_else (eq_attr "is_arch6" "yes")
4755 (const_int 4) (const_int 6))])
4756 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 4757)
4758
caedf871 4759(define_expand "extendsfdf2"
4760 [(set (match_operand:DF 0 "s_register_operand" "")
4761 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4762 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4763 ""
4764)
9b8516be 4765
4766/* HFmode -> DFmode conversions have to go through SFmode. */
4767(define_expand "extendhfdf2"
4768 [(set (match_operand:DF 0 "general_operand" "")
4769 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4770 "TARGET_EITHER"
4771 "
4772 {
4773 rtx op1;
4774 op1 = convert_to_mode (SFmode, operands[1], 0);
4775 op1 = convert_to_mode (DFmode, op1, 0);
4776 emit_insn (gen_movdf (operands[0], op1));
4777 DONE;
4778 }"
4779)
b11cae9e 4780\f
4781;; Move insns (including loads and stores)
4782
4783;; XXX Just some ideas about movti.
9c08d1fa 4784;; I don't think these are a good idea on the arm, there just aren't enough
4785;; registers
b11cae9e 4786;;(define_expand "loadti"
9c08d1fa 4787;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4788;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4789;; "" "")
4790
4791;;(define_expand "storeti"
4792;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4793;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4794;; "" "")
4795
4796;;(define_expand "movti"
4797;; [(set (match_operand:TI 0 "general_operand" "")
4798;; (match_operand:TI 1 "general_operand" ""))]
4799;; ""
4800;; "
4801;;{
4802;; rtx insn;
4803;;
4804;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4805;; operands[1] = copy_to_reg (operands[1]);
4806;; if (GET_CODE (operands[0]) == MEM)
4807;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4808;; else if (GET_CODE (operands[1]) == MEM)
4809;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4810;; else
4811;; FAIL;
4812;;
4813;; emit_insn (insn);
4814;; DONE;
4815;;}")
4816
a2f10574 4817;; Recognize garbage generated above.
b11cae9e 4818
4819;;(define_insn ""
4820;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4821;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4822;; ""
4823;; "*
4824;; {
4825;; register mem = (which_alternative < 3);
0d66636f 4826;; register const char *template;
b11cae9e 4827;;
4828;; operands[mem] = XEXP (operands[mem], 0);
4829;; switch (which_alternative)
4830;; {
4831;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4832;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4833;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4834;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4835;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4836;; case 5: template = \"stmia\\t%0, %M1\"; break;
4837;; }
e2348bcb 4838;; output_asm_insn (template, operands);
4839;; return \"\";
b11cae9e 4840;; }")
4841
cffb2a26 4842(define_expand "movdi"
4843 [(set (match_operand:DI 0 "general_operand" "")
4844 (match_operand:DI 1 "general_operand" ""))]
4845 "TARGET_EITHER"
4846 "
e1ba4a27 4847 if (can_create_pseudo_p ())
cffb2a26 4848 {
b2778788 4849 if (GET_CODE (operands[0]) != REG)
4850 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4851 }
4852 "
4853)
b11cae9e 4854
cffb2a26 4855(define_insn "*arm_movdi"
d51f92df 4856 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4857 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 4858 "TARGET_32BIT
b2778788 4859 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4860 && !TARGET_IWMMXT
4861 && ( register_operand (operands[0], DImode)
4862 || register_operand (operands[1], DImode))"
b11cae9e 4863 "*
d51f92df 4864 switch (which_alternative)
4865 {
4866 case 0:
4867 case 1:
4868 case 2:
4869 return \"#\";
4870 default:
4871 return output_move_double (operands);
4872 }
cffb2a26 4873 "
359a6e9f 4874 [(set_attr "length" "8,12,16,8,8")
4875 (set_attr "type" "*,*,*,load2,store2")
cde1623a 4876 (set_attr "arm_pool_range" "*,*,*,1020,*")
4877 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
4878 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
4879 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 4880)
4881
d51f92df 4882(define_split
4883 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4884 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4885 "TARGET_32BIT
d51f92df 4886 && reload_completed
4887 && (arm_const_double_inline_cost (operands[1])
4888 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4889 [(const_int 0)]
4890 "
4891 arm_split_constant (SET, SImode, curr_insn,
4892 INTVAL (gen_lowpart (SImode, operands[1])),
4893 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4894 arm_split_constant (SET, SImode, curr_insn,
4895 INTVAL (gen_highpart_mode (SImode,
4896 GET_MODE (operands[0]),
4897 operands[1])),
4898 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4899 DONE;
4900 "
4901)
4902
e5ba9289 4903; If optimizing for size, or if we have load delay slots, then
4904; we want to split the constant into two separate operations.
4905; In both cases this may split a trivial part into a single data op
4906; leaving a single complex constant to load. We can also get longer
4907; offsets in a LDR which means we get better chances of sharing the pool
4908; entries. Finally, we can normally do a better job of scheduling
4909; LDR instructions than we can with LDM.
4910; This pattern will only match if the one above did not.
4911(define_split
4912 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4913 (match_operand:ANY64 1 "const_double_operand" ""))]
4914 "TARGET_ARM && reload_completed
4915 && arm_const_double_by_parts (operands[1])"
4916 [(set (match_dup 0) (match_dup 1))
4917 (set (match_dup 2) (match_dup 3))]
4918 "
4919 operands[2] = gen_highpart (SImode, operands[0]);
4920 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4921 operands[1]);
4922 operands[0] = gen_lowpart (SImode, operands[0]);
4923 operands[1] = gen_lowpart (SImode, operands[1]);
4924 "
4925)
4926
d51f92df 4927(define_split
4928 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4929 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4930 "TARGET_EITHER && reload_completed"
4931 [(set (match_dup 0) (match_dup 1))
4932 (set (match_dup 2) (match_dup 3))]
4933 "
4934 operands[2] = gen_highpart (SImode, operands[0]);
4935 operands[3] = gen_highpart (SImode, operands[1]);
4936 operands[0] = gen_lowpart (SImode, operands[0]);
4937 operands[1] = gen_lowpart (SImode, operands[1]);
4938
4939 /* Handle a partial overlap. */
4940 if (rtx_equal_p (operands[0], operands[3]))
4941 {
4942 rtx tmp0 = operands[0];
4943 rtx tmp1 = operands[1];
4944
4945 operands[0] = operands[2];
4946 operands[1] = operands[3];
4947 operands[2] = tmp0;
4948 operands[3] = tmp1;
4949 }
4950 "
4951)
4952
a8a3b539 4953;; We can't actually do base+index doubleword loads if the index and
4954;; destination overlap. Split here so that we at least have chance to
4955;; schedule.
4956(define_split
4957 [(set (match_operand:DI 0 "s_register_operand" "")
4958 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4959 (match_operand:SI 2 "s_register_operand" ""))))]
4960 "TARGET_LDRD
4961 && reg_overlap_mentioned_p (operands[0], operands[1])
4962 && reg_overlap_mentioned_p (operands[0], operands[2])"
4963 [(set (match_dup 4)
4964 (plus:SI (match_dup 1)
4965 (match_dup 2)))
4966 (set (match_dup 0)
4967 (mem:DI (match_dup 4)))]
4968 "
4969 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4970 "
4971)
4972
cffb2a26 4973;;; ??? This should have alternatives for constants.
4974;;; ??? This was originally identical to the movdf_insn pattern.
4975;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4976;;; thumb_reorg with a memory reference.
25f905c2 4977(define_insn "*thumb1_movdi_insn"
215b30b3 4978 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4979 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4980 "TARGET_THUMB1
a2cd141b 4981 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4982 && ( register_operand (operands[0], DImode)
4983 || register_operand (operands[1], DImode))"
4984 "*
4985 {
4986 switch (which_alternative)
4987 {
4988 default:
4989 case 0:
4990 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4991 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4992 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4993 case 1:
4994 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4995 case 2:
4996 operands[1] = GEN_INT (- INTVAL (operands[1]));
4997 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4998 case 3:
4999 return \"ldmia\\t%1, {%0, %H0}\";
5000 case 4:
5001 return \"stmia\\t%0, {%1, %H1}\";
5002 case 5:
5003 return thumb_load_double_from_address (operands);
5004 case 6:
1a83b3ff 5005 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5006 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5007 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5008 return \"\";
5009 case 7:
5010 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5011 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5012 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5013 }
5014 }"
5015 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5016 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5017 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5018 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5019)
b11cae9e 5020
9c08d1fa 5021(define_expand "movsi"
5022 [(set (match_operand:SI 0 "general_operand" "")
5023 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5024 "TARGET_EITHER"
9c08d1fa 5025 "
befb0bac 5026 {
e348ff3e 5027 rtx base, offset, tmp;
5028
25f905c2 5029 if (TARGET_32BIT)
9c08d1fa 5030 {
674a8f0b 5031 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5032 if (GET_CODE (operands[0]) == MEM)
5033 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5034 if (arm_general_register_operand (operands[0], SImode)
5035 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5036 && !(const_ok_for_arm (INTVAL (operands[1]))
5037 || const_ok_for_arm (~INTVAL (operands[1]))))
5038 {
96f57e36 5039 arm_split_constant (SET, SImode, NULL_RTX,
5040 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5041 optimize && can_create_pseudo_p ());
cffb2a26 5042 DONE;
5043 }
d0e6a121 5044
5045 if (TARGET_USE_MOVT && !target_word_relocations
5046 && GET_CODE (operands[1]) == SYMBOL_REF
5047 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5048 {
5049 arm_emit_movpair (operands[0], operands[1]);
5050 DONE;
5051 }
cffb2a26 5052 }
25f905c2 5053 else /* TARGET_THUMB1... */
cffb2a26 5054 {
e1ba4a27 5055 if (can_create_pseudo_p ())
cffb2a26 5056 {
5057 if (GET_CODE (operands[0]) != REG)
5058 operands[1] = force_reg (SImode, operands[1]);
5059 }
9c08d1fa 5060 }
f655717d 5061
e348ff3e 5062 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5063 {
5064 split_const (operands[1], &base, &offset);
5065 if (GET_CODE (base) == SYMBOL_REF
5066 && !offset_within_block_p (base, INTVAL (offset)))
5067 {
b308ddcf 5068 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5069 emit_move_insn (tmp, base);
5070 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5071 DONE;
5072 }
5073 }
5074
f655717d 5075 /* Recognize the case where operand[1] is a reference to thread-local
5076 data and load its address to a register. */
5077 if (arm_tls_referenced_p (operands[1]))
5078 {
5079 rtx tmp = operands[1];
5080 rtx addend = NULL;
5081
5082 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5083 {
5084 addend = XEXP (XEXP (tmp, 0), 1);
5085 tmp = XEXP (XEXP (tmp, 0), 0);
5086 }
5087
5088 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5089 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5090
e1ba4a27 5091 tmp = legitimize_tls_address (tmp,
5092 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5093 if (addend)
5094 {
5095 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5096 tmp = force_operand (tmp, operands[0]);
5097 }
5098 operands[1] = tmp;
5099 }
5100 else if (flag_pic
5101 && (CONSTANT_P (operands[1])
5102 || symbol_mentioned_p (operands[1])
5103 || label_mentioned_p (operands[1])))
5104 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5105 (!can_create_pseudo_p ()
5106 ? operands[0]
5107 : 0));
befb0bac 5108 }
215b30b3 5109 "
5110)
9c08d1fa 5111
d0e6a121 5112;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5113;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5114;; so this does not matter.
5115(define_insn "*arm_movt"
5116 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5117 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5118 (match_operand:SI 2 "general_operand" "i")))]
5119 "TARGET_32BIT"
5120 "movt%?\t%0, #:upper16:%c2"
5121 [(set_attr "predicable" "yes")
5122 (set_attr "length" "4")]
5123)
5124
cffb2a26 5125(define_insn "*arm_movsi_insn"
aaa37ad6 5126 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5127 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5128 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5129 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5130 && ( register_operand (operands[0], SImode)
5131 || register_operand (operands[1], SImode))"
f7fbdd4a 5132 "@
aaa37ad6 5133 mov%?\\t%0, %1
f7fbdd4a 5134 mov%?\\t%0, %1
5135 mvn%?\\t%0, #%B1
25f905c2 5136 movw%?\\t%0, %1
f7fbdd4a 5137 ldr%?\\t%0, %1
5138 str%?\\t%1, %0"
aaa37ad6 5139 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5140 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5141 (set_attr "predicable" "yes")
aaa37ad6 5142 (set_attr "pool_range" "*,*,*,*,4096,*")
5143 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5144)
87b22bf7 5145
5146(define_split
a2cd141b 5147 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5148 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5149 "TARGET_32BIT
215b30b3 5150 && (!(const_ok_for_arm (INTVAL (operands[1]))
5151 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5152 [(clobber (const_int 0))]
5153 "
96f57e36 5154 arm_split_constant (SET, SImode, NULL_RTX,
5155 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5156 DONE;
215b30b3 5157 "
5158)
9c08d1fa 5159
25f905c2 5160(define_insn "*thumb1_movsi_insn"
aaa37ad6 5161 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5162 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
25f905c2 5163 "TARGET_THUMB1
cffb2a26 5164 && ( register_operand (operands[0], SImode)
5165 || register_operand (operands[1], SImode))"
5166 "@
5167 mov %0, %1
5168 mov %0, %1
5169 #
5170 #
5171 ldmia\\t%1, {%0}
5172 stmia\\t%0, {%1}
5173 ldr\\t%0, %1
5174 str\\t%1, %0
5175 mov\\t%0, %1"
5176 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5177 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5178 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5179 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5180
5181(define_split
5182 [(set (match_operand:SI 0 "register_operand" "")
5183 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5184 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5185 [(set (match_dup 2) (match_dup 1))
5186 (set (match_dup 0) (neg:SI (match_dup 2)))]
5187 "
5188 {
5189 operands[1] = GEN_INT (- INTVAL (operands[1]));
5190 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5191 }"
cffb2a26 5192)
5193
5194(define_split
5195 [(set (match_operand:SI 0 "register_operand" "")
5196 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5197 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5198 [(set (match_dup 2) (match_dup 1))
5199 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5200 "
5201 {
e4aeee53 5202 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5203 unsigned HOST_WIDE_INT mask = 0xff;
5204 int i;
5205
5206 for (i = 0; i < 25; i++)
5207 if ((val & (mask << i)) == val)
5208 break;
5209
1276f1b8 5210 /* Don't split if the shift is zero. */
cffb2a26 5211 if (i == 0)
5212 FAIL;
5213
5214 operands[1] = GEN_INT (val >> i);
1276f1b8 5215 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5216 operands[3] = GEN_INT (i);
cffb2a26 5217 }"
5218)
5219
67336bcf 5220;; When generating pic, we need to load the symbol offset into a register.
5221;; So that the optimizer does not confuse this with a normal symbol load
5222;; we use an unspec. The offset will be loaded from a constant pool entry,
5223;; since that is the only type of relocation we can use.
5224
94f8caca 5225;; Wrap calculation of the whole PIC address in a single pattern for the
5226;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5227;; a PIC address involves two loads from memory, so we want to CSE it
5228;; as often as possible.
5229;; This pattern will be split into one of the pic_load_addr_* patterns
5230;; and a move after GCSE optimizations.
5231;;
5232;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5233(define_expand "calculate_pic_address"
5234 [(set (match_operand:SI 0 "register_operand" "")
5235 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5236 (unspec:SI [(match_operand:SI 2 "" "")]
5237 UNSPEC_PIC_SYM))))]
5238 "flag_pic"
5239)
5240
5241;; Split calculate_pic_address into pic_load_addr_* and a move.
5242(define_split
5243 [(set (match_operand:SI 0 "register_operand" "")
5244 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5245 (unspec:SI [(match_operand:SI 2 "" "")]
5246 UNSPEC_PIC_SYM))))]
5247 "flag_pic"
5248 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5249 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5250 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5251)
5252
67336bcf 5253;; The rather odd constraints on the following are to force reload to leave
5254;; the insn alone, and to force the minipool generation pass to then move
5255;; the GOT symbol to memory.
849170fd 5256
b3cd5f55 5257(define_insn "pic_load_addr_32bit"
849170fd 5258 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5259 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5260 "TARGET_32BIT && flag_pic"
67336bcf 5261 "ldr%?\\t%0, %1"
a2cd141b 5262 [(set_attr "type" "load1")
b3cd5f55 5263 (set_attr "pool_range" "4096")
5264 (set (attr "neg_pool_range")
5265 (if_then_else (eq_attr "is_thumb" "no")
5266 (const_int 4084)
5267 (const_int 0)))]
8c4d8060 5268)
5269
25f905c2 5270(define_insn "pic_load_addr_thumb1"
8c4d8060 5271 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5272 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5273 "TARGET_THUMB1 && flag_pic"
8c4d8060 5274 "ldr\\t%0, %1"
a2cd141b 5275 [(set_attr "type" "load1")
8c4d8060 5276 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5277)
849170fd 5278
cffb2a26 5279(define_insn "pic_add_dot_plus_four"
15d5d060 5280 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5281 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5282 (const_int 4)
beef0fb5 5283 (match_operand 2 "" "")]
5284 UNSPEC_PIC_BASE))]
b3cd5f55 5285 "TARGET_THUMB"
cffb2a26 5286 "*
6cdcb15c 5287 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5288 INTVAL (operands[2]));
cffb2a26 5289 return \"add\\t%0, %|pc\";
5290 "
5291 [(set_attr "length" "2")]
5292)
849170fd 5293
5294(define_insn "pic_add_dot_plus_eight"
15d5d060 5295 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5296 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5297 (const_int 8)
beef0fb5 5298 (match_operand 2 "" "")]
5299 UNSPEC_PIC_BASE))]
f655717d 5300 "TARGET_ARM"
c4034607 5301 "*
6cdcb15c 5302 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5303 INTVAL (operands[2]));
15d5d060 5304 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5305 "
0d66636f 5306 [(set_attr "predicable" "yes")]
cffb2a26 5307)
849170fd 5308
f655717d 5309(define_insn "tls_load_dot_plus_eight"
cc071db6 5310 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5311 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5312 (const_int 8)
beef0fb5 5313 (match_operand 2 "" "")]
5314 UNSPEC_PIC_BASE)))]
f655717d 5315 "TARGET_ARM"
5316 "*
6cdcb15c 5317 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5318 INTVAL (operands[2]));
f655717d 5319 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5320 "
5321 [(set_attr "predicable" "yes")]
5322)
5323
5324;; PIC references to local variables can generate pic_add_dot_plus_eight
5325;; followed by a load. These sequences can be crunched down to
5326;; tls_load_dot_plus_eight by a peephole.
5327
5328(define_peephole2
c0c1fba5 5329 [(set (match_operand:SI 0 "register_operand" "")
5330 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5331 (const_int 8)
5332 (match_operand 1 "" "")]
5333 UNSPEC_PIC_BASE))
f655717d 5334 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5335 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5336 [(set (match_dup 2)
5337 (mem:SI (unspec:SI [(match_dup 3)
5338 (const_int 8)
5339 (match_dup 1)]
5340 UNSPEC_PIC_BASE)))]
f655717d 5341 ""
5342)
5343
bac7fc85 5344(define_insn "pic_offset_arm"
5345 [(set (match_operand:SI 0 "register_operand" "=r")
5346 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5347 (unspec:SI [(match_operand:SI 2 "" "X")]
5348 UNSPEC_PIC_OFFSET))))]
5349 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5350 "ldr%?\\t%0, [%1,%2]"
5351 [(set_attr "type" "load1")]
5352)
5353
95373f08 5354(define_expand "builtin_setjmp_receiver"
5355 [(label_ref (match_operand 0 "" ""))]
5356 "flag_pic"
5357 "
5358{
b935b306 5359 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5360 register. */
2cb7d577 5361 if (arm_pic_register != INVALID_REGNUM)
5362 arm_load_pic_register (1UL << 3);
95373f08 5363 DONE;
5364}")
5365
9c08d1fa 5366;; If copying one reg to another we can set the condition codes according to
5367;; its value. Such a move is common after a return from subroutine and the
5368;; result is being tested against zero.
5369
f7fbdd4a 5370(define_insn "*movsi_compare0"
bd5b4116 5371 [(set (reg:CC CC_REGNUM)
cffb2a26 5372 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5373 (const_int 0)))
5374 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5375 (match_dup 1))]
25f905c2 5376 "TARGET_32BIT"
e2348bcb 5377 "@
40dbec34 5378 cmp%?\\t%0, #0
25f905c2 5379 sub%.\\t%0, %1, #0"
cffb2a26 5380 [(set_attr "conds" "set")]
5381)
b11cae9e 5382
b11cae9e 5383;; Subroutine to store a half word from a register into memory.
5384;; Operand 0 is the source register (HImode)
c8f69309 5385;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5386
9c08d1fa 5387;; In both this routine and the next, we must be careful not to spill
01cc3b75 5388;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5389;; can generate unrecognizable rtl.
5390
b11cae9e 5391(define_expand "storehi"
c8f69309 5392 [;; store the low byte
f082f1c4 5393 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5394 ;; extract the high byte
c8f69309 5395 (set (match_dup 2)
5396 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5397 ;; store the high byte
787f8210 5398 (set (match_dup 4) (match_dup 5))]
cffb2a26 5399 "TARGET_ARM"
b11cae9e 5400 "
215b30b3 5401 {
537ffcfc 5402 rtx op1 = operands[1];
5403 rtx addr = XEXP (op1, 0);
215b30b3 5404 enum rtx_code code = GET_CODE (addr);
5405
5406 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5407 || code == MINUS)
537ffcfc 5408 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5409
537ffcfc 5410 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5411 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5412 operands[3] = gen_lowpart (QImode, operands[0]);
5413 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5414 operands[2] = gen_reg_rtx (SImode);
5415 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5416 }"
5417)
b11cae9e 5418
c7597b5d 5419(define_expand "storehi_bigend"
f082f1c4 5420 [(set (match_dup 4) (match_dup 3))
c7597b5d 5421 (set (match_dup 2)
5422 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5423 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5424 "TARGET_ARM"
b11cae9e 5425 "
215b30b3 5426 {
537ffcfc 5427 rtx op1 = operands[1];
5428 rtx addr = XEXP (op1, 0);
215b30b3 5429 enum rtx_code code = GET_CODE (addr);
5430
5431 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5432 || code == MINUS)
537ffcfc 5433 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5434
537ffcfc 5435 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5436 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5437 operands[3] = gen_lowpart (QImode, operands[0]);
5438 operands[0] = gen_lowpart (SImode, operands[0]);
5439 operands[2] = gen_reg_rtx (SImode);
787f8210 5440 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5441 }"
5442)
c7597b5d 5443
5444;; Subroutine to store a half word integer constant into memory.
5445(define_expand "storeinthi"
f082f1c4 5446 [(set (match_operand 0 "" "")
787f8210 5447 (match_operand 1 "" ""))
9e8503e6 5448 (set (match_dup 3) (match_dup 2))]
cffb2a26 5449 "TARGET_ARM"
c7597b5d 5450 "
215b30b3 5451 {
5452 HOST_WIDE_INT value = INTVAL (operands[1]);
5453 rtx addr = XEXP (operands[0], 0);
537ffcfc 5454 rtx op0 = operands[0];
215b30b3 5455 enum rtx_code code = GET_CODE (addr);
c7597b5d 5456
215b30b3 5457 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5458 || code == MINUS)
537ffcfc 5459 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5460
215b30b3 5461 operands[1] = gen_reg_rtx (SImode);
5462 if (BYTES_BIG_ENDIAN)
5463 {
5464 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5465 if ((value & 255) == ((value >> 8) & 255))
5466 operands[2] = operands[1];
5467 else
5468 {
5469 operands[2] = gen_reg_rtx (SImode);
5470 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5471 }
5472 }
5473 else
5474 {
5475 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5476 if ((value & 255) == ((value >> 8) & 255))
5477 operands[2] = operands[1];
5478 else
5479 {
5480 operands[2] = gen_reg_rtx (SImode);
5481 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5482 }
5483 }
c7597b5d 5484
537ffcfc 5485 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5486 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5487 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5488 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5489 }"
5490)
b11cae9e 5491
f7fbdd4a 5492(define_expand "storehi_single_op"
5493 [(set (match_operand:HI 0 "memory_operand" "")
5494 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5495 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5496 "
215b30b3 5497 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5498 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5499 "
5500)
f7fbdd4a 5501
b11cae9e 5502(define_expand "movhi"
5503 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5504 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5505 "TARGET_EITHER"
b11cae9e 5506 "
cffb2a26 5507 if (TARGET_ARM)
b11cae9e 5508 {
e1ba4a27 5509 if (can_create_pseudo_p ())
cffb2a26 5510 {
5511 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5512 {
cffb2a26 5513 if (arm_arch4)
5514 {
5515 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5516 DONE;
5517 }
5518 if (GET_CODE (operands[1]) == CONST_INT)
5519 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5520 else
cffb2a26 5521 {
5522 if (GET_CODE (operands[1]) == MEM)
5523 operands[1] = force_reg (HImode, operands[1]);
5524 if (BYTES_BIG_ENDIAN)
5525 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5526 else
5527 emit_insn (gen_storehi (operands[1], operands[0]));
5528 }
5529 DONE;
b11cae9e 5530 }
cffb2a26 5531 /* Sign extend a constant, and keep it in an SImode reg. */
5532 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5533 {
cffb2a26 5534 rtx reg = gen_reg_rtx (SImode);
5535 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5536
5537 /* If the constant is already valid, leave it alone. */
215b30b3 5538 if (!const_ok_for_arm (val))
cffb2a26 5539 {
5540 /* If setting all the top bits will make the constant
5541 loadable in a single instruction, then set them.
5542 Otherwise, sign extend the number. */
5543
215b30b3 5544 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5545 val |= ~0xffff;
5546 else if (val & 0x8000)
5547 val |= ~0xffff;
5548 }
5549
5550 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5551 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5552 }
e1ba4a27 5553 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5554 && GET_CODE (operands[1]) == MEM)
5555 {
5556 rtx reg = gen_reg_rtx (SImode);
5557
5558 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5559 operands[1] = gen_lowpart (HImode, reg);
5560 }
215b30b3 5561 else if (!arm_arch4)
f7fbdd4a 5562 {
cffb2a26 5563 if (GET_CODE (operands[1]) == MEM)
5564 {
c1a66faf 5565 rtx base;
5566 rtx offset = const0_rtx;
5567 rtx reg = gen_reg_rtx (SImode);
5568
5569 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5570 || (GET_CODE (base) == PLUS
5571 && (GET_CODE (offset = XEXP (base, 1))
5572 == CONST_INT)
5573 && ((INTVAL(offset) & 1) != 1)
5574 && GET_CODE (base = XEXP (base, 0)) == REG))
5575 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5576 {
8deb3959 5577 rtx new_rtx;
c1a66faf 5578
8deb3959 5579 new_rtx = widen_memory_access (operands[1], SImode,
5580 ((INTVAL (offset) & ~3)
5581 - INTVAL (offset)));
5582 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5583 if (((INTVAL (offset) & 2) != 0)
5584 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5585 {
5586 rtx reg2 = gen_reg_rtx (SImode);
5587
5588 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5589 reg = reg2;
5590 }
206ee9a2 5591 }
c1a66faf 5592 else
5593 emit_insn (gen_movhi_bytes (reg, operands[1]));
5594
5595 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5596 }
5597 }
5598 }
674a8f0b 5599 /* Handle loading a large integer during reload. */
cffb2a26 5600 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5601 && !const_ok_for_arm (INTVAL (operands[1]))
5602 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5603 {
5604 /* Writing a constant to memory needs a scratch, which should
5605 be handled with SECONDARY_RELOADs. */
ed29c566 5606 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5607
5608 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5609 emit_insn (gen_movsi (operands[0], operands[1]));
5610 DONE;
5611 }
5612 }
25f905c2 5613 else if (TARGET_THUMB2)
5614 {
5615 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5616 if (can_create_pseudo_p ())
25f905c2 5617 {
5618 if (GET_CODE (operands[0]) != REG)
5619 operands[1] = force_reg (HImode, operands[1]);
5620 /* Zero extend a constant, and keep it in an SImode reg. */
5621 else if (GET_CODE (operands[1]) == CONST_INT)
5622 {
5623 rtx reg = gen_reg_rtx (SImode);
5624 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5625
5626 emit_insn (gen_movsi (reg, GEN_INT (val)));
5627 operands[1] = gen_lowpart (HImode, reg);
5628 }
5629 }
5630 }
5631 else /* TARGET_THUMB1 */
cffb2a26 5632 {
e1ba4a27 5633 if (can_create_pseudo_p ())
cffb2a26 5634 {
6cffc037 5635 if (GET_CODE (operands[1]) == CONST_INT)
5636 {
5637 rtx reg = gen_reg_rtx (SImode);
5638
5639 emit_insn (gen_movsi (reg, operands[1]));
5640 operands[1] = gen_lowpart (HImode, reg);
5641 }
cffb2a26 5642
5643 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5644 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5645 virtual register (also rejected as illegitimate for HImode/QImode)
5646 relative address. */
cffb2a26 5647 /* ??? This should perhaps be fixed elsewhere, for instance, in
5648 fixup_stack_1, by checking for other kinds of invalid addresses,
5649 e.g. a bare reference to a virtual register. This may confuse the
5650 alpha though, which must handle this case differently. */
5651 if (GET_CODE (operands[0]) == MEM
215b30b3 5652 && !memory_address_p (GET_MODE (operands[0]),
5653 XEXP (operands[0], 0)))
537ffcfc 5654 operands[0]
5655 = replace_equiv_address (operands[0],
5656 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5657
5658 if (GET_CODE (operands[1]) == MEM
215b30b3 5659 && !memory_address_p (GET_MODE (operands[1]),
5660 XEXP (operands[1], 0)))
537ffcfc 5661 operands[1]
5662 = replace_equiv_address (operands[1],
5663 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5664
5665 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5666 {
5667 rtx reg = gen_reg_rtx (SImode);
5668
5669 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5670 operands[1] = gen_lowpart (HImode, reg);
5671 }
5672
5673 if (GET_CODE (operands[0]) == MEM)
5674 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5675 }
cffb2a26 5676 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5677 && !satisfies_constraint_I (operands[1]))
cffb2a26 5678 {
6cffc037 5679 /* Handle loading a large integer during reload. */
5680
cffb2a26 5681 /* Writing a constant to memory needs a scratch, which should
5682 be handled with SECONDARY_RELOADs. */
ed29c566 5683 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5684
1a83b3ff 5685 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5686 emit_insn (gen_movsi (operands[0], operands[1]));
5687 DONE;
5688 }
b11cae9e 5689 }
cffb2a26 5690 "
5691)
5692
25f905c2 5693(define_insn "*thumb1_movhi_insn"
a941568e 5694 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5695 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5696 "TARGET_THUMB1
cffb2a26 5697 && ( register_operand (operands[0], HImode)
5698 || register_operand (operands[1], HImode))"
5699 "*
5700 switch (which_alternative)
d79300ac 5701 {
cffb2a26 5702 case 0: return \"add %0, %1, #0\";
5703 case 2: return \"strh %1, %0\";
5704 case 3: return \"mov %0, %1\";
5705 case 4: return \"mov %0, %1\";
5706 case 5: return \"mov %0, %1\";
ed29c566 5707 default: gcc_unreachable ();
cffb2a26 5708 case 1:
5709 /* The stack pointer can end up being taken as an index register.
5710 Catch this case here and deal with it. */
5711 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5712 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5713 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5714 {
5715 rtx ops[2];
5716 ops[0] = operands[0];
5717 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5718
5719 output_asm_insn (\"mov %0, %1\", ops);
5720
5721 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5722
5723 }
5724 return \"ldrh %0, %1\";
5725 }"
5726 [(set_attr "length" "2,4,2,2,2,2")
747b7458 5727 (set_attr "type" "*,load1,store1,*,*,*")
5728 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 5729
b11cae9e 5730
25f7a26e 5731(define_expand "movhi_bytes"
eab14235 5732 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5733 (set (match_dup 3)
eab14235 5734 (zero_extend:SI (match_dup 6)))
25f7a26e 5735 (set (match_operand:SI 0 "" "")
5736 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5737 "TARGET_ARM"
25f7a26e 5738 "
215b30b3 5739 {
5740 rtx mem1, mem2;
5741 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5742
788fcce0 5743 mem1 = change_address (operands[1], QImode, addr);
5744 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5745 operands[0] = gen_lowpart (SImode, operands[0]);
5746 operands[1] = mem1;
5747 operands[2] = gen_reg_rtx (SImode);
5748 operands[3] = gen_reg_rtx (SImode);
5749 operands[6] = mem2;
25f7a26e 5750
215b30b3 5751 if (BYTES_BIG_ENDIAN)
5752 {
5753 operands[4] = operands[2];
5754 operands[5] = operands[3];
5755 }
5756 else
5757 {
5758 operands[4] = operands[3];
5759 operands[5] = operands[2];
5760 }
5761 }"
5762)
25f7a26e 5763
c7597b5d 5764(define_expand "movhi_bigend"
5765 [(set (match_dup 2)
5766 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5767 (const_int 16)))
5768 (set (match_dup 3)
5769 (ashiftrt:SI (match_dup 2) (const_int 16)))
5770 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5771 (match_dup 4))]
cffb2a26 5772 "TARGET_ARM"
c7597b5d 5773 "
5774 operands[2] = gen_reg_rtx (SImode);
5775 operands[3] = gen_reg_rtx (SImode);
787f8210 5776 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5777 "
5778)
b11cae9e 5779
a2f10574 5780;; Pattern to recognize insn generated default case above
f7fbdd4a 5781(define_insn "*movhi_insn_arch4"
cde1623a 5782 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5783 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5784 "TARGET_ARM
5785 && arm_arch4
f7fbdd4a 5786 && (GET_CODE (operands[1]) != CONST_INT
5787 || const_ok_for_arm (INTVAL (operands[1]))
5788 || const_ok_for_arm (~INTVAL (operands[1])))"
5789 "@
5790 mov%?\\t%0, %1\\t%@ movhi
5791 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5792 str%(h%)\\t%1, %0\\t%@ movhi
5793 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5794 [(set_attr "type" "*,*,store1,load1")
0d66636f 5795 (set_attr "predicable" "yes")
d2a518d1 5796 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 5797 (set_attr "pool_range" "*,*,*,256")
5798 (set_attr "neg_pool_range" "*,*,*,244")]
5799)
f7fbdd4a 5800
f7fbdd4a 5801(define_insn "*movhi_bytes"
25f7a26e 5802 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5803 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5804 "TARGET_ARM"
25f7a26e 5805 "@
5806 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5807 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 5808 [(set_attr "predicable" "yes")
5809 (set_attr "insn" "mov,mvn")]
0d66636f 5810)
25f7a26e 5811
f90b51f1 5812(define_expand "thumb_movhi_clobber"
5813 [(set (match_operand:HI 0 "memory_operand" "")
5814 (match_operand:HI 1 "register_operand" ""))
5815 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5816 "TARGET_THUMB1"
f90b51f1 5817 "
5818 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5819 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5820 {
5821 emit_insn (gen_movhi (operands[0], operands[1]));
5822 DONE;
5823 }
5824 /* XXX Fixme, need to handle other cases here as well. */
5825 gcc_unreachable ();
5826 "
cffb2a26 5827)
5828
bc5c7e08 5829;; We use a DImode scratch because we may occasionally need an additional
5830;; temporary if the address isn't offsettable -- push_reload doesn't seem
5831;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5832(define_expand "reload_outhi"
cffb2a26 5833 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5834 (match_operand:HI 1 "s_register_operand" "r")
5835 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5836 "TARGET_EITHER"
5837 "if (TARGET_ARM)
5838 arm_reload_out_hi (operands);
5839 else
5840 thumb_reload_out_hi (operands);
d3373b54 5841 DONE;
cffb2a26 5842 "
5843)
d3373b54 5844
25f7a26e 5845(define_expand "reload_inhi"
5846 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5847 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5848 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5849 "TARGET_EITHER"
25f7a26e 5850 "
cffb2a26 5851 if (TARGET_ARM)
5852 arm_reload_in_hi (operands);
5853 else
5854 thumb_reload_out_hi (operands);
25f7a26e 5855 DONE;
5856")
5857
9c08d1fa 5858(define_expand "movqi"
5859 [(set (match_operand:QI 0 "general_operand" "")
5860 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5861 "TARGET_EITHER"
9c08d1fa 5862 "
6cffc037 5863 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5864
e1ba4a27 5865 if (can_create_pseudo_p ())
cffb2a26 5866 {
6cffc037 5867 if (GET_CODE (operands[1]) == CONST_INT)
5868 {
5869 rtx reg = gen_reg_rtx (SImode);
5870
03770691 5871 /* For thumb we want an unsigned immediate, then we are more likely
5872 to be able to use a movs insn. */
5873 if (TARGET_THUMB)
5874 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5875
6cffc037 5876 emit_insn (gen_movsi (reg, operands[1]));
5877 operands[1] = gen_lowpart (QImode, reg);
5878 }
cffb2a26 5879
6cffc037 5880 if (TARGET_THUMB)
5881 {
cffb2a26 5882 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5883 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5884 virtual register (also rejected as illegitimate for HImode/QImode)
5885 relative address. */
cffb2a26 5886 /* ??? This should perhaps be fixed elsewhere, for instance, in
5887 fixup_stack_1, by checking for other kinds of invalid addresses,
5888 e.g. a bare reference to a virtual register. This may confuse the
5889 alpha though, which must handle this case differently. */
5890 if (GET_CODE (operands[0]) == MEM
215b30b3 5891 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5892 XEXP (operands[0], 0)))
537ffcfc 5893 operands[0]
5894 = replace_equiv_address (operands[0],
5895 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5896 if (GET_CODE (operands[1]) == MEM
5897 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5898 XEXP (operands[1], 0)))
537ffcfc 5899 operands[1]
5900 = replace_equiv_address (operands[1],
5901 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5902 }
5903
5904 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5905 {
5906 rtx reg = gen_reg_rtx (SImode);
5907
5908 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5909 operands[1] = gen_lowpart (QImode, reg);
5910 }
5911
5912 if (GET_CODE (operands[0]) == MEM)
5913 operands[1] = force_reg (QImode, operands[1]);
5914 }
5915 else if (TARGET_THUMB
5916 && GET_CODE (operands[1]) == CONST_INT
234f6557 5917 && !satisfies_constraint_I (operands[1]))
6cffc037 5918 {
674a8f0b 5919 /* Handle loading a large integer during reload. */
cffb2a26 5920
6cffc037 5921 /* Writing a constant to memory needs a scratch, which should
5922 be handled with SECONDARY_RELOADs. */
5923 gcc_assert (GET_CODE (operands[0]) == REG);
5924
5925 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5926 emit_insn (gen_movsi (operands[0], operands[1]));
5927 DONE;
cffb2a26 5928 }
5929 "
5930)
b11cae9e 5931
9c08d1fa 5932
cffb2a26 5933(define_insn "*arm_movqi_insn"
5934 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5935 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5936 "TARGET_32BIT
cffb2a26 5937 && ( register_operand (operands[0], QImode)
5938 || register_operand (operands[1], QImode))"
5565501b 5939 "@
5940 mov%?\\t%0, %1
5941 mvn%?\\t%0, #%B1
25f905c2 5942 ldr%(b%)\\t%0, %1
5943 str%(b%)\\t%1, %0"
a2cd141b 5944 [(set_attr "type" "*,*,load1,store1")
d2a518d1 5945 (set_attr "insn" "mov,mvn,*,*")
0d66636f 5946 (set_attr "predicable" "yes")]
cffb2a26 5947)
5948
25f905c2 5949(define_insn "*thumb1_movqi_insn"
cffb2a26 5950 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5951 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5952 "TARGET_THUMB1
cffb2a26 5953 && ( register_operand (operands[0], QImode)
5954 || register_operand (operands[1], QImode))"
5955 "@
5956 add\\t%0, %1, #0
5957 ldrb\\t%0, %1
5958 strb\\t%1, %0
5959 mov\\t%0, %1
5960 mov\\t%0, %1
5961 mov\\t%0, %1"
5962 [(set_attr "length" "2")
a2cd141b 5963 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 5964 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 5965 (set_attr "pool_range" "*,32,*,*,*,*")
5966 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 5967
9b8516be 5968;; HFmode moves
5969(define_expand "movhf"
5970 [(set (match_operand:HF 0 "general_operand" "")
5971 (match_operand:HF 1 "general_operand" ""))]
5972 "TARGET_EITHER"
5973 "
5974 if (TARGET_32BIT)
5975 {
5976 if (GET_CODE (operands[0]) == MEM)
5977 operands[1] = force_reg (HFmode, operands[1]);
5978 }
5979 else /* TARGET_THUMB1 */
5980 {
5981 if (can_create_pseudo_p ())
5982 {
5983 if (GET_CODE (operands[0]) != REG)
5984 operands[1] = force_reg (HFmode, operands[1]);
5985 }
5986 }
5987 "
5988)
5989
5990(define_insn "*arm32_movhf"
5991 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5992 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 5993 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 5994 && ( s_register_operand (operands[0], HFmode)
5995 || s_register_operand (operands[1], HFmode))"
5996 "*
5997 switch (which_alternative)
5998 {
5999 case 0: /* ARM register from memory */
6000 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6001 case 1: /* memory from ARM register */
6002 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6003 case 2: /* ARM register from ARM register */
6004 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6005 case 3: /* ARM register from constant */
6006 {
6007 REAL_VALUE_TYPE r;
6008 long bits;
6009 rtx ops[4];
6010
6011 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6012 bits = real_to_target (NULL, &r, HFmode);
6013 ops[0] = operands[0];
6014 ops[1] = GEN_INT (bits);
6015 ops[2] = GEN_INT (bits & 0xff00);
6016 ops[3] = GEN_INT (bits & 0x00ff);
6017
6018 if (arm_arch_thumb2)
6019 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6020 else
6021 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6022 return \"\";
6023 }
6024 default:
6025 gcc_unreachable ();
6026 }
6027 "
6028 [(set_attr "conds" "unconditional")
6029 (set_attr "type" "load1,store1,*,*")
d2a518d1 6030 (set_attr "insn" "*,*,mov,mov")
9b8516be 6031 (set_attr "length" "4,4,4,8")
d2a518d1 6032 (set_attr "predicable" "yes")]
9b8516be 6033)
6034
6035(define_insn "*thumb1_movhf"
6036 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6037 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6038 "TARGET_THUMB1
6039 && ( s_register_operand (operands[0], HFmode)
6040 || s_register_operand (operands[1], HFmode))"
6041 "*
6042 switch (which_alternative)
6043 {
6044 case 1:
6045 {
6046 rtx addr;
6047 gcc_assert (GET_CODE(operands[1]) == MEM);
6048 addr = XEXP (operands[1], 0);
6049 if (GET_CODE (addr) == LABEL_REF
6050 || (GET_CODE (addr) == CONST
6051 && GET_CODE (XEXP (addr, 0)) == PLUS
6052 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6053 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6054 {
6055 /* Constant pool entry. */
6056 return \"ldr\\t%0, %1\";
6057 }
6058 return \"ldrh\\t%0, %1\";
6059 }
6060 case 2: return \"strh\\t%1, %0\";
6061 default: return \"mov\\t%0, %1\";
6062 }
6063 "
6064 [(set_attr "length" "2")
6065 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6066 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6067 (set_attr "pool_range" "*,1020,*,*,*")
6068 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6069
87b22bf7 6070(define_expand "movsf"
6071 [(set (match_operand:SF 0 "general_operand" "")
6072 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6073 "TARGET_EITHER"
87b22bf7 6074 "
25f905c2 6075 if (TARGET_32BIT)
cffb2a26 6076 {
6077 if (GET_CODE (operands[0]) == MEM)
6078 operands[1] = force_reg (SFmode, operands[1]);
6079 }
25f905c2 6080 else /* TARGET_THUMB1 */
cffb2a26 6081 {
e1ba4a27 6082 if (can_create_pseudo_p ())
cffb2a26 6083 {
6084 if (GET_CODE (operands[0]) != REG)
6085 operands[1] = force_reg (SFmode, operands[1]);
6086 }
6087 }
6088 "
6089)
6090
03d440a6 6091;; Transform a floating-point move of a constant into a core register into
6092;; an SImode operation.
cffb2a26 6093(define_split
03d440a6 6094 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6095 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6096 "TARGET_EITHER
cffb2a26 6097 && reload_completed
6098 && GET_CODE (operands[1]) == CONST_DOUBLE"
6099 [(set (match_dup 2) (match_dup 3))]
6100 "
6101 operands[2] = gen_lowpart (SImode, operands[0]);
6102 operands[3] = gen_lowpart (SImode, operands[1]);
6103 if (operands[2] == 0 || operands[3] == 0)
6104 FAIL;
215b30b3 6105 "
6106)
87b22bf7 6107
cffb2a26 6108(define_insn "*arm_movsf_soft_insn"
6109 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6110 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6111 "TARGET_32BIT
cffb2a26 6112 && TARGET_SOFT_FLOAT
215b30b3 6113 && (GET_CODE (operands[0]) != MEM
6114 || register_operand (operands[1], SFmode))"
9a1112d7 6115 "@
6116 mov%?\\t%0, %1
6117 ldr%?\\t%0, %1\\t%@ float
6118 str%?\\t%1, %0\\t%@ float"
cde1623a 6119 [(set_attr "predicable" "yes")
a2cd141b 6120 (set_attr "type" "*,load1,store1")
d2a518d1 6121 (set_attr "insn" "mov,*,*")
cffb2a26 6122 (set_attr "pool_range" "*,4096,*")
cde1623a 6123 (set_attr "arm_neg_pool_range" "*,4084,*")
6124 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6125)
6126
6127;;; ??? This should have alternatives for constants.
25f905c2 6128(define_insn "*thumb1_movsf_insn"
215b30b3 6129 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6130 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6131 "TARGET_THUMB1
cffb2a26 6132 && ( register_operand (operands[0], SFmode)
6133 || register_operand (operands[1], SFmode))"
6134 "@
6135 add\\t%0, %1, #0
6136 ldmia\\t%1, {%0}
6137 stmia\\t%0, {%1}
6138 ldr\\t%0, %1
6139 str\\t%1, %0
6140 mov\\t%0, %1
6141 mov\\t%0, %1"
6142 [(set_attr "length" "2")
a2cd141b 6143 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6144 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6145 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6146 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6147)
9a1112d7 6148
9c08d1fa 6149(define_expand "movdf"
87b22bf7 6150 [(set (match_operand:DF 0 "general_operand" "")
6151 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6152 "TARGET_EITHER"
9c08d1fa 6153 "
25f905c2 6154 if (TARGET_32BIT)
cffb2a26 6155 {
6156 if (GET_CODE (operands[0]) == MEM)
6157 operands[1] = force_reg (DFmode, operands[1]);
6158 }
6159 else /* TARGET_THUMB */
6160 {
e1ba4a27 6161 if (can_create_pseudo_p ())
cffb2a26 6162 {
6163 if (GET_CODE (operands[0]) != REG)
6164 operands[1] = force_reg (DFmode, operands[1]);
6165 }
6166 }
6167 "
6168)
b11cae9e 6169
9c08d1fa 6170;; Reloading a df mode value stored in integer regs to memory can require a
6171;; scratch reg.
6172(define_expand "reload_outdf"
cffb2a26 6173 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6174 (match_operand:DF 1 "s_register_operand" "r")
6175 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6176 "TARGET_32BIT"
87b22bf7 6177 "
215b30b3 6178 {
6179 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6180
215b30b3 6181 if (code == REG)
6182 operands[2] = XEXP (operands[0], 0);
6183 else if (code == POST_INC || code == PRE_DEC)
6184 {
6185 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6186 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6187 emit_insn (gen_movdi (operands[0], operands[1]));
6188 DONE;
6189 }
6190 else if (code == PRE_INC)
6191 {
6192 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6193
215b30b3 6194 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6195 operands[2] = reg;
6196 }
6197 else if (code == POST_DEC)
6198 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6199 else
6200 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6201 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6202
788fcce0 6203 emit_insn (gen_rtx_SET (VOIDmode,
6204 replace_equiv_address (operands[0], operands[2]),
215b30b3 6205 operands[1]));
f7fbdd4a 6206
215b30b3 6207 if (code == POST_DEC)
6208 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6209
6210 DONE;
6211 }"
6212)
9c08d1fa 6213
9a1112d7 6214(define_insn "*movdf_soft_insn"
359a6e9f 6215 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6216 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6217 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6218 && ( register_operand (operands[0], DFmode)
6219 || register_operand (operands[1], DFmode))"
d51f92df 6220 "*
6221 switch (which_alternative)
6222 {
6223 case 0:
6224 case 1:
6225 case 2:
6226 return \"#\";
6227 default:
6228 return output_move_double (operands);
6229 }
6230 "
359a6e9f 6231 [(set_attr "length" "8,12,16,8,8")
6232 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6233 (set_attr "pool_range" "*,*,*,1020,*")
6234 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6235 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6236)
6237
6238;;; ??? This should have alternatives for constants.
6239;;; ??? This was originally identical to the movdi_insn pattern.
6240;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6241;;; thumb_reorg with a memory reference.
6242(define_insn "*thumb_movdf_insn"
215b30b3 6243 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6244 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6245 "TARGET_THUMB1
cffb2a26 6246 && ( register_operand (operands[0], DFmode)
6247 || register_operand (operands[1], DFmode))"
6248 "*
6249 switch (which_alternative)
6250 {
6251 default:
6252 case 0:
6253 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6254 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6255 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6256 case 1:
6257 return \"ldmia\\t%1, {%0, %H0}\";
6258 case 2:
6259 return \"stmia\\t%0, {%1, %H1}\";
6260 case 3:
6261 return thumb_load_double_from_address (operands);
6262 case 4:
1a83b3ff 6263 operands[2] = gen_rtx_MEM (SImode,
6264 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6265 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6266 return \"\";
6267 case 5:
6268 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6269 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6270 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6271 }
6272 "
6273 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6274 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6275 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6276 (set_attr "pool_range" "*,*,*,1020,*,*")]
6277)
755eb2b4 6278
ccd90aaa 6279(define_expand "movxf"
6280 [(set (match_operand:XF 0 "general_operand" "")
6281 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6282 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6283 "
6284 if (GET_CODE (operands[0]) == MEM)
6285 operands[1] = force_reg (XFmode, operands[1]);
6286 "
6287)
6288
b11cae9e 6289\f
b11cae9e 6290
9c08d1fa 6291;; load- and store-multiple insns
6292;; The arm can load/store any set of registers, provided that they are in
320ea44d 6293;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6294
9c08d1fa 6295(define_expand "load_multiple"
6296 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6297 (match_operand:SI 1 "" ""))
6298 (use (match_operand:SI 2 "" ""))])]
25f905c2 6299 "TARGET_32BIT"
9580c25f 6300{
6301 HOST_WIDE_INT offset = 0;
6302
bd5b4116 6303 /* Support only fixed point registers. */
9c08d1fa 6304 if (GET_CODE (operands[2]) != CONST_INT
6305 || INTVAL (operands[2]) > 14
6306 || INTVAL (operands[2]) < 2
6307 || GET_CODE (operands[1]) != MEM
6308 || GET_CODE (operands[0]) != REG
bd5b4116 6309 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6310 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6311 FAIL;
6312
6313 operands[3]
320ea44d 6314 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6315 INTVAL (operands[2]),
f082f1c4 6316 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6317 FALSE, operands[1], &offset);
9580c25f 6318})
b11cae9e 6319
9c08d1fa 6320(define_expand "store_multiple"
6321 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6322 (match_operand:SI 1 "" ""))
6323 (use (match_operand:SI 2 "" ""))])]
25f905c2 6324 "TARGET_32BIT"
9580c25f 6325{
6326 HOST_WIDE_INT offset = 0;
6327
674a8f0b 6328 /* Support only fixed point registers. */
9c08d1fa 6329 if (GET_CODE (operands[2]) != CONST_INT
6330 || INTVAL (operands[2]) > 14
6331 || INTVAL (operands[2]) < 2
6332 || GET_CODE (operands[1]) != REG
6333 || GET_CODE (operands[0]) != MEM
bd5b4116 6334 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6335 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6336 FAIL;
6337
6338 operands[3]
320ea44d 6339 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6340 INTVAL (operands[2]),
f082f1c4 6341 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6342 FALSE, operands[0], &offset);
9580c25f 6343})
b11cae9e 6344
9c08d1fa 6345
6346;; Move a block of memory if it is word aligned and MORE than 2 words long.
6347;; We could let this apply for blocks of less than this, but it clobbers so
6348;; many registers that there is then probably a better way.
6349
008c057d 6350(define_expand "movmemqi"
34191dd1 6351 [(match_operand:BLK 0 "general_operand" "")
6352 (match_operand:BLK 1 "general_operand" "")
6353 (match_operand:SI 2 "const_int_operand" "")
6354 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6355 "TARGET_EITHER"
9c08d1fa 6356 "
25f905c2 6357 if (TARGET_32BIT)
cffb2a26 6358 {
008c057d 6359 if (arm_gen_movmemqi (operands))
cffb2a26 6360 DONE;
6361 FAIL;
6362 }
25f905c2 6363 else /* TARGET_THUMB1 */
cffb2a26 6364 {
6365 if ( INTVAL (operands[3]) != 4
6366 || INTVAL (operands[2]) > 48)
6367 FAIL;
6368
008c057d 6369 thumb_expand_movmemqi (operands);
cffb2a26 6370 DONE;
6371 }
6372 "
6373)
6374
2162064c 6375;; Thumb block-move insns
cffb2a26 6376
6377(define_insn "movmem12b"
960f3acf 6378 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6379 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6380 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6381 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6382 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6383 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6384 (set (match_operand:SI 0 "register_operand" "=l")
6385 (plus:SI (match_dup 2) (const_int 12)))
6386 (set (match_operand:SI 1 "register_operand" "=l")
6387 (plus:SI (match_dup 3) (const_int 12)))
6388 (clobber (match_scratch:SI 4 "=&l"))
6389 (clobber (match_scratch:SI 5 "=&l"))
6390 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6391 "TARGET_THUMB1"
cffb2a26 6392 "* return thumb_output_move_mem_multiple (3, operands);"
6393 [(set_attr "length" "4")
215b30b3 6394 ; This isn't entirely accurate... It loads as well, but in terms of
6395 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6396 (set_attr "type" "store3")]
6397)
6398
6399(define_insn "movmem8b"
960f3acf 6400 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6401 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6402 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6403 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6404 (set (match_operand:SI 0 "register_operand" "=l")
6405 (plus:SI (match_dup 2) (const_int 8)))
6406 (set (match_operand:SI 1 "register_operand" "=l")
6407 (plus:SI (match_dup 3) (const_int 8)))
6408 (clobber (match_scratch:SI 4 "=&l"))
6409 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6410 "TARGET_THUMB1"
cffb2a26 6411 "* return thumb_output_move_mem_multiple (2, operands);"
6412 [(set_attr "length" "4")
215b30b3 6413 ; This isn't entirely accurate... It loads as well, but in terms of
6414 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6415 (set_attr "type" "store2")]
6416)
6417
9c08d1fa 6418\f
b11cae9e 6419
341940e8 6420;; Compare & branch insns
8d232dc7 6421;; The range calculations are based as follows:
341940e8 6422;; For forward branches, the address calculation returns the address of
6423;; the next instruction. This is 2 beyond the branch instruction.
6424;; For backward branches, the address calculation returns the address of
6425;; the first instruction in this pattern (cmp). This is 2 before the branch
6426;; instruction for the shortest sequence, and 4 before the branch instruction
6427;; if we have to jump around an unconditional branch.
6428;; To the basic branch range the PC offset must be added (this is +4).
6429;; So for forward branches we have
6430;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6431;; And for backward branches we have
6432;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6433;;
6434;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6435;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6436
aeac46d4 6437(define_expand "cbranchsi4"
6438 [(set (pc) (if_then_else
6439 (match_operator 0 "arm_comparison_operator"
6440 [(match_operand:SI 1 "s_register_operand" "")
6441 (match_operand:SI 2 "nonmemory_operand" "")])
6442 (label_ref (match_operand 3 "" ""))
6443 (pc)))]
74f4459c 6444 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6445 "
74f4459c 6446 if (!TARGET_THUMB1)
6447 {
6448 if (!arm_add_operand (operands[2], SImode))
6449 operands[2] = force_reg (SImode, operands[2]);
6450 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6451 operands[3]));
6452 DONE;
6453 }
25f905c2 6454 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6455 {
6456 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6457 operands[3], operands[0]));
6458 DONE;
6459 }
25f905c2 6460 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6461 operands[2] = force_reg (SImode, operands[2]);
6462 ")
6463
a8e6c15d 6464;; A pattern to recognize a special situation and optimize for it.
6465;; On the thumb, zero-extension from memory is preferrable to sign-extension
6466;; due to the available addressing modes. Hence, convert a signed comparison
6467;; with zero into an unsigned comparison with 127 if possible.
6468(define_expand "cbranchqi4"
6469 [(set (pc) (if_then_else
6470 (match_operator 0 "lt_ge_comparison_operator"
6471 [(match_operand:QI 1 "memory_operand" "")
6472 (match_operand:QI 2 "const0_operand" "")])
6473 (label_ref (match_operand 3 "" ""))
6474 (pc)))]
6475 "TARGET_THUMB1"
6476{
d0f6c30d 6477 rtx xops[4];
a8e6c15d 6478 xops[1] = gen_reg_rtx (SImode);
6479 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6480 xops[2] = GEN_INT (127);
6481 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6482 VOIDmode, xops[1], xops[2]);
6483 xops[3] = operands[3];
6484 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6485 DONE;
6486})
6487
74f4459c 6488(define_expand "cbranchsf4"
6489 [(set (pc) (if_then_else
6490 (match_operator 0 "arm_comparison_operator"
6491 [(match_operand:SF 1 "s_register_operand" "")
6492 (match_operand:SF 2 "arm_float_compare_operand" "")])
6493 (label_ref (match_operand 3 "" ""))
6494 (pc)))]
6495 "TARGET_32BIT && TARGET_HARD_FLOAT"
6496 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6497 operands[3])); DONE;"
6498)
6499
6500(define_expand "cbranchdf4"
6501 [(set (pc) (if_then_else
6502 (match_operator 0 "arm_comparison_operator"
6503 [(match_operand:DF 1 "s_register_operand" "")
6504 (match_operand:DF 2 "arm_float_compare_operand" "")])
6505 (label_ref (match_operand 3 "" ""))
6506 (pc)))]
a50d7267 6507 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6508 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6509 operands[3])); DONE;"
6510)
6511
74f4459c 6512(define_expand "cbranchdi4"
6513 [(set (pc) (if_then_else
6514 (match_operator 0 "arm_comparison_operator"
a8045a4f 6515 [(match_operand:DI 1 "cmpdi_operand" "")
6516 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6517 (label_ref (match_operand 3 "" ""))
6518 (pc)))]
a8045a4f 6519 "TARGET_32BIT"
6520 "{
6521 rtx swap = NULL_RTX;
6522 enum rtx_code code = GET_CODE (operands[0]);
6523
6524 /* We should not have two constants. */
6525 gcc_assert (GET_MODE (operands[1]) == DImode
6526 || GET_MODE (operands[2]) == DImode);
6527
6528 /* Flip unimplemented DImode comparisons to a form that
6529 arm_gen_compare_reg can handle. */
6530 switch (code)
6531 {
6532 case GT:
6533 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6534 case LE:
6535 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6536 case GTU:
6537 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6538 case LEU:
6539 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6540 default:
6541 break;
6542 }
6543 if (swap)
6544 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6545 operands[3]));
6546 else
6547 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6548 operands[3]));
6549 DONE;
6550 }"
74f4459c 6551)
6552
d60047aa 6553(define_insn "cbranchsi4_insn"
aeac46d4 6554 [(set (pc) (if_then_else
6555 (match_operator 0 "arm_comparison_operator"
747b7458 6556 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 6557 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6558 (label_ref (match_operand 3 "" ""))
6559 (pc)))]
25f905c2 6560 "TARGET_THUMB1"
747b7458 6561{
6562 rtx t = cfun->machine->thumb1_cc_insn;
6563 if (t != NULL_RTX)
d60047aa 6564 {
747b7458 6565 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6566 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6567 t = NULL_RTX;
6568 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6569 {
6570 if (!noov_comparison_operator (operands[0], VOIDmode))
6571 t = NULL_RTX;
6572 }
6573 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 6574 t = NULL_RTX;
6575 }
d60047aa 6576 if (t == NULL_RTX)
747b7458 6577 {
6578 output_asm_insn ("cmp\t%1, %2", operands);
6579 cfun->machine->thumb1_cc_insn = insn;
6580 cfun->machine->thumb1_cc_op0 = operands[1];
6581 cfun->machine->thumb1_cc_op1 = operands[2];
6582 cfun->machine->thumb1_cc_mode = CCmode;
6583 }
6584 else
6585 /* Ensure we emit the right type of condition code on the jump. */
6586 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6587 CC_REGNUM);
aeac46d4 6588
cffb2a26 6589 switch (get_attr_length (insn))
6590 {
6591 case 4: return \"b%d0\\t%l3\";
6592 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6593 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6594 }
747b7458 6595}
cffb2a26 6596 [(set (attr "far_jump")
6597 (if_then_else
6598 (eq_attr "length" "8")
6599 (const_string "yes")
6600 (const_string "no")))
6601 (set (attr "length")
6602 (if_then_else
6603 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6604 (le (minus (match_dup 3) (pc)) (const_int 256)))
6605 (const_int 4)
6606 (if_then_else
6607 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6608 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6609 (const_int 6)
6610 (const_int 8))))]
6611)
6612
aeac46d4 6613(define_insn "cbranchsi4_scratch"
6614 [(set (pc) (if_then_else
6615 (match_operator 4 "arm_comparison_operator"
6616 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6617 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6618 (label_ref (match_operand 3 "" ""))
6619 (pc)))
6620 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6621 "TARGET_THUMB1"
aeac46d4 6622 "*
6623 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6624
6625 switch (get_attr_length (insn))
6626 {
6627 case 4: return \"b%d4\\t%l3\";
6628 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6629 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6630 }
6631 "
6632 [(set (attr "far_jump")
6633 (if_then_else
6634 (eq_attr "length" "8")
6635 (const_string "yes")
6636 (const_string "no")))
6637 (set (attr "length")
6638 (if_then_else
6639 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6640 (le (minus (match_dup 3) (pc)) (const_int 256)))
6641 (const_int 4)
6642 (if_then_else
6643 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6644 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6645 (const_int 6)
6646 (const_int 8))))]
6647)
446a1e96 6648
747b7458 6649;; Two peepholes to generate subtract of 0 instead of a move if the
6650;; condition codes will be useful.
446a1e96 6651(define_peephole2
6652 [(set (match_operand:SI 0 "low_register_operand" "")
6653 (match_operand:SI 1 "low_register_operand" ""))
6654 (set (pc)
6655 (if_then_else (match_operator 2 "arm_comparison_operator"
6656 [(match_dup 1) (const_int 0)])
6657 (label_ref (match_operand 3 "" ""))
6658 (pc)))]
6659 "TARGET_THUMB1"
747b7458 6660 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6661 (set (pc)
6662 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6663 (label_ref (match_dup 3))
747b7458 6664 (pc)))]
6665 "")
446a1e96 6666
6667;; Sigh! This variant shouldn't be needed, but combine often fails to
6668;; merge cases like this because the op1 is a hard register in
6669;; CLASS_LIKELY_SPILLED_P.
6670(define_peephole2
6671 [(set (match_operand:SI 0 "low_register_operand" "")
6672 (match_operand:SI 1 "low_register_operand" ""))
6673 (set (pc)
6674 (if_then_else (match_operator 2 "arm_comparison_operator"
6675 [(match_dup 0) (const_int 0)])
6676 (label_ref (match_operand 3 "" ""))
6677 (pc)))]
6678 "TARGET_THUMB1"
747b7458 6679 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6680 (set (pc)
6681 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6682 (label_ref (match_dup 3))
747b7458 6683 (pc)))]
6684 "")
446a1e96 6685
cffb2a26 6686(define_insn "*negated_cbranchsi4"
6687 [(set (pc)
6688 (if_then_else
aed179ae 6689 (match_operator 0 "equality_operator"
aeac46d4 6690 [(match_operand:SI 1 "s_register_operand" "l")
6691 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6692 (label_ref (match_operand 3 "" ""))
215b30b3 6693 (pc)))]
25f905c2 6694 "TARGET_THUMB1"
cffb2a26 6695 "*
6696 output_asm_insn (\"cmn\\t%1, %2\", operands);
6697 switch (get_attr_length (insn))
6698 {
6699 case 4: return \"b%d0\\t%l3\";
6700 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6701 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6702 }
6703 "
6704 [(set (attr "far_jump")
6705 (if_then_else
6706 (eq_attr "length" "8")
6707 (const_string "yes")
6708 (const_string "no")))
6709 (set (attr "length")
6710 (if_then_else
6711 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6712 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6713 (const_int 4)
6714 (if_then_else
341940e8 6715 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6716 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6717 (const_int 6)
6718 (const_int 8))))]
6719)
6720
58d6528b 6721(define_insn "*tbit_cbranch"
6722 [(set (pc)
6723 (if_then_else
6724 (match_operator 0 "equality_operator"
6725 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6726 (const_int 1)
6727 (match_operand:SI 2 "const_int_operand" "i"))
6728 (const_int 0)])
6729 (label_ref (match_operand 3 "" ""))
6730 (pc)))
6731 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6732 "TARGET_THUMB1"
58d6528b 6733 "*
6734 {
6735 rtx op[3];
6736 op[0] = operands[4];
6737 op[1] = operands[1];
6738 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6739
86efa74d 6740 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6741 switch (get_attr_length (insn))
6742 {
6743 case 4: return \"b%d0\\t%l3\";
6744 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6745 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6746 }
6747 }"
6748 [(set (attr "far_jump")
6749 (if_then_else
6750 (eq_attr "length" "8")
6751 (const_string "yes")
6752 (const_string "no")))
6753 (set (attr "length")
6754 (if_then_else
6755 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6756 (le (minus (match_dup 3) (pc)) (const_int 256)))
6757 (const_int 4)
6758 (if_then_else
6759 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6760 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6761 (const_int 6)
6762 (const_int 8))))]
6763)
6764
6765(define_insn "*tlobits_cbranch"
6766 [(set (pc)
6767 (if_then_else
6768 (match_operator 0 "equality_operator"
6769 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6770 (match_operand:SI 2 "const_int_operand" "i")
6771 (const_int 0))
6772 (const_int 0)])
6773 (label_ref (match_operand 3 "" ""))
6774 (pc)))
6775 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6776 "TARGET_THUMB1"
86efa74d 6777 "*
6778 {
6779 rtx op[3];
6780 op[0] = operands[4];
6781 op[1] = operands[1];
6782 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6783
58d6528b 6784 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6785 switch (get_attr_length (insn))
6786 {
6787 case 4: return \"b%d0\\t%l3\";
6788 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6789 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6790 }
6791 }"
6792 [(set (attr "far_jump")
6793 (if_then_else
6794 (eq_attr "length" "8")
6795 (const_string "yes")
6796 (const_string "no")))
6797 (set (attr "length")
6798 (if_then_else
6799 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6800 (le (minus (match_dup 3) (pc)) (const_int 256)))
6801 (const_int 4)
6802 (if_then_else
6803 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6804 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6805 (const_int 6)
6806 (const_int 8))))]
6807)
747b7458 6808
aeac46d4 6809(define_insn "*tstsi3_cbranch"
58d6528b 6810 [(set (pc)
6811 (if_then_else
aeac46d4 6812 (match_operator 3 "equality_operator"
6813 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6814 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6815 (const_int 0)])
aeac46d4 6816 (label_ref (match_operand 2 "" ""))
6817 (pc)))]
25f905c2 6818 "TARGET_THUMB1"
58d6528b 6819 "*
6820 {
aeac46d4 6821 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6822 switch (get_attr_length (insn))
6823 {
aeac46d4 6824 case 4: return \"b%d3\\t%l2\";
6825 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6826 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6827 }
6828 }"
6829 [(set (attr "far_jump")
6830 (if_then_else
6831 (eq_attr "length" "8")
6832 (const_string "yes")
6833 (const_string "no")))
6834 (set (attr "length")
6835 (if_then_else
aeac46d4 6836 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6837 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6838 (const_int 4)
6839 (if_then_else
aeac46d4 6840 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6841 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6842 (const_int 6)
6843 (const_int 8))))]
6844)
6845
203c488f 6846(define_insn "*cbranchne_decr1"
6847 [(set (pc)
6848 (if_then_else (match_operator 3 "equality_operator"
6849 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6850 (const_int 0)])
6851 (label_ref (match_operand 4 "" ""))
6852 (pc)))
aeac46d4 6853 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6854 (plus:SI (match_dup 2) (const_int -1)))
6855 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6856 "TARGET_THUMB1"
203c488f 6857 "*
6858 {
6859 rtx cond[2];
6860 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6861 ? GEU : LTU),
58d6528b 6862 VOIDmode, operands[2], const1_rtx);
203c488f 6863 cond[1] = operands[4];
6864
6865 if (which_alternative == 0)
6866 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6867 else if (which_alternative == 1)
6868 {
6869 /* We must provide an alternative for a hi reg because reload
6870 cannot handle output reloads on a jump instruction, but we
6871 can't subtract into that. Fortunately a mov from lo to hi
6872 does not clobber the condition codes. */
6873 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6874 output_asm_insn (\"mov\\t%0, %1\", operands);
6875 }
6876 else
6877 {
6878 /* Similarly, but the target is memory. */
6879 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6880 output_asm_insn (\"str\\t%1, %0\", operands);
6881 }
6882
6883 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6884 {
6885 case 4:
8aea555f 6886 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6887 return \"\";
6888 case 6:
8aea555f 6889 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6890 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6891 default:
8aea555f 6892 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6893 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6894 }
6895 }
6896 "
6897 [(set (attr "far_jump")
6898 (if_then_else
6899 (ior (and (eq (symbol_ref ("which_alternative"))
6900 (const_int 0))
6901 (eq_attr "length" "8"))
6902 (eq_attr "length" "10"))
6903 (const_string "yes")
6904 (const_string "no")))
6905 (set_attr_alternative "length"
6906 [
6907 ;; Alternative 0
6908 (if_then_else
6909 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6910 (le (minus (match_dup 4) (pc)) (const_int 256)))
6911 (const_int 4)
6912 (if_then_else
6913 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6914 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6915 (const_int 6)
6916 (const_int 8)))
6917 ;; Alternative 1
6918 (if_then_else
6919 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6920 (le (minus (match_dup 4) (pc)) (const_int 256)))
6921 (const_int 6)
6922 (if_then_else
6923 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6924 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6925 (const_int 8)
6926 (const_int 10)))
6927 ;; Alternative 2
6928 (if_then_else
6929 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6930 (le (minus (match_dup 4) (pc)) (const_int 256)))
6931 (const_int 6)
6932 (if_then_else
6933 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6934 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6935 (const_int 8)
6936 (const_int 10)))
6937 ;; Alternative 3
6938 (if_then_else
6939 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6940 (le (minus (match_dup 4) (pc)) (const_int 256)))
6941 (const_int 6)
6942 (if_then_else
6943 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6944 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6945 (const_int 8)
6946 (const_int 10)))])]
6947)
cffb2a26 6948
58d6528b 6949(define_insn "*addsi3_cbranch"
6950 [(set (pc)
6951 (if_then_else
b0694be0 6952 (match_operator 4 "arm_comparison_operator"
58d6528b 6953 [(plus:SI
e54011cb 6954 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
6955 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 6956 (const_int 0)])
6957 (label_ref (match_operand 5 "" ""))
6958 (pc)))
aeac46d4 6959 (set
6960 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6961 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 6962 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 6963 "TARGET_THUMB1
58d6528b 6964 && (GET_CODE (operands[4]) == EQ
6965 || GET_CODE (operands[4]) == NE
6966 || GET_CODE (operands[4]) == GE
6967 || GET_CODE (operands[4]) == LT)"
6968 "*
6969 {
6970 rtx cond[3];
6971
956a6170 6972 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 6973 cond[1] = operands[2];
6974 cond[2] = operands[3];
6975
6976 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6977 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6978 else
6979 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6980
956a6170 6981 if (which_alternative >= 2
58d6528b 6982 && which_alternative < 4)
6983 output_asm_insn (\"mov\\t%0, %1\", operands);
6984 else if (which_alternative >= 4)
6985 output_asm_insn (\"str\\t%1, %0\", operands);
6986
d0f6c30d 6987 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 6988 {
6989 case 4:
6990 return \"b%d4\\t%l5\";
6991 case 6:
6992 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6993 default:
6994 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6995 }
6996 }
6997 "
6998 [(set (attr "far_jump")
6999 (if_then_else
7000 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7001 (const_int 2))
58d6528b 7002 (eq_attr "length" "8"))
7003 (eq_attr "length" "10"))
7004 (const_string "yes")
7005 (const_string "no")))
7006 (set (attr "length")
7007 (if_then_else
7008 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7009 (const_int 2))
58d6528b 7010 (if_then_else
7011 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7012 (le (minus (match_dup 5) (pc)) (const_int 256)))
7013 (const_int 4)
7014 (if_then_else
7015 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7016 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7017 (const_int 6)
7018 (const_int 8)))
7019 (if_then_else
7020 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7021 (le (minus (match_dup 5) (pc)) (const_int 256)))
7022 (const_int 6)
7023 (if_then_else
7024 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7025 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7026 (const_int 8)
7027 (const_int 10)))))]
7028)
7029
7030(define_insn "*addsi3_cbranch_scratch"
7031 [(set (pc)
7032 (if_then_else
b0694be0 7033 (match_operator 3 "arm_comparison_operator"
58d6528b 7034 [(plus:SI
7035 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7036 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7037 (const_int 0)])
7038 (label_ref (match_operand 4 "" ""))
7039 (pc)))
7040 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7041 "TARGET_THUMB1
58d6528b 7042 && (GET_CODE (operands[3]) == EQ
7043 || GET_CODE (operands[3]) == NE
7044 || GET_CODE (operands[3]) == GE
7045 || GET_CODE (operands[3]) == LT)"
7046 "*
7047 {
7048 switch (which_alternative)
7049 {
7050 case 0:
7051 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7052 break;
7053 case 1:
7054 output_asm_insn (\"cmn\t%1, %2\", operands);
7055 break;
0f5e9701 7056 case 2:
3a445a04 7057 if (INTVAL (operands[2]) < 0)
7058 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7059 else
7060 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7061 break;
0f5e9701 7062 case 3:
3a445a04 7063 if (INTVAL (operands[2]) < 0)
7064 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7065 else
7066 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7067 break;
7068 }
7069
7070 switch (get_attr_length (insn))
7071 {
7072 case 4:
7073 return \"b%d3\\t%l4\";
7074 case 6:
7075 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7076 default:
7077 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7078 }
7079 }
7080 "
7081 [(set (attr "far_jump")
7082 (if_then_else
7083 (eq_attr "length" "8")
7084 (const_string "yes")
7085 (const_string "no")))
7086 (set (attr "length")
7087 (if_then_else
7088 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7089 (le (minus (match_dup 4) (pc)) (const_int 256)))
7090 (const_int 4)
7091 (if_then_else
7092 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7093 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7094 (const_int 6)
7095 (const_int 8))))]
7096)
7097
58d6528b 7098
9c08d1fa 7099;; Comparison and test insns
7100
cffb2a26 7101(define_insn "*arm_cmpsi_insn"
bd5b4116 7102 [(set (reg:CC CC_REGNUM)
aea4c774 7103 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7104 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7105 "TARGET_32BIT"
5565501b 7106 "@
aea4c774 7107 cmp%?\\t%0, %1
7108 cmn%?\\t%0, #%n1"
cffb2a26 7109 [(set_attr "conds" "set")]
7110)
b11cae9e 7111
d5d4dc8d 7112(define_insn "*cmpsi_shiftsi"
bd5b4116 7113 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7114 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7115 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7116 [(match_operand:SI 1 "s_register_operand" "r,r")
7117 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7118 "TARGET_32BIT"
aea4c774 7119 "cmp%?\\t%0, %1%S3"
344495ea 7120 [(set_attr "conds" "set")
331beb1a 7121 (set_attr "shift" "1")
d5d4dc8d 7122 (set_attr "arch" "32,a")
7123 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7124
d5d4dc8d 7125(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7126 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7127 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7128 [(match_operand:SI 1 "s_register_operand" "r,r")
7129 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7130 (match_operand:SI 0 "s_register_operand" "r,r")))]
7131 "TARGET_32BIT"
aea4c774 7132 "cmp%?\\t%0, %1%S3"
344495ea 7133 [(set_attr "conds" "set")
331beb1a 7134 (set_attr "shift" "1")
d5d4dc8d 7135 (set_attr "arch" "32,a")
7136 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7137
25f905c2 7138(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7139 [(set (reg:CC_Z CC_REGNUM)
7140 (compare:CC_Z
7141 (neg:SI (match_operator:SI 1 "shift_operator"
7142 [(match_operand:SI 2 "s_register_operand" "r")
7143 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7144 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7145 "TARGET_ARM"
aed179ae 7146 "cmn%?\\t%0, %2%S1"
344495ea 7147 [(set_attr "conds" "set")
aed179ae 7148 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7149 (const_string "alu_shift")
7150 (const_string "alu_shift_reg")))]
0d66636f 7151)
b11cae9e 7152
a8045a4f 7153;; DImode comparisons. The generic code generates branches that
7154;; if-conversion can not reduce to a conditional compare, so we do
7155;; that directly.
7156
7157(define_insn "*arm_cmpdi_insn"
7158 [(set (reg:CC_NCV CC_REGNUM)
7159 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7160 (match_operand:DI 1 "arm_di_operand" "rDi")))
7161 (clobber (match_scratch:SI 2 "=r"))]
7162 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7163 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7164 [(set_attr "conds" "set")
7165 (set_attr "length" "8")]
7166)
7167
7168(define_insn "*arm_cmpdi_unsigned"
7169 [(set (reg:CC_CZ CC_REGNUM)
7170 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7171 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7172 "TARGET_ARM"
7173 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7174 [(set_attr "conds" "set")
7175 (set_attr "length" "8")]
7176)
7177
7178(define_insn "*arm_cmpdi_zero"
7179 [(set (reg:CC_Z CC_REGNUM)
7180 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7181 (const_int 0)))
7182 (clobber (match_scratch:SI 1 "=r"))]
7183 "TARGET_32BIT"
7184 "orr%.\\t%1, %Q0, %R0"
7185 [(set_attr "conds" "set")]
7186)
7187
7188(define_insn "*thumb_cmpdi_zero"
7189 [(set (reg:CC_Z CC_REGNUM)
7190 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7191 (const_int 0)))
7192 (clobber (match_scratch:SI 1 "=l"))]
7193 "TARGET_THUMB1"
7194 "orr\\t%1, %Q0, %R0"
7195 [(set_attr "conds" "set")
7196 (set_attr "length" "2")]
7197)
7198
7d57ec45 7199;; Cirrus SF compare instruction
7200(define_insn "*cirrus_cmpsf"
7201 [(set (reg:CCFP CC_REGNUM)
7202 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7203 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7204 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7205 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7206 [(set_attr "type" "mav_farith")
7d57ec45 7207 (set_attr "cirrus" "compare")]
7208)
7209
7210;; Cirrus DF compare instruction
7211(define_insn "*cirrus_cmpdf"
7212 [(set (reg:CCFP CC_REGNUM)
7213 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7214 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7215 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7216 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7217 [(set_attr "type" "mav_farith")
7d57ec45 7218 (set_attr "cirrus" "compare")]
7219)
7220
7d57ec45 7221(define_insn "*cirrus_cmpdi"
7222 [(set (reg:CC CC_REGNUM)
7223 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7224 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7225 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7226 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7227 [(set_attr "type" "mav_farith")
7d57ec45 7228 (set_attr "cirrus" "compare")]
7229)
7230
9c08d1fa 7231; This insn allows redundant compares to be removed by cse, nothing should
7232; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7233; is deleted later on. The match_dup will match the mode here, so that
7234; mode changes of the condition codes aren't lost by this even though we don't
7235; specify what they are.
7236
8a18b90c 7237(define_insn "*deleted_compare"
9c08d1fa 7238 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7239 "TARGET_32BIT"
40dbec34 7240 "\\t%@ deleted compare"
cffb2a26 7241 [(set_attr "conds" "set")
7242 (set_attr "length" "0")]
7243)
9c08d1fa 7244
7245\f
7246;; Conditional branch insns
7247
74f4459c 7248(define_expand "cbranch_cc"
9c08d1fa 7249 [(set (pc)
74f4459c 7250 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7251 (match_operand 2 "" "")])
7252 (label_ref (match_operand 3 "" ""))
9c08d1fa 7253 (pc)))]
25f905c2 7254 "TARGET_32BIT"
74f4459c 7255 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7256 operands[1], operands[2]);
7257 operands[2] = const0_rtx;"
8fa3ba89 7258)
7259
7260;;
7261;; Patterns to match conditional branch insns.
7262;;
7263
cffb2a26 7264(define_insn "*arm_cond_branch"
9c08d1fa 7265 [(set (pc)
8fa3ba89 7266 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7267 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7268 (label_ref (match_operand 0 "" ""))
7269 (pc)))]
25f905c2 7270 "TARGET_32BIT"
d75350ce 7271 "*
9c08d1fa 7272 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7273 {
7274 arm_ccfsm_state += 2;
7275 return \"\";
7276 }
e2348bcb 7277 return \"b%d1\\t%l0\";
cffb2a26 7278 "
a2cd141b 7279 [(set_attr "conds" "use")
7280 (set_attr "type" "branch")]
cffb2a26 7281)
d75350ce 7282
cffb2a26 7283(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7284 [(set (pc)
8fa3ba89 7285 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7286 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7287 (pc)
7288 (label_ref (match_operand 0 "" ""))))]
25f905c2 7289 "TARGET_32BIT"
d75350ce 7290 "*
9c08d1fa 7291 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7292 {
7293 arm_ccfsm_state += 2;
7294 return \"\";
7295 }
e2348bcb 7296 return \"b%D1\\t%l0\";
cffb2a26 7297 "
a2cd141b 7298 [(set_attr "conds" "use")
7299 (set_attr "type" "branch")]
cffb2a26 7300)
7301
b11cae9e 7302\f
9c08d1fa 7303
7304; scc insns
7305
74f4459c 7306(define_expand "cstore_cc"
7db9af5d 7307 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7308 (match_operator:SI 1 "" [(match_operand 2 "" "")
7309 (match_operand 3 "" "")]))]
25f905c2 7310 "TARGET_32BIT"
74f4459c 7311 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7312 operands[2], operands[3]);
7313 operands[3] = const0_rtx;"
8fa3ba89 7314)
7315
f7fbdd4a 7316(define_insn "*mov_scc"
9c08d1fa 7317 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7318 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7319 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7320 "TARGET_ARM"
4d61e570 7321 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7322 [(set_attr "conds" "use")
d2a518d1 7323 (set_attr "insn" "mov")
cffb2a26 7324 (set_attr "length" "8")]
7325)
9c08d1fa 7326
f7fbdd4a 7327(define_insn "*mov_negscc"
9c08d1fa 7328 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7329 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7330 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7331 "TARGET_ARM"
4d61e570 7332 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7333 [(set_attr "conds" "use")
d2a518d1 7334 (set_attr "insn" "mov")
cffb2a26 7335 (set_attr "length" "8")]
7336)
9c08d1fa 7337
f7fbdd4a 7338(define_insn "*mov_notscc"
9c08d1fa 7339 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7340 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7341 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7342 "TARGET_ARM"
4d61e570 7343 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7344 [(set_attr "conds" "use")
d2a518d1 7345 (set_attr "insn" "mov")
cffb2a26 7346 (set_attr "length" "8")]
7347)
9c08d1fa 7348
595d88b5 7349(define_expand "cstoresi4"
7350 [(set (match_operand:SI 0 "s_register_operand" "")
7351 (match_operator:SI 1 "arm_comparison_operator"
7352 [(match_operand:SI 2 "s_register_operand" "")
7353 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7354 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7355 "{
7356 rtx op3, scratch, scratch2;
7357
74f4459c 7358 if (!TARGET_THUMB1)
7359 {
7360 if (!arm_add_operand (operands[3], SImode))
7361 operands[3] = force_reg (SImode, operands[3]);
7362 emit_insn (gen_cstore_cc (operands[0], operands[1],
7363 operands[2], operands[3]));
7364 DONE;
7365 }
7366
595d88b5 7367 if (operands[3] == const0_rtx)
7368 {
7369 switch (GET_CODE (operands[1]))
7370 {
7371 case EQ:
25f905c2 7372 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7373 break;
7374
7375 case NE:
25f905c2 7376 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7377 break;
7378
7379 case LE:
7380 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7381 NULL_RTX, 0, OPTAB_WIDEN);
7382 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7383 NULL_RTX, 0, OPTAB_WIDEN);
7384 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7385 operands[0], 1, OPTAB_WIDEN);
7386 break;
7387
7388 case GE:
7389 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7390 NULL_RTX, 1);
7391 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7392 NULL_RTX, 1, OPTAB_WIDEN);
7393 break;
7394
7395 case GT:
7396 scratch = expand_binop (SImode, ashr_optab, operands[2],
7397 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7398 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7399 NULL_RTX, 0, OPTAB_WIDEN);
7400 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7401 0, OPTAB_WIDEN);
7402 break;
7403
7404 /* LT is handled by generic code. No need for unsigned with 0. */
7405 default:
7406 FAIL;
7407 }
7408 DONE;
7409 }
7410
7411 switch (GET_CODE (operands[1]))
7412 {
7413 case EQ:
7414 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7415 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7416 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7417 break;
7418
7419 case NE:
7420 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7421 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7422 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7423 break;
7424
7425 case LE:
7426 op3 = force_reg (SImode, operands[3]);
7427
7428 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7429 NULL_RTX, 1, OPTAB_WIDEN);
7430 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7431 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7432 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7433 op3, operands[2]));
7434 break;
7435
7436 case GE:
7437 op3 = operands[3];
25f905c2 7438 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7439 op3 = force_reg (SImode, op3);
7440 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7441 NULL_RTX, 0, OPTAB_WIDEN);
7442 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7443 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7444 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7445 operands[2], op3));
7446 break;
7447
7448 case LEU:
7449 op3 = force_reg (SImode, operands[3]);
7450 scratch = force_reg (SImode, const0_rtx);
25f905c2 7451 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7452 op3, operands[2]));
7453 break;
7454
7455 case GEU:
7456 op3 = operands[3];
25f905c2 7457 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7458 op3 = force_reg (SImode, op3);
7459 scratch = force_reg (SImode, const0_rtx);
25f905c2 7460 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7461 operands[2], op3));
7462 break;
7463
7464 case LTU:
7465 op3 = operands[3];
25f905c2 7466 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7467 op3 = force_reg (SImode, op3);
7468 scratch = gen_reg_rtx (SImode);
408b7ae5 7469 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7470 break;
7471
7472 case GTU:
7473 op3 = force_reg (SImode, operands[3]);
7474 scratch = gen_reg_rtx (SImode);
408b7ae5 7475 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7476 break;
7477
7478 /* No good sequences for GT, LT. */
7479 default:
7480 FAIL;
7481 }
7482 DONE;
7483}")
7484
74f4459c 7485(define_expand "cstoresf4"
7486 [(set (match_operand:SI 0 "s_register_operand" "")
7487 (match_operator:SI 1 "arm_comparison_operator"
7488 [(match_operand:SF 2 "s_register_operand" "")
7489 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7490 "TARGET_32BIT && TARGET_HARD_FLOAT"
7491 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7492 operands[2], operands[3])); DONE;"
7493)
7494
7495(define_expand "cstoredf4"
7496 [(set (match_operand:SI 0 "s_register_operand" "")
7497 (match_operator:SI 1 "arm_comparison_operator"
7498 [(match_operand:DF 2 "s_register_operand" "")
7499 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7500 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7501 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7502 operands[2], operands[3])); DONE;"
7503)
7504
74f4459c 7505(define_expand "cstoredi4"
7506 [(set (match_operand:SI 0 "s_register_operand" "")
7507 (match_operator:SI 1 "arm_comparison_operator"
a8045a4f 7508 [(match_operand:DI 2 "cmpdi_operand" "")
7509 (match_operand:DI 3 "cmpdi_operand" "")]))]
7510 "TARGET_32BIT"
7511 "{
7512 rtx swap = NULL_RTX;
7513 enum rtx_code code = GET_CODE (operands[1]);
7514
7515 /* We should not have two constants. */
7516 gcc_assert (GET_MODE (operands[2]) == DImode
7517 || GET_MODE (operands[3]) == DImode);
7518
7519 /* Flip unimplemented DImode comparisons to a form that
7520 arm_gen_compare_reg can handle. */
7521 switch (code)
7522 {
7523 case GT:
7524 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7525 case LE:
7526 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7527 case GTU:
7528 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7529 case LEU:
7530 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7531 default:
7532 break;
7533 }
7534 if (swap)
7535 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7536 operands[2]));
7537 else
7538 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7539 operands[3]));
7540 DONE;
7541 }"
74f4459c 7542)
7543
25f905c2 7544(define_expand "cstoresi_eq0_thumb1"
595d88b5 7545 [(parallel
7546 [(set (match_operand:SI 0 "s_register_operand" "")
7547 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7548 (const_int 0)))
7549 (clobber (match_dup:SI 2))])]
25f905c2 7550 "TARGET_THUMB1"
595d88b5 7551 "operands[2] = gen_reg_rtx (SImode);"
7552)
7553
25f905c2 7554(define_expand "cstoresi_ne0_thumb1"
595d88b5 7555 [(parallel
7556 [(set (match_operand:SI 0 "s_register_operand" "")
7557 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7558 (const_int 0)))
7559 (clobber (match_dup:SI 2))])]
25f905c2 7560 "TARGET_THUMB1"
595d88b5 7561 "operands[2] = gen_reg_rtx (SImode);"
7562)
7563
25f905c2 7564(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7565 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7566 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7567 (const_int 0)))
7568 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7569 "TARGET_THUMB1"
595d88b5 7570 "@
7571 neg\\t%0, %1\;adc\\t%0, %0, %1
7572 neg\\t%2, %1\;adc\\t%0, %1, %2"
7573 [(set_attr "length" "4")]
7574)
7575
25f905c2 7576(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7577 [(set (match_operand:SI 0 "s_register_operand" "=l")
7578 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7579 (const_int 0)))
7580 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7581 "TARGET_THUMB1"
595d88b5 7582 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7583 [(set_attr "length" "4")]
7584)
7585
408b7ae5 7586;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 7587(define_insn "cstoresi_nltu_thumb1"
595d88b5 7588 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7589 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7590 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7591 "TARGET_THUMB1"
595d88b5 7592 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7593 [(set_attr "length" "4")]
7594)
7595
408b7ae5 7596(define_insn_and_split "cstoresi_ltu_thumb1"
7597 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7598 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7599 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7600 "TARGET_THUMB1"
7601 "#"
7602 "TARGET_THUMB1"
7603 [(set (match_dup 3)
7604 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7605 (set (match_dup 0) (neg:SI (match_dup 3)))]
7606 "operands[3] = gen_reg_rtx (SImode);"
7607 [(set_attr "length" "4")]
7608)
7609
595d88b5 7610;; Used as part of the expansion of thumb les sequence.
25f905c2 7611(define_insn "thumb1_addsi3_addgeu"
595d88b5 7612 [(set (match_operand:SI 0 "s_register_operand" "=l")
7613 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7614 (match_operand:SI 2 "s_register_operand" "l"))
7615 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 7616 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7617 "TARGET_THUMB1"
595d88b5 7618 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7619 [(set_attr "length" "4")]
7620)
7621
9c08d1fa 7622\f
39b5e676 7623;; Conditional move insns
7624
7625(define_expand "movsicc"
8a18b90c 7626 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7627 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7628 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7629 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7630 "TARGET_32BIT"
39b5e676 7631 "
215b30b3 7632 {
7633 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7634 rtx ccreg;
7635
7636 if (code == UNEQ || code == LTGT)
7637 FAIL;
39b5e676 7638
74f4459c 7639 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7640 XEXP (operands[1], 1));
29bb088d 7641 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7642 }"
7643)
39b5e676 7644
7645(define_expand "movsfcc"
8a18b90c 7646 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7647 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7648 (match_operand:SF 2 "s_register_operand" "")
7649 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 7650 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7651 "
215b30b3 7652 {
7653 enum rtx_code code = GET_CODE (operands[1]);
7654 rtx ccreg;
f082f1c4 7655
278b301d 7656 if (code == UNEQ || code == LTGT)
7657 FAIL;
7658
215b30b3 7659 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7660 Otherwise, ensure it is a valid FP add operand */
7661 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7662 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7663 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7664
74f4459c 7665 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7666 XEXP (operands[1], 1));
29bb088d 7667 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7668 }"
7669)
39b5e676 7670
7671(define_expand "movdfcc"
8a18b90c 7672 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7673 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7674 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7675 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 7676 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 7677 "
215b30b3 7678 {
7679 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7680 rtx ccreg;
39b5e676 7681
278b301d 7682 if (code == UNEQ || code == LTGT)
7683 FAIL;
7684
74f4459c 7685 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7686 XEXP (operands[1], 1));
29bb088d 7687 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7688 }"
7689)
39b5e676 7690
7691(define_insn "*movsicc_insn"
f082f1c4 7692 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7693 (if_then_else:SI
8fa3ba89 7694 (match_operator 3 "arm_comparison_operator"
8a18b90c 7695 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7696 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7697 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7698 "TARGET_ARM"
39b5e676 7699 "@
8a18b90c 7700 mov%D3\\t%0, %2
7701 mvn%D3\\t%0, #%B2
f082f1c4 7702 mov%d3\\t%0, %1
7703 mvn%d3\\t%0, #%B1
8a18b90c 7704 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7705 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7706 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7707 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7708 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7709 (set_attr "conds" "use")
7710 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 7711)
39b5e676 7712
39b5e676 7713(define_insn "*movsfcc_soft_insn"
f082f1c4 7714 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7715 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7716 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7717 (match_operand:SF 1 "s_register_operand" "0,r")
7718 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7719 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7720 "@
7721 mov%D3\\t%0, %2
7722 mov%d3\\t%0, %1"
d2a518d1 7723 [(set_attr "conds" "use")
7724 (set_attr "insn" "mov")]
8fa3ba89 7725)
39b5e676 7726
39b5e676 7727\f
9c08d1fa 7728;; Jump and linkage insns
7729
cffb2a26 7730(define_expand "jump"
9c08d1fa 7731 [(set (pc)
7732 (label_ref (match_operand 0 "" "")))]
cffb2a26 7733 "TARGET_EITHER"
9c08d1fa 7734 ""
cffb2a26 7735)
7736
7737(define_insn "*arm_jump"
7738 [(set (pc)
7739 (label_ref (match_operand 0 "" "")))]
25f905c2 7740 "TARGET_32BIT"
9c08d1fa 7741 "*
0d66636f 7742 {
7743 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7744 {
7745 arm_ccfsm_state += 2;
7746 return \"\";
7747 }
7748 return \"b%?\\t%l0\";
7749 }
7750 "
7751 [(set_attr "predicable" "yes")]
7752)
9c08d1fa 7753
cffb2a26 7754(define_insn "*thumb_jump"
7755 [(set (pc)
7756 (label_ref (match_operand 0 "" "")))]
25f905c2 7757 "TARGET_THUMB1"
cffb2a26 7758 "*
7759 if (get_attr_length (insn) == 2)
7760 return \"b\\t%l0\";
7761 return \"bl\\t%l0\\t%@ far jump\";
7762 "
7763 [(set (attr "far_jump")
7764 (if_then_else
7765 (eq_attr "length" "4")
7766 (const_string "yes")
7767 (const_string "no")))
7768 (set (attr "length")
7769 (if_then_else
911ed8af 7770 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7771 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7772 (const_int 2)
7773 (const_int 4)))]
7774)
7775
d3373b54 7776(define_expand "call"
7777 [(parallel [(call (match_operand 0 "memory_operand" "")
7778 (match_operand 1 "general_operand" ""))
cffb2a26 7779 (use (match_operand 2 "" ""))
bd5b4116 7780 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7781 "TARGET_EITHER"
6c4c2133 7782 "
7783 {
bac7fc85 7784 rtx callee, pat;
bbe777ea 7785
bbe777ea 7786 /* In an untyped call, we can get NULL for operand 2. */
7787 if (operands[2] == NULL_RTX)
7788 operands[2] = const0_rtx;
7789
de55252a 7790 /* Decide if we should generate indirect calls by loading the
85c36fd1 7791 32-bit address of the callee into a register before performing the
de55252a 7792 branch and link. */
7793 callee = XEXP (operands[0], 0);
7794 if (GET_CODE (callee) == SYMBOL_REF
7795 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7796 : !REG_P (callee))
bbe777ea 7797 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7798
7799 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7800 arm_emit_call_insn (pat, XEXP (operands[0], 0));
7801 DONE;
6c4c2133 7802 }"
7803)
d3373b54 7804
bac7fc85 7805(define_expand "call_internal"
7806 [(parallel [(call (match_operand 0 "memory_operand" "")
7807 (match_operand 1 "general_operand" ""))
7808 (use (match_operand 2 "" ""))
7809 (clobber (reg:SI LR_REGNUM))])])
7810
f1039640 7811(define_insn "*call_reg_armv5"
d3373b54 7812 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7813 (match_operand 1 "" ""))
7814 (use (match_operand 2 "" ""))
bd5b4116 7815 (clobber (reg:SI LR_REGNUM))]
f1039640 7816 "TARGET_ARM && arm_arch5"
7817 "blx%?\\t%0"
7818 [(set_attr "type" "call")]
7819)
7820
7821(define_insn "*call_reg_arm"
7822 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7823 (match_operand 1 "" ""))
7824 (use (match_operand 2 "" ""))
7825 (clobber (reg:SI LR_REGNUM))]
7826 "TARGET_ARM && !arm_arch5"
9c08d1fa 7827 "*
5565501b 7828 return output_call (operands);
cffb2a26 7829 "
7830 ;; length is worst case, normally it is only two
7831 [(set_attr "length" "12")
7832 (set_attr "type" "call")]
7833)
9c08d1fa 7834
89504fc1 7835
7836;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7837;; considered a function call by the branch predictor of some cores (PR40887).
7838;; Falls back to blx rN (*call_reg_armv5).
7839
f7fbdd4a 7840(define_insn "*call_mem"
a3c63a9d 7841 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7842 (match_operand 1 "" ""))
7843 (use (match_operand 2 "" ""))
bd5b4116 7844 (clobber (reg:SI LR_REGNUM))]
89504fc1 7845 "TARGET_ARM && !arm_arch5"
9c08d1fa 7846 "*
5565501b 7847 return output_call_mem (operands);
cffb2a26 7848 "
7849 [(set_attr "length" "12")
7850 (set_attr "type" "call")]
7851)
7852
25f905c2 7853(define_insn "*call_reg_thumb1_v5"
cffb2a26 7854 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7855 (match_operand 1 "" ""))
7856 (use (match_operand 2 "" ""))
bd5b4116 7857 (clobber (reg:SI LR_REGNUM))]
25f905c2 7858 "TARGET_THUMB1 && arm_arch5"
f1039640 7859 "blx\\t%0"
7860 [(set_attr "length" "2")
7861 (set_attr "type" "call")]
cffb2a26 7862)
7863
25f905c2 7864(define_insn "*call_reg_thumb1"
f1039640 7865 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7866 (match_operand 1 "" ""))
7867 (use (match_operand 2 "" ""))
bd5b4116 7868 (clobber (reg:SI LR_REGNUM))]
25f905c2 7869 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 7870 "*
7871 {
150502c9 7872 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7873 return thumb_call_via_reg (operands[0]);
150502c9 7874 else if (operands[1] == const0_rtx)
f1039640 7875 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7876 else if (frame_pointer_needed)
7877 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7878 else
150502c9 7879 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7880 }"
7881 [(set_attr "type" "call")]
7882)
9c08d1fa 7883
d3373b54 7884(define_expand "call_value"
e0698af7 7885 [(parallel [(set (match_operand 0 "" "")
7886 (call (match_operand 1 "memory_operand" "")
7887 (match_operand 2 "general_operand" "")))
cffb2a26 7888 (use (match_operand 3 "" ""))
bd5b4116 7889 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7890 "TARGET_EITHER"
6c4c2133 7891 "
7892 {
bac7fc85 7893 rtx pat, callee;
bbe777ea 7894
7895 /* In an untyped call, we can get NULL for operand 2. */
7896 if (operands[3] == 0)
7897 operands[3] = const0_rtx;
7898
de55252a 7899 /* Decide if we should generate indirect calls by loading the
7900 32-bit address of the callee into a register before performing the
7901 branch and link. */
7902 callee = XEXP (operands[1], 0);
7903 if (GET_CODE (callee) == SYMBOL_REF
7904 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7905 : !REG_P (callee))
78fe751b 7906 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7907
7908 pat = gen_call_value_internal (operands[0], operands[1],
7909 operands[2], operands[3]);
7910 arm_emit_call_insn (pat, XEXP (operands[1], 0));
7911 DONE;
6c4c2133 7912 }"
7913)
d3373b54 7914
bac7fc85 7915(define_expand "call_value_internal"
7916 [(parallel [(set (match_operand 0 "" "")
7917 (call (match_operand 1 "memory_operand" "")
7918 (match_operand 2 "general_operand" "")))
7919 (use (match_operand 3 "" ""))
7920 (clobber (reg:SI LR_REGNUM))])])
7921
f1039640 7922(define_insn "*call_value_reg_armv5"
27ed6835 7923 [(set (match_operand 0 "" "")
755eb2b4 7924 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7925 (match_operand 2 "" "")))
bbe777ea 7926 (use (match_operand 3 "" ""))
bd5b4116 7927 (clobber (reg:SI LR_REGNUM))]
f1039640 7928 "TARGET_ARM && arm_arch5"
7929 "blx%?\\t%1"
7930 [(set_attr "type" "call")]
7931)
7932
7933(define_insn "*call_value_reg_arm"
7934 [(set (match_operand 0 "" "")
7935 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7936 (match_operand 2 "" "")))
7937 (use (match_operand 3 "" ""))
7938 (clobber (reg:SI LR_REGNUM))]
7939 "TARGET_ARM && !arm_arch5"
9c08d1fa 7940 "*
215b30b3 7941 return output_call (&operands[1]);
cffb2a26 7942 "
7943 [(set_attr "length" "12")
7944 (set_attr "type" "call")]
7945)
9c08d1fa 7946
89504fc1 7947;; Note: see *call_mem
7948
f7fbdd4a 7949(define_insn "*call_value_mem"
27ed6835 7950 [(set (match_operand 0 "" "")
a3c63a9d 7951 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7952 (match_operand 2 "" "")))
bbe777ea 7953 (use (match_operand 3 "" ""))
bd5b4116 7954 (clobber (reg:SI LR_REGNUM))]
89504fc1 7955 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7956 "*
215b30b3 7957 return output_call_mem (&operands[1]);
cffb2a26 7958 "
7959 [(set_attr "length" "12")
7960 (set_attr "type" "call")]
7961)
9c08d1fa 7962
25f905c2 7963(define_insn "*call_value_reg_thumb1_v5"
f1039640 7964 [(set (match_operand 0 "" "")
7965 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7966 (match_operand 2 "" "")))
7967 (use (match_operand 3 "" ""))
7968 (clobber (reg:SI LR_REGNUM))]
25f905c2 7969 "TARGET_THUMB1 && arm_arch5"
f1039640 7970 "blx\\t%1"
7971 [(set_attr "length" "2")
7972 (set_attr "type" "call")]
7973)
7974
25f905c2 7975(define_insn "*call_value_reg_thumb1"
f1039640 7976 [(set (match_operand 0 "" "")
7977 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7978 (match_operand 2 "" "")))
7979 (use (match_operand 3 "" ""))
7980 (clobber (reg:SI LR_REGNUM))]
25f905c2 7981 "TARGET_THUMB1 && !arm_arch5"
f1039640 7982 "*
7983 {
150502c9 7984 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7985 return thumb_call_via_reg (operands[1]);
150502c9 7986 else if (operands[2] == const0_rtx)
f1039640 7987 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7988 else if (frame_pointer_needed)
7989 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7990 else
150502c9 7991 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 7992 }"
7993 [(set_attr "type" "call")]
7994)
7995
9c08d1fa 7996;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7997;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7998
f7fbdd4a 7999(define_insn "*call_symbol"
27ed6835 8000 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8001 (match_operand 1 "" ""))
bbe777ea 8002 (use (match_operand 2 "" ""))
bd5b4116 8003 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8004 "TARGET_32BIT
cffb2a26 8005 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8006 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8007 "*
8008 {
55c1e470 8009 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8010 }"
cffb2a26 8011 [(set_attr "type" "call")]
8012)
9c08d1fa 8013
f7fbdd4a 8014(define_insn "*call_value_symbol"
ccd90aaa 8015 [(set (match_operand 0 "" "")
27ed6835 8016 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8017 (match_operand:SI 2 "" "")))
bbe777ea 8018 (use (match_operand 3 "" ""))
bd5b4116 8019 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8020 "TARGET_32BIT
cffb2a26 8021 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8022 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8023 "*
8024 {
55c1e470 8025 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8026 }"
cffb2a26 8027 [(set_attr "type" "call")]
8028)
8029
8030(define_insn "*call_insn"
27ed6835 8031 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8032 (match_operand:SI 1 "" ""))
8033 (use (match_operand 2 "" ""))
bd5b4116 8034 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8035 "TARGET_THUMB1
1675c6e9 8036 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8037 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8038 "bl\\t%a0"
8039 [(set_attr "length" "4")
8040 (set_attr "type" "call")]
8041)
8042
8043(define_insn "*call_value_insn"
ccd90aaa 8044 [(set (match_operand 0 "" "")
27ed6835 8045 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8046 (match_operand 2 "" "")))
8047 (use (match_operand 3 "" ""))
bd5b4116 8048 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8049 "TARGET_THUMB1
1675c6e9 8050 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8051 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8052 "bl\\t%a1"
8053 [(set_attr "length" "4")
8054 (set_attr "type" "call")]
8055)
9c08d1fa 8056
1c494086 8057;; We may also be able to do sibcalls for Thumb, but it's much harder...
8058(define_expand "sibcall"
8059 [(parallel [(call (match_operand 0 "memory_operand" "")
8060 (match_operand 1 "general_operand" ""))
2ba80634 8061 (return)
8062 (use (match_operand 2 "" ""))])]
d68c2c10 8063 "TARGET_32BIT"
1c494086 8064 "
8065 {
8066 if (operands[2] == NULL_RTX)
8067 operands[2] = const0_rtx;
1c494086 8068 }"
8069)
8070
8071(define_expand "sibcall_value"
ccd90aaa 8072 [(parallel [(set (match_operand 0 "" "")
1c494086 8073 (call (match_operand 1 "memory_operand" "")
8074 (match_operand 2 "general_operand" "")))
2ba80634 8075 (return)
8076 (use (match_operand 3 "" ""))])]
d68c2c10 8077 "TARGET_32BIT"
1c494086 8078 "
8079 {
8080 if (operands[3] == NULL_RTX)
8081 operands[3] = const0_rtx;
1c494086 8082 }"
8083)
8084
8085(define_insn "*sibcall_insn"
8086 [(call (mem:SI (match_operand:SI 0 "" "X"))
8087 (match_operand 1 "" ""))
2ba80634 8088 (return)
8089 (use (match_operand 2 "" ""))]
d68c2c10 8090 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8091 "*
8092 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8093 "
8094 [(set_attr "type" "call")]
8095)
8096
8097(define_insn "*sibcall_value_insn"
ccd90aaa 8098 [(set (match_operand 0 "" "")
755eb2b4 8099 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8100 (match_operand 2 "" "")))
2ba80634 8101 (return)
8102 (use (match_operand 3 "" ""))]
d68c2c10 8103 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8104 "*
8105 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8106 "
8107 [(set_attr "type" "call")]
8108)
8109
d68c2c10 8110(define_expand "return"
8111 [(return)]
8112 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8113 "")
8114
9c08d1fa 8115;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8116(define_insn "*arm_return"
9c08d1fa 8117 [(return)]
cffb2a26 8118 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8119 "*
9c08d1fa 8120 {
cffb2a26 8121 if (arm_ccfsm_state == 2)
8122 {
8123 arm_ccfsm_state += 2;
8124 return \"\";
8125 }
5db468b7 8126 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8127 }"
a2cd141b 8128 [(set_attr "type" "load1")
755eb2b4 8129 (set_attr "length" "12")
0d66636f 8130 (set_attr "predicable" "yes")]
cffb2a26 8131)
9c08d1fa 8132
f7fbdd4a 8133(define_insn "*cond_return"
9c08d1fa 8134 [(set (pc)
8fa3ba89 8135 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8136 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8137 (return)
8138 (pc)))]
cffb2a26 8139 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8140 "*
8fa3ba89 8141 {
8142 if (arm_ccfsm_state == 2)
8143 {
8144 arm_ccfsm_state += 2;
8145 return \"\";
8146 }
8147 return output_return_instruction (operands[0], TRUE, FALSE);
8148 }"
8149 [(set_attr "conds" "use")
755eb2b4 8150 (set_attr "length" "12")
a2cd141b 8151 (set_attr "type" "load1")]
8fa3ba89 8152)
9c08d1fa 8153
f7fbdd4a 8154(define_insn "*cond_return_inverted"
9c08d1fa 8155 [(set (pc)
8fa3ba89 8156 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8157 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8158 (pc)
8159 (return)))]
cffb2a26 8160 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8161 "*
8fa3ba89 8162 {
8163 if (arm_ccfsm_state == 2)
8164 {
8165 arm_ccfsm_state += 2;
8166 return \"\";
8167 }
8168 return output_return_instruction (operands[0], TRUE, TRUE);
8169 }"
8170 [(set_attr "conds" "use")
37a1317b 8171 (set_attr "length" "12")
a2cd141b 8172 (set_attr "type" "load1")]
8fa3ba89 8173)
9c08d1fa 8174
68121397 8175;; Generate a sequence of instructions to determine if the processor is
8176;; in 26-bit or 32-bit mode, and return the appropriate return address
8177;; mask.
8178
8179(define_expand "return_addr_mask"
8180 [(set (match_dup 1)
8181 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8182 (const_int 0)))
8183 (set (match_operand:SI 0 "s_register_operand" "")
8184 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8185 (const_int -1)
8186 (const_int 67108860)))] ; 0x03fffffc
8187 "TARGET_ARM"
8188 "
62eddbd4 8189 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8190 ")
8191
8192(define_insn "*check_arch2"
8193 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8194 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8195 (const_int 0)))]
8196 "TARGET_ARM"
8197 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8198 [(set_attr "length" "8")
8199 (set_attr "conds" "set")]
8200)
8201
9c08d1fa 8202;; Call subroutine returning any type.
8203
8204(define_expand "untyped_call"
8205 [(parallel [(call (match_operand 0 "" "")
8206 (const_int 0))
8207 (match_operand 1 "" "")
8208 (match_operand 2 "" "")])]
ccd90aaa 8209 "TARGET_EITHER"
9c08d1fa 8210 "
215b30b3 8211 {
8212 int i;
ccd90aaa 8213 rtx par = gen_rtx_PARALLEL (VOIDmode,
8214 rtvec_alloc (XVECLEN (operands[2], 0)));
8215 rtx addr = gen_reg_rtx (Pmode);
8216 rtx mem;
8217 int size = 0;
9c08d1fa 8218
ccd90aaa 8219 emit_move_insn (addr, XEXP (operands[1], 0));
8220 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8221
215b30b3 8222 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8223 {
ccd90aaa 8224 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8225
ccd90aaa 8226 /* Default code only uses r0 as a return value, but we could
8227 be using anything up to 4 registers. */
8228 if (REGNO (src) == R0_REGNUM)
8229 src = gen_rtx_REG (TImode, R0_REGNUM);
8230
8231 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8232 GEN_INT (size));
8233 size += GET_MODE_SIZE (GET_MODE (src));
8234 }
8235
8236 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8237 const0_rtx));
8238
8239 size = 0;
8240
8241 for (i = 0; i < XVECLEN (par, 0); i++)
8242 {
8243 HOST_WIDE_INT offset = 0;
8244 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8245
8246 if (size != 0)
8247 emit_move_insn (addr, plus_constant (addr, size));
8248
8249 mem = change_address (mem, GET_MODE (reg), NULL);
8250 if (REGNO (reg) == R0_REGNUM)
8251 {
8252 /* On thumb we have to use a write-back instruction. */
320ea44d 8253 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8254 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8255 size = TARGET_ARM ? 16 : 0;
8256 }
8257 else
8258 {
8259 emit_move_insn (mem, reg);
8260 size = GET_MODE_SIZE (GET_MODE (reg));
8261 }
215b30b3 8262 }
9c08d1fa 8263
215b30b3 8264 /* The optimizer does not know that the call sets the function value
8265 registers we stored in the result block. We avoid problems by
8266 claiming that all hard registers are used and clobbered at this
8267 point. */
8268 emit_insn (gen_blockage ());
8269
8270 DONE;
8271 }"
8272)
9c08d1fa 8273
ccd90aaa 8274(define_expand "untyped_return"
8275 [(match_operand:BLK 0 "memory_operand" "")
8276 (match_operand 1 "" "")]
8277 "TARGET_EITHER"
8278 "
8279 {
8280 int i;
8281 rtx addr = gen_reg_rtx (Pmode);
8282 rtx mem;
8283 int size = 0;
8284
8285 emit_move_insn (addr, XEXP (operands[0], 0));
8286 mem = change_address (operands[0], BLKmode, addr);
8287
8288 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8289 {
8290 HOST_WIDE_INT offset = 0;
8291 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8292
8293 if (size != 0)
8294 emit_move_insn (addr, plus_constant (addr, size));
8295
8296 mem = change_address (mem, GET_MODE (reg), NULL);
8297 if (REGNO (reg) == R0_REGNUM)
8298 {
8299 /* On thumb we have to use a write-back instruction. */
320ea44d 8300 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8301 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8302 size = TARGET_ARM ? 16 : 0;
8303 }
8304 else
8305 {
8306 emit_move_insn (reg, mem);
8307 size = GET_MODE_SIZE (GET_MODE (reg));
8308 }
8309 }
8310
8311 /* Emit USE insns before the return. */
8312 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8313 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8314
8315 /* Construct the return. */
8316 expand_naked_return ();
8317
8318 DONE;
8319 }"
8320)
8321
9c08d1fa 8322;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8323;; all of memory. This blocks insns from being moved across this point.
8324
8325(define_insn "blockage"
e1159bbe 8326 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8327 "TARGET_EITHER"
9c08d1fa 8328 ""
cffb2a26 8329 [(set_attr "length" "0")
8330 (set_attr "type" "block")]
8331)
9c08d1fa 8332
f7fbdd4a 8333(define_expand "casesi"
8334 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8335 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8336 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8337 (match_operand:SI 3 "" "") ; table label
8338 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8339 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8340 "
215b30b3 8341 {
e6ac8414 8342 enum insn_code code;
215b30b3 8343 if (operands[1] != const0_rtx)
8344 {
e6ac8414 8345 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8346
215b30b3 8347 emit_insn (gen_addsi3 (reg, operands[0],
8348 GEN_INT (-INTVAL (operands[1]))));
8349 operands[0] = reg;
8350 }
9c08d1fa 8351
25f905c2 8352 if (TARGET_ARM)
e6ac8414 8353 code = CODE_FOR_arm_casesi_internal;
3db2019b 8354 else if (TARGET_THUMB1)
e6ac8414 8355 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8356 else if (flag_pic)
e6ac8414 8357 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8358 else
e6ac8414 8359 code = CODE_FOR_thumb2_casesi_internal;
8360
8361 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8362 operands[2] = force_reg (SImode, operands[2]);
8363
8364 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8365 operands[3], operands[4]));
215b30b3 8366 DONE;
8367 }"
8368)
f7fbdd4a 8369
f082f1c4 8370;; The USE in this pattern is needed to tell flow analysis that this is
8371;; a CASESI insn. It has no other purpose.
25f905c2 8372(define_insn "arm_casesi_internal"
f082f1c4 8373 [(parallel [(set (pc)
8374 (if_then_else
8375 (leu (match_operand:SI 0 "s_register_operand" "r")
8376 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8377 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8378 (label_ref (match_operand 2 "" ""))))
8379 (label_ref (match_operand 3 "" ""))))
bd5b4116 8380 (clobber (reg:CC CC_REGNUM))
f082f1c4 8381 (use (label_ref (match_dup 2)))])]
cffb2a26 8382 "TARGET_ARM"
f7fbdd4a 8383 "*
0d66636f 8384 if (flag_pic)
8385 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8386 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8387 "
8388 [(set_attr "conds" "clob")
8389 (set_attr "length" "12")]
8390)
9c08d1fa 8391
e6ac8414 8392(define_expand "thumb1_casesi_internal_pic"
8393 [(match_operand:SI 0 "s_register_operand" "")
8394 (match_operand:SI 1 "thumb1_cmp_operand" "")
8395 (match_operand 2 "" "")
8396 (match_operand 3 "" "")]
3db2019b 8397 "TARGET_THUMB1"
e6ac8414 8398 {
8399 rtx reg0;
8400 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8401 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8402 operands[3]));
8403 reg0 = gen_rtx_REG (SImode, 0);
8404 emit_move_insn (reg0, operands[0]);
8405 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8406 DONE;
8407 }
8408)
8409
8410(define_insn "thumb1_casesi_dispatch"
8411 [(parallel [(set (pc) (unspec [(reg:SI 0)
8412 (label_ref (match_operand 0 "" ""))
8413;; (label_ref (match_operand 1 "" ""))
8414]
8415 UNSPEC_THUMB1_CASESI))
8416 (clobber (reg:SI IP_REGNUM))
8417 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8418 "TARGET_THUMB1"
e6ac8414 8419 "* return thumb1_output_casesi(operands);"
8420 [(set_attr "length" "4")]
8421)
8422
cffb2a26 8423(define_expand "indirect_jump"
9c08d1fa 8424 [(set (pc)
cffb2a26 8425 (match_operand:SI 0 "s_register_operand" ""))]
8426 "TARGET_EITHER"
25f905c2 8427 "
8428 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8429 address and use bx. */
8430 if (TARGET_THUMB2)
8431 {
8432 rtx tmp;
8433 tmp = gen_reg_rtx (SImode);
8434 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8435 operands[0] = tmp;
8436 }
8437 "
cffb2a26 8438)
8439
f1039640 8440;; NB Never uses BX.
cffb2a26 8441(define_insn "*arm_indirect_jump"
8442 [(set (pc)
8443 (match_operand:SI 0 "s_register_operand" "r"))]
8444 "TARGET_ARM"
8445 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8446 [(set_attr "predicable" "yes")]
cffb2a26 8447)
9c08d1fa 8448
f7fbdd4a 8449(define_insn "*load_indirect_jump"
9c08d1fa 8450 [(set (pc)
8451 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8452 "TARGET_ARM"
8453 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8454 [(set_attr "type" "load1")
61a2d04c 8455 (set_attr "pool_range" "4096")
8456 (set_attr "neg_pool_range" "4084")
0d66636f 8457 (set_attr "predicable" "yes")]
cffb2a26 8458)
8459
f1039640 8460;; NB Never uses BX.
25f905c2 8461(define_insn "*thumb1_indirect_jump"
cffb2a26 8462 [(set (pc)
8463 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8464 "TARGET_THUMB1"
cffb2a26 8465 "mov\\tpc, %0"
8466 [(set_attr "conds" "clob")
8467 (set_attr "length" "2")]
8468)
8469
9c08d1fa 8470\f
8471;; Misc insns
8472
8473(define_insn "nop"
8474 [(const_int 0)]
cffb2a26 8475 "TARGET_EITHER"
8476 "*
25f905c2 8477 if (TARGET_UNIFIED_ASM)
8478 return \"nop\";
cffb2a26 8479 if (TARGET_ARM)
8480 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8481 return \"mov\\tr8, r8\";
8482 "
8483 [(set (attr "length")
8484 (if_then_else (eq_attr "is_thumb" "yes")
8485 (const_int 2)
8486 (const_int 4)))]
8487)
8488
9c08d1fa 8489\f
8490;; Patterns to allow combination of arithmetic, cond code and shifts
8491
f7fbdd4a 8492(define_insn "*arith_shiftsi"
d5d4dc8d 8493 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8494 (match_operator:SI 1 "shiftable_operator"
8495 [(match_operator:SI 3 "shift_operator"
d5d4dc8d 8496 [(match_operand:SI 4 "s_register_operand" "r,r")
8497 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8498 (match_operand:SI 2 "s_register_operand" "rk,rk")]))]
8499 "TARGET_32BIT"
6c4c2133 8500 "%i1%?\\t%0, %2, %4%S3"
344495ea 8501 [(set_attr "predicable" "yes")
331beb1a 8502 (set_attr "shift" "4")
d5d4dc8d 8503 (set_attr "arch" "32,a")
8504 ;; We have to make sure to disable the second alternative if
8505 ;; the shift_operator is MULT, since otherwise the insn will
8506 ;; also match a multiply_accumulate pattern and validate_change
8507 ;; will allow a replacement of the constant with a register
8508 ;; despite the checks done in shift_operator.
8509 (set_attr_alternative "insn_enabled"
8510 [(const_string "yes")
8511 (if_then_else
8512 (match_operand:SI 3 "mult_operator" "")
8513 (const_string "no") (const_string "yes"))])
8514 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8515
d7863cfe 8516(define_split
8517 [(set (match_operand:SI 0 "s_register_operand" "")
8518 (match_operator:SI 1 "shiftable_operator"
8519 [(match_operator:SI 2 "shiftable_operator"
8520 [(match_operator:SI 3 "shift_operator"
8521 [(match_operand:SI 4 "s_register_operand" "")
8522 (match_operand:SI 5 "reg_or_int_operand" "")])
8523 (match_operand:SI 6 "s_register_operand" "")])
8524 (match_operand:SI 7 "arm_rhs_operand" "")]))
8525 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8526 "TARGET_32BIT"
d7863cfe 8527 [(set (match_dup 8)
8528 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8529 (match_dup 6)]))
8530 (set (match_dup 0)
8531 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8532 "")
8533
f7fbdd4a 8534(define_insn "*arith_shiftsi_compare0"
bd5b4116 8535 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8536 (compare:CC_NOOV
8537 (match_operator:SI 1 "shiftable_operator"
8538 [(match_operator:SI 3 "shift_operator"
8539 [(match_operand:SI 4 "s_register_operand" "r,r")
8540 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8541 (match_operand:SI 2 "s_register_operand" "r,r")])
8542 (const_int 0)))
8543 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8544 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8545 (match_dup 2)]))]
d5d4dc8d 8546 "TARGET_32BIT"
25f905c2 8547 "%i1%.\\t%0, %2, %4%S3"
344495ea 8548 [(set_attr "conds" "set")
331beb1a 8549 (set_attr "shift" "4")
d5d4dc8d 8550 (set_attr "arch" "32,a")
8551 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8552
f7fbdd4a 8553(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8554 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8555 (compare:CC_NOOV
8556 (match_operator:SI 1 "shiftable_operator"
8557 [(match_operator:SI 3 "shift_operator"
8558 [(match_operand:SI 4 "s_register_operand" "r,r")
8559 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8560 (match_operand:SI 2 "s_register_operand" "r,r")])
8561 (const_int 0)))
8562 (clobber (match_scratch:SI 0 "=r,r"))]
8563 "TARGET_32BIT"
25f905c2 8564 "%i1%.\\t%0, %2, %4%S3"
344495ea 8565 [(set_attr "conds" "set")
331beb1a 8566 (set_attr "shift" "4")
d5d4dc8d 8567 (set_attr "arch" "32,a")
8568 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8569
f7fbdd4a 8570(define_insn "*sub_shiftsi"
d5d4dc8d 8571 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8572 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8573 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8574 [(match_operand:SI 3 "s_register_operand" "r,r")
8575 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8576 "TARGET_32BIT"
6c4c2133 8577 "sub%?\\t%0, %1, %3%S2"
344495ea 8578 [(set_attr "predicable" "yes")
331beb1a 8579 (set_attr "shift" "3")
d5d4dc8d 8580 (set_attr "arch" "32,a")
8581 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8582
f7fbdd4a 8583(define_insn "*sub_shiftsi_compare0"
bd5b4116 8584 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8585 (compare:CC_NOOV
d5d4dc8d 8586 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8587 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8588 [(match_operand:SI 3 "s_register_operand" "r,r")
8589 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8590 (const_int 0)))
d5d4dc8d 8591 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8592 (minus:SI (match_dup 1)
8593 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8594 "TARGET_32BIT"
25f905c2 8595 "sub%.\\t%0, %1, %3%S2"
344495ea 8596 [(set_attr "conds" "set")
a2cd141b 8597 (set_attr "shift" "3")
d5d4dc8d 8598 (set_attr "arch" "32,a")
8599 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8600
f7fbdd4a 8601(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8602 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8603 (compare:CC_NOOV
d5d4dc8d 8604 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8605 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8606 [(match_operand:SI 3 "s_register_operand" "r,r")
8607 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8608 (const_int 0)))
d5d4dc8d 8609 (clobber (match_scratch:SI 0 "=r,r"))]
8610 "TARGET_32BIT"
25f905c2 8611 "sub%.\\t%0, %1, %3%S2"
344495ea 8612 [(set_attr "conds" "set")
a2cd141b 8613 (set_attr "shift" "3")
d5d4dc8d 8614 (set_attr "arch" "32,a")
8615 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8616\f
8617
f7fbdd4a 8618(define_insn "*and_scc"
9c08d1fa 8619 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8620 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8621 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8622 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8623 "TARGET_ARM"
e2348bcb 8624 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8625 [(set_attr "conds" "use")
d2a518d1 8626 (set_attr "insn" "mov")
8fa3ba89 8627 (set_attr "length" "8")]
8628)
9c08d1fa 8629
f7fbdd4a 8630(define_insn "*ior_scc"
9c08d1fa 8631 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8632 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8633 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8634 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8635 "TARGET_ARM"
e2348bcb 8636 "@
899850b0 8637 orr%d2\\t%0, %1, #1
8638 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8639 [(set_attr "conds" "use")
8640 (set_attr "length" "4,8")]
8641)
9c08d1fa 8642
2df9477b 8643; A series of splitters for the compare_scc pattern below. Note that
8644; order is important.
8645(define_split
8646 [(set (match_operand:SI 0 "s_register_operand" "")
8647 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8648 (const_int 0)))
8649 (clobber (reg:CC CC_REGNUM))]
8650 "TARGET_32BIT && reload_completed"
8651 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8652
8653(define_split
8654 [(set (match_operand:SI 0 "s_register_operand" "")
8655 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8656 (const_int 0)))
8657 (clobber (reg:CC CC_REGNUM))]
8658 "TARGET_32BIT && reload_completed"
8659 [(set (match_dup 0) (not:SI (match_dup 1)))
8660 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8661
8662(define_split
8663 [(set (match_operand:SI 0 "s_register_operand" "")
8664 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8665 (const_int 0)))
8666 (clobber (reg:CC CC_REGNUM))]
8667 "TARGET_32BIT && reload_completed"
8668 [(parallel
080c0b9a 8669 [(set (reg:CC CC_REGNUM)
8670 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8671 (set (match_dup 0)
8672 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8673 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8674 (set (match_dup 0) (const_int 0)))])
8675
8676(define_split
8677 [(set (match_operand:SI 0 "s_register_operand" "")
8678 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8679 (match_operand:SI 2 "const_int_operand" "")))
8680 (clobber (reg:CC CC_REGNUM))]
8681 "TARGET_32BIT && reload_completed"
8682 [(parallel
8683 [(set (reg:CC CC_REGNUM)
8684 (compare:CC (match_dup 1) (match_dup 2)))
8685 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8686 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8687 (set (match_dup 0) (const_int 1)))]
8688{
8689 operands[3] = GEN_INT (-INTVAL (operands[2]));
8690})
8691
8692(define_split
8693 [(set (match_operand:SI 0 "s_register_operand" "")
8694 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8695 (match_operand:SI 2 "arm_add_operand" "")))
8696 (clobber (reg:CC CC_REGNUM))]
8697 "TARGET_32BIT && reload_completed"
8698 [(parallel
8699 [(set (reg:CC_NOOV CC_REGNUM)
8700 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8701 (const_int 0)))
8702 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8703 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8704 (set (match_dup 0) (const_int 1)))])
8705
8706(define_insn_and_split "*compare_scc"
5565501b 8707 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8708 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8709 [(match_operand:SI 2 "s_register_operand" "r,r")
8710 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8711 (clobber (reg:CC CC_REGNUM))]
2df9477b 8712 "TARGET_32BIT"
8713 "#"
8714 "&& reload_completed"
8715 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8716 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8717 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8718{
8719 rtx tmp1;
8720 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8721 operands[2], operands[3]);
8722 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8723
2df9477b 8724 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8725
2df9477b 8726 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8727 if (mode == CCFPmode || mode == CCFPEmode)
8728 rc = reverse_condition_maybe_unordered (rc);
8729 else
8730 rc = reverse_condition (rc);
8731 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8732})
9c08d1fa 8733
080c0b9a 8734;; Attempt to improve the sequence generated by the compare_scc splitters
8735;; not to use conditional execution.
8736(define_peephole2
8737 [(set (reg:CC CC_REGNUM)
8738 (compare:CC (match_operand:SI 1 "register_operand" "")
8739 (match_operand:SI 2 "arm_rhs_operand" "")))
8740 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8741 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8742 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8743 (set (match_dup 0) (const_int 1)))
8744 (match_scratch:SI 3 "r")]
8745 "TARGET_32BIT"
8746 [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
8747 (parallel
8748 [(set (reg:CC CC_REGNUM)
8749 (compare:CC (const_int 0) (match_dup 3)))
8750 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8751 (set (match_dup 0)
8752 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8753 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
8754
f7fbdd4a 8755(define_insn "*cond_move"
9c08d1fa 8756 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8757 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8758 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8759 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8760 (const_int 0)])
8761 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8762 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8763 "TARGET_ARM"
9c08d1fa 8764 "*
8fa3ba89 8765 if (GET_CODE (operands[3]) == NE)
8766 {
8767 if (which_alternative != 1)
8768 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8769 if (which_alternative != 0)
8770 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8771 return \"\";
8772 }
8773 if (which_alternative != 0)
8774 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8775 if (which_alternative != 1)
8776 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8777 return \"\";
8778 "
8779 [(set_attr "conds" "use")
d2a518d1 8780 (set_attr "insn" "mov")
8fa3ba89 8781 (set_attr "length" "4,4,8")]
8782)
9c08d1fa 8783
f7fbdd4a 8784(define_insn "*cond_arith"
9c08d1fa 8785 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8786 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8787 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8788 [(match_operand:SI 2 "s_register_operand" "r,r")
8789 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8790 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8791 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8792 "TARGET_ARM"
9c08d1fa 8793 "*
8fa3ba89 8794 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8795 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8796
8fa3ba89 8797 output_asm_insn (\"cmp\\t%2, %3\", operands);
8798 if (GET_CODE (operands[5]) == AND)
8799 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8800 else if (GET_CODE (operands[5]) == MINUS)
8801 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8802 else if (which_alternative != 0)
8803 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8804 return \"%i5%d4\\t%0, %1, #1\";
8805 "
8806 [(set_attr "conds" "clob")
8807 (set_attr "length" "12")]
8808)
9c08d1fa 8809
f7fbdd4a 8810(define_insn "*cond_sub"
9c08d1fa 8811 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8812 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8813 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8814 [(match_operand:SI 2 "s_register_operand" "r,r")
8815 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8816 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8817 "TARGET_ARM"
9c08d1fa 8818 "*
8fa3ba89 8819 output_asm_insn (\"cmp\\t%2, %3\", operands);
8820 if (which_alternative != 0)
8821 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8822 return \"sub%d4\\t%0, %1, #1\";
8823 "
8824 [(set_attr "conds" "clob")
8825 (set_attr "length" "8,12")]
8826)
9c08d1fa 8827
25f905c2 8828;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 8829(define_insn "*cmp_ite0"
cffb2a26 8830 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8831 (compare
8832 (if_then_else:SI
8fa3ba89 8833 (match_operator 4 "arm_comparison_operator"
aea4c774 8834 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8835 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8836 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8837 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8838 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8839 (const_int 0))
8840 (const_int 0)))]
cffb2a26 8841 "TARGET_ARM"
9c08d1fa 8842 "*
aea4c774 8843 {
8fa3ba89 8844 static const char * const opcodes[4][2] =
8845 {
8846 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8847 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8848 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8849 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8850 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8851 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8852 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8853 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8854 };
8855 int swap =
8856 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8857
8858 return opcodes[which_alternative][swap];
8859 }"
8860 [(set_attr "conds" "set")
8861 (set_attr "length" "8")]
8862)
9c08d1fa 8863
aea4c774 8864(define_insn "*cmp_ite1"
cffb2a26 8865 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8866 (compare
8867 (if_then_else:SI
8fa3ba89 8868 (match_operator 4 "arm_comparison_operator"
aea4c774 8869 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8870 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8871 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8872 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8873 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8874 (const_int 1))
8875 (const_int 0)))]
cffb2a26 8876 "TARGET_ARM"
9c08d1fa 8877 "*
9c08d1fa 8878 {
215b30b3 8879 static const char * const opcodes[4][2] =
8880 {
8881 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8882 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8883 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8884 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8885 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8886 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8887 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8888 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8889 };
8890 int swap =
8891 comparison_dominates_p (GET_CODE (operands[5]),
8892 reverse_condition (GET_CODE (operands[4])));
8893
8894 return opcodes[which_alternative][swap];
8895 }"
8fa3ba89 8896 [(set_attr "conds" "set")
8897 (set_attr "length" "8")]
8898)
9c08d1fa 8899
f6c53574 8900(define_insn "*cmp_and"
8901 [(set (match_operand 6 "dominant_cc_register" "")
8902 (compare
8903 (and:SI
8904 (match_operator 4 "arm_comparison_operator"
8905 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8906 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8907 (match_operator:SI 5 "arm_comparison_operator"
8908 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8909 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8910 (const_int 0)))]
8911 "TARGET_ARM"
8912 "*
8913 {
35823b64 8914 static const char *const opcodes[4][2] =
f6c53574 8915 {
8916 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8917 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8918 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8919 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8920 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8921 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8922 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8923 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8924 };
8925 int swap =
8926 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8927
8928 return opcodes[which_alternative][swap];
8929 }"
8930 [(set_attr "conds" "set")
8931 (set_attr "predicable" "no")
8932 (set_attr "length" "8")]
8933)
8934
8935(define_insn "*cmp_ior"
8936 [(set (match_operand 6 "dominant_cc_register" "")
8937 (compare
8938 (ior:SI
8939 (match_operator 4 "arm_comparison_operator"
8940 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8941 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8942 (match_operator:SI 5 "arm_comparison_operator"
8943 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8944 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8945 (const_int 0)))]
8946 "TARGET_ARM"
8947 "*
8948{
35823b64 8949 static const char *const opcodes[4][2] =
f6c53574 8950 {
8951 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8952 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8953 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8954 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8955 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8956 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8957 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8958 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8959 };
8960 int swap =
8961 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8962
8963 return opcodes[which_alternative][swap];
8964}
8965"
8966 [(set_attr "conds" "set")
8967 (set_attr "length" "8")]
8968)
8969
3c5afce6 8970(define_insn_and_split "*ior_scc_scc"
8971 [(set (match_operand:SI 0 "s_register_operand" "=r")
8972 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8973 [(match_operand:SI 1 "s_register_operand" "r")
8974 (match_operand:SI 2 "arm_add_operand" "rIL")])
8975 (match_operator:SI 6 "arm_comparison_operator"
8976 [(match_operand:SI 4 "s_register_operand" "r")
8977 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8978 (clobber (reg:CC CC_REGNUM))]
8979 "TARGET_ARM
8980 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8981 != CCmode)"
8982 "#"
8983 "TARGET_ARM && reload_completed"
8984 [(set (match_dup 7)
8985 (compare
8986 (ior:SI
8987 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8988 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8989 (const_int 0)))
8990 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8991 "operands[7]
8992 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8993 DOM_CC_X_OR_Y),
601f584c 8994 CC_REGNUM);"
8995 [(set_attr "conds" "clob")
8996 (set_attr "length" "16")])
8997
8998; If the above pattern is followed by a CMP insn, then the compare is
8999; redundant, since we can rework the conditional instruction that follows.
9000(define_insn_and_split "*ior_scc_scc_cmp"
9001 [(set (match_operand 0 "dominant_cc_register" "")
9002 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9003 [(match_operand:SI 1 "s_register_operand" "r")
9004 (match_operand:SI 2 "arm_add_operand" "rIL")])
9005 (match_operator:SI 6 "arm_comparison_operator"
9006 [(match_operand:SI 4 "s_register_operand" "r")
9007 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9008 (const_int 0)))
9009 (set (match_operand:SI 7 "s_register_operand" "=r")
9010 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9011 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9012 "TARGET_ARM"
9013 "#"
9014 "TARGET_ARM && reload_completed"
9015 [(set (match_dup 0)
9016 (compare
9017 (ior:SI
9018 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9019 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9020 (const_int 0)))
9021 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9022 ""
9023 [(set_attr "conds" "set")
9024 (set_attr "length" "16")])
3c5afce6 9025
9026(define_insn_and_split "*and_scc_scc"
9027 [(set (match_operand:SI 0 "s_register_operand" "=r")
9028 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9029 [(match_operand:SI 1 "s_register_operand" "r")
9030 (match_operand:SI 2 "arm_add_operand" "rIL")])
9031 (match_operator:SI 6 "arm_comparison_operator"
9032 [(match_operand:SI 4 "s_register_operand" "r")
9033 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9034 (clobber (reg:CC CC_REGNUM))]
9035 "TARGET_ARM
9036 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9037 != CCmode)"
9038 "#"
601f584c 9039 "TARGET_ARM && reload_completed
9040 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9041 != CCmode)"
3c5afce6 9042 [(set (match_dup 7)
9043 (compare
9044 (and:SI
9045 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9046 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9047 (const_int 0)))
9048 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9049 "operands[7]
9050 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9051 DOM_CC_X_AND_Y),
601f584c 9052 CC_REGNUM);"
9053 [(set_attr "conds" "clob")
9054 (set_attr "length" "16")])
9055
9056; If the above pattern is followed by a CMP insn, then the compare is
9057; redundant, since we can rework the conditional instruction that follows.
9058(define_insn_and_split "*and_scc_scc_cmp"
9059 [(set (match_operand 0 "dominant_cc_register" "")
9060 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9061 [(match_operand:SI 1 "s_register_operand" "r")
9062 (match_operand:SI 2 "arm_add_operand" "rIL")])
9063 (match_operator:SI 6 "arm_comparison_operator"
9064 [(match_operand:SI 4 "s_register_operand" "r")
9065 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9066 (const_int 0)))
9067 (set (match_operand:SI 7 "s_register_operand" "=r")
9068 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9069 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9070 "TARGET_ARM"
9071 "#"
9072 "TARGET_ARM && reload_completed"
9073 [(set (match_dup 0)
9074 (compare
9075 (and:SI
9076 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9077 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9078 (const_int 0)))
9079 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9080 ""
9081 [(set_attr "conds" "set")
9082 (set_attr "length" "16")])
9083
9084;; If there is no dominance in the comparison, then we can still save an
9085;; instruction in the AND case, since we can know that the second compare
9086;; need only zero the value if false (if true, then the value is already
9087;; correct).
9088(define_insn_and_split "*and_scc_scc_nodom"
9089 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9090 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9091 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9092 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9093 (match_operator:SI 6 "arm_comparison_operator"
9094 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9095 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9096 (clobber (reg:CC CC_REGNUM))]
9097 "TARGET_ARM
9098 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9099 == CCmode)"
9100 "#"
9101 "TARGET_ARM && reload_completed"
9102 [(parallel [(set (match_dup 0)
9103 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9104 (clobber (reg:CC CC_REGNUM))])
9105 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9106 (set (match_dup 0)
9107 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9108 (match_dup 0)
9109 (const_int 0)))]
9110 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9111 operands[4], operands[5]),
9112 CC_REGNUM);
9113 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9114 operands[5]);"
9115 [(set_attr "conds" "clob")
9116 (set_attr "length" "20")])
3c5afce6 9117
3a0bdee0 9118(define_split
9119 [(set (reg:CC_NOOV CC_REGNUM)
9120 (compare:CC_NOOV (ior:SI
9121 (and:SI (match_operand:SI 0 "s_register_operand" "")
9122 (const_int 1))
b0694be0 9123 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9124 [(match_operand:SI 2 "s_register_operand" "")
9125 (match_operand:SI 3 "arm_add_operand" "")]))
9126 (const_int 0)))
9127 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9128 "TARGET_ARM"
9129 [(set (match_dup 4)
9130 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9131 (match_dup 0)))
9132 (set (reg:CC_NOOV CC_REGNUM)
9133 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9134 (const_int 0)))]
9135 "")
9136
9137(define_split
9138 [(set (reg:CC_NOOV CC_REGNUM)
9139 (compare:CC_NOOV (ior:SI
b0694be0 9140 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9141 [(match_operand:SI 2 "s_register_operand" "")
9142 (match_operand:SI 3 "arm_add_operand" "")])
9143 (and:SI (match_operand:SI 0 "s_register_operand" "")
9144 (const_int 1)))
9145 (const_int 0)))
9146 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9147 "TARGET_ARM"
9148 [(set (match_dup 4)
9149 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9150 (match_dup 0)))
9151 (set (reg:CC_NOOV CC_REGNUM)
9152 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9153 (const_int 0)))]
9154 "")
25f905c2 9155;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9156
f7fbdd4a 9157(define_insn "*negscc"
9c08d1fa 9158 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9159 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9160 [(match_operand:SI 1 "s_register_operand" "r")
9161 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9162 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9163 "TARGET_ARM"
9c08d1fa 9164 "*
2ca2ec2e 9165 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9166 return \"mov\\t%0, %1, asr #31\";
9167
9c08d1fa 9168 if (GET_CODE (operands[3]) == NE)
e2348bcb 9169 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9170
e2348bcb 9171 output_asm_insn (\"cmp\\t%1, %2\", operands);
9172 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9173 return \"mvn%d3\\t%0, #0\";
215b30b3 9174 "
8fa3ba89 9175 [(set_attr "conds" "clob")
9176 (set_attr "length" "12")]
9177)
9c08d1fa 9178
9179(define_insn "movcond"
9180 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9181 (if_then_else:SI
8fa3ba89 9182 (match_operator 5 "arm_comparison_operator"
5565501b 9183 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9184 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9185 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9186 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9187 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9188 "TARGET_ARM"
9c08d1fa 9189 "*
9190 if (GET_CODE (operands[5]) == LT
9191 && (operands[4] == const0_rtx))
9192 {
5565501b 9193 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9194 {
9c08d1fa 9195 if (operands[2] == const0_rtx)
e2348bcb 9196 return \"and\\t%0, %1, %3, asr #31\";
9197 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9198 }
9199 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9200 {
9c08d1fa 9201 if (operands[1] == const0_rtx)
e2348bcb 9202 return \"bic\\t%0, %2, %3, asr #31\";
9203 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9204 }
9205 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9206 are constants. */
9c08d1fa 9207 }
e2348bcb 9208
9c08d1fa 9209 if (GET_CODE (operands[5]) == GE
9210 && (operands[4] == const0_rtx))
9211 {
9212 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9213 {
9c08d1fa 9214 if (operands[2] == const0_rtx)
e2348bcb 9215 return \"bic\\t%0, %1, %3, asr #31\";
9216 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9217 }
9218 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9219 {
9c08d1fa 9220 if (operands[1] == const0_rtx)
e2348bcb 9221 return \"and\\t%0, %2, %3, asr #31\";
9222 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9223 }
9224 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9225 are constants. */
9c08d1fa 9226 }
9227 if (GET_CODE (operands[4]) == CONST_INT
9228 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9229 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9230 else
e2348bcb 9231 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9232 if (which_alternative != 0)
e2348bcb 9233 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9234 if (which_alternative != 1)
e2348bcb 9235 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9236 return \"\";
215b30b3 9237 "
8fa3ba89 9238 [(set_attr "conds" "clob")
9239 (set_attr "length" "8,8,12")]
9240)
9c08d1fa 9241
25f905c2 9242;; ??? The patterns below need checking for Thumb-2 usefulness.
9243
8a18b90c 9244(define_insn "*ifcompare_plus_move"
9245 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9246 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9247 [(match_operand:SI 4 "s_register_operand" "r,r")
9248 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9249 (plus:SI
9250 (match_operand:SI 2 "s_register_operand" "r,r")
9251 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9252 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9253 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9254 "TARGET_ARM"
8a18b90c 9255 "#"
8fa3ba89 9256 [(set_attr "conds" "clob")
9257 (set_attr "length" "8,12")]
9258)
8a18b90c 9259
9260(define_insn "*if_plus_move"
129a2fe4 9261 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9262 (if_then_else:SI
8fa3ba89 9263 (match_operator 4 "arm_comparison_operator"
8a18b90c 9264 [(match_operand 5 "cc_register" "") (const_int 0)])
9265 (plus:SI
129a2fe4 9266 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9267 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9268 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9269 "TARGET_ARM"
8a18b90c 9270 "@
9271 add%d4\\t%0, %2, %3
9272 sub%d4\\t%0, %2, #%n3
9273 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9274 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9275 [(set_attr "conds" "use")
9276 (set_attr "length" "4,4,8,8")
9277 (set_attr "type" "*,*,*,*")]
9278)
8a18b90c 9279
9280(define_insn "*ifcompare_move_plus"
5565501b 9281 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9282 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9283 [(match_operand:SI 4 "s_register_operand" "r,r")
9284 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9285 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9286 (plus:SI
9287 (match_operand:SI 2 "s_register_operand" "r,r")
9288 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9289 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9290 "TARGET_ARM"
8a18b90c 9291 "#"
8fa3ba89 9292 [(set_attr "conds" "clob")
9293 (set_attr "length" "8,12")]
9294)
8a18b90c 9295
9296(define_insn "*if_move_plus"
129a2fe4 9297 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9298 (if_then_else:SI
8fa3ba89 9299 (match_operator 4 "arm_comparison_operator"
8a18b90c 9300 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9301 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9302 (plus:SI
129a2fe4 9303 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9304 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9305 "TARGET_ARM"
8a18b90c 9306 "@
9307 add%D4\\t%0, %2, %3
9308 sub%D4\\t%0, %2, #%n3
9309 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9310 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9311 [(set_attr "conds" "use")
9312 (set_attr "length" "4,4,8,8")
9313 (set_attr "type" "*,*,*,*")]
9314)
8a18b90c 9315
9316(define_insn "*ifcompare_arith_arith"
9317 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9318 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9319 [(match_operand:SI 5 "s_register_operand" "r")
9320 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9321 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9322 [(match_operand:SI 1 "s_register_operand" "r")
9323 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9324 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9325 [(match_operand:SI 3 "s_register_operand" "r")
9326 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9327 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9328 "TARGET_ARM"
8a18b90c 9329 "#"
8fa3ba89 9330 [(set_attr "conds" "clob")
9331 (set_attr "length" "12")]
9332)
9c08d1fa 9333
8a18b90c 9334(define_insn "*if_arith_arith"
9335 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9336 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9337 [(match_operand 8 "cc_register" "") (const_int 0)])
9338 (match_operator:SI 6 "shiftable_operator"
9339 [(match_operand:SI 1 "s_register_operand" "r")
9340 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9341 (match_operator:SI 7 "shiftable_operator"
9342 [(match_operand:SI 3 "s_register_operand" "r")
9343 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9344 "TARGET_ARM"
8a18b90c 9345 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9346 [(set_attr "conds" "use")
9347 (set_attr "length" "8")]
9348)
8a18b90c 9349
f7fbdd4a 9350(define_insn "*ifcompare_arith_move"
9c08d1fa 9351 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9352 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9353 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9354 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9355 (match_operator:SI 7 "shiftable_operator"
9356 [(match_operand:SI 4 "s_register_operand" "r,r")
9357 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9358 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9359 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9360 "TARGET_ARM"
9c08d1fa 9361 "*
9c08d1fa 9362 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9363 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9364 everything is in registers then we can do this in two instructions. */
9c08d1fa 9365 if (operands[3] == const0_rtx
9366 && GET_CODE (operands[7]) != AND
9367 && GET_CODE (operands[5]) == REG
9368 && GET_CODE (operands[1]) == REG
9369 && REGNO (operands[1]) == REGNO (operands[4])
9370 && REGNO (operands[4]) != REGNO (operands[0]))
9371 {
9372 if (GET_CODE (operands[6]) == LT)
40dbec34 9373 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9374 else if (GET_CODE (operands[6]) == GE)
40dbec34 9375 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9376 }
9377 if (GET_CODE (operands[3]) == CONST_INT
9378 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9379 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9380 else
e2348bcb 9381 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9382 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9383 if (which_alternative != 0)
129a2fe4 9384 return \"mov%D6\\t%0, %1\";
9c08d1fa 9385 return \"\";
215b30b3 9386 "
8fa3ba89 9387 [(set_attr "conds" "clob")
9388 (set_attr "length" "8,12")]
9389)
9c08d1fa 9390
8a18b90c 9391(define_insn "*if_arith_move"
129a2fe4 9392 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9393 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9394 [(match_operand 6 "cc_register" "") (const_int 0)])
9395 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9396 [(match_operand:SI 2 "s_register_operand" "r,r")
9397 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9398 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9399 "TARGET_ARM"
8a18b90c 9400 "@
9401 %I5%d4\\t%0, %2, %3
129a2fe4 9402 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9403 [(set_attr "conds" "use")
9404 (set_attr "length" "4,8")
9405 (set_attr "type" "*,*")]
9406)
8a18b90c 9407
f7fbdd4a 9408(define_insn "*ifcompare_move_arith"
9c08d1fa 9409 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9410 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9411 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9412 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9413 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9414 (match_operator:SI 7 "shiftable_operator"
9415 [(match_operand:SI 2 "s_register_operand" "r,r")
9416 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9417 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9418 "TARGET_ARM"
9c08d1fa 9419 "*
9c08d1fa 9420 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9421 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9422 everything is in registers then we can do this in two instructions */
9423 if (operands[5] == const0_rtx
9424 && GET_CODE (operands[7]) != AND
9425 && GET_CODE (operands[3]) == REG
9426 && GET_CODE (operands[1]) == REG
9427 && REGNO (operands[1]) == REGNO (operands[2])
9428 && REGNO (operands[2]) != REGNO (operands[0]))
9429 {
9430 if (GET_CODE (operands[6]) == GE)
40dbec34 9431 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9432 else if (GET_CODE (operands[6]) == LT)
40dbec34 9433 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9434 }
40dbec34 9435
9c08d1fa 9436 if (GET_CODE (operands[5]) == CONST_INT
9437 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9438 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9439 else
e2348bcb 9440 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9441
9c08d1fa 9442 if (which_alternative != 0)
129a2fe4 9443 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9444 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9445 "
8fa3ba89 9446 [(set_attr "conds" "clob")
9447 (set_attr "length" "8,12")]
9448)
9c08d1fa 9449
8a18b90c 9450(define_insn "*if_move_arith"
129a2fe4 9451 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9452 (if_then_else:SI
8fa3ba89 9453 (match_operator 4 "arm_comparison_operator"
8a18b90c 9454 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9455 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9456 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9457 [(match_operand:SI 2 "s_register_operand" "r,r")
9458 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9459 "TARGET_ARM"
8a18b90c 9460 "@
9461 %I5%D4\\t%0, %2, %3
129a2fe4 9462 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9463 [(set_attr "conds" "use")
9464 (set_attr "length" "4,8")
9465 (set_attr "type" "*,*")]
9466)
8a18b90c 9467
9468(define_insn "*ifcompare_move_not"
9c08d1fa 9469 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9470 (if_then_else:SI
8fa3ba89 9471 (match_operator 5 "arm_comparison_operator"
8a18b90c 9472 [(match_operand:SI 3 "s_register_operand" "r,r")
9473 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9474 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9475 (not:SI
9476 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9477 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9478 "TARGET_ARM"
8a18b90c 9479 "#"
8fa3ba89 9480 [(set_attr "conds" "clob")
9481 (set_attr "length" "8,12")]
9482)
9c08d1fa 9483
8a18b90c 9484(define_insn "*if_move_not"
9485 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9486 (if_then_else:SI
8fa3ba89 9487 (match_operator 4 "arm_comparison_operator"
8a18b90c 9488 [(match_operand 3 "cc_register" "") (const_int 0)])
9489 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9490 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9491 "TARGET_ARM"
8a18b90c 9492 "@
9493 mvn%D4\\t%0, %2
9494 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9495 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9496 [(set_attr "conds" "use")
d2a518d1 9497 (set_attr "insn" "mvn")
8fa3ba89 9498 (set_attr "length" "4,8,8")]
9499)
8a18b90c 9500
9501(define_insn "*ifcompare_not_move"
9c08d1fa 9502 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9503 (if_then_else:SI
8fa3ba89 9504 (match_operator 5 "arm_comparison_operator"
8a18b90c 9505 [(match_operand:SI 3 "s_register_operand" "r,r")
9506 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9507 (not:SI
9508 (match_operand:SI 2 "s_register_operand" "r,r"))
9509 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9510 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9511 "TARGET_ARM"
8a18b90c 9512 "#"
8fa3ba89 9513 [(set_attr "conds" "clob")
9514 (set_attr "length" "8,12")]
9515)
9c08d1fa 9516
8a18b90c 9517(define_insn "*if_not_move"
9518 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9519 (if_then_else:SI
8fa3ba89 9520 (match_operator 4 "arm_comparison_operator"
8a18b90c 9521 [(match_operand 3 "cc_register" "") (const_int 0)])
9522 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9523 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9524 "TARGET_ARM"
8a18b90c 9525 "@
9526 mvn%d4\\t%0, %2
9527 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9528 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9529 [(set_attr "conds" "use")
d2a518d1 9530 (set_attr "insn" "mvn")
8fa3ba89 9531 (set_attr "length" "4,8,8")]
9532)
8a18b90c 9533
9534(define_insn "*ifcompare_shift_move"
9c08d1fa 9535 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9536 (if_then_else:SI
8fa3ba89 9537 (match_operator 6 "arm_comparison_operator"
8a18b90c 9538 [(match_operand:SI 4 "s_register_operand" "r,r")
9539 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9540 (match_operator:SI 7 "shift_operator"
9541 [(match_operand:SI 2 "s_register_operand" "r,r")
9542 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9543 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9544 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9545 "TARGET_ARM"
9c08d1fa 9546 "#"
8fa3ba89 9547 [(set_attr "conds" "clob")
9548 (set_attr "length" "8,12")]
9549)
9c08d1fa 9550
8a18b90c 9551(define_insn "*if_shift_move"
9552 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9553 (if_then_else:SI
8fa3ba89 9554 (match_operator 5 "arm_comparison_operator"
8a18b90c 9555 [(match_operand 6 "cc_register" "") (const_int 0)])
9556 (match_operator:SI 4 "shift_operator"
9557 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9558 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9559 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9560 "TARGET_ARM"
5565501b 9561 "@
8a18b90c 9562 mov%d5\\t%0, %2%S4
9563 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9564 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9565 [(set_attr "conds" "use")
331beb1a 9566 (set_attr "shift" "2")
a2cd141b 9567 (set_attr "length" "4,8,8")
d2a518d1 9568 (set_attr "insn" "mov")
a2cd141b 9569 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9570 (const_string "alu_shift")
9571 (const_string "alu_shift_reg")))]
8fa3ba89 9572)
5565501b 9573
8a18b90c 9574(define_insn "*ifcompare_move_shift"
9575 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9576 (if_then_else:SI
8fa3ba89 9577 (match_operator 6 "arm_comparison_operator"
8a18b90c 9578 [(match_operand:SI 4 "s_register_operand" "r,r")
9579 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9580 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9581 (match_operator:SI 7 "shift_operator"
8a18b90c 9582 [(match_operand:SI 2 "s_register_operand" "r,r")
9583 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9584 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9585 "TARGET_ARM"
8a18b90c 9586 "#"
8fa3ba89 9587 [(set_attr "conds" "clob")
9588 (set_attr "length" "8,12")]
9589)
5565501b 9590
8a18b90c 9591(define_insn "*if_move_shift"
9592 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9593 (if_then_else:SI
8fa3ba89 9594 (match_operator 5 "arm_comparison_operator"
8a18b90c 9595 [(match_operand 6 "cc_register" "") (const_int 0)])
9596 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9597 (match_operator:SI 4 "shift_operator"
9598 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9599 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9600 "TARGET_ARM"
5565501b 9601 "@
8a18b90c 9602 mov%D5\\t%0, %2%S4
9603 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9604 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9605 [(set_attr "conds" "use")
331beb1a 9606 (set_attr "shift" "2")
a2cd141b 9607 (set_attr "length" "4,8,8")
d2a518d1 9608 (set_attr "insn" "mov")
a2cd141b 9609 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9610 (const_string "alu_shift")
9611 (const_string "alu_shift_reg")))]
8fa3ba89 9612)
9c08d1fa 9613
f7fbdd4a 9614(define_insn "*ifcompare_shift_shift"
8a18b90c 9615 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9616 (if_then_else:SI
8fa3ba89 9617 (match_operator 7 "arm_comparison_operator"
8a18b90c 9618 [(match_operand:SI 5 "s_register_operand" "r")
9619 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9620 (match_operator:SI 8 "shift_operator"
8a18b90c 9621 [(match_operand:SI 1 "s_register_operand" "r")
9622 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9623 (match_operator:SI 9 "shift_operator"
8a18b90c 9624 [(match_operand:SI 3 "s_register_operand" "r")
9625 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9626 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9627 "TARGET_ARM"
8a18b90c 9628 "#"
8fa3ba89 9629 [(set_attr "conds" "clob")
9630 (set_attr "length" "12")]
9631)
9c08d1fa 9632
8a18b90c 9633(define_insn "*if_shift_shift"
9634 [(set (match_operand:SI 0 "s_register_operand" "=r")
9635 (if_then_else:SI
8fa3ba89 9636 (match_operator 5 "arm_comparison_operator"
8a18b90c 9637 [(match_operand 8 "cc_register" "") (const_int 0)])
9638 (match_operator:SI 6 "shift_operator"
9639 [(match_operand:SI 1 "s_register_operand" "r")
9640 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9641 (match_operator:SI 7 "shift_operator"
9642 [(match_operand:SI 3 "s_register_operand" "r")
9643 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9644 "TARGET_ARM"
8a18b90c 9645 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9646 [(set_attr "conds" "use")
331beb1a 9647 (set_attr "shift" "1")
a2cd141b 9648 (set_attr "length" "8")
d2a518d1 9649 (set_attr "insn" "mov")
a2cd141b 9650 (set (attr "type") (if_then_else
9651 (and (match_operand 2 "const_int_operand" "")
9652 (match_operand 4 "const_int_operand" ""))
9653 (const_string "alu_shift")
9654 (const_string "alu_shift_reg")))]
8fa3ba89 9655)
8a18b90c 9656
f7fbdd4a 9657(define_insn "*ifcompare_not_arith"
8a18b90c 9658 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9659 (if_then_else:SI
8fa3ba89 9660 (match_operator 6 "arm_comparison_operator"
8a18b90c 9661 [(match_operand:SI 4 "s_register_operand" "r")
9662 (match_operand:SI 5 "arm_add_operand" "rIL")])
9663 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9664 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9665 [(match_operand:SI 2 "s_register_operand" "r")
9666 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9667 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9668 "TARGET_ARM"
8a18b90c 9669 "#"
8fa3ba89 9670 [(set_attr "conds" "clob")
9671 (set_attr "length" "12")]
9672)
9c08d1fa 9673
8a18b90c 9674(define_insn "*if_not_arith"
9675 [(set (match_operand:SI 0 "s_register_operand" "=r")
9676 (if_then_else:SI
8fa3ba89 9677 (match_operator 5 "arm_comparison_operator"
8a18b90c 9678 [(match_operand 4 "cc_register" "") (const_int 0)])
9679 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9680 (match_operator:SI 6 "shiftable_operator"
9681 [(match_operand:SI 2 "s_register_operand" "r")
9682 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9683 "TARGET_ARM"
8a18b90c 9684 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9685 [(set_attr "conds" "use")
d2a518d1 9686 (set_attr "insn" "mvn")
8fa3ba89 9687 (set_attr "length" "8")]
9688)
8a18b90c 9689
9690(define_insn "*ifcompare_arith_not"
9691 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9692 (if_then_else:SI
8fa3ba89 9693 (match_operator 6 "arm_comparison_operator"
8a18b90c 9694 [(match_operand:SI 4 "s_register_operand" "r")
9695 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9696 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9697 [(match_operand:SI 2 "s_register_operand" "r")
9698 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9699 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9700 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9701 "TARGET_ARM"
8a18b90c 9702 "#"
8fa3ba89 9703 [(set_attr "conds" "clob")
9704 (set_attr "length" "12")]
9705)
9c08d1fa 9706
8a18b90c 9707(define_insn "*if_arith_not"
9708 [(set (match_operand:SI 0 "s_register_operand" "=r")
9709 (if_then_else:SI
8fa3ba89 9710 (match_operator 5 "arm_comparison_operator"
8a18b90c 9711 [(match_operand 4 "cc_register" "") (const_int 0)])
9712 (match_operator:SI 6 "shiftable_operator"
9713 [(match_operand:SI 2 "s_register_operand" "r")
9714 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9715 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9716 "TARGET_ARM"
8a18b90c 9717 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9718 [(set_attr "conds" "use")
d2a518d1 9719 (set_attr "insn" "mvn")
8fa3ba89 9720 (set_attr "length" "8")]
9721)
8a18b90c 9722
f7fbdd4a 9723(define_insn "*ifcompare_neg_move"
8a18b90c 9724 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9725 (if_then_else:SI
8fa3ba89 9726 (match_operator 5 "arm_comparison_operator"
8a18b90c 9727 [(match_operand:SI 3 "s_register_operand" "r,r")
9728 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9729 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9730 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9731 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9732 "TARGET_ARM"
8a18b90c 9733 "#"
8fa3ba89 9734 [(set_attr "conds" "clob")
9735 (set_attr "length" "8,12")]
9736)
8a18b90c 9737
9738(define_insn "*if_neg_move"
9739 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9740 (if_then_else:SI
8fa3ba89 9741 (match_operator 4 "arm_comparison_operator"
8a18b90c 9742 [(match_operand 3 "cc_register" "") (const_int 0)])
9743 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9744 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9745 "TARGET_ARM"
8a18b90c 9746 "@
9747 rsb%d4\\t%0, %2, #0
9748 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9749 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9750 [(set_attr "conds" "use")
9751 (set_attr "length" "4,8,8")]
9752)
9c08d1fa 9753
f7fbdd4a 9754(define_insn "*ifcompare_move_neg"
8a18b90c 9755 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9756 (if_then_else:SI
8fa3ba89 9757 (match_operator 5 "arm_comparison_operator"
8a18b90c 9758 [(match_operand:SI 3 "s_register_operand" "r,r")
9759 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9760 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9761 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9762 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9763 "TARGET_ARM"
8a18b90c 9764 "#"
8fa3ba89 9765 [(set_attr "conds" "clob")
9766 (set_attr "length" "8,12")]
9767)
8a18b90c 9768
9769(define_insn "*if_move_neg"
9770 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9771 (if_then_else:SI
8fa3ba89 9772 (match_operator 4 "arm_comparison_operator"
8a18b90c 9773 [(match_operand 3 "cc_register" "") (const_int 0)])
9774 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9775 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9776 "TARGET_ARM"
8a18b90c 9777 "@
9778 rsb%D4\\t%0, %2, #0
9779 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9780 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9781 [(set_attr "conds" "use")
9782 (set_attr "length" "4,8,8")]
9783)
9c08d1fa 9784
f7fbdd4a 9785(define_insn "*arith_adjacentmem"
9c08d1fa 9786 [(set (match_operand:SI 0 "s_register_operand" "=r")
9787 (match_operator:SI 1 "shiftable_operator"
9788 [(match_operand:SI 2 "memory_operand" "m")
9789 (match_operand:SI 3 "memory_operand" "m")]))
9790 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9791 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9792 "*
215b30b3 9793 {
9794 rtx ldm[3];
9795 rtx arith[4];
94dee231 9796 rtx base_reg;
9797 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9798
215b30b3 9799 if (REGNO (operands[0]) > REGNO (operands[4]))
9800 {
9801 ldm[1] = operands[4];
9802 ldm[2] = operands[0];
9803 }
9804 else
9805 {
9806 ldm[1] = operands[0];
9807 ldm[2] = operands[4];
9808 }
94dee231 9809
9810 base_reg = XEXP (operands[2], 0);
9811
9812 if (!REG_P (base_reg))
9813 {
9814 val1 = INTVAL (XEXP (base_reg, 1));
9815 base_reg = XEXP (base_reg, 0);
9816 }
9817
9818 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9819 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9820
215b30b3 9821 arith[0] = operands[0];
9822 arith[3] = operands[1];
94dee231 9823
215b30b3 9824 if (val1 < val2)
9825 {
9826 arith[1] = ldm[1];
9827 arith[2] = ldm[2];
9828 }
9829 else
9830 {
9831 arith[1] = ldm[2];
9832 arith[2] = ldm[1];
9833 }
94dee231 9834
9835 ldm[0] = base_reg;
9836 if (val1 !=0 && val2 != 0)
215b30b3 9837 {
cdb1295a 9838 rtx ops[3];
9839
94dee231 9840 if (val1 == 4 || val2 == 4)
9841 /* Other val must be 8, since we know they are adjacent and neither
9842 is zero. */
25f905c2 9843 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 9844 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 9845 {
94dee231 9846 ldm[0] = ops[0] = operands[4];
9847 ops[1] = base_reg;
9848 ops[2] = GEN_INT (val1);
9849 output_add_immediate (ops);
9850 if (val1 < val2)
25f905c2 9851 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 9852 else
25f905c2 9853 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 9854 }
cdb1295a 9855 else
9856 {
9857 /* Offset is out of range for a single add, so use two ldr. */
9858 ops[0] = ldm[1];
9859 ops[1] = base_reg;
9860 ops[2] = GEN_INT (val1);
9861 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9862 ops[0] = ldm[2];
9863 ops[2] = GEN_INT (val2);
9864 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9865 }
215b30b3 9866 }
94dee231 9867 else if (val1 != 0)
215b30b3 9868 {
215b30b3 9869 if (val1 < val2)
25f905c2 9870 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9871 else
25f905c2 9872 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9873 }
9874 else
9875 {
215b30b3 9876 if (val1 < val2)
25f905c2 9877 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9878 else
25f905c2 9879 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9880 }
9881 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9882 return \"\";
9883 }"
9884 [(set_attr "length" "12")
9885 (set_attr "predicable" "yes")
a2cd141b 9886 (set_attr "type" "load1")]
215b30b3 9887)
9c08d1fa 9888
9c08d1fa 9889; This pattern is never tried by combine, so do it as a peephole
9890
a0f94409 9891(define_peephole2
372575c7 9892 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9893 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9894 (set (reg:CC CC_REGNUM)
aea4c774 9895 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9896 "TARGET_ARM"
a0f94409 9897 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9898 (set (match_dup 0) (match_dup 1))])]
9899 ""
0d66636f 9900)
9c08d1fa 9901
9c08d1fa 9902(define_split
9903 [(set (match_operand:SI 0 "s_register_operand" "")
9904 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9905 (const_int 0))
8fa3ba89 9906 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9907 [(match_operand:SI 3 "s_register_operand" "")
9908 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9909 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9910 "TARGET_ARM"
9c08d1fa 9911 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9912 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9913 (match_dup 5)))]
215b30b3 9914 ""
9915)
9c08d1fa 9916
aea4c774 9917;; This split can be used because CC_Z mode implies that the following
9918;; branch will be an equality, or an unsigned inequality, so the sign
9919;; extension is not needed.
9c08d1fa 9920
aea4c774 9921(define_split
bd5b4116 9922 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9923 (compare:CC_Z
9924 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9925 (const_int 24))
aea4c774 9926 (match_operand 1 "const_int_operand" "")))
9927 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9928 "TARGET_ARM
9929 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9930 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9931 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9932 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9933 "
9c08d1fa 9934 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9935 "
9936)
25f905c2 9937;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 9938
87b22bf7 9939(define_expand "prologue"
9940 [(clobber (const_int 0))]
cffb2a26 9941 "TARGET_EITHER"
25f905c2 9942 "if (TARGET_32BIT)
cffb2a26 9943 arm_expand_prologue ();
9944 else
25f905c2 9945 thumb1_expand_prologue ();
87b22bf7 9946 DONE;
cffb2a26 9947 "
9948)
87b22bf7 9949
56d27660 9950(define_expand "epilogue"
4c44712e 9951 [(clobber (const_int 0))]
cffb2a26 9952 "TARGET_EITHER"
56d27660 9953 "
18d50ae6 9954 if (crtl->calls_eh_return)
4c44712e 9955 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 9956 if (TARGET_THUMB1)
9957 thumb1_expand_epilogue ();
cffb2a26 9958 else if (USE_RETURN_INSN (FALSE))
56d27660 9959 {
9960 emit_jump_insn (gen_return ());
9961 DONE;
9962 }
cffb2a26 9963 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9964 gen_rtvec (1,
9965 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9966 VUNSPEC_EPILOGUE));
cffb2a26 9967 DONE;
9968 "
9969)
56d27660 9970
ef5651d0 9971;; Note - although unspec_volatile's USE all hard registers,
9972;; USEs are ignored after relaod has completed. Thus we need
9973;; to add an unspec of the link register to ensure that flow
9974;; does not think that it is unused by the sibcall branch that
9975;; will replace the standard function epilogue.
1c494086 9976(define_insn "sibcall_epilogue"
ef5651d0 9977 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9978 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 9979 "TARGET_32BIT"
1c494086 9980 "*
ffc9d00c 9981 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9982 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9983 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9984 "
9985;; Length is absolute worst case
9986 [(set_attr "length" "44")
defc47cf 9987 (set_attr "type" "block")
9988 ;; We don't clobber the conditions, but the potential length of this
9989 ;; operation is sufficient to make conditionalizing the sequence
9990 ;; unlikely to be profitable.
9991 (set_attr "conds" "clob")]
1c494086 9992)
9993
cffb2a26 9994(define_insn "*epilogue_insns"
e1159bbe 9995 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9996 "TARGET_EITHER"
56d27660 9997 "*
25f905c2 9998 if (TARGET_32BIT)
ffc9d00c 9999 return arm_output_epilogue (NULL);
25f905c2 10000 else /* TARGET_THUMB1 */
cffb2a26 10001 return thumb_unexpanded_epilogue ();
10002 "
215b30b3 10003 ; Length is absolute worst case
cffb2a26 10004 [(set_attr "length" "44")
defc47cf 10005 (set_attr "type" "block")
10006 ;; We don't clobber the conditions, but the potential length of this
10007 ;; operation is sufficient to make conditionalizing the sequence
10008 ;; unlikely to be profitable.
10009 (set_attr "conds" "clob")]
cffb2a26 10010)
10011
10012(define_expand "eh_epilogue"
7db9af5d 10013 [(use (match_operand:SI 0 "register_operand" ""))
10014 (use (match_operand:SI 1 "register_operand" ""))
10015 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10016 "TARGET_EITHER"
10017 "
215b30b3 10018 {
10019 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10020 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10021 {
10022 rtx ra = gen_rtx_REG (Pmode, 2);
10023
10024 emit_move_insn (ra, operands[2]);
10025 operands[2] = ra;
10026 }
5cf3595a 10027 /* This is a hack -- we may have crystalized the function type too
10028 early. */
10029 cfun->machine->func_type = 0;
215b30b3 10030 }"
10031)
56d27660 10032
9c08d1fa 10033;; This split is only used during output to reduce the number of patterns
10034;; that need assembler instructions adding to them. We allowed the setting
10035;; of the conditions to be implicit during rtl generation so that
10036;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10037;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10038;; up again here.
10039
25f905c2 10040;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10041;; conditional execution sufficient?
10042
9c08d1fa 10043(define_split
10044 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10045 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10046 [(match_operand 2 "" "") (match_operand 3 "" "")])
10047 (match_dup 0)
10048 (match_operand 4 "" "")))
bd5b4116 10049 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10050 "TARGET_ARM && reload_completed"
8fa3ba89 10051 [(set (match_dup 5) (match_dup 6))
10052 (cond_exec (match_dup 7)
10053 (set (match_dup 0) (match_dup 4)))]
10054 "
10055 {
10056 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10057 operands[2], operands[3]);
10058 enum rtx_code rc = GET_CODE (operands[1]);
10059
bd5b4116 10060 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10061 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10062 if (mode == CCFPmode || mode == CCFPEmode)
10063 rc = reverse_condition_maybe_unordered (rc);
10064 else
10065 rc = reverse_condition (rc);
10066
10067 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10068 }"
10069)
10070
10071(define_split
10072 [(set (match_operand:SI 0 "s_register_operand" "")
10073 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10074 [(match_operand 2 "" "") (match_operand 3 "" "")])
10075 (match_operand 4 "" "")
10076 (match_dup 0)))
bd5b4116 10077 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10078 "TARGET_ARM && reload_completed"
8fa3ba89 10079 [(set (match_dup 5) (match_dup 6))
10080 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10081 (set (match_dup 0) (match_dup 4)))]
10082 "
10083 {
10084 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10085 operands[2], operands[3]);
10086
bd5b4116 10087 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10088 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10089 }"
10090)
10091
10092(define_split
10093 [(set (match_operand:SI 0 "s_register_operand" "")
10094 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10095 [(match_operand 2 "" "") (match_operand 3 "" "")])
10096 (match_operand 4 "" "")
10097 (match_operand 5 "" "")))
bd5b4116 10098 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10099 "TARGET_ARM && reload_completed"
8fa3ba89 10100 [(set (match_dup 6) (match_dup 7))
10101 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10102 (set (match_dup 0) (match_dup 4)))
10103 (cond_exec (match_dup 8)
10104 (set (match_dup 0) (match_dup 5)))]
10105 "
10106 {
10107 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10108 operands[2], operands[3]);
10109 enum rtx_code rc = GET_CODE (operands[1]);
10110
bd5b4116 10111 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10112 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10113 if (mode == CCFPmode || mode == CCFPEmode)
10114 rc = reverse_condition_maybe_unordered (rc);
10115 else
10116 rc = reverse_condition (rc);
10117
10118 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10119 }"
10120)
10121
cffb2a26 10122(define_split
10123 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10124 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10125 [(match_operand:SI 2 "s_register_operand" "")
10126 (match_operand:SI 3 "arm_add_operand" "")])
10127 (match_operand:SI 4 "arm_rhs_operand" "")
10128 (not:SI
10129 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10130 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10131 "TARGET_ARM && reload_completed"
cffb2a26 10132 [(set (match_dup 6) (match_dup 7))
f6c53574 10133 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10134 (set (match_dup 0) (match_dup 4)))
10135 (cond_exec (match_dup 8)
10136 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10137 "
215b30b3 10138 {
10139 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10140 operands[2], operands[3]);
f6c53574 10141 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10142
bd5b4116 10143 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10144 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10145 if (mode == CCFPmode || mode == CCFPEmode)
10146 rc = reverse_condition_maybe_unordered (rc);
10147 else
10148 rc = reverse_condition (rc);
10149
10150 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10151 }"
10152)
cffb2a26 10153
10154(define_insn "*cond_move_not"
10155 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10156 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10157 [(match_operand 3 "cc_register" "") (const_int 0)])
10158 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10159 (not:SI
10160 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10161 "TARGET_ARM"
10162 "@
10163 mvn%D4\\t%0, %2
10164 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10165 [(set_attr "conds" "use")
d2a518d1 10166 (set_attr "insn" "mvn")
0d66636f 10167 (set_attr "length" "4,8")]
10168)
cffb2a26 10169
9c08d1fa 10170;; The next two patterns occur when an AND operation is followed by a
10171;; scc insn sequence
10172
f7fbdd4a 10173(define_insn "*sign_extract_onebit"
9c08d1fa 10174 [(set (match_operand:SI 0 "s_register_operand" "=r")
10175 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10176 (const_int 1)
ed750274 10177 (match_operand:SI 2 "const_int_operand" "n")))
10178 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10179 "TARGET_ARM"
9c08d1fa 10180 "*
0d66636f 10181 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10182 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10183 return \"mvnne\\t%0, #0\";
10184 "
10185 [(set_attr "conds" "clob")
10186 (set_attr "length" "8")]
10187)
9c08d1fa 10188
f7fbdd4a 10189(define_insn "*not_signextract_onebit"
9c08d1fa 10190 [(set (match_operand:SI 0 "s_register_operand" "=r")
10191 (not:SI
10192 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10193 (const_int 1)
ed750274 10194 (match_operand:SI 2 "const_int_operand" "n"))))
10195 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10196 "TARGET_ARM"
9c08d1fa 10197 "*
0d66636f 10198 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10199 output_asm_insn (\"tst\\t%1, %2\", operands);
10200 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10201 return \"movne\\t%0, #0\";
10202 "
10203 [(set_attr "conds" "clob")
10204 (set_attr "length" "12")]
10205)
25f905c2 10206;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10207
0d66636f 10208;; Push multiple registers to the stack. Registers are in parallel (use ...)
10209;; expressions. For simplicity, the first register is also in the unspec
10210;; part.
f7fbdd4a 10211(define_insn "*push_multi"
87b22bf7 10212 [(match_parallel 2 "multi_register_push"
10213 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10214 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10215 UNSPEC_PUSH_MULT))])]
25f905c2 10216 "TARGET_32BIT"
87b22bf7 10217 "*
215b30b3 10218 {
10219 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10220
215b30b3 10221 /* For the StrongARM at least it is faster to
25f905c2 10222 use STR to store only a single register.
542d5028 10223 In Thumb mode always use push, and the assembler will pick
10224 something appropriate. */
25f905c2 10225 if (num_saves == 1 && TARGET_ARM)
215b30b3 10226 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10227 else
10228 {
10229 int i;
10230 char pattern[100];
ed593f11 10231
25f905c2 10232 if (TARGET_ARM)
10233 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10234 else
10235 strcpy (pattern, \"push\\t{%1\");
215b30b3 10236
6079f055 10237 for (i = 1; i < num_saves; i++)
215b30b3 10238 {
10239 strcat (pattern, \", %|\");
10240 strcat (pattern,
10241 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10242 }
10243
10244 strcat (pattern, \"}\");
10245 output_asm_insn (pattern, operands);
10246 }
10247
10248 return \"\";
10249 }"
10250 [(set_attr "type" "store4")]
10251)
f7fbdd4a 10252
4c58c898 10253(define_insn "stack_tie"
10254 [(set (mem:BLK (scratch))
aaa37ad6 10255 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10256 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10257 UNSPEC_PRLG_STK))]
10258 ""
10259 ""
10260 [(set_attr "length" "0")]
10261)
10262
3398e91d 10263;; Similarly for the floating point registers
7b1d2fc4 10264(define_insn "*push_fp_multi"
10265 [(match_parallel 2 "multi_register_push"
10266 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10267 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10268 UNSPEC_PUSH_MULT))])]
25f905c2 10269 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10270 "*
215b30b3 10271 {
10272 char pattern[100];
7b1d2fc4 10273
215b30b3 10274 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10275 output_asm_insn (pattern, operands);
10276 return \"\";
10277 }"
10278 [(set_attr "type" "f_store")]
10279)
7b1d2fc4 10280
f7fbdd4a 10281;; Special patterns for dealing with the constant pool
10282
cffb2a26 10283(define_insn "align_4"
e1159bbe 10284 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10285 "TARGET_EITHER"
f7fbdd4a 10286 "*
cffb2a26 10287 assemble_align (32);
f7fbdd4a 10288 return \"\";
cffb2a26 10289 "
10290)
f7fbdd4a 10291
755eb2b4 10292(define_insn "align_8"
10293 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10294 "TARGET_EITHER"
755eb2b4 10295 "*
10296 assemble_align (64);
10297 return \"\";
10298 "
10299)
10300
cffb2a26 10301(define_insn "consttable_end"
e1159bbe 10302 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10303 "TARGET_EITHER"
f7fbdd4a 10304 "*
cffb2a26 10305 making_const_table = FALSE;
f7fbdd4a 10306 return \"\";
cffb2a26 10307 "
10308)
f7fbdd4a 10309
cffb2a26 10310(define_insn "consttable_1"
e1159bbe 10311 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10312 "TARGET_THUMB1"
f7fbdd4a 10313 "*
cffb2a26 10314 making_const_table = TRUE;
09d688ff 10315 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10316 assemble_zeros (3);
f7fbdd4a 10317 return \"\";
cffb2a26 10318 "
10319 [(set_attr "length" "4")]
10320)
f7fbdd4a 10321
cffb2a26 10322(define_insn "consttable_2"
e1159bbe 10323 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10324 "TARGET_THUMB1"
f7fbdd4a 10325 "*
cffb2a26 10326 making_const_table = TRUE;
9b8516be 10327 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10328 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10329 assemble_zeros (2);
f7fbdd4a 10330 return \"\";
cffb2a26 10331 "
10332 [(set_attr "length" "4")]
10333)
10334
10335(define_insn "consttable_4"
e1159bbe 10336 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10337 "TARGET_EITHER"
10338 "*
10339 {
9b8516be 10340 rtx x = operands[0];
cffb2a26 10341 making_const_table = TRUE;
9b8516be 10342 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10343 {
10344 case MODE_FLOAT:
9b8516be 10345 if (GET_MODE (x) == HFmode)
10346 arm_emit_fp16_const (x);
10347 else
10348 {
10349 REAL_VALUE_TYPE r;
10350 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10351 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10352 }
10353 break;
cffb2a26 10354 default:
7b04c5d5 10355 /* XXX: Sometimes gcc does something really dumb and ends up with
10356 a HIGH in a constant pool entry, usually because it's trying to
10357 load into a VFP register. We know this will always be used in
10358 combination with a LO_SUM which ignores the high bits, so just
10359 strip off the HIGH. */
10360 if (GET_CODE (x) == HIGH)
10361 x = XEXP (x, 0);
9b8516be 10362 assemble_integer (x, 4, BITS_PER_WORD, 1);
10363 mark_symbol_refs_as_used (x);
cffb2a26 10364 break;
10365 }
10366 return \"\";
10367 }"
10368 [(set_attr "length" "4")]
10369)
10370
10371(define_insn "consttable_8"
e1159bbe 10372 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10373 "TARGET_EITHER"
10374 "*
10375 {
10376 making_const_table = TRUE;
10377 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10378 {
10379 case MODE_FLOAT:
10380 {
badfe841 10381 REAL_VALUE_TYPE r;
10382 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10383 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10384 break;
10385 }
10386 default:
09d688ff 10387 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10388 break;
10389 }
10390 return \"\";
10391 }"
10392 [(set_attr "length" "8")]
10393)
10394
d98a3884 10395(define_insn "consttable_16"
10396 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10397 "TARGET_EITHER"
10398 "*
10399 {
10400 making_const_table = TRUE;
10401 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10402 {
10403 case MODE_FLOAT:
10404 {
10405 REAL_VALUE_TYPE r;
10406 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10407 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10408 break;
10409 }
10410 default:
10411 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10412 break;
10413 }
10414 return \"\";
10415 }"
10416 [(set_attr "length" "16")]
10417)
10418
cffb2a26 10419;; Miscellaneous Thumb patterns
10420
fd957ef3 10421(define_expand "tablejump"
7db9af5d 10422 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10423 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10424 "TARGET_THUMB1"
fd957ef3 10425 "
10426 if (flag_pic)
10427 {
10428 /* Hopefully, CSE will eliminate this copy. */
10429 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10430 rtx reg2 = gen_reg_rtx (SImode);
10431
10432 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10433 operands[0] = reg2;
10434 }
10435 "
10436)
10437
f1039640 10438;; NB never uses BX.
25f905c2 10439(define_insn "*thumb1_tablejump"
cffb2a26 10440 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10441 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10442 "TARGET_THUMB1"
fd957ef3 10443 "mov\\t%|pc, %0"
cffb2a26 10444 [(set_attr "length" "2")]
10445)
0d66636f 10446
331beb1a 10447;; V5 Instructions,
10448
8f4be2be 10449(define_insn "clzsi2"
10450 [(set (match_operand:SI 0 "s_register_operand" "=r")
10451 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10452 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10453 "clz%?\\t%0, %1"
bcaec148 10454 [(set_attr "predicable" "yes")
10455 (set_attr "insn" "clz")])
331beb1a 10456
099ad98b 10457(define_insn "rbitsi2"
10458 [(set (match_operand:SI 0 "s_register_operand" "=r")
10459 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10460 "TARGET_32BIT && arm_arch_thumb2"
10461 "rbit%?\\t%0, %1"
10462 [(set_attr "predicable" "yes")
10463 (set_attr "insn" "clz")])
10464
10465(define_expand "ctzsi2"
10466 [(set (match_operand:SI 0 "s_register_operand" "")
10467 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10468 "TARGET_32BIT && arm_arch_thumb2"
10469 "
30191172 10470 {
10471 rtx tmp = gen_reg_rtx (SImode);
10472 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10473 emit_insn (gen_clzsi2 (operands[0], tmp));
10474 }
099ad98b 10475 DONE;
10476 "
10477)
10478
e1159bbe 10479;; V5E instructions.
331beb1a 10480
10481(define_insn "prefetch"
f4e79814 10482 [(prefetch (match_operand:SI 0 "address_operand" "p")
10483 (match_operand:SI 1 "" "")
10484 (match_operand:SI 2 "" ""))]
25f905c2 10485 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10486 "pld\\t%a0")
331beb1a 10487
0d66636f 10488;; General predication pattern
10489
10490(define_cond_exec
10491 [(match_operator 0 "arm_comparison_operator"
10492 [(match_operand 1 "cc_register" "")
10493 (const_int 0)])]
25f905c2 10494 "TARGET_32BIT"
0d66636f 10495 ""
10496)
10497
063a05c7 10498(define_insn "prologue_use"
10499 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10500 ""
10501 "%@ %0 needed for prologue"
02cfc9c9 10502 [(set_attr "length" "0")]
063a05c7 10503)
7db9af5d 10504
4c44712e 10505
10506;; Patterns for exception handling
10507
10508(define_expand "eh_return"
10509 [(use (match_operand 0 "general_operand" ""))]
10510 "TARGET_EITHER"
10511 "
10512 {
25f905c2 10513 if (TARGET_32BIT)
4c44712e 10514 emit_insn (gen_arm_eh_return (operands[0]));
10515 else
10516 emit_insn (gen_thumb_eh_return (operands[0]));
10517 DONE;
10518 }"
10519)
10520
10521;; We can't expand this before we know where the link register is stored.
10522(define_insn_and_split "arm_eh_return"
10523 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10524 VUNSPEC_EH_RETURN)
10525 (clobber (match_scratch:SI 1 "=&r"))]
10526 "TARGET_ARM"
10527 "#"
10528 "&& reload_completed"
10529 [(const_int 0)]
10530 "
10531 {
10532 arm_set_return_address (operands[0], operands[1]);
10533 DONE;
10534 }"
10535)
10536
10537(define_insn_and_split "thumb_eh_return"
10538 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10539 VUNSPEC_EH_RETURN)
10540 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10541 "TARGET_THUMB1"
4c44712e 10542 "#"
10543 "&& reload_completed"
10544 [(const_int 0)]
10545 "
10546 {
10547 thumb_set_return_address (operands[0], operands[1]);
10548 DONE;
10549 }"
10550)
10551
f655717d 10552\f
10553;; TLS support
10554
10555(define_insn "load_tp_hard"
10556 [(set (match_operand:SI 0 "register_operand" "=r")
10557 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10558 "TARGET_HARD_TP"
10559 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10560 [(set_attr "predicable" "yes")]
10561)
10562
10563;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10564(define_insn "load_tp_soft"
10565 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10566 (clobber (reg:SI LR_REGNUM))
10567 (clobber (reg:SI IP_REGNUM))
10568 (clobber (reg:CC CC_REGNUM))]
10569 "TARGET_SOFT_TP"
10570 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10571 [(set_attr "conds" "clob")]
10572)
10573
eca5c984 10574(define_insn "*arm_movtas_ze"
10575 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10576 (const_int 16)
10577 (const_int 16))
10578 (match_operand:SI 1 "const_int_operand" ""))]
10579 "TARGET_32BIT"
10580 "movt%?\t%0, %c1"
10581 [(set_attr "predicable" "yes")
10582 (set_attr "length" "4")]
10583)
10584
c0fc3696 10585(define_insn "*arm_rev"
ff82f757 10586 [(set (match_operand:SI 0 "s_register_operand" "=r")
10587 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 10588 "TARGET_32BIT && arm_arch6"
10589 "rev%?\t%0, %1"
10590 [(set_attr "predicable" "yes")
10591 (set_attr "length" "4")]
10592)
10593
10594(define_insn "*thumb1_rev"
10595 [(set (match_operand:SI 0 "s_register_operand" "=l")
10596 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10597 "TARGET_THUMB1 && arm_arch6"
10598 "rev\t%0, %1"
10599 [(set_attr "length" "2")]
ff82f757 10600)
10601
10602(define_expand "arm_legacy_rev"
10603 [(set (match_operand:SI 2 "s_register_operand" "")
10604 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10605 (const_int 16))
10606 (match_dup 1)))
10607 (set (match_dup 2)
10608 (lshiftrt:SI (match_dup 2)
10609 (const_int 8)))
10610 (set (match_operand:SI 3 "s_register_operand" "")
10611 (rotatert:SI (match_dup 1)
10612 (const_int 8)))
10613 (set (match_dup 2)
10614 (and:SI (match_dup 2)
10615 (const_int -65281)))
10616 (set (match_operand:SI 0 "s_register_operand" "")
10617 (xor:SI (match_dup 3)
10618 (match_dup 2)))]
10619 "TARGET_32BIT"
10620 ""
10621)
10622
10623;; Reuse temporaries to keep register pressure down.
10624(define_expand "thumb_legacy_rev"
10625 [(set (match_operand:SI 2 "s_register_operand" "")
10626 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10627 (const_int 24)))
10628 (set (match_operand:SI 3 "s_register_operand" "")
10629 (lshiftrt:SI (match_dup 1)
10630 (const_int 24)))
10631 (set (match_dup 3)
10632 (ior:SI (match_dup 3)
10633 (match_dup 2)))
10634 (set (match_operand:SI 4 "s_register_operand" "")
10635 (const_int 16))
10636 (set (match_operand:SI 5 "s_register_operand" "")
10637 (rotatert:SI (match_dup 1)
10638 (match_dup 4)))
10639 (set (match_dup 2)
10640 (ashift:SI (match_dup 5)
10641 (const_int 24)))
10642 (set (match_dup 5)
10643 (lshiftrt:SI (match_dup 5)
10644 (const_int 24)))
10645 (set (match_dup 5)
10646 (ior:SI (match_dup 5)
10647 (match_dup 2)))
10648 (set (match_dup 5)
10649 (rotatert:SI (match_dup 5)
10650 (match_dup 4)))
10651 (set (match_operand:SI 0 "s_register_operand" "")
10652 (ior:SI (match_dup 5)
10653 (match_dup 3)))]
10654 "TARGET_THUMB"
10655 ""
10656)
10657
10658(define_expand "bswapsi2"
10659 [(set (match_operand:SI 0 "s_register_operand" "=r")
10660 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
10661"TARGET_EITHER"
10662"
10663 if (!arm_arch6)
10664 {
10665 if (!optimize_size)
10666 {
10667 rtx op2 = gen_reg_rtx (SImode);
10668 rtx op3 = gen_reg_rtx (SImode);
10669
10670 if (TARGET_THUMB)
10671 {
10672 rtx op4 = gen_reg_rtx (SImode);
10673 rtx op5 = gen_reg_rtx (SImode);
10674
10675 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10676 op2, op3, op4, op5));
10677 }
10678 else
10679 {
10680 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10681 op2, op3));
10682 }
10683
10684 DONE;
10685 }
10686 else
10687 FAIL;
10688 }
10689 "
10690)
10691
320ea44d 10692;; Load the load/store multiple patterns
10693(include "ldmstm.md")
7db9af5d 10694;; Load the FPA co-processor patterns
10695(include "fpa.md")
10696;; Load the Maverick co-processor patterns
10697(include "cirrus.md")
d98a3884 10698;; Vector bits common to IWMMXT and Neon
10699(include "vec-common.md")
755eb2b4 10700;; Load the Intel Wireless Multimedia Extension patterns
10701(include "iwmmxt.md")
a2cd141b 10702;; Load the VFP co-processor patterns
10703(include "vfp.md")
25f905c2 10704;; Thumb-2 patterns
10705(include "thumb2.md")
d98a3884 10706;; Neon patterns
10707(include "neon.md")
06df6b17 10708;; Synchronization Primitives
10709(include "sync.md")