]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* tree.h (struct typed_tree): New.
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
7cf0dbf3 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
934a1e72 4;; Free Software Foundation, Inc.
b11cae9e 5;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 6;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 7;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 8
acf6ed70 9;; This file is part of GCC.
b11cae9e 10
acf6ed70 11;; GCC is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published
038d1e19 13;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 14;; option) any later version.
b11cae9e 15
acf6ed70 16;; GCC is distributed in the hope that it will be useful, but WITHOUT
17;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19;; License for more details.
b11cae9e 20
21;; You should have received a copy of the GNU General Public License
038d1e19 22;; along with GCC; see the file COPYING3. If not see
23;; <http://www.gnu.org/licenses/>.
b11cae9e 24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
9c08d1fa 27\f
e1159bbe 28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
ccd90aaa 33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
e1159bbe 35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
ccd90aaa 39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
e1159bbe 51
9c08d1fa 52;; UNSPEC Usage:
8a18b90c 53;; Note: sin and cos are no-longer used.
e7d6d136 54;; Unspec enumerators for Neon are defined in neon.md.
e1159bbe 55
e7d6d136 56(define_c_enum "unspec" [
57 UNSPEC_SIN ; `sin' operation (MODE_FLOAT):
58 ; operand 0 is the result,
59 ; operand 1 the parameter.
60 UNPSEC_COS ; `cos' operation (MODE_FLOAT):
61 ; operand 0 is the result,
62 ; operand 1 the parameter.
63 UNSPEC_PUSH_MULT ; `push multiple' operation:
64 ; operand 0 is the first register,
65 ; subsequent registers are in parallel (use ...)
66 ; expressions.
67 UNSPEC_PIC_SYM ; A symbol that has been treated properly for pic
68 ; usage, that is, we will add the pic_register
69 ; value to it before trying to dereference it.
70 UNSPEC_PIC_BASE ; Add PC and all but the last operand together,
71 ; The last operand is the number of a PIC_LABEL
72 ; that points at the containing instruction.
73 UNSPEC_PRLG_STK ; A special barrier that prevents frame accesses
74 ; being scheduled before the stack adjustment insn.
75 UNSPEC_PROLOGUE_USE ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
79 ; register to "use".
80 UNSPEC_CHECK_ARCH ; Set CCs to indicate 26-bit or 32-bit mode.
81 UNSPEC_WSHUFH ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 UNSPEC_WACC ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 UNSPEC_TMOVMSK ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 UNSPEC_WSAD ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 UNSPEC_WSADZ ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 UNSPEC_WMACS ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 UNSPEC_WMACU ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 UNSPEC_WMACSZ ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 UNSPEC_WMACUZ ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 UNSPEC_CLRDI ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 UNSPEC_WMADDS ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 UNSPEC_WMADDU ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 UNSPEC_TLS ; A symbol that has been treated properly for TLS usage.
94 UNSPEC_PIC_LABEL ; A label used for PIC access that does not appear in the
95 ; instruction stream.
96 UNSPEC_STACK_ALIGN ; Doubleword aligned stack pointer. Used to
97 ; generate correct unwind information.
98 UNSPEC_PIC_OFFSET ; A symbolic 12-bit OFFSET that has been treated
99 ; correctly for PIC usage.
851d9296 100 UNSPEC_GOTSYM_OFF ; The offset of the start of the GOT from a
e7d6d136 101 ; a given symbolic address.
102 UNSPEC_THUMB1_CASESI ; A Thumb1 compressed dispatch-table call.
103 UNSPEC_RBIT ; rbit operation.
104 UNSPEC_SYMBOL_OFFSET ; The offset of the start of the symbol from
105 ; another symbolic address.
106 UNSPEC_MEMORY_BARRIER ; Represent a memory barrier.
107])
e1159bbe 108
215b30b3 109;; UNSPEC_VOLATILE Usage:
e1159bbe 110
e7d6d136 111(define_c_enum "unspecv" [
112 VUNSPEC_BLOCKAGE ; `blockage' insn to prevent scheduling across an
113 ; insn in the code.
114 VUNSPEC_EPILOGUE ; `epilogue' insn, used to represent any part of the
115 ; instruction epilogue sequence that isn't expanded
116 ; into normal RTL. Used for both normal and sibcall
117 ; epilogues.
118 VUNSPEC_ALIGN ; `align' insn. Used at the head of a minipool table
119 ; for inlined constants.
120 VUNSPEC_POOL_END ; `end-of-table'. Used to mark the end of a minipool
121 ; table.
122 VUNSPEC_POOL_1 ; `pool-entry(1)'. An entry in the constant pool for
123 ; an 8-bit object.
124 VUNSPEC_POOL_2 ; `pool-entry(2)'. An entry in the constant pool for
125 ; a 16-bit object.
126 VUNSPEC_POOL_4 ; `pool-entry(4)'. An entry in the constant pool for
127 ; a 32-bit object.
128 VUNSPEC_POOL_8 ; `pool-entry(8)'. An entry in the constant pool for
129 ; a 64-bit object.
130 VUNSPEC_POOL_16 ; `pool-entry(16)'. An entry in the constant pool for
131 ; a 128-bit object.
132 VUNSPEC_TMRC ; Used by the iWMMXt TMRC instruction.
133 VUNSPEC_TMCR ; Used by the iWMMXt TMCR instruction.
134 VUNSPEC_ALIGN8 ; 8-byte alignment version of VUNSPEC_ALIGN
135 VUNSPEC_WCMP_EQ ; Used by the iWMMXt WCMPEQ instructions
136 VUNSPEC_WCMP_GTU ; Used by the iWMMXt WCMPGTU instructions
137 VUNSPEC_WCMP_GT ; Used by the iwMMXT WCMPGT instructions
138 VUNSPEC_EH_RETURN ; Use to override the return address for exception
139 ; handling.
140 VUNSPEC_SYNC_COMPARE_AND_SWAP ; Represent an atomic compare swap.
141 VUNSPEC_SYNC_LOCK ; Represent a sync_lock_test_and_set.
142 VUNSPEC_SYNC_OP ; Represent a sync_<op>
143 VUNSPEC_SYNC_NEW_OP ; Represent a sync_new_<op>
144 VUNSPEC_SYNC_OLD_OP ; Represent a sync_old_<op>
145])
b11cae9e 146\f
e1159bbe 147;;---------------------------------------------------------------------------
9c08d1fa 148;; Attributes
149
a651f34d 150;; Processor type. This is created automatically from arm-cores.def.
151(include "arm-tune.md")
152
215b30b3 153; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
154; generating ARM code. This is used to control the length of some insn
155; patterns that share the same RTL in both ARM and Thumb code.
1c494086 156(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 157
ef51b8e1 158; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
159(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
160
747b7458 161; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
162(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
163
331beb1a 164;; Operand number of an input operand that is shifted. Zero if the
165;; given instruction does not shift one of its input operands.
331beb1a 166(define_attr "shift" "" (const_int 0))
167
3d91c5d6 168; Floating Point Unit. If we only have floating point emulation, then there
169; is no point in scheduling the floating point insns. (Well, for best
170; performance we should try and group them together).
4fea7d65 171(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 172 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 173
06df6b17 174(define_attr "sync_result" "none,0,1,2,3,4,5" (const_string "none"))
175(define_attr "sync_memory" "none,0,1,2,3,4,5" (const_string "none"))
176(define_attr "sync_required_value" "none,0,1,2,3,4,5" (const_string "none"))
177(define_attr "sync_new_value" "none,0,1,2,3,4,5" (const_string "none"))
178(define_attr "sync_t1" "none,0,1,2,3,4,5" (const_string "none"))
179(define_attr "sync_t2" "none,0,1,2,3,4,5" (const_string "none"))
180(define_attr "sync_release_barrier" "yes,no" (const_string "yes"))
181(define_attr "sync_op" "none,add,sub,ior,xor,and,nand"
182 (const_string "none"))
183
094e994f 184; LENGTH of an instruction (in bytes)
06df6b17 185(define_attr "length" ""
186 (cond [(not (eq_attr "sync_memory" "none"))
187 (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
188 ] (const_int 4)))
9c08d1fa 189
d5d4dc8d 190; The architecture which supports the instruction (or alternative).
191; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
192; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
193; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
194; arm_arch6. This attribute is used to compute attribute "enabled",
195; use type "any" to enable an alternative in all cases.
a651f34d 196(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,nota8"
d5d4dc8d 197 (const_string "any"))
198
199(define_attr "arch_enabled" "no,yes"
200 (cond [(eq_attr "arch" "any")
201 (const_string "yes")
202
203 (and (eq_attr "arch" "a")
204 (ne (symbol_ref "TARGET_ARM") (const_int 0)))
205 (const_string "yes")
206
207 (and (eq_attr "arch" "t")
208 (ne (symbol_ref "TARGET_THUMB") (const_int 0)))
209 (const_string "yes")
210
211 (and (eq_attr "arch" "t1")
212 (ne (symbol_ref "TARGET_THUMB1") (const_int 0)))
213 (const_string "yes")
214
215 (and (eq_attr "arch" "t2")
216 (ne (symbol_ref "TARGET_THUMB2") (const_int 0)))
217 (const_string "yes")
218
219 (and (eq_attr "arch" "32")
220 (ne (symbol_ref "TARGET_32BIT") (const_int 0)))
221 (const_string "yes")
222
223 (and (eq_attr "arch" "v6")
224 (ne (symbol_ref "(TARGET_32BIT && arm_arch6)") (const_int 0)))
225 (const_string "yes")
226
227 (and (eq_attr "arch" "nov6")
228 (ne (symbol_ref "(TARGET_32BIT && !arm_arch6)") (const_int 0)))
a651f34d 229 (const_string "yes")
230
231 (and (eq_attr "arch" "onlya8")
232 (eq_attr "tune" "cortexa8"))
233 (const_string "yes")
234
235 (and (eq_attr "arch" "nota8")
236 (not (eq_attr "tune" "cortexa8")))
d5d4dc8d 237 (const_string "yes")]
238 (const_string "no")))
239
240; Allows an insn to disable certain alternatives for reasons other than
241; arch support.
242(define_attr "insn_enabled" "no,yes"
243 (const_string "yes"))
244
245; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 246 (define_attr "enabled" "no,yes"
247 (if_then_else (eq_attr "insn_enabled" "yes")
248 (if_then_else (eq_attr "arch_enabled" "yes")
249 (const_string "yes")
250 (const_string "no"))
251 (const_string "no")))
d5d4dc8d 252
56d27660 253; POOL_RANGE is how far away from a constant pool entry that this insn
254; can be placed. If the distance is zero, then this insn will never
255; reference the pool.
cffb2a26 256; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
257; before its address.
cde1623a 258(define_attr "arm_pool_range" "" (const_int 0))
259(define_attr "thumb2_pool_range" "" (const_int 0))
260(define_attr "arm_neg_pool_range" "" (const_int 0))
261(define_attr "thumb2_neg_pool_range" "" (const_int 0))
262
263(define_attr "pool_range" ""
264 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
265 (attr "arm_pool_range")))
266(define_attr "neg_pool_range" ""
267 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
268 (attr "arm_neg_pool_range")))
56d27660 269
215b30b3 270; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 271; If such an insn references the pool, then we have no way of knowing how,
272; so use the most conservative value for pool_range.
9c08d1fa 273(define_asm_attributes
4d7a8451 274 [(set_attr "conds" "clob")
275 (set_attr "length" "4")
276 (set_attr "pool_range" "250")])
9c08d1fa 277
a2cd141b 278;; The instruction used to implement a particular pattern. This
279;; information is used by pipeline descriptions to provide accurate
280;; scheduling information.
281
282(define_attr "insn"
934a1e72 283 "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other"
a2cd141b 284 (const_string "other"))
285
9c08d1fa 286; TYPE attribute is used to detect floating point instructions which, if
287; running on a co-processor can run in parallel with other, basic instructions
288; If write-buffer scheduling is enabled then it can also be used in the
289; scheduling of writes.
290
291; Classification of each insn
607978a1 292; Note: vfp.md has different meanings for some of these, and some further
293; types as well. See that file for details.
a2cd141b 294; alu any alu instruction that doesn't hit memory or fp
295; regs or have a shifted source operand
296; alu_shift any data instruction that doesn't hit memory or fp
297; regs, but has a source operand shifted by a constant
298; alu_shift_reg any data instruction that doesn't hit memory or fp
299; regs, but has a source operand shifted by a register value
f7fbdd4a 300; mult a multiply instruction
9c08d1fa 301; block blockage insn, this blocks all functional units
302; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 303; fdivd DFmode floating point division
304; fdivs SFmode floating point division
305; fmul Floating point multiply
306; ffmul Fast floating point multiply
307; farith Floating point arithmetic (4 cycle)
308; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 309; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 310; even on a machine with an fpa.
013b9671 311; f_fpa_load a floating point load from memory. Only for the FPA.
312; f_fpa_store a floating point store to memory. Only for the FPA.
313; f_load[sd] A single/double load from memory. Used for VFP unit.
314; f_store[sd] A single/double store to memory. Used for VFP unit.
c0e1af52 315; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 316; f_mem_r a transfer of a floating point register to a real reg via mem
317; r_mem_f the reverse of f_mem_r
318; f_2_r fast transfer float to arm (no memory needed)
319; r_2_f fast transfer arm to float
c0e1af52 320; f_cvt convert floating<->integral
a2cd141b 321; branch a branch
9c08d1fa 322; call a subroutine call
a2cd141b 323; load_byte load byte(s) from memory to arm registers
324; load1 load 1 word from memory to arm registers
325; load2 load 2 words from memory to arm registers
326; load3 load 3 words from memory to arm registers
327; load4 load 4 words from memory to arm registers
328; store store 1 word to memory from arm registers
9c08d1fa 329; store2 store 2 words
330; store3 store 3 words
a2cd141b 331; store4 store 4 (or more) words
2c6c7d8b 332; Additions for Cirrus Maverick co-processor:
333; mav_farith Floating point arithmetic (4 cycle)
334; mav_dmult Double multiplies (7 cycle)
9c08d1fa 335;
bcaec148 336
9c08d1fa 337(define_attr "type"
013b9671 338 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_fpa_load,f_fpa_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
a2cd141b 339 (if_then_else
340 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
341 (const_string "mult")
342 (const_string "alu")))
9c08d1fa 343
9888ad6d 344; Load scheduling, set from the arm_ld_sched variable
4c834714 345; initialized by arm_option_override()
9888ad6d 346(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 347
c52acdd2 348;; Classification of NEON instructions for scheduling purposes.
349;; Do not set this attribute and the "type" attribute together in
350;; any one instruction pattern.
351(define_attr "neon_type"
352 "neon_int_1,\
353 neon_int_2,\
354 neon_int_3,\
355 neon_int_4,\
356 neon_int_5,\
357 neon_vqneg_vqabs,\
358 neon_vmov,\
359 neon_vaba,\
360 neon_vsma,\
361 neon_vaba_qqq,\
362 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
363 neon_mul_qqq_8_16_32_ddd_32,\
364 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
365 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
366 neon_mla_qqq_8_16,\
367 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
368 neon_mla_qqq_32_qqd_32_scalar,\
369 neon_mul_ddd_16_scalar_32_16_long_scalar,\
370 neon_mul_qqd_32_scalar,\
371 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
372 neon_shift_1,\
373 neon_shift_2,\
374 neon_shift_3,\
375 neon_vshl_ddd,\
376 neon_vqshl_vrshl_vqrshl_qqq,\
377 neon_vsra_vrsra,\
378 neon_fp_vadd_ddd_vabs_dd,\
379 neon_fp_vadd_qqq_vabs_qq,\
380 neon_fp_vsum,\
381 neon_fp_vmul_ddd,\
382 neon_fp_vmul_qqd,\
383 neon_fp_vmla_ddd,\
384 neon_fp_vmla_qqq,\
385 neon_fp_vmla_ddd_scalar,\
386 neon_fp_vmla_qqq_scalar,\
387 neon_fp_vrecps_vrsqrts_ddd,\
388 neon_fp_vrecps_vrsqrts_qqq,\
389 neon_bp_simple,\
390 neon_bp_2cycle,\
391 neon_bp_3cycle,\
392 neon_ldr,\
393 neon_str,\
394 neon_vld1_1_2_regs,\
395 neon_vld1_3_4_regs,\
396 neon_vld2_2_regs_vld1_vld2_all_lanes,\
397 neon_vld2_4_regs,\
398 neon_vld3_vld4,\
399 neon_vst1_1_2_regs_vst2_2_regs,\
400 neon_vst1_3_4_regs,\
401 neon_vst2_4_regs_vst3_vst4,\
402 neon_vst3_vst4,\
403 neon_vld1_vld2_lane,\
404 neon_vld3_vld4_lane,\
405 neon_vst1_vst2_lane,\
406 neon_vst3_vst4_lane,\
407 neon_vld3_vld4_all_lanes,\
408 neon_mcr,\
409 neon_mcr_2_mcrr,\
410 neon_mrc,\
411 neon_mrrc,\
412 neon_ldm_2,\
413 neon_stm_2,\
414 none"
415 (const_string "none"))
416
f7fbdd4a 417; condition codes: this one is used by final_prescan_insn to speed up
418; conditionalizing instructions. It saves having to scan the rtl to see if
419; it uses or alters the condition codes.
215b30b3 420;
f7fbdd4a 421; USE means that the condition codes are used by the insn in the process of
215b30b3 422; outputting code, this means (at present) that we can't use the insn in
423; inlined branches
424;
f7fbdd4a 425; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 426; well defined manner.
427;
f7fbdd4a 428; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 429; they are altered at all
430;
ad6d3e2a 431; UNCONDITIONAL means the instruction can not be conditionally executed and
432; that the instruction does not use or alter the condition codes.
c52acdd2 433;
ad6d3e2a 434; NOCOND means that the instruction does not use or alter the condition
435; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 436
b0694be0 437(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 438 (if_then_else
439 (ior (eq_attr "is_thumb1" "yes")
440 (eq_attr "type" "call"))
c1a66faf 441 (const_string "clob")
c52acdd2 442 (if_then_else (eq_attr "neon_type" "none")
443 (const_string "nocond")
444 (const_string "unconditional"))))
f7fbdd4a 445
215b30b3 446; Predicable means that the insn can be conditionally executed based on
447; an automatically added predicate (additional patterns are generated by
448; gen...). We default to 'no' because no Thumb patterns match this rule
449; and not all ARM patterns do.
0d66636f 450(define_attr "predicable" "no,yes" (const_string "no"))
451
129a2fe4 452; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
453; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 454; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 455; affect the schedule).
74a71f7d 456(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 457
215b30b3 458; WRITE_CONFLICT implies that a read following an unrelated write is likely
459; to stall the processor. Used with model_wbuf above.
9c08d1fa 460(define_attr "write_conflict" "no,yes"
461 (if_then_else (eq_attr "type"
013b9671 462 "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 463 (const_string "yes")
464 (const_string "no")))
465
215b30b3 466; Classify the insns into those that take one cycle and those that take more
467; than one on the main cpu execution unit.
f7fbdd4a 468(define_attr "core_cycles" "single,multi"
469 (if_then_else (eq_attr "type"
a2cd141b 470 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 471 (const_string "single")
472 (const_string "multi")))
473
cffb2a26 474;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 475;; distant label. Only applicable to Thumb code.
cffb2a26 476(define_attr "far_jump" "yes,no" (const_string "no"))
477
d51f92df 478
25f905c2 479;; The number of machine instructions this pattern expands to.
480;; Used for Thumb-2 conditional execution.
481(define_attr "ce_count" "" (const_int 1))
482
d51f92df 483;;---------------------------------------------------------------------------
fd781bb2 484;; Mode iterators
d51f92df 485
3de0dec6 486(include "iterators.md")
03770691 487
d51f92df 488;;---------------------------------------------------------------------------
489;; Predicates
490
9c9db025 491(include "predicates.md")
234f6557 492(include "constraints.md")
9c9db025 493
a2cd141b 494;;---------------------------------------------------------------------------
495;; Pipeline descriptions
215b30b3 496
e3879fd0 497(define_attr "tune_cortexr4" "yes,no"
498 (const (if_then_else
499 (eq_attr "tune" "cortexr4,cortexr4f")
500 (const_string "yes")
501 (const_string "no"))))
502
a2cd141b 503;; True if the generic scheduling description should be used.
504
505(define_attr "generic_sched" "yes,no"
2546d93a 506 (const (if_then_else
0e266d06 507 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexm4")
2546d93a 508 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 509 (const_string "no")
510 (const_string "yes"))))
511
c0e1af52 512(define_attr "generic_vfp" "yes,no"
513 (const (if_then_else
514 (and (eq_attr "fpu" "vfp")
2546d93a 515 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 516 (eq_attr "tune_cortexr4" "no"))
c0e1af52 517 (const_string "yes")
518 (const_string "no"))))
519
a2cd141b 520(include "arm-generic.md")
521(include "arm926ejs.md")
c0e1af52 522(include "arm1020e.md")
a2cd141b 523(include "arm1026ejs.md")
524(include "arm1136jfs.md")
0e266d06 525(include "fa526.md")
526(include "fa606te.md")
527(include "fa626te.md")
528(include "fmp626.md")
529(include "fa726te.md")
3f1e069f 530(include "cortex-a5.md")
bcaec148 531(include "cortex-a8.md")
036068af 532(include "cortex-a9.md")
934a1e72 533(include "cortex-r4.md")
e3879fd0 534(include "cortex-r4f.md")
2546d93a 535(include "cortex-m4.md")
536(include "cortex-m4-fpu.md")
55e3ada8 537(include "vfp11.md")
3586df96 538
9c08d1fa 539\f
215b30b3 540;;---------------------------------------------------------------------------
e1159bbe 541;; Insn patterns
542;;
a0f94409 543;; Addition insns.
215b30b3 544
9c08d1fa 545;; Note: For DImode insns, there is normally no reason why operands should
546;; not be in the same register, what we don't want is for something being
547;; written to partially overlap something that is an input.
7d57ec45 548;; Cirrus 64bit additions should not be split because we have a native
549;; 64bit addition instructions.
9c08d1fa 550
cffb2a26 551(define_expand "adddi3"
552 [(parallel
215b30b3 553 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 554 (plus:DI (match_operand:DI 1 "s_register_operand" "")
555 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 556 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 557 "TARGET_EITHER"
558 "
a2cd141b 559 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 560 {
561 if (!cirrus_fp_register (operands[0], DImode))
562 operands[0] = force_reg (DImode, operands[0]);
563 if (!cirrus_fp_register (operands[1], DImode))
564 operands[1] = force_reg (DImode, operands[1]);
565 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
566 DONE;
567 }
568
25f905c2 569 if (TARGET_THUMB1)
cffb2a26 570 {
571 if (GET_CODE (operands[1]) != REG)
bc5a93af 572 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 573 if (GET_CODE (operands[2]) != REG)
bc5a93af 574 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 575 }
576 "
577)
578
25f905c2 579(define_insn "*thumb1_adddi3"
cffb2a26 580 [(set (match_operand:DI 0 "register_operand" "=l")
581 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 582 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 583 (clobber (reg:CC CC_REGNUM))
cffb2a26 584 ]
25f905c2 585 "TARGET_THUMB1"
cffb2a26 586 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
587 [(set_attr "length" "4")]
588)
589
a0f94409 590(define_insn_and_split "*arm_adddi3"
cffb2a26 591 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 592 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
593 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 594 (clobber (reg:CC CC_REGNUM))]
94829feb 595 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 596 "#"
94829feb 597 "TARGET_32BIT && reload_completed
598 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 599 [(parallel [(set (reg:CC_C CC_REGNUM)
600 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
601 (match_dup 1)))
602 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 603 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
604 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 605 "
606 {
607 operands[3] = gen_highpart (SImode, operands[0]);
608 operands[0] = gen_lowpart (SImode, operands[0]);
609 operands[4] = gen_highpart (SImode, operands[1]);
610 operands[1] = gen_lowpart (SImode, operands[1]);
611 operands[5] = gen_highpart (SImode, operands[2]);
612 operands[2] = gen_lowpart (SImode, operands[2]);
613 }"
cffb2a26 614 [(set_attr "conds" "clob")
615 (set_attr "length" "8")]
616)
9c08d1fa 617
a0f94409 618(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 619 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
620 (plus:DI (sign_extend:DI
97499065 621 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 622 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 623 (clobber (reg:CC CC_REGNUM))]
25f905c2 624 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 625 "#"
25f905c2 626 "TARGET_32BIT && reload_completed"
a0f94409 627 [(parallel [(set (reg:CC_C CC_REGNUM)
628 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
629 (match_dup 1)))
630 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 631 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 632 (const_int 31))
080c0b9a 633 (match_dup 4))
634 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 635 "
636 {
637 operands[3] = gen_highpart (SImode, operands[0]);
638 operands[0] = gen_lowpart (SImode, operands[0]);
639 operands[4] = gen_highpart (SImode, operands[1]);
640 operands[1] = gen_lowpart (SImode, operands[1]);
641 operands[2] = gen_lowpart (SImode, operands[2]);
642 }"
215b30b3 643 [(set_attr "conds" "clob")
644 (set_attr "length" "8")]
645)
9c08d1fa 646
a0f94409 647(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 648 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
649 (plus:DI (zero_extend:DI
97499065 650 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 651 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 652 (clobber (reg:CC CC_REGNUM))]
25f905c2 653 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 654 "#"
25f905c2 655 "TARGET_32BIT && reload_completed"
a0f94409 656 [(parallel [(set (reg:CC_C CC_REGNUM)
657 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
658 (match_dup 1)))
659 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 660 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
661 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 662 "
663 {
664 operands[3] = gen_highpart (SImode, operands[0]);
665 operands[0] = gen_lowpart (SImode, operands[0]);
666 operands[4] = gen_highpart (SImode, operands[1]);
667 operands[1] = gen_lowpart (SImode, operands[1]);
668 operands[2] = gen_lowpart (SImode, operands[2]);
669 }"
cffb2a26 670 [(set_attr "conds" "clob")
671 (set_attr "length" "8")]
672)
b11cae9e 673
87b22bf7 674(define_expand "addsi3"
cffb2a26 675 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 676 (plus:SI (match_operand:SI 1 "s_register_operand" "")
677 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 678 "TARGET_EITHER"
87b22bf7 679 "
25f905c2 680 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 681 {
96f57e36 682 arm_split_constant (PLUS, SImode, NULL_RTX,
683 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 684 optimize && can_create_pseudo_p ());
87b22bf7 685 DONE;
686 }
cffb2a26 687 "
688)
87b22bf7 689
5bd751ff 690; If there is a scratch available, this will be faster than synthesizing the
a0f94409 691; addition.
692(define_peephole2
693 [(match_scratch:SI 3 "r")
372575c7 694 (set (match_operand:SI 0 "arm_general_register_operand" "")
695 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 696 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 697 "TARGET_32BIT &&
a0f94409 698 !(const_ok_for_arm (INTVAL (operands[2]))
699 || const_ok_for_arm (-INTVAL (operands[2])))
700 && const_ok_for_arm (~INTVAL (operands[2]))"
701 [(set (match_dup 3) (match_dup 2))
702 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
703 ""
704)
87b22bf7 705
2f02c19f 706;; The r/r/k alternative is required when reloading the address
707;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
708;; put the duplicated register first, and not try the commutative version.
a0f94409 709(define_insn_and_split "*arm_addsi3"
bccb5444 710 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k,r")
711 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
712 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
25f905c2 713 "TARGET_32BIT"
5565501b 714 "@
715 add%?\\t%0, %1, %2
aaa37ad6 716 add%?\\t%0, %1, %2
2f02c19f 717 add%?\\t%0, %2, %1
aaa37ad6 718 sub%?\\t%0, %1, #%n2
87b22bf7 719 sub%?\\t%0, %1, #%n2
720 #"
a3ffc315 721 "TARGET_32BIT
722 && GET_CODE (operands[2]) == CONST_INT
a0f94409 723 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 724 || const_ok_for_arm (-INTVAL (operands[2])))
725 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 726 [(clobber (const_int 0))]
727 "
96f57e36 728 arm_split_constant (PLUS, SImode, curr_insn,
729 INTVAL (operands[2]), operands[0],
a0f94409 730 operands[1], 0);
731 DONE;
732 "
2f02c19f 733 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 734 (set_attr "predicable" "yes")]
cffb2a26 735)
736
0bdb6455 737(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 738 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
739 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
740 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 741 "TARGET_THUMB1"
cffb2a26 742 "*
0d66636f 743 static const char * const asms[] =
cffb2a26 744 {
745 \"add\\t%0, %0, %2\",
746 \"sub\\t%0, %0, #%n2\",
747 \"add\\t%0, %1, %2\",
748 \"add\\t%0, %0, %2\",
749 \"add\\t%0, %0, %2\",
750 \"add\\t%0, %1, %2\",
0bdb6455 751 \"add\\t%0, %1, %2\",
752 \"#\",
bf7bc2f6 753 \"#\",
0bdb6455 754 \"#\"
cffb2a26 755 };
756 if ((which_alternative == 2 || which_alternative == 6)
757 && GET_CODE (operands[2]) == CONST_INT
758 && INTVAL (operands[2]) < 0)
759 return \"sub\\t%0, %1, #%n2\";
760 return asms[which_alternative];
761 "
0bdb6455 762 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 763 && ((operands[1] != stack_pointer_rtx
764 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
765 || (operands[1] == stack_pointer_rtx
766 && INTVAL (operands[2]) > 1020))"
0bdb6455 767 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
768 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
769 {
770 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 771 if (operands[1] == stack_pointer_rtx)
772 offset -= 1020;
773 else
774 {
775 if (offset > 255)
776 offset = 255;
777 else if (offset < -255)
778 offset = -255;
779 }
0bdb6455 780 operands[3] = GEN_INT (offset);
781 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
782 }
bf7bc2f6 783 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 784)
785
786;; Reloading and elimination of the frame pointer can
787;; sometimes cause this optimization to be missed.
a0f94409 788(define_peephole2
372575c7 789 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 790 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 791 (set (match_dup 0)
372575c7 792 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 793 "TARGET_THUMB1
cffb2a26 794 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
795 && (INTVAL (operands[1]) & 3) == 0"
372575c7 796 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 797 ""
cffb2a26 798)
b11cae9e 799
f7fbdd4a 800(define_insn "*addsi3_compare0"
bd5b4116 801 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 802 (compare:CC_NOOV
215b30b3 803 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
804 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 805 (const_int 0)))
806 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 807 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 808 "TARGET_ARM"
5565501b 809 "@
25f905c2 810 add%.\\t%0, %1, %2
811 sub%.\\t%0, %1, #%n2"
cffb2a26 812 [(set_attr "conds" "set")]
813)
9c08d1fa 814
aea4c774 815(define_insn "*addsi3_compare0_scratch"
bd5b4116 816 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 817 (compare:CC_NOOV
215b30b3 818 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
819 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 820 (const_int 0)))]
ec792a7b 821 "TARGET_ARM"
cffb2a26 822 "@
823 cmn%?\\t%0, %1
824 cmp%?\\t%0, #%n1"
0d66636f 825 [(set_attr "conds" "set")]
826)
cffb2a26 827
aed179ae 828(define_insn "*compare_negsi_si"
829 [(set (reg:CC_Z CC_REGNUM)
830 (compare:CC_Z
831 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
832 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 833 "TARGET_32BIT"
aed179ae 834 "cmn%?\\t%1, %0"
0d66636f 835 [(set_attr "conds" "set")]
836)
aea4c774 837
203c488f 838;; This is the canonicalization of addsi3_compare0_for_combiner when the
839;; addend is a constant.
840(define_insn "*cmpsi2_addneg"
841 [(set (reg:CC CC_REGNUM)
842 (compare:CC
843 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 844 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 845 (set (match_operand:SI 0 "s_register_operand" "=r,r")
846 (plus:SI (match_dup 1)
2a977b78 847 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 848 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 849 "@
2a977b78 850 add%.\\t%0, %1, %3
851 sub%.\\t%0, %1, #%n3"
203c488f 852 [(set_attr "conds" "set")]
853)
854
855;; Convert the sequence
856;; sub rd, rn, #1
857;; cmn rd, #1 (equivalent to cmp rd, #-1)
858;; bne dest
859;; into
860;; subs rd, rn, #1
861;; bcs dest ((unsigned)rn >= 1)
862;; similarly for the beq variant using bcc.
863;; This is a common looping idiom (while (n--))
864(define_peephole2
372575c7 865 [(set (match_operand:SI 0 "arm_general_register_operand" "")
866 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 867 (const_int -1)))
868 (set (match_operand 2 "cc_register" "")
869 (compare (match_dup 0) (const_int -1)))
870 (set (pc)
871 (if_then_else (match_operator 3 "equality_operator"
872 [(match_dup 2) (const_int 0)])
873 (match_operand 4 "" "")
874 (match_operand 5 "" "")))]
25f905c2 875 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 876 [(parallel[
877 (set (match_dup 2)
878 (compare:CC
879 (match_dup 1) (const_int 1)))
880 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
881 (set (pc)
882 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
883 (match_dup 4)
884 (match_dup 5)))]
885 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
886 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
887 ? GEU : LTU),
888 VOIDmode,
889 operands[2], const0_rtx);"
890)
891
ebcc79bc 892;; The next four insns work because they compare the result with one of
893;; the operands, and we know that the use of the condition code is
894;; either GEU or LTU, so we can use the carry flag from the addition
895;; instead of doing the compare a second time.
896(define_insn "*addsi3_compare_op1"
bd5b4116 897 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 898 (compare:CC_C
899 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
900 (match_operand:SI 2 "arm_add_operand" "rI,L"))
901 (match_dup 1)))
902 (set (match_operand:SI 0 "s_register_operand" "=r,r")
903 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 904 "TARGET_32BIT"
ebcc79bc 905 "@
25f905c2 906 add%.\\t%0, %1, %2
907 sub%.\\t%0, %1, #%n2"
0d66636f 908 [(set_attr "conds" "set")]
909)
ebcc79bc 910
911(define_insn "*addsi3_compare_op2"
bd5b4116 912 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 913 (compare:CC_C
914 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
915 (match_operand:SI 2 "arm_add_operand" "rI,L"))
916 (match_dup 2)))
5565501b 917 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 918 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 919 "TARGET_32BIT"
5565501b 920 "@
25f905c2 921 add%.\\t%0, %1, %2
922 sub%.\\t%0, %1, #%n2"
0d66636f 923 [(set_attr "conds" "set")]
924)
9c08d1fa 925
ebcc79bc 926(define_insn "*compare_addsi2_op0"
bd5b4116 927 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 928 (compare:CC_C
929 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
930 (match_operand:SI 1 "arm_add_operand" "rI,L"))
931 (match_dup 0)))]
25f905c2 932 "TARGET_32BIT"
ebcc79bc 933 "@
934 cmn%?\\t%0, %1
935 cmp%?\\t%0, #%n1"
0d66636f 936 [(set_attr "conds" "set")]
937)
ebcc79bc 938
939(define_insn "*compare_addsi2_op1"
bd5b4116 940 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 941 (compare:CC_C
942 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
943 (match_operand:SI 1 "arm_add_operand" "rI,L"))
944 (match_dup 1)))]
25f905c2 945 "TARGET_32BIT"
ebcc79bc 946 "@
947 cmn%?\\t%0, %1
948 cmp%?\\t%0, #%n1"
0d66636f 949 [(set_attr "conds" "set")]
950)
ebcc79bc 951
080c0b9a 952(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 953 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 954 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 955 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 956 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 957 "TARGET_32BIT"
ebcc79bc 958 "adc%?\\t%0, %1, %2"
cffb2a26 959 [(set_attr "conds" "use")]
960)
ebcc79bc 961
080c0b9a 962(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 963 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 964 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
965 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 966 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 967 "TARGET_32BIT"
ebcc79bc 968 "adc%?\\t%0, %1, %2"
0d66636f 969 [(set_attr "conds" "use")]
970)
ebcc79bc 971
080c0b9a 972(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 973 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 974 (plus:SI (plus:SI
975 (match_operator:SI 2 "shift_operator"
976 [(match_operand:SI 3 "s_register_operand" "r")
977 (match_operand:SI 4 "reg_or_int_operand" "rM")])
978 (match_operand:SI 1 "s_register_operand" "r"))
979 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 980 "TARGET_32BIT"
080c0b9a 981 "adc%?\\t%0, %1, %3%S2"
982 [(set_attr "conds" "use")
983 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
984 (const_string "alu_shift")
985 (const_string "alu_shift_reg")))]
cffb2a26 986)
ebcc79bc 987
25f905c2 988(define_expand "incscc"
989 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
990 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
991 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
992 (match_operand:SI 1 "s_register_operand" "0,?r")))]
993 "TARGET_32BIT"
994 ""
995)
996
997(define_insn "*arm_incscc"
9c08d1fa 998 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 999 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1000 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 1001 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 1002 "TARGET_ARM"
5565501b 1003 "@
1004 add%d2\\t%0, %1, #1
1005 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 1006 [(set_attr "conds" "use")
215b30b3 1007 (set_attr "length" "4,8")]
1008)
9c08d1fa 1009
d795fb69 1010; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1011(define_split
1012 [(set (match_operand:SI 0 "s_register_operand" "")
1013 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1014 (match_operand:SI 2 "s_register_operand" ""))
1015 (const_int -1)))
1016 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1017 "TARGET_32BIT"
d795fb69 1018 [(set (match_dup 3) (match_dup 1))
1019 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1020 "
1021 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1022")
1023
604f3a0a 1024(define_expand "addsf3"
1025 [(set (match_operand:SF 0 "s_register_operand" "")
1026 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1027 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 1028 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1029 "
a2cd141b 1030 if (TARGET_MAVERICK
604f3a0a 1031 && !cirrus_fp_register (operands[2], SFmode))
1032 operands[2] = force_reg (SFmode, operands[2]);
1033")
1034
604f3a0a 1035(define_expand "adddf3"
1036 [(set (match_operand:DF 0 "s_register_operand" "")
1037 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1038 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1039 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1040 "
a2cd141b 1041 if (TARGET_MAVERICK
604f3a0a 1042 && !cirrus_fp_register (operands[2], DFmode))
1043 operands[2] = force_reg (DFmode, operands[2]);
1044")
1045
cffb2a26 1046(define_expand "subdi3"
1047 [(parallel
1048 [(set (match_operand:DI 0 "s_register_operand" "")
1049 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1050 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1051 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1052 "TARGET_EITHER"
1053 "
a2cd141b 1054 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1055 && TARGET_32BIT
7d57ec45 1056 && cirrus_fp_register (operands[0], DImode)
1057 && cirrus_fp_register (operands[1], DImode))
1058 {
1059 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1060 DONE;
1061 }
1062
25f905c2 1063 if (TARGET_THUMB1)
cffb2a26 1064 {
1065 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1066 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1067 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1068 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1069 }
1070 "
1071)
1072
1073(define_insn "*arm_subdi3"
1074 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1075 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1076 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1077 (clobber (reg:CC CC_REGNUM))]
94829feb 1078 "TARGET_32BIT && !TARGET_NEON"
97499065 1079 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1080 [(set_attr "conds" "clob")
1081 (set_attr "length" "8")]
1082)
1083
1084(define_insn "*thumb_subdi3"
1085 [(set (match_operand:DI 0 "register_operand" "=l")
1086 (minus:DI (match_operand:DI 1 "register_operand" "0")
1087 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1088 (clobber (reg:CC CC_REGNUM))]
25f905c2 1089 "TARGET_THUMB1"
cffb2a26 1090 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1091 [(set_attr "length" "4")]
1092)
9c08d1fa 1093
f7fbdd4a 1094(define_insn "*subdi_di_zesidi"
cffb2a26 1095 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1096 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1097 (zero_extend:DI
cffb2a26 1098 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1099 (clobber (reg:CC CC_REGNUM))]
25f905c2 1100 "TARGET_32BIT"
97499065 1101 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1102 [(set_attr "conds" "clob")
1103 (set_attr "length" "8")]
1104)
9c08d1fa 1105
f7fbdd4a 1106(define_insn "*subdi_di_sesidi"
cffb2a26 1107 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1108 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1109 (sign_extend:DI
cffb2a26 1110 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1111 (clobber (reg:CC CC_REGNUM))]
25f905c2 1112 "TARGET_32BIT"
97499065 1113 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1114 [(set_attr "conds" "clob")
1115 (set_attr "length" "8")]
1116)
9c08d1fa 1117
f7fbdd4a 1118(define_insn "*subdi_zesidi_di"
cffb2a26 1119 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1120 (minus:DI (zero_extend:DI
cffb2a26 1121 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1122 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1123 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1124 "TARGET_ARM"
97499065 1125 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1126 [(set_attr "conds" "clob")
1127 (set_attr "length" "8")]
1128)
9c08d1fa 1129
f7fbdd4a 1130(define_insn "*subdi_sesidi_di"
cffb2a26 1131 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1132 (minus:DI (sign_extend:DI
cffb2a26 1133 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1134 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1135 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1136 "TARGET_ARM"
97499065 1137 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1138 [(set_attr "conds" "clob")
1139 (set_attr "length" "8")]
1140)
9c08d1fa 1141
f7fbdd4a 1142(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1143 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1144 (minus:DI (zero_extend:DI
cffb2a26 1145 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1146 (zero_extend:DI
cffb2a26 1147 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1148 (clobber (reg:CC CC_REGNUM))]
25f905c2 1149 "TARGET_32BIT"
1150 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1151 [(set_attr "conds" "clob")
1152 (set_attr "length" "8")]
1153)
b11cae9e 1154
87b22bf7 1155(define_expand "subsi3"
cffb2a26 1156 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1157 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1158 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1159 "TARGET_EITHER"
87b22bf7 1160 "
1161 if (GET_CODE (operands[1]) == CONST_INT)
1162 {
25f905c2 1163 if (TARGET_32BIT)
cffb2a26 1164 {
96f57e36 1165 arm_split_constant (MINUS, SImode, NULL_RTX,
1166 INTVAL (operands[1]), operands[0],
e1ba4a27 1167 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1168 DONE;
1169 }
25f905c2 1170 else /* TARGET_THUMB1 */
cffb2a26 1171 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1172 }
cffb2a26 1173 "
1174)
87b22bf7 1175
747b7458 1176(define_insn "thumb1_subsi3_insn"
cffb2a26 1177 [(set (match_operand:SI 0 "register_operand" "=l")
1178 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1179 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1180 "TARGET_THUMB1"
cffb2a26 1181 "sub\\t%0, %1, %2"
747b7458 1182 [(set_attr "length" "2")
1183 (set_attr "conds" "set")])
cffb2a26 1184
25f905c2 1185; ??? Check Thumb-2 split length
a0f94409 1186(define_insn_and_split "*arm_subsi3_insn"
080c0b9a 1187 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
bccb5444 1188 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1189 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
25f905c2 1190 "TARGET_32BIT"
e2348bcb 1191 "@
87b22bf7 1192 rsb%?\\t%0, %2, %1
aaa37ad6 1193 sub%?\\t%0, %1, %2
080c0b9a 1194 sub%?\\t%0, %1, %2
1195 #
87b22bf7 1196 #"
080c0b9a 1197 "&& ((GET_CODE (operands[1]) == CONST_INT
1198 && !const_ok_for_arm (INTVAL (operands[1])))
1199 || (GET_CODE (operands[2]) == CONST_INT
1200 && !const_ok_for_arm (INTVAL (operands[2]))))"
87b22bf7 1201 [(clobber (const_int 0))]
1202 "
96f57e36 1203 arm_split_constant (MINUS, SImode, curr_insn,
1204 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1205 DONE;
cffb2a26 1206 "
080c0b9a 1207 [(set_attr "length" "4,4,4,16,16")
a0f94409 1208 (set_attr "predicable" "yes")]
1209)
1210
1211(define_peephole2
1212 [(match_scratch:SI 3 "r")
372575c7 1213 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1214 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1215 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1216 "TARGET_32BIT
a0f94409 1217 && !const_ok_for_arm (INTVAL (operands[1]))
1218 && const_ok_for_arm (~INTVAL (operands[1]))"
1219 [(set (match_dup 3) (match_dup 1))
1220 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1221 ""
cffb2a26 1222)
b11cae9e 1223
f7fbdd4a 1224(define_insn "*subsi3_compare0"
bd5b4116 1225 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1226 (compare:CC_NOOV
1227 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1228 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1229 (const_int 0)))
9c08d1fa 1230 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1231 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1232 "TARGET_32BIT"
e2348bcb 1233 "@
25f905c2 1234 sub%.\\t%0, %1, %2
1235 rsb%.\\t%0, %2, %1"
cffb2a26 1236 [(set_attr "conds" "set")]
1237)
9c08d1fa 1238
080c0b9a 1239(define_insn "*subsi3_compare"
1240 [(set (reg:CC CC_REGNUM)
1241 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1242 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1243 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1244 (minus:SI (match_dup 1) (match_dup 2)))]
1245 "TARGET_32BIT"
1246 "@
1247 sub%.\\t%0, %1, %2
1248 rsb%.\\t%0, %2, %1"
1249 [(set_attr "conds" "set")]
1250)
1251
25f905c2 1252(define_expand "decscc"
1253 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1254 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1255 (match_operator:SI 2 "arm_comparison_operator"
1256 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1257 "TARGET_32BIT"
1258 ""
1259)
1260
1261(define_insn "*arm_decscc"
cffb2a26 1262 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1263 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1264 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1265 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1266 "TARGET_ARM"
e2348bcb 1267 "@
215b30b3 1268 sub%d2\\t%0, %1, #1
1269 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1270 [(set_attr "conds" "use")
1271 (set_attr "length" "*,8")]
1272)
9c08d1fa 1273
604f3a0a 1274(define_expand "subsf3"
1275 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1276 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1277 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1278 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1279 "
a2cd141b 1280 if (TARGET_MAVERICK)
604f3a0a 1281 {
1282 if (!cirrus_fp_register (operands[1], SFmode))
1283 operands[1] = force_reg (SFmode, operands[1]);
1284 if (!cirrus_fp_register (operands[2], SFmode))
1285 operands[2] = force_reg (SFmode, operands[2]);
1286 }
1287")
1288
604f3a0a 1289(define_expand "subdf3"
1290 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1291 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1292 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1293 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1294 "
a2cd141b 1295 if (TARGET_MAVERICK)
604f3a0a 1296 {
1297 if (!cirrus_fp_register (operands[1], DFmode))
1298 operands[1] = force_reg (DFmode, operands[1]);
1299 if (!cirrus_fp_register (operands[2], DFmode))
1300 operands[2] = force_reg (DFmode, operands[2]);
1301 }
1302")
1303
b11cae9e 1304\f
1305;; Multiplication insns
1306
cffb2a26 1307(define_expand "mulsi3"
1308 [(set (match_operand:SI 0 "s_register_operand" "")
1309 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1310 (match_operand:SI 1 "s_register_operand" "")))]
1311 "TARGET_EITHER"
1312 ""
1313)
1314
9c08d1fa 1315;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1316(define_insn "*arm_mulsi3"
1317 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1318 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1319 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1320 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1321 "mul%?\\t%0, %2, %1"
a2cd141b 1322 [(set_attr "insn" "mul")
0d66636f 1323 (set_attr "predicable" "yes")]
cffb2a26 1324)
1325
58d7d654 1326(define_insn "*arm_mulsi3_v6"
1327 [(set (match_operand:SI 0 "s_register_operand" "=r")
1328 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1329 (match_operand:SI 2 "s_register_operand" "r")))]
1330 "TARGET_32BIT && arm_arch6"
1331 "mul%?\\t%0, %1, %2"
1332 [(set_attr "insn" "mul")
1333 (set_attr "predicable" "yes")]
1334)
1335
215b30b3 1336; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1337; 1 and 2; are the same, because reload will make operand 0 match
1338; operand 1 without realizing that this conflicts with operand 2. We fix
1339; this by adding another alternative to match this case, and then `reload'
1340; it ourselves. This alternative must come first.
cffb2a26 1341(define_insn "*thumb_mulsi3"
1342 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1343 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1344 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1345 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1346 "*
1347 if (which_alternative < 2)
20c4e896 1348 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1349 else
20c4e896 1350 return \"mul\\t%0, %2\";
cffb2a26 1351 "
1352 [(set_attr "length" "4,4,2")
a2cd141b 1353 (set_attr "insn" "mul")]
cffb2a26 1354)
b11cae9e 1355
58d7d654 1356(define_insn "*thumb_mulsi3_v6"
1357 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1358 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1359 (match_operand:SI 2 "register_operand" "l,0,0")))]
1360 "TARGET_THUMB1 && arm_arch6"
1361 "@
1490694c 1362 mul\\t%0, %2
1363 mul\\t%0, %1
58d7d654 1364 mul\\t%0, %1"
1365 [(set_attr "length" "2")
1366 (set_attr "insn" "mul")]
1367)
1368
f7fbdd4a 1369(define_insn "*mulsi3_compare0"
bd5b4116 1370 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1371 (compare:CC_NOOV (mult:SI
1372 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1373 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1374 (const_int 0)))
1375 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1376 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1377 "TARGET_ARM && !arm_arch6"
1378 "mul%.\\t%0, %2, %1"
1379 [(set_attr "conds" "set")
1380 (set_attr "insn" "muls")]
1381)
1382
1383(define_insn "*mulsi3_compare0_v6"
1384 [(set (reg:CC_NOOV CC_REGNUM)
1385 (compare:CC_NOOV (mult:SI
1386 (match_operand:SI 2 "s_register_operand" "r")
1387 (match_operand:SI 1 "s_register_operand" "r"))
1388 (const_int 0)))
1389 (set (match_operand:SI 0 "s_register_operand" "=r")
1390 (mult:SI (match_dup 2) (match_dup 1)))]
1391 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1392 "mul%.\\t%0, %2, %1"
cffb2a26 1393 [(set_attr "conds" "set")
a2cd141b 1394 (set_attr "insn" "muls")]
cffb2a26 1395)
9c08d1fa 1396
f7fbdd4a 1397(define_insn "*mulsi_compare0_scratch"
bd5b4116 1398 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1399 (compare:CC_NOOV (mult:SI
1400 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1401 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1402 (const_int 0)))
1403 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1404 "TARGET_ARM && !arm_arch6"
1405 "mul%.\\t%0, %2, %1"
1406 [(set_attr "conds" "set")
1407 (set_attr "insn" "muls")]
1408)
1409
1410(define_insn "*mulsi_compare0_scratch_v6"
1411 [(set (reg:CC_NOOV CC_REGNUM)
1412 (compare:CC_NOOV (mult:SI
1413 (match_operand:SI 2 "s_register_operand" "r")
1414 (match_operand:SI 1 "s_register_operand" "r"))
1415 (const_int 0)))
1416 (clobber (match_scratch:SI 0 "=r"))]
1417 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1418 "mul%.\\t%0, %2, %1"
cffb2a26 1419 [(set_attr "conds" "set")
a2cd141b 1420 (set_attr "insn" "muls")]
cffb2a26 1421)
9c08d1fa 1422
b11cae9e 1423;; Unnamed templates to match MLA instruction.
1424
f7fbdd4a 1425(define_insn "*mulsi3addsi"
9c08d1fa 1426 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1427 (plus:SI
9c08d1fa 1428 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1429 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1430 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1431 "TARGET_32BIT && !arm_arch6"
1432 "mla%?\\t%0, %2, %1, %3"
1433 [(set_attr "insn" "mla")
1434 (set_attr "predicable" "yes")]
1435)
1436
1437(define_insn "*mulsi3addsi_v6"
1438 [(set (match_operand:SI 0 "s_register_operand" "=r")
1439 (plus:SI
1440 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1441 (match_operand:SI 1 "s_register_operand" "r"))
1442 (match_operand:SI 3 "s_register_operand" "r")))]
1443 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1444 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1445 [(set_attr "insn" "mla")
0d66636f 1446 (set_attr "predicable" "yes")]
1447)
b11cae9e 1448
f7fbdd4a 1449(define_insn "*mulsi3addsi_compare0"
bd5b4116 1450 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1451 (compare:CC_NOOV
1452 (plus:SI (mult:SI
1453 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1454 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1455 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1456 (const_int 0)))
9c08d1fa 1457 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1458 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1459 (match_dup 3)))]
58d7d654 1460 "TARGET_ARM && arm_arch6"
1461 "mla%.\\t%0, %2, %1, %3"
1462 [(set_attr "conds" "set")
1463 (set_attr "insn" "mlas")]
1464)
1465
1466(define_insn "*mulsi3addsi_compare0_v6"
1467 [(set (reg:CC_NOOV CC_REGNUM)
1468 (compare:CC_NOOV
1469 (plus:SI (mult:SI
1470 (match_operand:SI 2 "s_register_operand" "r")
1471 (match_operand:SI 1 "s_register_operand" "r"))
1472 (match_operand:SI 3 "s_register_operand" "r"))
1473 (const_int 0)))
1474 (set (match_operand:SI 0 "s_register_operand" "=r")
1475 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1476 (match_dup 3)))]
1477 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1478 "mla%.\\t%0, %2, %1, %3"
0d66636f 1479 [(set_attr "conds" "set")
a2cd141b 1480 (set_attr "insn" "mlas")]
0d66636f 1481)
9c08d1fa 1482
f7fbdd4a 1483(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1484 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1485 (compare:CC_NOOV
1486 (plus:SI (mult:SI
1487 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1488 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1489 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1490 (const_int 0)))
9c08d1fa 1491 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1492 "TARGET_ARM && !arm_arch6"
1493 "mla%.\\t%0, %2, %1, %3"
1494 [(set_attr "conds" "set")
1495 (set_attr "insn" "mlas")]
1496)
1497
1498(define_insn "*mulsi3addsi_compare0_scratch_v6"
1499 [(set (reg:CC_NOOV CC_REGNUM)
1500 (compare:CC_NOOV
1501 (plus:SI (mult:SI
1502 (match_operand:SI 2 "s_register_operand" "r")
1503 (match_operand:SI 1 "s_register_operand" "r"))
1504 (match_operand:SI 3 "s_register_operand" "r"))
1505 (const_int 0)))
1506 (clobber (match_scratch:SI 0 "=r"))]
1507 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1508 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1509 [(set_attr "conds" "set")
a2cd141b 1510 (set_attr "insn" "mlas")]
cffb2a26 1511)
f7fbdd4a 1512
89545238 1513(define_insn "*mulsi3subsi"
1514 [(set (match_operand:SI 0 "s_register_operand" "=r")
1515 (minus:SI
1516 (match_operand:SI 3 "s_register_operand" "r")
1517 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1518 (match_operand:SI 1 "s_register_operand" "r"))))]
1519 "TARGET_32BIT && arm_arch_thumb2"
1520 "mls%?\\t%0, %2, %1, %3"
1521 [(set_attr "insn" "mla")
1522 (set_attr "predicable" "yes")]
1523)
1524
5cdca009 1525(define_expand "maddsidi4"
1526 [(set (match_operand:DI 0 "s_register_operand" "")
1527 (plus:DI
1528 (mult:DI
1529 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1530 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1531 (match_operand:DI 3 "s_register_operand" "")))]
1532 "TARGET_32BIT && arm_arch3m"
1533 "")
82b85d08 1534
1535(define_insn "*mulsidi3adddi"
fe8dbf85 1536 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1537 (plus:DI
215b30b3 1538 (mult:DI
fe8dbf85 1539 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1540 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1541 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1542 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1543 "smlal%?\\t%Q0, %R0, %3, %2"
1544 [(set_attr "insn" "smlal")
1545 (set_attr "predicable" "yes")]
1546)
1547
1548(define_insn "*mulsidi3adddi_v6"
1549 [(set (match_operand:DI 0 "s_register_operand" "=r")
1550 (plus:DI
1551 (mult:DI
1552 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1553 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1554 (match_operand:DI 1 "s_register_operand" "0")))]
1555 "TARGET_32BIT && arm_arch6"
fe8dbf85 1556 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1557 [(set_attr "insn" "smlal")
0d66636f 1558 (set_attr "predicable" "yes")]
1559)
82b85d08 1560
957788b0 1561;; 32x32->64 widening multiply.
1562;; As with mulsi3, the only difference between the v3-5 and v6+
1563;; versions of these patterns is the requirement that the output not
1564;; overlap the inputs, but that still means we have to have a named
1565;; expander and two different starred insns.
1566
1567(define_expand "mulsidi3"
1568 [(set (match_operand:DI 0 "s_register_operand" "")
1569 (mult:DI
1570 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1571 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1572 "TARGET_32BIT && arm_arch3m"
1573 ""
1574)
1575
1576(define_insn "*mulsidi3_nov6"
f7fbdd4a 1577 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1578 (mult:DI
1579 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1580 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1581 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1582 "smull%?\\t%Q0, %R0, %1, %2"
1583 [(set_attr "insn" "smull")
1584 (set_attr "predicable" "yes")]
1585)
1586
957788b0 1587(define_insn "*mulsidi3_v6"
58d7d654 1588 [(set (match_operand:DI 0 "s_register_operand" "=r")
1589 (mult:DI
1590 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1591 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1592 "TARGET_32BIT && arm_arch6"
97499065 1593 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1594 [(set_attr "insn" "smull")
0d66636f 1595 (set_attr "predicable" "yes")]
1596)
f7fbdd4a 1597
957788b0 1598(define_expand "umulsidi3"
1599 [(set (match_operand:DI 0 "s_register_operand" "")
1600 (mult:DI
1601 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1602 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1603 "TARGET_32BIT && arm_arch3m"
1604 ""
1605)
1606
1607(define_insn "*umulsidi3_nov6"
f7fbdd4a 1608 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1609 (mult:DI
1610 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1611 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1612 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1613 "umull%?\\t%Q0, %R0, %1, %2"
1614 [(set_attr "insn" "umull")
1615 (set_attr "predicable" "yes")]
1616)
1617
957788b0 1618(define_insn "*umulsidi3_v6"
58d7d654 1619 [(set (match_operand:DI 0 "s_register_operand" "=r")
1620 (mult:DI
1621 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1622 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1623 "TARGET_32BIT && arm_arch6"
97499065 1624 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1625 [(set_attr "insn" "umull")
0d66636f 1626 (set_attr "predicable" "yes")]
1627)
b11cae9e 1628
5cdca009 1629(define_expand "umaddsidi4"
1630 [(set (match_operand:DI 0 "s_register_operand" "")
1631 (plus:DI
1632 (mult:DI
1633 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1634 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1635 (match_operand:DI 3 "s_register_operand" "")))]
1636 "TARGET_32BIT && arm_arch3m"
1637 "")
82b85d08 1638
1639(define_insn "*umulsidi3adddi"
8ead09f9 1640 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1641 (plus:DI
215b30b3 1642 (mult:DI
fe8dbf85 1643 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1644 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1645 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1646 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1647 "umlal%?\\t%Q0, %R0, %3, %2"
1648 [(set_attr "insn" "umlal")
1649 (set_attr "predicable" "yes")]
1650)
1651
1652(define_insn "*umulsidi3adddi_v6"
1653 [(set (match_operand:DI 0 "s_register_operand" "=r")
1654 (plus:DI
1655 (mult:DI
1656 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1657 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1658 (match_operand:DI 1 "s_register_operand" "0")))]
1659 "TARGET_32BIT && arm_arch6"
fe8dbf85 1660 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1661 [(set_attr "insn" "umlal")
0d66636f 1662 (set_attr "predicable" "yes")]
1663)
82b85d08 1664
957788b0 1665(define_expand "smulsi3_highpart"
1666 [(parallel
1667 [(set (match_operand:SI 0 "s_register_operand" "")
1668 (truncate:SI
1669 (lshiftrt:DI
1670 (mult:DI
1671 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1672 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1673 (const_int 32))))
1674 (clobber (match_scratch:SI 3 ""))])]
1675 "TARGET_32BIT && arm_arch3m"
1676 ""
1677)
1678
1679(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1680 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1681 (truncate:SI
1682 (lshiftrt:DI
215b30b3 1683 (mult:DI
e5fea38e 1684 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1685 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1686 (const_int 32))))
1687 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1688 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1689 "smull%?\\t%3, %0, %2, %1"
1690 [(set_attr "insn" "smull")
1691 (set_attr "predicable" "yes")]
1692)
1693
957788b0 1694(define_insn "*smulsi3_highpart_v6"
58d7d654 1695 [(set (match_operand:SI 0 "s_register_operand" "=r")
1696 (truncate:SI
1697 (lshiftrt:DI
1698 (mult:DI
1699 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1700 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1701 (const_int 32))))
1702 (clobber (match_scratch:SI 3 "=r"))]
1703 "TARGET_32BIT && arm_arch6"
f082f1c4 1704 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1705 [(set_attr "insn" "smull")
0d66636f 1706 (set_attr "predicable" "yes")]
cffb2a26 1707)
f082f1c4 1708
957788b0 1709(define_expand "umulsi3_highpart"
1710 [(parallel
1711 [(set (match_operand:SI 0 "s_register_operand" "")
1712 (truncate:SI
1713 (lshiftrt:DI
1714 (mult:DI
1715 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1716 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1717 (const_int 32))))
1718 (clobber (match_scratch:SI 3 ""))])]
1719 "TARGET_32BIT && arm_arch3m"
1720 ""
1721)
1722
1723(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1724 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1725 (truncate:SI
1726 (lshiftrt:DI
215b30b3 1727 (mult:DI
e5fea38e 1728 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1729 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1730 (const_int 32))))
1731 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1732 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1733 "umull%?\\t%3, %0, %2, %1"
1734 [(set_attr "insn" "umull")
1735 (set_attr "predicable" "yes")]
1736)
1737
957788b0 1738(define_insn "*umulsi3_highpart_v6"
58d7d654 1739 [(set (match_operand:SI 0 "s_register_operand" "=r")
1740 (truncate:SI
1741 (lshiftrt:DI
1742 (mult:DI
1743 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1744 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1745 (const_int 32))))
1746 (clobber (match_scratch:SI 3 "=r"))]
1747 "TARGET_32BIT && arm_arch6"
f082f1c4 1748 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1749 [(set_attr "insn" "umull")
0d66636f 1750 (set_attr "predicable" "yes")]
cffb2a26 1751)
f082f1c4 1752
331beb1a 1753(define_insn "mulhisi3"
1754 [(set (match_operand:SI 0 "s_register_operand" "=r")
1755 (mult:SI (sign_extend:SI
1756 (match_operand:HI 1 "s_register_operand" "%r"))
1757 (sign_extend:SI
1758 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1759 "TARGET_DSP_MULTIPLY"
61a2d04c 1760 "smulbb%?\\t%0, %1, %2"
a2cd141b 1761 [(set_attr "insn" "smulxy")
fec538d9 1762 (set_attr "predicable" "yes")]
1763)
1764
1765(define_insn "*mulhisi3tb"
1766 [(set (match_operand:SI 0 "s_register_operand" "=r")
1767 (mult:SI (ashiftrt:SI
1768 (match_operand:SI 1 "s_register_operand" "r")
1769 (const_int 16))
1770 (sign_extend:SI
1771 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1772 "TARGET_DSP_MULTIPLY"
fec538d9 1773 "smultb%?\\t%0, %1, %2"
a2cd141b 1774 [(set_attr "insn" "smulxy")
fec538d9 1775 (set_attr "predicable" "yes")]
1776)
1777
1778(define_insn "*mulhisi3bt"
1779 [(set (match_operand:SI 0 "s_register_operand" "=r")
1780 (mult:SI (sign_extend:SI
1781 (match_operand:HI 1 "s_register_operand" "r"))
1782 (ashiftrt:SI
1783 (match_operand:SI 2 "s_register_operand" "r")
1784 (const_int 16))))]
25f905c2 1785 "TARGET_DSP_MULTIPLY"
fec538d9 1786 "smulbt%?\\t%0, %1, %2"
a2cd141b 1787 [(set_attr "insn" "smulxy")
fec538d9 1788 (set_attr "predicable" "yes")]
1789)
1790
1791(define_insn "*mulhisi3tt"
1792 [(set (match_operand:SI 0 "s_register_operand" "=r")
1793 (mult:SI (ashiftrt:SI
1794 (match_operand:SI 1 "s_register_operand" "r")
1795 (const_int 16))
1796 (ashiftrt:SI
1797 (match_operand:SI 2 "s_register_operand" "r")
1798 (const_int 16))))]
25f905c2 1799 "TARGET_DSP_MULTIPLY"
fec538d9 1800 "smultt%?\\t%0, %1, %2"
a2cd141b 1801 [(set_attr "insn" "smulxy")
fec538d9 1802 (set_attr "predicable" "yes")]
331beb1a 1803)
1804
5cdca009 1805(define_insn "maddhisi4"
331beb1a 1806 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1807 (plus:SI (mult:SI (sign_extend:SI
1808 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1809 (sign_extend:SI
cfa6c608 1810 (match_operand:HI 2 "s_register_operand" "r")))
1811 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1812 "TARGET_DSP_MULTIPLY"
5cdca009 1813 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1814 [(set_attr "insn" "smlaxy")
fec538d9 1815 (set_attr "predicable" "yes")]
331beb1a 1816)
1817
5cdca009 1818(define_insn "*maddhidi4"
331beb1a 1819 [(set (match_operand:DI 0 "s_register_operand" "=r")
1820 (plus:DI
331beb1a 1821 (mult:DI (sign_extend:DI
cfa6c608 1822 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1823 (sign_extend:DI
cfa6c608 1824 (match_operand:HI 2 "s_register_operand" "r")))
1825 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1826 "TARGET_DSP_MULTIPLY"
5cdca009 1827 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1828 [(set_attr "insn" "smlalxy")
fec538d9 1829 (set_attr "predicable" "yes")])
331beb1a 1830
604f3a0a 1831(define_expand "mulsf3"
1832 [(set (match_operand:SF 0 "s_register_operand" "")
1833 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1834 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1835 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1836 "
a2cd141b 1837 if (TARGET_MAVERICK
604f3a0a 1838 && !cirrus_fp_register (operands[2], SFmode))
1839 operands[2] = force_reg (SFmode, operands[2]);
1840")
1841
604f3a0a 1842(define_expand "muldf3"
1843 [(set (match_operand:DF 0 "s_register_operand" "")
1844 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1845 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1846 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1847 "
a2cd141b 1848 if (TARGET_MAVERICK
604f3a0a 1849 && !cirrus_fp_register (operands[2], DFmode))
1850 operands[2] = force_reg (DFmode, operands[2]);
1851")
b11cae9e 1852\f
1853;; Division insns
1854
7db9af5d 1855(define_expand "divsf3"
1856 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1857 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1858 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1859 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1860 "")
9c08d1fa 1861
7db9af5d 1862(define_expand "divdf3"
1863 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1864 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1865 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1866 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1867 "")
b11cae9e 1868\f
1869;; Modulo insns
1870
7db9af5d 1871(define_expand "modsf3"
1872 [(set (match_operand:SF 0 "s_register_operand" "")
1873 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1874 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1875 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1876 "")
9c08d1fa 1877
7db9af5d 1878(define_expand "moddf3"
1879 [(set (match_operand:DF 0 "s_register_operand" "")
1880 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1881 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1882 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1883 "")
b11cae9e 1884\f
1885;; Boolean and,ior,xor insns
1886
f6ebffac 1887;; Split up double word logical operations
1888
1889;; Split up simple DImode logical operations. Simply perform the logical
1890;; operation on the upper and lower halves of the registers.
1891(define_split
1892 [(set (match_operand:DI 0 "s_register_operand" "")
1893 (match_operator:DI 6 "logical_binary_operator"
1894 [(match_operand:DI 1 "s_register_operand" "")
1895 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1896 "TARGET_32BIT && reload_completed
e2669ea7 1897 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1898 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1899 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1900 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1901 "
215b30b3 1902 {
1903 operands[3] = gen_highpart (SImode, operands[0]);
1904 operands[0] = gen_lowpart (SImode, operands[0]);
1905 operands[4] = gen_highpart (SImode, operands[1]);
1906 operands[1] = gen_lowpart (SImode, operands[1]);
1907 operands[5] = gen_highpart (SImode, operands[2]);
1908 operands[2] = gen_lowpart (SImode, operands[2]);
1909 }"
1910)
f6ebffac 1911
f6ebffac 1912(define_split
1913 [(set (match_operand:DI 0 "s_register_operand" "")
1914 (match_operator:DI 6 "logical_binary_operator"
1915 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1916 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1917 "TARGET_32BIT && reload_completed"
f6ebffac 1918 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1919 (set (match_dup 3) (match_op_dup:SI 6
1920 [(ashiftrt:SI (match_dup 2) (const_int 31))
1921 (match_dup 4)]))]
1922 "
215b30b3 1923 {
1924 operands[3] = gen_highpart (SImode, operands[0]);
1925 operands[0] = gen_lowpart (SImode, operands[0]);
1926 operands[4] = gen_highpart (SImode, operands[1]);
1927 operands[1] = gen_lowpart (SImode, operands[1]);
1928 operands[5] = gen_highpart (SImode, operands[2]);
1929 operands[2] = gen_lowpart (SImode, operands[2]);
1930 }"
1931)
f6ebffac 1932
f6ebffac 1933;; The zero extend of operand 2 means we can just copy the high part of
1934;; operand1 into operand0.
1935(define_split
1936 [(set (match_operand:DI 0 "s_register_operand" "")
1937 (ior:DI
1938 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1939 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1940 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1941 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1942 (set (match_dup 3) (match_dup 4))]
1943 "
215b30b3 1944 {
1945 operands[4] = gen_highpart (SImode, operands[1]);
1946 operands[3] = gen_highpart (SImode, operands[0]);
1947 operands[0] = gen_lowpart (SImode, operands[0]);
1948 operands[1] = gen_lowpart (SImode, operands[1]);
1949 }"
1950)
f6ebffac 1951
1952;; The zero extend of operand 2 means we can just copy the high part of
1953;; operand1 into operand0.
1954(define_split
1955 [(set (match_operand:DI 0 "s_register_operand" "")
1956 (xor:DI
1957 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1958 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1959 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1960 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1961 (set (match_dup 3) (match_dup 4))]
1962 "
215b30b3 1963 {
1964 operands[4] = gen_highpart (SImode, operands[1]);
1965 operands[3] = gen_highpart (SImode, operands[0]);
1966 operands[0] = gen_lowpart (SImode, operands[0]);
1967 operands[1] = gen_lowpart (SImode, operands[1]);
1968 }"
1969)
f6ebffac 1970
e2669ea7 1971(define_expand "anddi3"
1972 [(set (match_operand:DI 0 "s_register_operand" "")
1973 (and:DI (match_operand:DI 1 "s_register_operand" "")
1974 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1975 "TARGET_32BIT"
1976 ""
1977)
1978
1979(define_insn "*anddi3_insn"
cffb2a26 1980 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1981 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1982 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 1983 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 1984 "#"
215b30b3 1985 [(set_attr "length" "8")]
1986)
b11cae9e 1987
a0f94409 1988(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1989 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1990 (and:DI (zero_extend:DI
1991 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1992 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1993 "TARGET_32BIT"
f6ebffac 1994 "#"
25f905c2 1995 "TARGET_32BIT && reload_completed"
a0f94409 1996 ; The zero extend of operand 2 clears the high word of the output
1997 ; operand.
1998 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1999 (set (match_dup 3) (const_int 0))]
2000 "
2001 {
2002 operands[3] = gen_highpart (SImode, operands[0]);
2003 operands[0] = gen_lowpart (SImode, operands[0]);
2004 operands[1] = gen_lowpart (SImode, operands[1]);
2005 }"
215b30b3 2006 [(set_attr "length" "8")]
2007)
b11cae9e 2008
f7fbdd4a 2009(define_insn "*anddi_sesdi_di"
cffb2a26 2010 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2011 (and:DI (sign_extend:DI
2012 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2013 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2014 "TARGET_32BIT"
f6ebffac 2015 "#"
cffb2a26 2016 [(set_attr "length" "8")]
2017)
b11cae9e 2018
87b22bf7 2019(define_expand "andsi3"
cffb2a26 2020 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2021 (and:SI (match_operand:SI 1 "s_register_operand" "")
2022 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2023 "TARGET_EITHER"
87b22bf7 2024 "
25f905c2 2025 if (TARGET_32BIT)
87b22bf7 2026 {
cffb2a26 2027 if (GET_CODE (operands[2]) == CONST_INT)
2028 {
47b5b27b 2029 if (INTVAL (operands[2]) == 255 && arm_arch6)
2030 {
2031 operands[1] = convert_to_mode (QImode, operands[1], 1);
2032 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2033 operands[1]));
2034 }
2035 else
2036 arm_split_constant (AND, SImode, NULL_RTX,
2037 INTVAL (operands[2]), operands[0],
2038 operands[1],
2039 optimize && can_create_pseudo_p ());
615caa51 2040
cffb2a26 2041 DONE;
2042 }
87b22bf7 2043 }
25f905c2 2044 else /* TARGET_THUMB1 */
cffb2a26 2045 {
2046 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2047 {
2048 rtx tmp = force_reg (SImode, operands[2]);
2049 if (rtx_equal_p (operands[0], operands[1]))
2050 operands[2] = tmp;
2051 else
2052 {
2053 operands[2] = operands[1];
2054 operands[1] = tmp;
2055 }
2056 }
cffb2a26 2057 else
2058 {
2059 int i;
2060
215b30b3 2061 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2062 {
215b30b3 2063 operands[2] = force_reg (SImode,
2064 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2065
747b7458 2066 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2067
2068 DONE;
2069 }
87b22bf7 2070
cffb2a26 2071 for (i = 9; i <= 31; i++)
2072 {
2073 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2074 {
2075 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2076 const0_rtx));
2077 DONE;
2078 }
215b30b3 2079 else if ((((HOST_WIDE_INT) 1) << i) - 1
2080 == ~INTVAL (operands[2]))
cffb2a26 2081 {
2082 rtx shift = GEN_INT (i);
2083 rtx reg = gen_reg_rtx (SImode);
2084
2085 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2086 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2087
2088 DONE;
2089 }
2090 }
2091
2092 operands[2] = force_reg (SImode, operands[2]);
2093 }
215b30b3 2094 }
2095 "
cffb2a26 2096)
2097
25f905c2 2098; ??? Check split length for Thumb-2
a0f94409 2099(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2100 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2101 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2102 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2103 "TARGET_32BIT"
5565501b 2104 "@
2105 and%?\\t%0, %1, %2
87b22bf7 2106 bic%?\\t%0, %1, #%B2
2107 #"
25f905c2 2108 "TARGET_32BIT
a0f94409 2109 && GET_CODE (operands[2]) == CONST_INT
2110 && !(const_ok_for_arm (INTVAL (operands[2]))
2111 || const_ok_for_arm (~INTVAL (operands[2])))"
2112 [(clobber (const_int 0))]
2113 "
96f57e36 2114 arm_split_constant (AND, SImode, curr_insn,
2115 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2116 DONE;
2117 "
0d66636f 2118 [(set_attr "length" "4,4,16")
2119 (set_attr "predicable" "yes")]
cffb2a26 2120)
2121
25f905c2 2122(define_insn "*thumb1_andsi3_insn"
cffb2a26 2123 [(set (match_operand:SI 0 "register_operand" "=l")
2124 (and:SI (match_operand:SI 1 "register_operand" "%0")
2125 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2126 "TARGET_THUMB1"
747b7458 2127 "and\\t%0, %2"
2128 [(set_attr "length" "2")
2129 (set_attr "conds" "set")])
87b22bf7 2130
f7fbdd4a 2131(define_insn "*andsi3_compare0"
bd5b4116 2132 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2133 (compare:CC_NOOV
2134 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2135 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2136 (const_int 0)))
cffb2a26 2137 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2138 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2139 "TARGET_32BIT"
5565501b 2140 "@
25f905c2 2141 and%.\\t%0, %1, %2
2142 bic%.\\t%0, %1, #%B2"
cffb2a26 2143 [(set_attr "conds" "set")]
2144)
9c08d1fa 2145
f7fbdd4a 2146(define_insn "*andsi3_compare0_scratch"
bd5b4116 2147 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2148 (compare:CC_NOOV
2149 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2150 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2151 (const_int 0)))
dd193d7c 2152 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2153 "TARGET_32BIT"
5565501b 2154 "@
2155 tst%?\\t%0, %1
25f905c2 2156 bic%.\\t%2, %0, #%B1"
0d66636f 2157 [(set_attr "conds" "set")]
2158)
9c08d1fa 2159
f7fbdd4a 2160(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2161 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2162 (compare:CC_NOOV (zero_extract:SI
2163 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2164 (match_operand 1 "const_int_operand" "n")
2165 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2166 (const_int 0)))]
25f905c2 2167 "TARGET_32BIT
cffb2a26 2168 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2169 && INTVAL (operands[1]) > 0
2170 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2171 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2172 "*
5c49a439 2173 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2174 << INTVAL (operands[2]));
40dbec34 2175 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2176 return \"\";
0d66636f 2177 "
2178 [(set_attr "conds" "set")]
2179)
9c08d1fa 2180
f4462328 2181(define_insn_and_split "*ne_zeroextractsi"
c4034607 2182 [(set (match_operand:SI 0 "s_register_operand" "=r")
2183 (ne:SI (zero_extract:SI
2184 (match_operand:SI 1 "s_register_operand" "r")
2185 (match_operand:SI 2 "const_int_operand" "n")
2186 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2187 (const_int 0)))
2188 (clobber (reg:CC CC_REGNUM))]
25f905c2 2189 "TARGET_32BIT
cffb2a26 2190 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2191 && INTVAL (operands[2]) > 0
2192 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2193 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2194 "#"
25f905c2 2195 "TARGET_32BIT
f4462328 2196 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2197 && INTVAL (operands[2]) > 0
2198 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2199 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2200 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2201 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2202 (const_int 0)))
2203 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2204 (set (match_dup 0)
2205 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2206 (match_dup 0) (const_int 1)))]
2207 "
2208 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2209 << INTVAL (operands[3]));
2210 "
2211 [(set_attr "conds" "clob")
25f905c2 2212 (set (attr "length")
2213 (if_then_else (eq_attr "is_thumb" "yes")
2214 (const_int 12)
2215 (const_int 8)))]
f4462328 2216)
2217
2218(define_insn_and_split "*ne_zeroextractsi_shifted"
2219 [(set (match_operand:SI 0 "s_register_operand" "=r")
2220 (ne:SI (zero_extract:SI
2221 (match_operand:SI 1 "s_register_operand" "r")
2222 (match_operand:SI 2 "const_int_operand" "n")
2223 (const_int 0))
2224 (const_int 0)))
2225 (clobber (reg:CC CC_REGNUM))]
2226 "TARGET_ARM"
2227 "#"
2228 "TARGET_ARM"
2229 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2230 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2231 (const_int 0)))
2232 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2233 (set (match_dup 0)
2234 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2235 (match_dup 0) (const_int 1)))]
2236 "
2237 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2238 "
2239 [(set_attr "conds" "clob")
2240 (set_attr "length" "8")]
2241)
2242
2243(define_insn_and_split "*ite_ne_zeroextractsi"
2244 [(set (match_operand:SI 0 "s_register_operand" "=r")
2245 (if_then_else:SI (ne (zero_extract:SI
2246 (match_operand:SI 1 "s_register_operand" "r")
2247 (match_operand:SI 2 "const_int_operand" "n")
2248 (match_operand:SI 3 "const_int_operand" "n"))
2249 (const_int 0))
2250 (match_operand:SI 4 "arm_not_operand" "rIK")
2251 (const_int 0)))
2252 (clobber (reg:CC CC_REGNUM))]
2253 "TARGET_ARM
2254 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2255 && INTVAL (operands[2]) > 0
2256 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2257 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2258 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2259 "#"
2260 "TARGET_ARM
2261 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2262 && INTVAL (operands[2]) > 0
2263 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2264 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2265 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2266 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2267 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2268 (const_int 0)))
2269 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2270 (set (match_dup 0)
2271 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2272 (match_dup 0) (match_dup 4)))]
2273 "
c4034607 2274 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2275 << INTVAL (operands[3]));
2276 "
2277 [(set_attr "conds" "clob")
2278 (set_attr "length" "8")]
2279)
2280
2281(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2282 [(set (match_operand:SI 0 "s_register_operand" "=r")
2283 (if_then_else:SI (ne (zero_extract:SI
2284 (match_operand:SI 1 "s_register_operand" "r")
2285 (match_operand:SI 2 "const_int_operand" "n")
2286 (const_int 0))
2287 (const_int 0))
2288 (match_operand:SI 3 "arm_not_operand" "rIK")
2289 (const_int 0)))
2290 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2291 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2292 "#"
f8d7bf2f 2293 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2294 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2295 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2296 (const_int 0)))
2297 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2298 (set (match_dup 0)
2299 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2300 (match_dup 0) (match_dup 3)))]
2301 "
2302 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2303 "
2304 [(set_attr "conds" "clob")
215b30b3 2305 (set_attr "length" "8")]
2306)
9c08d1fa 2307
58d6528b 2308(define_split
2309 [(set (match_operand:SI 0 "s_register_operand" "")
2310 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2311 (match_operand:SI 2 "const_int_operand" "")
2312 (match_operand:SI 3 "const_int_operand" "")))
2313 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2314 "TARGET_THUMB1"
58d6528b 2315 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2316 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2317 "{
2318 HOST_WIDE_INT temp = INTVAL (operands[2]);
2319
2320 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2321 operands[3] = GEN_INT (32 - temp);
2322 }"
2323)
2324
25f905c2 2325;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2326(define_split
2327 [(set (match_operand:SI 0 "s_register_operand" "")
2328 (match_operator:SI 1 "shiftable_operator"
2329 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2330 (match_operand:SI 3 "const_int_operand" "")
2331 (match_operand:SI 4 "const_int_operand" ""))
2332 (match_operand:SI 5 "s_register_operand" "")]))
2333 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2334 "TARGET_ARM"
2335 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2336 (set (match_dup 0)
2337 (match_op_dup 1
2338 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2339 (match_dup 5)]))]
2340 "{
2341 HOST_WIDE_INT temp = INTVAL (operands[3]);
2342
2343 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2344 operands[4] = GEN_INT (32 - temp);
2345 }"
2346)
2347
58d6528b 2348(define_split
2349 [(set (match_operand:SI 0 "s_register_operand" "")
2350 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2351 (match_operand:SI 2 "const_int_operand" "")
2352 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2353 "TARGET_THUMB1"
58d6528b 2354 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2355 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2356 "{
2357 HOST_WIDE_INT temp = INTVAL (operands[2]);
2358
2359 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2360 operands[3] = GEN_INT (32 - temp);
2361 }"
2362)
2363
d7863cfe 2364(define_split
2365 [(set (match_operand:SI 0 "s_register_operand" "")
2366 (match_operator:SI 1 "shiftable_operator"
2367 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2368 (match_operand:SI 3 "const_int_operand" "")
2369 (match_operand:SI 4 "const_int_operand" ""))
2370 (match_operand:SI 5 "s_register_operand" "")]))
2371 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2372 "TARGET_ARM"
2373 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2374 (set (match_dup 0)
2375 (match_op_dup 1
2376 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2377 (match_dup 5)]))]
2378 "{
2379 HOST_WIDE_INT temp = INTVAL (operands[3]);
2380
2381 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2382 operands[4] = GEN_INT (32 - temp);
2383 }"
2384)
2385
a42059fd 2386;;; ??? This pattern is bogus. If operand3 has bits outside the range
2387;;; represented by the bitfield, then this will produce incorrect results.
2388;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2389;;; which have a real bit-field insert instruction, the truncation happens
2390;;; in the bit-field insert instruction itself. Since arm does not have a
2391;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2392;;; the value before we insert. This loses some of the advantage of having
2393;;; this insv pattern, so this pattern needs to be reevalutated.
2394
8a18b90c 2395(define_expand "insv"
2396 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2397 (match_operand:SI 1 "general_operand" "")
2398 (match_operand:SI 2 "general_operand" ""))
19335226 2399 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2400 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2401 "
215b30b3 2402 {
2403 int start_bit = INTVAL (operands[2]);
2404 int width = INTVAL (operands[1]);
2405 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2406 rtx target, subtarget;
2407
8b054d5a 2408 if (arm_arch_thumb2)
2409 {
2410 bool use_bfi = TRUE;
2411
2412 if (GET_CODE (operands[3]) == CONST_INT)
2413 {
2414 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2415
2416 if (val == 0)
2417 {
2418 emit_insn (gen_insv_zero (operands[0], operands[1],
2419 operands[2]));
2420 DONE;
2421 }
2422
2423 /* See if the set can be done with a single orr instruction. */
2424 if (val == mask && const_ok_for_arm (val << start_bit))
2425 use_bfi = FALSE;
2426 }
2427
2428 if (use_bfi)
2429 {
2430 if (GET_CODE (operands[3]) != REG)
2431 operands[3] = force_reg (SImode, operands[3]);
2432
2433 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2434 operands[3]));
2435 DONE;
2436 }
2437 }
2438
3f8fde42 2439 target = copy_rtx (operands[0]);
215b30b3 2440 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2441 subreg as the final target. */
2442 if (GET_CODE (target) == SUBREG)
2443 {
2444 subtarget = gen_reg_rtx (SImode);
2445 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2446 < GET_MODE_SIZE (SImode))
2447 target = SUBREG_REG (target);
2448 }
2449 else
2450 subtarget = target;
8a18b90c 2451
215b30b3 2452 if (GET_CODE (operands[3]) == CONST_INT)
2453 {
2454 /* Since we are inserting a known constant, we may be able to
2455 reduce the number of bits that we have to clear so that
2456 the mask becomes simple. */
2457 /* ??? This code does not check to see if the new mask is actually
2458 simpler. It may not be. */
2459 rtx op1 = gen_reg_rtx (SImode);
2460 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2461 start of this pattern. */
2462 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2463 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2464
c5b3a71b 2465 emit_insn (gen_andsi3 (op1, operands[0],
2466 gen_int_mode (~mask2, SImode)));
215b30b3 2467 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2468 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2469 }
2470 else if (start_bit == 0
2471 && !(const_ok_for_arm (mask)
2472 || const_ok_for_arm (~mask)))
2473 {
2474 /* A Trick, since we are setting the bottom bits in the word,
2475 we can shift operand[3] up, operand[0] down, OR them together
2476 and rotate the result back again. This takes 3 insns, and
5910bb95 2477 the third might be mergeable into another op. */
215b30b3 2478 /* The shift up copes with the possibility that operand[3] is
2479 wider than the bitfield. */
2480 rtx op0 = gen_reg_rtx (SImode);
2481 rtx op1 = gen_reg_rtx (SImode);
2482
2483 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2484 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2485 emit_insn (gen_iorsi3 (op1, op1, op0));
2486 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2487 }
2488 else if ((width + start_bit == 32)
2489 && !(const_ok_for_arm (mask)
2490 || const_ok_for_arm (~mask)))
2491 {
2492 /* Similar trick, but slightly less efficient. */
8a18b90c 2493
215b30b3 2494 rtx op0 = gen_reg_rtx (SImode);
2495 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2496
215b30b3 2497 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2498 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2499 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2500 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2501 }
2502 else
2503 {
c5b3a71b 2504 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2505 rtx op1 = gen_reg_rtx (SImode);
2506 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2507
215b30b3 2508 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2509 {
2510 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2511
215b30b3 2512 emit_insn (gen_movsi (tmp, op0));
2513 op0 = tmp;
2514 }
8a18b90c 2515
215b30b3 2516 /* Mask out any bits in operand[3] that are not needed. */
2517 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2518
215b30b3 2519 if (GET_CODE (op0) == CONST_INT
2520 && (const_ok_for_arm (mask << start_bit)
2521 || const_ok_for_arm (~(mask << start_bit))))
2522 {
c5b3a71b 2523 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2524 emit_insn (gen_andsi3 (op2, operands[0], op0));
2525 }
2526 else
2527 {
2528 if (GET_CODE (op0) == CONST_INT)
2529 {
2530 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2531
215b30b3 2532 emit_insn (gen_movsi (tmp, op0));
2533 op0 = tmp;
2534 }
2535
2536 if (start_bit != 0)
2537 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2538
215b30b3 2539 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2540 }
8a18b90c 2541
215b30b3 2542 if (start_bit != 0)
2543 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2544
215b30b3 2545 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2546 }
f082f1c4 2547
215b30b3 2548 if (subtarget != target)
2549 {
2550 /* If TARGET is still a SUBREG, then it must be wider than a word,
2551 so we must be careful only to set the subword we were asked to. */
2552 if (GET_CODE (target) == SUBREG)
2553 emit_move_insn (target, subtarget);
2554 else
2555 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2556 }
8a18b90c 2557
215b30b3 2558 DONE;
2559 }"
2560)
8a18b90c 2561
8b054d5a 2562(define_insn "insv_zero"
2563 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2564 (match_operand:SI 1 "const_int_operand" "M")
2565 (match_operand:SI 2 "const_int_operand" "M"))
2566 (const_int 0))]
2567 "arm_arch_thumb2"
2568 "bfc%?\t%0, %2, %1"
2569 [(set_attr "length" "4")
2570 (set_attr "predicable" "yes")]
2571)
2572
2573(define_insn "insv_t2"
2574 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2575 (match_operand:SI 1 "const_int_operand" "M")
2576 (match_operand:SI 2 "const_int_operand" "M"))
2577 (match_operand:SI 3 "s_register_operand" "r"))]
2578 "arm_arch_thumb2"
2579 "bfi%?\t%0, %3, %2, %1"
2580 [(set_attr "length" "4")
2581 (set_attr "predicable" "yes")]
2582)
2583
215b30b3 2584; constants for op 2 will never be given to these patterns.
a0f94409 2585(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2586 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2587 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2588 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2589 "TARGET_32BIT"
f6ebffac 2590 "#"
e2669ea7 2591 "TARGET_32BIT && reload_completed
2592 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2593 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2594 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2595 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2596 "
2597 {
2598 operands[3] = gen_highpart (SImode, operands[0]);
2599 operands[0] = gen_lowpart (SImode, operands[0]);
2600 operands[4] = gen_highpart (SImode, operands[1]);
2601 operands[1] = gen_lowpart (SImode, operands[1]);
2602 operands[5] = gen_highpart (SImode, operands[2]);
2603 operands[2] = gen_lowpart (SImode, operands[2]);
2604 }"
0d66636f 2605 [(set_attr "length" "8")
2606 (set_attr "predicable" "yes")]
2607)
9c08d1fa 2608
a0f94409 2609(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2610 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2611 (and:DI (not:DI (zero_extend:DI
2612 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2613 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2614 "TARGET_32BIT"
e2348bcb 2615 "@
97499065 2616 bic%?\\t%Q0, %Q1, %2
f6ebffac 2617 #"
a0f94409 2618 ; (not (zero_extend ...)) allows us to just copy the high word from
2619 ; operand1 to operand0.
25f905c2 2620 "TARGET_32BIT
a0f94409 2621 && reload_completed
2622 && operands[0] != operands[1]"
5a097f7d 2623 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2624 (set (match_dup 3) (match_dup 4))]
2625 "
2626 {
2627 operands[3] = gen_highpart (SImode, operands[0]);
2628 operands[0] = gen_lowpart (SImode, operands[0]);
2629 operands[4] = gen_highpart (SImode, operands[1]);
2630 operands[1] = gen_lowpart (SImode, operands[1]);
2631 }"
0d66636f 2632 [(set_attr "length" "4,8")
2633 (set_attr "predicable" "yes")]
2634)
9c08d1fa 2635
a0f94409 2636(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2637 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2638 (and:DI (not:DI (sign_extend:DI
2639 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2640 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2641 "TARGET_32BIT"
f6ebffac 2642 "#"
25f905c2 2643 "TARGET_32BIT && reload_completed"
5a097f7d 2644 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2645 (set (match_dup 3) (and:SI (not:SI
2646 (ashiftrt:SI (match_dup 2) (const_int 31)))
2647 (match_dup 4)))]
2648 "
2649 {
2650 operands[3] = gen_highpart (SImode, operands[0]);
2651 operands[0] = gen_lowpart (SImode, operands[0]);
2652 operands[4] = gen_highpart (SImode, operands[1]);
2653 operands[1] = gen_lowpart (SImode, operands[1]);
2654 }"
0d66636f 2655 [(set_attr "length" "8")
2656 (set_attr "predicable" "yes")]
2657)
9c08d1fa 2658
8a18b90c 2659(define_insn "andsi_notsi_si"
9c08d1fa 2660 [(set (match_operand:SI 0 "s_register_operand" "=r")
2661 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2662 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2663 "TARGET_32BIT"
0d66636f 2664 "bic%?\\t%0, %1, %2"
2665 [(set_attr "predicable" "yes")]
2666)
b11cae9e 2667
747b7458 2668(define_insn "thumb1_bicsi3"
cffb2a26 2669 [(set (match_operand:SI 0 "register_operand" "=l")
2670 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2671 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2672 "TARGET_THUMB1"
747b7458 2673 "bic\\t%0, %1"
2674 [(set_attr "length" "2")
2675 (set_attr "conds" "set")])
cffb2a26 2676
8a18b90c 2677(define_insn "andsi_not_shiftsi_si"
a2cd141b 2678 [(set (match_operand:SI 0 "s_register_operand" "=r")
2679 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2680 [(match_operand:SI 2 "s_register_operand" "r")
2681 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2682 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2683 "TARGET_ARM"
6c4c2133 2684 "bic%?\\t%0, %1, %2%S4"
344495ea 2685 [(set_attr "predicable" "yes")
331beb1a 2686 (set_attr "shift" "2")
a2cd141b 2687 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2688 (const_string "alu_shift")
2689 (const_string "alu_shift_reg")))]
6c4c2133 2690)
8a18b90c 2691
f7fbdd4a 2692(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2693 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2694 (compare:CC_NOOV
2695 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2696 (match_operand:SI 1 "s_register_operand" "r"))
2697 (const_int 0)))
9c08d1fa 2698 (set (match_operand:SI 0 "s_register_operand" "=r")
2699 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2700 "TARGET_32BIT"
2701 "bic%.\\t%0, %1, %2"
0d66636f 2702 [(set_attr "conds" "set")]
2703)
9c08d1fa 2704
f7fbdd4a 2705(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2706 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2707 (compare:CC_NOOV
2708 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2709 (match_operand:SI 1 "s_register_operand" "r"))
2710 (const_int 0)))
9c08d1fa 2711 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2712 "TARGET_32BIT"
2713 "bic%.\\t%0, %1, %2"
0d66636f 2714 [(set_attr "conds" "set")]
2715)
9c08d1fa 2716
e2669ea7 2717(define_expand "iordi3"
2718 [(set (match_operand:DI 0 "s_register_operand" "")
2719 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2720 (match_operand:DI 2 "neon_logic_op2" "")))]
2721 "TARGET_32BIT"
2722 ""
2723)
2724
2725(define_insn "*iordi3_insn"
cffb2a26 2726 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2727 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2728 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2729 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2730 "#"
0d66636f 2731 [(set_attr "length" "8")
2732 (set_attr "predicable" "yes")]
cffb2a26 2733)
9c08d1fa 2734
f7fbdd4a 2735(define_insn "*iordi_zesidi_di"
9c08d1fa 2736 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2737 (ior:DI (zero_extend:DI
2738 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2739 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2740 "TARGET_32BIT"
e2348bcb 2741 "@
97499065 2742 orr%?\\t%Q0, %Q1, %2
f6ebffac 2743 #"
0d66636f 2744 [(set_attr "length" "4,8")
2745 (set_attr "predicable" "yes")]
cffb2a26 2746)
9c08d1fa 2747
f7fbdd4a 2748(define_insn "*iordi_sesidi_di"
9c08d1fa 2749 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2750 (ior:DI (sign_extend:DI
2751 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2752 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2753 "TARGET_32BIT"
f6ebffac 2754 "#"
0d66636f 2755 [(set_attr "length" "8")
2756 (set_attr "predicable" "yes")]
cffb2a26 2757)
9c08d1fa 2758
87b22bf7 2759(define_expand "iorsi3"
cffb2a26 2760 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2761 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2762 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2763 "TARGET_EITHER"
87b22bf7 2764 "
2765 if (GET_CODE (operands[2]) == CONST_INT)
2766 {
25f905c2 2767 if (TARGET_32BIT)
cffb2a26 2768 {
96f57e36 2769 arm_split_constant (IOR, SImode, NULL_RTX,
2770 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2771 optimize && can_create_pseudo_p ());
cffb2a26 2772 DONE;
2773 }
25f905c2 2774 else /* TARGET_THUMB1 */
923ffadb 2775 {
2776 rtx tmp = force_reg (SImode, operands[2]);
2777 if (rtx_equal_p (operands[0], operands[1]))
2778 operands[2] = tmp;
2779 else
2780 {
2781 operands[2] = operands[1];
2782 operands[1] = tmp;
2783 }
2784 }
87b22bf7 2785 }
cffb2a26 2786 "
2787)
87b22bf7 2788
d5d4dc8d 2789(define_insn_and_split "*iorsi3_insn"
2790 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2791 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2792 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2793 "TARGET_32BIT"
87b22bf7 2794 "@
2795 orr%?\\t%0, %1, %2
d5d4dc8d 2796 orn%?\\t%0, %1, #%B2
87b22bf7 2797 #"
d5d4dc8d 2798 "TARGET_32BIT
a0f94409 2799 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2800 && !(const_ok_for_arm (INTVAL (operands[2]))
2801 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2802 [(clobber (const_int 0))]
d5d4dc8d 2803{
96f57e36 2804 arm_split_constant (IOR, SImode, curr_insn,
2805 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2806 DONE;
d5d4dc8d 2807}
2808 [(set_attr "length" "4,4,16")
2809 (set_attr "arch" "32,t2,32")
2810 (set_attr "predicable" "yes")])
cffb2a26 2811
747b7458 2812(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2813 [(set (match_operand:SI 0 "register_operand" "=l")
2814 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2815 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2816 "TARGET_THUMB1"
747b7458 2817 "orr\\t%0, %2"
2818 [(set_attr "length" "2")
2819 (set_attr "conds" "set")])
9c08d1fa 2820
a0f94409 2821(define_peephole2
2822 [(match_scratch:SI 3 "r")
372575c7 2823 (set (match_operand:SI 0 "arm_general_register_operand" "")
2824 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2825 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2826 "TARGET_ARM
a0f94409 2827 && !const_ok_for_arm (INTVAL (operands[2]))
2828 && const_ok_for_arm (~INTVAL (operands[2]))"
2829 [(set (match_dup 3) (match_dup 2))
2830 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2831 ""
215b30b3 2832)
a0f94409 2833
f7fbdd4a 2834(define_insn "*iorsi3_compare0"
bd5b4116 2835 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2836 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2837 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2838 (const_int 0)))
2839 (set (match_operand:SI 0 "s_register_operand" "=r")
2840 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2841 "TARGET_32BIT"
2842 "orr%.\\t%0, %1, %2"
cffb2a26 2843 [(set_attr "conds" "set")]
2844)
9c08d1fa 2845
f7fbdd4a 2846(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2847 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2848 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2849 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2850 (const_int 0)))
2851 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2852 "TARGET_32BIT"
2853 "orr%.\\t%0, %1, %2"
0d66636f 2854 [(set_attr "conds" "set")]
2855)
9c08d1fa 2856
e2669ea7 2857(define_expand "xordi3"
2858 [(set (match_operand:DI 0 "s_register_operand" "")
2859 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2860 (match_operand:DI 2 "s_register_operand" "")))]
2861 "TARGET_32BIT"
2862 ""
2863)
2864
2865(define_insn "*xordi3_insn"
cffb2a26 2866 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2867 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2868 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2869 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2870 "#"
0d66636f 2871 [(set_attr "length" "8")
2872 (set_attr "predicable" "yes")]
cffb2a26 2873)
9c08d1fa 2874
f7fbdd4a 2875(define_insn "*xordi_zesidi_di"
9c08d1fa 2876 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2877 (xor:DI (zero_extend:DI
2878 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2879 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2880 "TARGET_32BIT"
e2348bcb 2881 "@
97499065 2882 eor%?\\t%Q0, %Q1, %2
f6ebffac 2883 #"
0d66636f 2884 [(set_attr "length" "4,8")
2885 (set_attr "predicable" "yes")]
cffb2a26 2886)
9c08d1fa 2887
f7fbdd4a 2888(define_insn "*xordi_sesidi_di"
9c08d1fa 2889 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2890 (xor:DI (sign_extend:DI
2891 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2892 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2893 "TARGET_32BIT"
f6ebffac 2894 "#"
0d66636f 2895 [(set_attr "length" "8")
2896 (set_attr "predicable" "yes")]
cffb2a26 2897)
9c08d1fa 2898
cffb2a26 2899(define_expand "xorsi3"
2900 [(set (match_operand:SI 0 "s_register_operand" "")
2901 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2902 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2903 "TARGET_EITHER"
923ffadb 2904 "if (GET_CODE (operands[2]) == CONST_INT)
2905 {
2906 if (TARGET_32BIT)
2907 {
2908 arm_split_constant (XOR, SImode, NULL_RTX,
2909 INTVAL (operands[2]), operands[0], operands[1],
2910 optimize && can_create_pseudo_p ());
2911 DONE;
2912 }
2913 else /* TARGET_THUMB1 */
2914 {
2915 rtx tmp = force_reg (SImode, operands[2]);
2916 if (rtx_equal_p (operands[0], operands[1]))
2917 operands[2] = tmp;
2918 else
2919 {
2920 operands[2] = operands[1];
2921 operands[1] = tmp;
2922 }
2923 }
2924 }"
cffb2a26 2925)
2926
2927(define_insn "*arm_xorsi3"
2928 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2929 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2930 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2931 "TARGET_32BIT"
cffb2a26 2932 "eor%?\\t%0, %1, %2"
0d66636f 2933 [(set_attr "predicable" "yes")]
cffb2a26 2934)
2935
747b7458 2936(define_insn "*thumb1_xorsi3_insn"
cffb2a26 2937 [(set (match_operand:SI 0 "register_operand" "=l")
2938 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2939 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2940 "TARGET_THUMB1"
747b7458 2941 "eor\\t%0, %2"
2942 [(set_attr "length" "2")
2943 (set_attr "conds" "set")])
9c08d1fa 2944
f7fbdd4a 2945(define_insn "*xorsi3_compare0"
bd5b4116 2946 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2947 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2948 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2949 (const_int 0)))
2950 (set (match_operand:SI 0 "s_register_operand" "=r")
2951 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2952 "TARGET_32BIT"
2953 "eor%.\\t%0, %1, %2"
0d66636f 2954 [(set_attr "conds" "set")]
2955)
9c08d1fa 2956
f7fbdd4a 2957(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2958 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2959 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2960 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2961 (const_int 0)))]
25f905c2 2962 "TARGET_32BIT"
40dbec34 2963 "teq%?\\t%0, %1"
cffb2a26 2964 [(set_attr "conds" "set")]
2965)
9c08d1fa 2966
215b30b3 2967; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2968; (NOT D) we can sometimes merge the final NOT into one of the following
2969; insns.
9c08d1fa 2970
2971(define_split
a058e94a 2972 [(set (match_operand:SI 0 "s_register_operand" "")
2973 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2974 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2975 (match_operand:SI 3 "arm_rhs_operand" "")))
2976 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2977 "TARGET_32BIT"
9c08d1fa 2978 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2979 (not:SI (match_dup 3))))
2980 (set (match_dup 0) (not:SI (match_dup 4)))]
2981 ""
2982)
2983
f7fbdd4a 2984(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2985 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 2986 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 2987 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2988 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2989 "TARGET_32BIT"
40dbec34 2990 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2991 [(set_attr "length" "8")
25f905c2 2992 (set_attr "ce_count" "2")
0d66636f 2993 (set_attr "predicable" "yes")]
cffb2a26 2994)
9c08d1fa 2995
25f905c2 2996; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2997; insns are available?
d7863cfe 2998(define_split
2999 [(set (match_operand:SI 0 "s_register_operand" "")
3000 (match_operator:SI 1 "logical_binary_operator"
3001 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3002 (match_operand:SI 3 "const_int_operand" "")
3003 (match_operand:SI 4 "const_int_operand" ""))
3004 (match_operator:SI 9 "logical_binary_operator"
3005 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3006 (match_operand:SI 6 "const_int_operand" ""))
3007 (match_operand:SI 7 "s_register_operand" "")])]))
3008 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3009 "TARGET_32BIT
d7863cfe 3010 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3011 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3012 [(set (match_dup 8)
3013 (match_op_dup 1
3014 [(ashift:SI (match_dup 2) (match_dup 4))
3015 (match_dup 5)]))
3016 (set (match_dup 0)
3017 (match_op_dup 1
3018 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3019 (match_dup 7)]))]
3020 "
3021 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3022")
3023
3024(define_split
3025 [(set (match_operand:SI 0 "s_register_operand" "")
3026 (match_operator:SI 1 "logical_binary_operator"
3027 [(match_operator:SI 9 "logical_binary_operator"
3028 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3029 (match_operand:SI 6 "const_int_operand" ""))
3030 (match_operand:SI 7 "s_register_operand" "")])
3031 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3032 (match_operand:SI 3 "const_int_operand" "")
3033 (match_operand:SI 4 "const_int_operand" ""))]))
3034 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3035 "TARGET_32BIT
d7863cfe 3036 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3037 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3038 [(set (match_dup 8)
3039 (match_op_dup 1
3040 [(ashift:SI (match_dup 2) (match_dup 4))
3041 (match_dup 5)]))
3042 (set (match_dup 0)
3043 (match_op_dup 1
3044 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3045 (match_dup 7)]))]
3046 "
3047 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3048")
3049
3050(define_split
3051 [(set (match_operand:SI 0 "s_register_operand" "")
3052 (match_operator:SI 1 "logical_binary_operator"
3053 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3054 (match_operand:SI 3 "const_int_operand" "")
3055 (match_operand:SI 4 "const_int_operand" ""))
3056 (match_operator:SI 9 "logical_binary_operator"
3057 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3058 (match_operand:SI 6 "const_int_operand" ""))
3059 (match_operand:SI 7 "s_register_operand" "")])]))
3060 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3061 "TARGET_32BIT
d7863cfe 3062 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3063 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3064 [(set (match_dup 8)
3065 (match_op_dup 1
3066 [(ashift:SI (match_dup 2) (match_dup 4))
3067 (match_dup 5)]))
3068 (set (match_dup 0)
3069 (match_op_dup 1
3070 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3071 (match_dup 7)]))]
3072 "
3073 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3074")
3075
3076(define_split
3077 [(set (match_operand:SI 0 "s_register_operand" "")
3078 (match_operator:SI 1 "logical_binary_operator"
3079 [(match_operator:SI 9 "logical_binary_operator"
3080 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3081 (match_operand:SI 6 "const_int_operand" ""))
3082 (match_operand:SI 7 "s_register_operand" "")])
3083 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3084 (match_operand:SI 3 "const_int_operand" "")
3085 (match_operand:SI 4 "const_int_operand" ""))]))
3086 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3087 "TARGET_32BIT
d7863cfe 3088 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3089 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3090 [(set (match_dup 8)
3091 (match_op_dup 1
3092 [(ashift:SI (match_dup 2) (match_dup 4))
3093 (match_dup 5)]))
3094 (set (match_dup 0)
3095 (match_op_dup 1
3096 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3097 (match_dup 7)]))]
3098 "
3099 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3100")
9c08d1fa 3101\f
3102
3103;; Minimum and maximum insns
3104
8b9dc177 3105(define_expand "smaxsi3"
3106 [(parallel [
3107 (set (match_operand:SI 0 "s_register_operand" "")
3108 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3109 (match_operand:SI 2 "arm_rhs_operand" "")))
3110 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3111 "TARGET_32BIT"
8b9dc177 3112 "
8774928b 3113 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3114 {
3115 /* No need for a clobber of the condition code register here. */
3116 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3117 gen_rtx_SMAX (SImode, operands[1],
3118 operands[2])));
3119 DONE;
3120 }
3121")
3122
3123(define_insn "*smax_0"
3124 [(set (match_operand:SI 0 "s_register_operand" "=r")
3125 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3126 (const_int 0)))]
25f905c2 3127 "TARGET_32BIT"
8b9dc177 3128 "bic%?\\t%0, %1, %1, asr #31"
3129 [(set_attr "predicable" "yes")]
3130)
3131
8774928b 3132(define_insn "*smax_m1"
3133 [(set (match_operand:SI 0 "s_register_operand" "=r")
3134 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3135 (const_int -1)))]
25f905c2 3136 "TARGET_32BIT"
8774928b 3137 "orr%?\\t%0, %1, %1, asr #31"
3138 [(set_attr "predicable" "yes")]
3139)
3140
25f905c2 3141(define_insn "*arm_smax_insn"
8b9dc177 3142 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3143 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3144 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3145 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3146 "TARGET_ARM"
e2348bcb 3147 "@
3148 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3149 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3150 [(set_attr "conds" "clob")
8b9dc177 3151 (set_attr "length" "8,12")]
cffb2a26 3152)
9c08d1fa 3153
8b9dc177 3154(define_expand "sminsi3"
3155 [(parallel [
3156 (set (match_operand:SI 0 "s_register_operand" "")
3157 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3158 (match_operand:SI 2 "arm_rhs_operand" "")))
3159 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3160 "TARGET_32BIT"
8b9dc177 3161 "
3162 if (operands[2] == const0_rtx)
3163 {
3164 /* No need for a clobber of the condition code register here. */
3165 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3166 gen_rtx_SMIN (SImode, operands[1],
3167 operands[2])));
3168 DONE;
3169 }
3170")
3171
3172(define_insn "*smin_0"
3173 [(set (match_operand:SI 0 "s_register_operand" "=r")
3174 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3175 (const_int 0)))]
25f905c2 3176 "TARGET_32BIT"
8b9dc177 3177 "and%?\\t%0, %1, %1, asr #31"
3178 [(set_attr "predicable" "yes")]
3179)
3180
25f905c2 3181(define_insn "*arm_smin_insn"
8b9dc177 3182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3183 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3184 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3185 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3186 "TARGET_ARM"
e2348bcb 3187 "@
3188 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3189 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3190 [(set_attr "conds" "clob")
8b9dc177 3191 (set_attr "length" "8,12")]
0d66636f 3192)
9c08d1fa 3193
25f905c2 3194(define_expand "umaxsi3"
3195 [(parallel [
3196 (set (match_operand:SI 0 "s_register_operand" "")
3197 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3198 (match_operand:SI 2 "arm_rhs_operand" "")))
3199 (clobber (reg:CC CC_REGNUM))])]
3200 "TARGET_32BIT"
3201 ""
3202)
3203
3204(define_insn "*arm_umaxsi3"
9c08d1fa 3205 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3206 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3207 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3208 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3209 "TARGET_ARM"
e2348bcb 3210 "@
3211 cmp\\t%1, %2\;movcc\\t%0, %2
3212 cmp\\t%1, %2\;movcs\\t%0, %1
3213 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3214 [(set_attr "conds" "clob")
3215 (set_attr "length" "8,8,12")]
3216)
9c08d1fa 3217
25f905c2 3218(define_expand "uminsi3"
3219 [(parallel [
3220 (set (match_operand:SI 0 "s_register_operand" "")
3221 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3222 (match_operand:SI 2 "arm_rhs_operand" "")))
3223 (clobber (reg:CC CC_REGNUM))])]
3224 "TARGET_32BIT"
3225 ""
3226)
3227
3228(define_insn "*arm_uminsi3"
9c08d1fa 3229 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3230 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3231 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3232 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3233 "TARGET_ARM"
e2348bcb 3234 "@
3235 cmp\\t%1, %2\;movcs\\t%0, %2
3236 cmp\\t%1, %2\;movcc\\t%0, %1
3237 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3238 [(set_attr "conds" "clob")
3239 (set_attr "length" "8,8,12")]
3240)
9c08d1fa 3241
8a18b90c 3242(define_insn "*store_minmaxsi"
9c08d1fa 3243 [(set (match_operand:SI 0 "memory_operand" "=m")
3244 (match_operator:SI 3 "minmax_operator"
3245 [(match_operand:SI 1 "s_register_operand" "r")
3246 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3247 (clobber (reg:CC CC_REGNUM))]
25f905c2 3248 "TARGET_32BIT"
9c08d1fa 3249 "*
dc55b8a9 3250 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3251 operands[1], operands[2]);
e2348bcb 3252 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3253 if (TARGET_THUMB2)
3254 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3255 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3256 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3257 return \"\";
0d66636f 3258 "
3259 [(set_attr "conds" "clob")
25f905c2 3260 (set (attr "length")
3261 (if_then_else (eq_attr "is_thumb" "yes")
3262 (const_int 14)
3263 (const_int 12)))
0d66636f 3264 (set_attr "type" "store1")]
3265)
9c08d1fa 3266
8a18b90c 3267; Reject the frame pointer in operand[1], since reloading this after
3268; it has been eliminated can cause carnage.
f7fbdd4a 3269(define_insn "*minmax_arithsi"
9c08d1fa 3270 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3271 (match_operator:SI 4 "shiftable_operator"
3272 [(match_operator:SI 5 "minmax_operator"
3273 [(match_operand:SI 2 "s_register_operand" "r,r")
3274 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3275 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3276 (clobber (reg:CC CC_REGNUM))]
25f905c2 3277 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3278 "*
0d66636f 3279 {
3280 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3281 bool need_else;
3282
3283 if (which_alternative != 0 || operands[3] != const0_rtx
3284 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3285 need_else = true;
3286 else
3287 need_else = false;
0d66636f 3288
dc55b8a9 3289 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3290 operands[2], operands[3]);
0d66636f 3291 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3292 if (TARGET_THUMB2)
3293 {
3294 if (need_else)
3295 output_asm_insn (\"ite\\t%d5\", operands);
3296 else
3297 output_asm_insn (\"it\\t%d5\", operands);
3298 }
0d66636f 3299 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3300 if (need_else)
0d66636f 3301 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3302 return \"\";
215b30b3 3303 }"
0d66636f 3304 [(set_attr "conds" "clob")
25f905c2 3305 (set (attr "length")
3306 (if_then_else (eq_attr "is_thumb" "yes")
3307 (const_int 14)
3308 (const_int 12)))]
0d66636f 3309)
9c08d1fa 3310
b11cae9e 3311\f
3312;; Shift and rotation insns
3313
a2cd141b 3314(define_expand "ashldi3"
3315 [(set (match_operand:DI 0 "s_register_operand" "")
3316 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3317 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3318 "TARGET_32BIT"
a2cd141b 3319 "
3320 if (GET_CODE (operands[2]) == CONST_INT)
3321 {
3322 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3323 {
3324 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3325 DONE;
3326 }
3327 /* Ideally we shouldn't fail here if we could know that operands[1]
3328 ends up already living in an iwmmxt register. Otherwise it's
3329 cheaper to have the alternate code being generated than moving
1d60d981 3330 values to iwmmxt regs and back. */
a2cd141b 3331 FAIL;
3332 }
3333 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3334 FAIL;
3335 "
3336)
3337
3338(define_insn "arm_ashldi3_1bit"
50ad1bf9 3339 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3340 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3341 (const_int 1)))
3342 (clobber (reg:CC CC_REGNUM))]
25f905c2 3343 "TARGET_32BIT"
a2cd141b 3344 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3345 [(set_attr "conds" "clob")
3346 (set_attr "length" "8")]
3347)
3348
87b22bf7 3349(define_expand "ashlsi3"
cffb2a26 3350 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3351 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3352 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3353 "TARGET_EITHER"
87b22bf7 3354 "
3355 if (GET_CODE (operands[2]) == CONST_INT
3356 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3357 {
3358 emit_insn (gen_movsi (operands[0], const0_rtx));
3359 DONE;
3360 }
cffb2a26 3361 "
3362)
3363
25f905c2 3364(define_insn "*thumb1_ashlsi3"
cffb2a26 3365 [(set (match_operand:SI 0 "register_operand" "=l,l")
3366 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3367 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3368 "TARGET_THUMB1"
cffb2a26 3369 "lsl\\t%0, %1, %2"
747b7458 3370 [(set_attr "length" "2")
3371 (set_attr "conds" "set")])
b11cae9e 3372
a2cd141b 3373(define_expand "ashrdi3"
3374 [(set (match_operand:DI 0 "s_register_operand" "")
3375 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3376 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3377 "TARGET_32BIT"
a2cd141b 3378 "
3379 if (GET_CODE (operands[2]) == CONST_INT)
3380 {
3381 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3382 {
3383 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3384 DONE;
3385 }
3386 /* Ideally we shouldn't fail here if we could know that operands[1]
3387 ends up already living in an iwmmxt register. Otherwise it's
3388 cheaper to have the alternate code being generated than moving
1d60d981 3389 values to iwmmxt regs and back. */
a2cd141b 3390 FAIL;
3391 }
3392 else if (!TARGET_REALLY_IWMMXT)
3393 FAIL;
3394 "
3395)
3396
3397(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3398 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3399 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3400 (const_int 1)))
3401 (clobber (reg:CC CC_REGNUM))]
25f905c2 3402 "TARGET_32BIT"
a2cd141b 3403 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3404 [(set_attr "conds" "clob")
d2a518d1 3405 (set_attr "insn" "mov")
a2cd141b 3406 (set_attr "length" "8")]
3407)
3408
87b22bf7 3409(define_expand "ashrsi3"
cffb2a26 3410 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3411 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3412 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3413 "TARGET_EITHER"
87b22bf7 3414 "
3415 if (GET_CODE (operands[2]) == CONST_INT
3416 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3417 operands[2] = GEN_INT (31);
cffb2a26 3418 "
3419)
3420
25f905c2 3421(define_insn "*thumb1_ashrsi3"
cffb2a26 3422 [(set (match_operand:SI 0 "register_operand" "=l,l")
3423 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3424 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3425 "TARGET_THUMB1"
cffb2a26 3426 "asr\\t%0, %1, %2"
747b7458 3427 [(set_attr "length" "2")
3428 (set_attr "conds" "set")])
b11cae9e 3429
a2cd141b 3430(define_expand "lshrdi3"
3431 [(set (match_operand:DI 0 "s_register_operand" "")
3432 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3433 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3434 "TARGET_32BIT"
a2cd141b 3435 "
3436 if (GET_CODE (operands[2]) == CONST_INT)
3437 {
3438 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3439 {
3440 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3441 DONE;
3442 }
3443 /* Ideally we shouldn't fail here if we could know that operands[1]
3444 ends up already living in an iwmmxt register. Otherwise it's
3445 cheaper to have the alternate code being generated than moving
1d60d981 3446 values to iwmmxt regs and back. */
a2cd141b 3447 FAIL;
3448 }
3449 else if (!TARGET_REALLY_IWMMXT)
3450 FAIL;
3451 "
3452)
3453
3454(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3455 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3456 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3457 (const_int 1)))
3458 (clobber (reg:CC CC_REGNUM))]
25f905c2 3459 "TARGET_32BIT"
a2cd141b 3460 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3461 [(set_attr "conds" "clob")
d2a518d1 3462 (set_attr "insn" "mov")
a2cd141b 3463 (set_attr "length" "8")]
3464)
3465
87b22bf7 3466(define_expand "lshrsi3"
cffb2a26 3467 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3468 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3469 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3470 "TARGET_EITHER"
87b22bf7 3471 "
3472 if (GET_CODE (operands[2]) == CONST_INT
3473 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3474 {
3475 emit_insn (gen_movsi (operands[0], const0_rtx));
3476 DONE;
3477 }
cffb2a26 3478 "
3479)
3480
25f905c2 3481(define_insn "*thumb1_lshrsi3"
cffb2a26 3482 [(set (match_operand:SI 0 "register_operand" "=l,l")
3483 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3484 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3485 "TARGET_THUMB1"
cffb2a26 3486 "lsr\\t%0, %1, %2"
747b7458 3487 [(set_attr "length" "2")
3488 (set_attr "conds" "set")])
b11cae9e 3489
87b22bf7 3490(define_expand "rotlsi3"
cffb2a26 3491 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3492 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3493 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3494 "TARGET_32BIT"
87b22bf7 3495 "
3496 if (GET_CODE (operands[2]) == CONST_INT)
3497 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3498 else
b11cae9e 3499 {
87b22bf7 3500 rtx reg = gen_reg_rtx (SImode);
3501 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3502 operands[2] = reg;
b11cae9e 3503 }
cffb2a26 3504 "
3505)
9c08d1fa 3506
87b22bf7 3507(define_expand "rotrsi3"
cffb2a26 3508 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3509 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3510 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3511 "TARGET_EITHER"
87b22bf7 3512 "
25f905c2 3513 if (TARGET_32BIT)
cffb2a26 3514 {
3515 if (GET_CODE (operands[2]) == CONST_INT
3516 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3517 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3518 }
25f905c2 3519 else /* TARGET_THUMB1 */
cffb2a26 3520 {
3521 if (GET_CODE (operands [2]) == CONST_INT)
3522 operands [2] = force_reg (SImode, operands[2]);
3523 }
3524 "
3525)
87b22bf7 3526
25f905c2 3527(define_insn "*thumb1_rotrsi3"
cffb2a26 3528 [(set (match_operand:SI 0 "register_operand" "=l")
3529 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3530 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3531 "TARGET_THUMB1"
cffb2a26 3532 "ror\\t%0, %0, %2"
3533 [(set_attr "length" "2")]
3534)
3535
3536(define_insn "*arm_shiftsi3"
3537 [(set (match_operand:SI 0 "s_register_operand" "=r")
3538 (match_operator:SI 3 "shift_operator"
3539 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3540 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3541 "TARGET_32BIT"
3542 "* return arm_output_shift(operands, 0);"
344495ea 3543 [(set_attr "predicable" "yes")
331beb1a 3544 (set_attr "shift" "1")
a2cd141b 3545 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3546 (const_string "alu_shift")
3547 (const_string "alu_shift_reg")))]
6c4c2133 3548)
87b22bf7 3549
f7fbdd4a 3550(define_insn "*shiftsi3_compare0"
bd5b4116 3551 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3552 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3553 [(match_operand:SI 1 "s_register_operand" "r")
3554 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3555 (const_int 0)))
3556 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3557 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3558 "TARGET_32BIT"
3559 "* return arm_output_shift(operands, 1);"
344495ea 3560 [(set_attr "conds" "set")
331beb1a 3561 (set_attr "shift" "1")
a2cd141b 3562 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3563 (const_string "alu_shift")
3564 (const_string "alu_shift_reg")))]
0d66636f 3565)
9c08d1fa 3566
f7fbdd4a 3567(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3568 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3569 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3570 [(match_operand:SI 1 "s_register_operand" "r")
3571 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3572 (const_int 0)))
3573 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3574 "TARGET_32BIT"
3575 "* return arm_output_shift(operands, 1);"
344495ea 3576 [(set_attr "conds" "set")
a2cd141b 3577 (set_attr "shift" "1")]
0d66636f 3578)
9c08d1fa 3579
d5d4dc8d 3580(define_insn "*not_shiftsi"
3581 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3582 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3583 [(match_operand:SI 1 "s_register_operand" "r,r")
3584 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3585 "TARGET_32BIT"
6c4c2133 3586 "mvn%?\\t%0, %1%S3"
344495ea 3587 [(set_attr "predicable" "yes")
331beb1a 3588 (set_attr "shift" "1")
d2a518d1 3589 (set_attr "insn" "mvn")
d5d4dc8d 3590 (set_attr "arch" "32,a")
3591 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3592
d5d4dc8d 3593(define_insn "*not_shiftsi_compare0"
bd5b4116 3594 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3595 (compare:CC_NOOV
3596 (not:SI (match_operator:SI 3 "shift_operator"
3597 [(match_operand:SI 1 "s_register_operand" "r,r")
3598 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3599 (const_int 0)))
3600 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3601 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3602 "TARGET_32BIT"
25f905c2 3603 "mvn%.\\t%0, %1%S3"
344495ea 3604 [(set_attr "conds" "set")
331beb1a 3605 (set_attr "shift" "1")
d2a518d1 3606 (set_attr "insn" "mvn")
d5d4dc8d 3607 (set_attr "arch" "32,a")
3608 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3609
d5d4dc8d 3610(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3611 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3612 (compare:CC_NOOV
3613 (not:SI (match_operator:SI 3 "shift_operator"
3614 [(match_operand:SI 1 "s_register_operand" "r,r")
3615 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3616 (const_int 0)))
3617 (clobber (match_scratch:SI 0 "=r,r"))]
3618 "TARGET_32BIT"
25f905c2 3619 "mvn%.\\t%0, %1%S3"
344495ea 3620 [(set_attr "conds" "set")
331beb1a 3621 (set_attr "shift" "1")
d2a518d1 3622 (set_attr "insn" "mvn")
d5d4dc8d 3623 (set_attr "arch" "32,a")
3624 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3625
cffb2a26 3626;; We don't really have extzv, but defining this using shifts helps
3627;; to reduce register pressure later on.
3628
3629(define_expand "extzv"
3630 [(set (match_dup 4)
3631 (ashift:SI (match_operand:SI 1 "register_operand" "")
3632 (match_operand:SI 2 "const_int_operand" "")))
3633 (set (match_operand:SI 0 "register_operand" "")
3634 (lshiftrt:SI (match_dup 4)
215b30b3 3635 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3636 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3637 "
3638 {
3639 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3640 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3641
8b054d5a 3642 if (arm_arch_thumb2)
3643 {
3644 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3645 operands[3]));
3646 DONE;
3647 }
3648
cffb2a26 3649 operands[3] = GEN_INT (rshift);
3650
3651 if (lshift == 0)
3652 {
3653 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3654 DONE;
3655 }
3656
3657 operands[2] = GEN_INT (lshift);
3658 operands[4] = gen_reg_rtx (SImode);
215b30b3 3659 }"
cffb2a26 3660)
3661
8b054d5a 3662(define_insn "extv"
3663 [(set (match_operand:SI 0 "s_register_operand" "=r")
3664 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3665 (match_operand:SI 2 "const_int_operand" "M")
3666 (match_operand:SI 3 "const_int_operand" "M")))]
3667 "arm_arch_thumb2"
3668 "sbfx%?\t%0, %1, %3, %2"
3669 [(set_attr "length" "4")
3670 (set_attr "predicable" "yes")]
3671)
3672
3673(define_insn "extzv_t2"
3674 [(set (match_operand:SI 0 "s_register_operand" "=r")
3675 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3676 (match_operand:SI 2 "const_int_operand" "M")
3677 (match_operand:SI 3 "const_int_operand" "M")))]
3678 "arm_arch_thumb2"
3679 "ubfx%?\t%0, %1, %3, %2"
3680 [(set_attr "length" "4")
3681 (set_attr "predicable" "yes")]
3682)
3683
b11cae9e 3684\f
3685;; Unary arithmetic insns
3686
cffb2a26 3687(define_expand "negdi2"
3688 [(parallel
8135a42b 3689 [(set (match_operand:DI 0 "s_register_operand" "")
3690 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3691 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3692 "TARGET_EITHER"
8135a42b 3693 ""
cffb2a26 3694)
3695
3696;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 3697;; The first alternative allows the common case of a *full* overlap.
cffb2a26 3698(define_insn "*arm_negdi2"
3699 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3700 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 3701 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3702 "TARGET_ARM"
97499065 3703 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3704 [(set_attr "conds" "clob")
3705 (set_attr "length" "8")]
3706)
b11cae9e 3707
25f905c2 3708(define_insn "*thumb1_negdi2"
8135a42b 3709 [(set (match_operand:DI 0 "register_operand" "=&l")
3710 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3711 (clobber (reg:CC CC_REGNUM))]
25f905c2 3712 "TARGET_THUMB1"
cffb2a26 3713 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3714 [(set_attr "length" "6")]
3715)
3716
3717(define_expand "negsi2"
3718 [(set (match_operand:SI 0 "s_register_operand" "")
3719 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3720 "TARGET_EITHER"
b11cae9e 3721 ""
cffb2a26 3722)
3723
3724(define_insn "*arm_negsi2"
3725 [(set (match_operand:SI 0 "s_register_operand" "=r")
3726 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3727 "TARGET_32BIT"
cffb2a26 3728 "rsb%?\\t%0, %1, #0"
0d66636f 3729 [(set_attr "predicable" "yes")]
cffb2a26 3730)
3731
25f905c2 3732(define_insn "*thumb1_negsi2"
cffb2a26 3733 [(set (match_operand:SI 0 "register_operand" "=l")
3734 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3735 "TARGET_THUMB1"
cffb2a26 3736 "neg\\t%0, %1"
3737 [(set_attr "length" "2")]
3738)
b11cae9e 3739
604f3a0a 3740(define_expand "negsf2"
3741 [(set (match_operand:SF 0 "s_register_operand" "")
3742 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3743 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3744 ""
3745)
3746
3747(define_expand "negdf2"
3748 [(set (match_operand:DF 0 "s_register_operand" "")
3749 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3750 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3751 "")
3752
9c08d1fa 3753;; abssi2 doesn't really clobber the condition codes if a different register
3754;; is being set. To keep things simple, assume during rtl manipulations that
3755;; it does, but tell the final scan operator the truth. Similarly for
3756;; (neg (abs...))
3757
604f3a0a 3758(define_expand "abssi2"
3759 [(parallel
3760 [(set (match_operand:SI 0 "s_register_operand" "")
3761 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3762 (clobber (match_dup 2))])]
3763 "TARGET_EITHER"
3764 "
25f905c2 3765 if (TARGET_THUMB1)
ba156559 3766 operands[2] = gen_rtx_SCRATCH (SImode);
3767 else
3768 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3769")
604f3a0a 3770
7d57ec45 3771(define_insn "*arm_abssi2"
ba156559 3772 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3773 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3774 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3775 "TARGET_ARM"
e2348bcb 3776 "@
3777 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3778 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3779 [(set_attr "conds" "clob,*")
331beb1a 3780 (set_attr "shift" "1")
0d66636f 3781 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3782 (set_attr "length" "8")]
3783)
9c08d1fa 3784
25f905c2 3785(define_insn_and_split "*thumb1_abssi2"
ba156559 3786 [(set (match_operand:SI 0 "s_register_operand" "=l")
3787 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3788 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3789 "TARGET_THUMB1"
ba156559 3790 "#"
25f905c2 3791 "TARGET_THUMB1 && reload_completed"
ba156559 3792 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3793 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3794 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3795 ""
3796 [(set_attr "length" "6")]
3797)
3798
3799(define_insn "*arm_neg_abssi2"
9c08d1fa 3800 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3801 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3802 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3803 "TARGET_ARM"
e2348bcb 3804 "@
3805 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3806 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3807 [(set_attr "conds" "clob,*")
331beb1a 3808 (set_attr "shift" "1")
0d66636f 3809 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3810 (set_attr "length" "8")]
3811)
b11cae9e 3812
25f905c2 3813(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3814 [(set (match_operand:SI 0 "s_register_operand" "=l")
3815 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3816 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3817 "TARGET_THUMB1"
ba156559 3818 "#"
25f905c2 3819 "TARGET_THUMB1 && reload_completed"
ba156559 3820 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3821 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3822 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3823 ""
3824 [(set_attr "length" "6")]
3825)
3826
604f3a0a 3827(define_expand "abssf2"
3828 [(set (match_operand:SF 0 "s_register_operand" "")
3829 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3830 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3831 "")
3832
604f3a0a 3833(define_expand "absdf2"
3834 [(set (match_operand:DF 0 "s_register_operand" "")
3835 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3836 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3837 "")
3838
7db9af5d 3839(define_expand "sqrtsf2"
3840 [(set (match_operand:SF 0 "s_register_operand" "")
3841 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3842 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3843 "")
9c08d1fa 3844
7db9af5d 3845(define_expand "sqrtdf2"
3846 [(set (match_operand:DF 0 "s_register_operand" "")
3847 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3848 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3849 "")
9c08d1fa 3850
a0f94409 3851(define_insn_and_split "one_cmpldi2"
9c08d1fa 3852 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3853 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3854 "TARGET_32BIT"
f6ebffac 3855 "#"
25f905c2 3856 "TARGET_32BIT && reload_completed"
a0f94409 3857 [(set (match_dup 0) (not:SI (match_dup 1)))
3858 (set (match_dup 2) (not:SI (match_dup 3)))]
3859 "
3860 {
3861 operands[2] = gen_highpart (SImode, operands[0]);
3862 operands[0] = gen_lowpart (SImode, operands[0]);
3863 operands[3] = gen_highpart (SImode, operands[1]);
3864 operands[1] = gen_lowpart (SImode, operands[1]);
3865 }"
0d66636f 3866 [(set_attr "length" "8")
3867 (set_attr "predicable" "yes")]
cffb2a26 3868)
b11cae9e 3869
cffb2a26 3870(define_expand "one_cmplsi2"
3871 [(set (match_operand:SI 0 "s_register_operand" "")
3872 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3873 "TARGET_EITHER"
b11cae9e 3874 ""
cffb2a26 3875)
3876
3877(define_insn "*arm_one_cmplsi2"
3878 [(set (match_operand:SI 0 "s_register_operand" "=r")
3879 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3880 "TARGET_32BIT"
cffb2a26 3881 "mvn%?\\t%0, %1"
d2a518d1 3882 [(set_attr "predicable" "yes")
3883 (set_attr "insn" "mvn")]
cffb2a26 3884)
3885
25f905c2 3886(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3887 [(set (match_operand:SI 0 "register_operand" "=l")
3888 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3889 "TARGET_THUMB1"
cffb2a26 3890 "mvn\\t%0, %1"
d2a518d1 3891 [(set_attr "length" "2")
3892 (set_attr "insn" "mvn")]
cffb2a26 3893)
9c08d1fa 3894
f7fbdd4a 3895(define_insn "*notsi_compare0"
bd5b4116 3896 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3897 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3898 (const_int 0)))
3899 (set (match_operand:SI 0 "s_register_operand" "=r")
3900 (not:SI (match_dup 1)))]
25f905c2 3901 "TARGET_32BIT"
3902 "mvn%.\\t%0, %1"
d2a518d1 3903 [(set_attr "conds" "set")
3904 (set_attr "insn" "mvn")]
cffb2a26 3905)
9c08d1fa 3906
f7fbdd4a 3907(define_insn "*notsi_compare0_scratch"
bd5b4116 3908 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3909 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3910 (const_int 0)))
3911 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3912 "TARGET_32BIT"
3913 "mvn%.\\t%0, %1"
d2a518d1 3914 [(set_attr "conds" "set")
3915 (set_attr "insn" "mvn")]
cffb2a26 3916)
b11cae9e 3917\f
3918;; Fixed <--> Floating conversion insns
3919
9b8516be 3920(define_expand "floatsihf2"
3921 [(set (match_operand:HF 0 "general_operand" "")
3922 (float:HF (match_operand:SI 1 "general_operand" "")))]
3923 "TARGET_EITHER"
3924 "
3925 {
3926 rtx op1 = gen_reg_rtx (SFmode);
3927 expand_float (op1, operands[1], 0);
3928 op1 = convert_to_mode (HFmode, op1, 0);
3929 emit_move_insn (operands[0], op1);
3930 DONE;
3931 }"
3932)
3933
3934(define_expand "floatdihf2"
3935 [(set (match_operand:HF 0 "general_operand" "")
3936 (float:HF (match_operand:DI 1 "general_operand" "")))]
3937 "TARGET_EITHER"
3938 "
3939 {
3940 rtx op1 = gen_reg_rtx (SFmode);
3941 expand_float (op1, operands[1], 0);
3942 op1 = convert_to_mode (HFmode, op1, 0);
3943 emit_move_insn (operands[0], op1);
3944 DONE;
3945 }"
3946)
3947
604f3a0a 3948(define_expand "floatsisf2"
3949 [(set (match_operand:SF 0 "s_register_operand" "")
3950 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3951 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3952 "
a2cd141b 3953 if (TARGET_MAVERICK)
604f3a0a 3954 {
3955 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3956 DONE;
3957 }
3958")
3959
604f3a0a 3960(define_expand "floatsidf2"
3961 [(set (match_operand:DF 0 "s_register_operand" "")
3962 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 3963 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3964 "
a2cd141b 3965 if (TARGET_MAVERICK)
604f3a0a 3966 {
3967 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3968 DONE;
3969 }
3970")
3971
9b8516be 3972(define_expand "fix_trunchfsi2"
3973 [(set (match_operand:SI 0 "general_operand" "")
3974 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3975 "TARGET_EITHER"
3976 "
3977 {
3978 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3979 expand_fix (operands[0], op1, 0);
3980 DONE;
3981 }"
3982)
3983
3984(define_expand "fix_trunchfdi2"
3985 [(set (match_operand:DI 0 "general_operand" "")
3986 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3987 "TARGET_EITHER"
3988 "
3989 {
3990 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3991 expand_fix (operands[0], op1, 0);
3992 DONE;
3993 }"
3994)
3995
604f3a0a 3996(define_expand "fix_truncsfsi2"
3997 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3998 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3999 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4000 "
a2cd141b 4001 if (TARGET_MAVERICK)
604f3a0a 4002 {
4003 if (!cirrus_fp_register (operands[0], SImode))
4004 operands[0] = force_reg (SImode, operands[0]);
4005 if (!cirrus_fp_register (operands[1], SFmode))
4006 operands[1] = force_reg (SFmode, operands[0]);
4007 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4008 DONE;
4009 }
4010")
4011
604f3a0a 4012(define_expand "fix_truncdfsi2"
4013 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4014 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4015 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4016 "
a2cd141b 4017 if (TARGET_MAVERICK)
604f3a0a 4018 {
4019 if (!cirrus_fp_register (operands[1], DFmode))
4020 operands[1] = force_reg (DFmode, operands[0]);
4021 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4022 DONE;
4023 }
4024")
4025
f544c6d2 4026;; Truncation insns
b11cae9e 4027
604f3a0a 4028(define_expand "truncdfsf2"
4029 [(set (match_operand:SF 0 "s_register_operand" "")
4030 (float_truncate:SF
4031 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4032 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4033 ""
4034)
9b8516be 4035
4036/* DFmode -> HFmode conversions have to go through SFmode. */
4037(define_expand "truncdfhf2"
4038 [(set (match_operand:HF 0 "general_operand" "")
4039 (float_truncate:HF
4040 (match_operand:DF 1 "general_operand" "")))]
4041 "TARGET_EITHER"
4042 "
4043 {
4044 rtx op1;
4045 op1 = convert_to_mode (SFmode, operands[1], 0);
4046 op1 = convert_to_mode (HFmode, op1, 0);
4047 emit_move_insn (operands[0], op1);
4048 DONE;
4049 }"
4050)
b11cae9e 4051\f
9c08d1fa 4052;; Zero and sign extension instructions.
b11cae9e 4053
848e66ac 4054(define_insn "zero_extend<mode>di2"
4055 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4056 (zero_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4057 "<qhs_extenddi_cstr>")))]
848e66ac 4058 "TARGET_32BIT <qhs_zextenddi_cond>"
4059 "#"
4060 [(set_attr "length" "8")
4061 (set_attr "ce_count" "2")
4062 (set_attr "predicable" "yes")]
25f905c2 4063)
4064
848e66ac 4065(define_insn "extend<mode>di2"
9c08d1fa 4066 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4067 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4068 "<qhs_extenddi_cstr>")))]
848e66ac 4069 "TARGET_32BIT <qhs_sextenddi_cond>"
4070 "#"
0d66636f 4071 [(set_attr "length" "8")
848e66ac 4072 (set_attr "ce_count" "2")
4073 (set_attr "shift" "1")
0d66636f 4074 (set_attr "predicable" "yes")]
4075)
9c08d1fa 4076
848e66ac 4077;; Splits for all extensions to DImode
4078(define_split
4079 [(set (match_operand:DI 0 "s_register_operand" "")
4080 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4081 "TARGET_32BIT"
848e66ac 4082 [(set (match_dup 0) (match_dup 1))]
4083{
848e66ac 4084 rtx lo_part = gen_lowpart (SImode, operands[0]);
4085 enum machine_mode src_mode = GET_MODE (operands[1]);
4086
4087 if (REG_P (operands[0])
4088 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4089 emit_clobber (operands[0]);
4090 if (!REG_P (lo_part) || src_mode != SImode
4091 || !rtx_equal_p (lo_part, operands[1]))
4092 {
4093 if (src_mode == SImode)
4094 emit_move_insn (lo_part, operands[1]);
4095 else
4096 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4097 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4098 operands[1] = lo_part;
4099 }
4100 operands[0] = gen_highpart (SImode, operands[0]);
4101 operands[1] = const0_rtx;
4102})
9c08d1fa 4103
848e66ac 4104(define_split
25f905c2 4105 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4106 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4107 "TARGET_32BIT"
848e66ac 4108 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4109{
4110 rtx lo_part = gen_lowpart (SImode, operands[0]);
4111 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4112
848e66ac 4113 if (REG_P (operands[0])
4114 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4115 emit_clobber (operands[0]);
4116
4117 if (!REG_P (lo_part) || src_mode != SImode
4118 || !rtx_equal_p (lo_part, operands[1]))
4119 {
4120 if (src_mode == SImode)
4121 emit_move_insn (lo_part, operands[1]);
4122 else
4123 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4124 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4125 operands[1] = lo_part;
4126 }
4127 operands[0] = gen_highpart (SImode, operands[0]);
4128})
9c08d1fa 4129
4130(define_expand "zero_extendhisi2"
ef51b8e1 4131 [(set (match_operand:SI 0 "s_register_operand" "")
4132 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4133 "TARGET_EITHER"
ef51b8e1 4134{
4135 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4136 {
ef51b8e1 4137 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4138 DONE;
25f7a26e 4139 }
ef51b8e1 4140 if (!arm_arch6 && !MEM_P (operands[1]))
4141 {
4142 rtx t = gen_lowpart (SImode, operands[1]);
4143 rtx tmp = gen_reg_rtx (SImode);
4144 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4145 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4146 DONE;
4147 }
4148})
9c08d1fa 4149
ef51b8e1 4150(define_split
b146458f 4151 [(set (match_operand:SI 0 "s_register_operand" "")
4152 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4153 "!TARGET_THUMB2 && !arm_arch6"
4154 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4155 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4156{
4157 operands[2] = gen_lowpart (SImode, operands[1]);
4158})
4159
4160(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4161 [(set (match_operand:SI 0 "register_operand" "=l,l")
4162 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4163 "TARGET_THUMB1"
848e66ac 4164{
a2cd141b 4165 rtx mem;
4166
ef51b8e1 4167 if (which_alternative == 0 && arm_arch6)
848e66ac 4168 return "uxth\t%0, %1";
ef51b8e1 4169 if (which_alternative == 0)
848e66ac 4170 return "#";
a2cd141b 4171
4172 mem = XEXP (operands[1], 0);
4173
4174 if (GET_CODE (mem) == CONST)
4175 mem = XEXP (mem, 0);
4176
a2cd141b 4177 if (GET_CODE (mem) == PLUS)
4178 {
4179 rtx a = XEXP (mem, 0);
a2cd141b 4180
4181 /* This can happen due to bugs in reload. */
4182 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4183 {
4184 rtx ops[2];
4185 ops[0] = operands[0];
4186 ops[1] = a;
4187
848e66ac 4188 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4189
4190 XEXP (mem, 0) = operands[0];
4191 }
a2cd141b 4192 }
4193
848e66ac 4194 return "ldrh\t%0, %1";
4195}
ef51b8e1 4196 [(set_attr_alternative "length"
4197 [(if_then_else (eq_attr "is_arch6" "yes")
4198 (const_int 2) (const_int 4))
4199 (const_int 4)])
848e66ac 4200 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4201)
4202
cffb2a26 4203(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4204 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4205 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4206 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4207 "@
4208 #
4209 ldr%(h%)\\t%0, %1"
4210 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4211 (set_attr "predicable" "yes")]
cffb2a26 4212)
f7fbdd4a 4213
a2cd141b 4214(define_insn "*arm_zero_extendhisi2_v6"
4215 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4216 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4217 "TARGET_ARM && arm_arch6"
4218 "@
4219 uxth%?\\t%0, %1
25f905c2 4220 ldr%(h%)\\t%0, %1"
a2cd141b 4221 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4222 (set_attr "predicable" "yes")]
a2cd141b 4223)
4224
4225(define_insn "*arm_zero_extendhisi2addsi"
4226 [(set (match_operand:SI 0 "s_register_operand" "=r")
4227 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4228 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4229 "TARGET_INT_SIMD"
a2cd141b 4230 "uxtah%?\\t%0, %2, %1"
4231 [(set_attr "type" "alu_shift")
4232 (set_attr "predicable" "yes")]
4233)
4234
87b22bf7 4235(define_expand "zero_extendqisi2"
cffb2a26 4236 [(set (match_operand:SI 0 "s_register_operand" "")
4237 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4238 "TARGET_EITHER"
ef51b8e1 4239{
4240 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4241 {
ef51b8e1 4242 emit_insn (gen_andsi3 (operands[0],
4243 gen_lowpart (SImode, operands[1]),
4244 GEN_INT (255)));
4245 DONE;
4246 }
4247 if (!arm_arch6 && !MEM_P (operands[1]))
4248 {
4249 rtx t = gen_lowpart (SImode, operands[1]);
4250 rtx tmp = gen_reg_rtx (SImode);
4251 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4252 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4253 DONE;
4254 }
4255})
cffb2a26 4256
ef51b8e1 4257(define_split
b146458f 4258 [(set (match_operand:SI 0 "s_register_operand" "")
4259 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4260 "!arm_arch6"
4261 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4262 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4263{
4264 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4265 if (TARGET_ARM)
4266 {
4267 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4268 DONE;
4269 }
ef51b8e1 4270})
9c08d1fa 4271
25f905c2 4272(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4273 [(set (match_operand:SI 0 "register_operand" "=l,l")
4274 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4275 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4276 "@
4277 #
4278 ldrb\\t%0, %1"
4279 [(set_attr "length" "4,2")
4280 (set_attr "type" "alu_shift,load_byte")
4281 (set_attr "pool_range" "*,32")]
cffb2a26 4282)
4283
25f905c2 4284(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4285 [(set (match_operand:SI 0 "register_operand" "=l,l")
4286 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4287 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4288 "@
4289 uxtb\\t%0, %1
4290 ldrb\\t%0, %1"
848e66ac 4291 [(set_attr "length" "2")
4292 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4293)
4294
cffb2a26 4295(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4296 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4297 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4298 "TARGET_ARM && !arm_arch6"
ef51b8e1 4299 "@
4300 #
4301 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4302 [(set_attr "length" "8,4")
4303 (set_attr "type" "alu_shift,load_byte")
848e66ac 4304 (set_attr "predicable" "yes")]
cffb2a26 4305)
87b22bf7 4306
a2cd141b 4307(define_insn "*arm_zero_extendqisi2_v6"
4308 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4309 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4310 "TARGET_ARM && arm_arch6"
4311 "@
25f905c2 4312 uxtb%(%)\\t%0, %1
4313 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4314 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4315 (set_attr "predicable" "yes")]
a2cd141b 4316)
4317
4318(define_insn "*arm_zero_extendqisi2addsi"
4319 [(set (match_operand:SI 0 "s_register_operand" "=r")
4320 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4321 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4322 "TARGET_INT_SIMD"
a2cd141b 4323 "uxtab%?\\t%0, %2, %1"
4324 [(set_attr "predicable" "yes")
bcaec148 4325 (set_attr "insn" "xtab")
a2cd141b 4326 (set_attr "type" "alu_shift")]
4327)
4328
87b22bf7 4329(define_split
4330 [(set (match_operand:SI 0 "s_register_operand" "")
4331 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4332 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4333 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4334 [(set (match_dup 2) (match_dup 1))
4335 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4336 ""
4337)
9c08d1fa 4338
8a4d25d6 4339(define_split
4340 [(set (match_operand:SI 0 "s_register_operand" "")
4341 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4342 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4343 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4344 [(set (match_dup 2) (match_dup 1))
4345 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4346 ""
4347)
4348
1c274529 4349
4350(define_split
4351 [(set (match_operand:SI 0 "s_register_operand" "")
4352 (ior_xor:SI (and:SI (ashift:SI
4353 (match_operand:SI 1 "s_register_operand" "")
4354 (match_operand:SI 2 "const_int_operand" ""))
4355 (match_operand:SI 3 "const_int_operand" ""))
4356 (zero_extend:SI
4357 (match_operator 5 "subreg_lowpart_operator"
4358 [(match_operand:SI 4 "s_register_operand" "")]))))]
4359 "TARGET_32BIT
63787642 4360 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4361 == (GET_MODE_MASK (GET_MODE (operands[5]))
4362 & (GET_MODE_MASK (GET_MODE (operands[5]))
4363 << (INTVAL (operands[2])))))"
4364 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4365 (match_dup 4)))
4366 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4367 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4368)
4369
f7fbdd4a 4370(define_insn "*compareqi_eq0"
bd5b4116 4371 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4372 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4373 (const_int 0)))]
25f905c2 4374 "TARGET_32BIT"
87b22bf7 4375 "tst\\t%0, #255"
cffb2a26 4376 [(set_attr "conds" "set")]
4377)
b11cae9e 4378
b11cae9e 4379(define_expand "extendhisi2"
ef51b8e1 4380 [(set (match_operand:SI 0 "s_register_operand" "")
4381 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4382 "TARGET_EITHER"
ef51b8e1 4383{
4384 if (TARGET_THUMB1)
4385 {
4386 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4387 DONE;
4388 }
4389 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4390 {
4391 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4392 DONE;
4393 }
ed29c566 4394
ef51b8e1 4395 if (!arm_arch6 && !MEM_P (operands[1]))
4396 {
4397 rtx t = gen_lowpart (SImode, operands[1]);
4398 rtx tmp = gen_reg_rtx (SImode);
4399 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4400 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4401 DONE;
4402 }
4403})
cffb2a26 4404
ef51b8e1 4405(define_split
4406 [(parallel
4407 [(set (match_operand:SI 0 "register_operand" "")
4408 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4409 (clobber (match_scratch:SI 2 ""))])]
4410 "!arm_arch6"
4411 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4412 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4413{
4414 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4415})
25f7a26e 4416
a2cd141b 4417;; We used to have an early-clobber on the scratch register here.
4418;; However, there's a bug somewhere in reload which means that this
4419;; can be partially ignored during spill allocation if the memory
ed29c566 4420;; address also needs reloading; this causes us to die later on when
a2cd141b 4421;; we try to verify the operands. Fortunately, we don't really need
4422;; the early-clobber: we can always use operand 0 if operand 2
4423;; overlaps the address.
ef51b8e1 4424(define_insn "thumb1_extendhisi2"
a2cd141b 4425 [(set (match_operand:SI 0 "register_operand" "=l,l")
4426 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4427 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4428 "TARGET_THUMB1"
a2cd141b 4429 "*
4430 {
4431 rtx ops[4];
4432 rtx mem;
4433
ef51b8e1 4434 if (which_alternative == 0 && !arm_arch6)
4435 return \"#\";
a2cd141b 4436 if (which_alternative == 0)
4437 return \"sxth\\t%0, %1\";
4438
4439 mem = XEXP (operands[1], 0);
4440
4441 /* This code used to try to use 'V', and fix the address only if it was
4442 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4443 range of QImode offsets, and offsettable_address_p does a QImode
4444 address check. */
4445
4446 if (GET_CODE (mem) == CONST)
4447 mem = XEXP (mem, 0);
4448
4449 if (GET_CODE (mem) == LABEL_REF)
4450 return \"ldr\\t%0, %1\";
4451
4452 if (GET_CODE (mem) == PLUS)
4453 {
4454 rtx a = XEXP (mem, 0);
4455 rtx b = XEXP (mem, 1);
4456
4457 if (GET_CODE (a) == LABEL_REF
4458 && GET_CODE (b) == CONST_INT)
4459 return \"ldr\\t%0, %1\";
4460
4461 if (GET_CODE (b) == REG)
4462 return \"ldrsh\\t%0, %1\";
4463
4464 ops[1] = a;
4465 ops[2] = b;
4466 }
4467 else
4468 {
4469 ops[1] = mem;
4470 ops[2] = const0_rtx;
4471 }
4472
ed29c566 4473 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4474
4475 ops[0] = operands[0];
4476 if (reg_mentioned_p (operands[2], ops[1]))
4477 ops[3] = ops[0];
4478 else
4479 ops[3] = operands[2];
4480 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4481 return \"\";
4482 }"
ef51b8e1 4483 [(set_attr_alternative "length"
4484 [(if_then_else (eq_attr "is_arch6" "yes")
4485 (const_int 2) (const_int 4))
4486 (const_int 4)])
a2cd141b 4487 (set_attr "type" "alu_shift,load_byte")
4488 (set_attr "pool_range" "*,1020")]
4489)
4490
25f905c2 4491;; This pattern will only be used when ldsh is not available
25f7a26e 4492(define_expand "extendhisi2_mem"
eab14235 4493 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4494 (set (match_dup 3)
eab14235 4495 (zero_extend:SI (match_dup 7)))
25f7a26e 4496 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4497 (set (match_operand:SI 0 "" "")
4498 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4499 "TARGET_ARM"
25f7a26e 4500 "
215b30b3 4501 {
4502 rtx mem1, mem2;
4503 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4504
788fcce0 4505 mem1 = change_address (operands[1], QImode, addr);
4506 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4507 operands[0] = gen_lowpart (SImode, operands[0]);
4508 operands[1] = mem1;
4509 operands[2] = gen_reg_rtx (SImode);
4510 operands[3] = gen_reg_rtx (SImode);
4511 operands[6] = gen_reg_rtx (SImode);
4512 operands[7] = mem2;
25f7a26e 4513
215b30b3 4514 if (BYTES_BIG_ENDIAN)
4515 {
4516 operands[4] = operands[2];
4517 operands[5] = operands[3];
4518 }
4519 else
4520 {
4521 operands[4] = operands[3];
4522 operands[5] = operands[2];
4523 }
4524 }"
4525)
b11cae9e 4526
ef51b8e1 4527(define_split
4528 [(set (match_operand:SI 0 "register_operand" "")
4529 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4530 "!arm_arch6"
4531 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4532 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4533{
4534 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4535})
4536
a2cd141b 4537(define_insn "*arm_extendhisi2"
ef51b8e1 4538 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4539 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4540 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4541 "@
4542 #
4543 ldr%(sh%)\\t%0, %1"
4544 [(set_attr "length" "8,4")
4545 (set_attr "type" "alu_shift,load_byte")
0d66636f 4546 (set_attr "predicable" "yes")
ef51b8e1 4547 (set_attr "pool_range" "*,256")
4548 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4549)
f7fbdd4a 4550
25f905c2 4551;; ??? Check Thumb-2 pool range
a2cd141b 4552(define_insn "*arm_extendhisi2_v6"
4553 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4554 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4555 "TARGET_32BIT && arm_arch6"
a2cd141b 4556 "@
4557 sxth%?\\t%0, %1
25f905c2 4558 ldr%(sh%)\\t%0, %1"
a2cd141b 4559 [(set_attr "type" "alu_shift,load_byte")
4560 (set_attr "predicable" "yes")
4561 (set_attr "pool_range" "*,256")
4562 (set_attr "neg_pool_range" "*,244")]
4563)
4564
4565(define_insn "*arm_extendhisi2addsi"
4566 [(set (match_operand:SI 0 "s_register_operand" "=r")
4567 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4568 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4569 "TARGET_INT_SIMD"
a2cd141b 4570 "sxtah%?\\t%0, %2, %1"
4571)
4572
c8f69309 4573(define_expand "extendqihi2"
4574 [(set (match_dup 2)
bed7d9a5 4575 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4576 (const_int 24)))
9c08d1fa 4577 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4578 (ashiftrt:SI (match_dup 2)
4579 (const_int 24)))]
cffb2a26 4580 "TARGET_ARM"
c8f69309 4581 "
215b30b3 4582 {
4583 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4584 {
4585 emit_insn (gen_rtx_SET (VOIDmode,
4586 operands[0],
4587 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4588 DONE;
4589 }
4590 if (!s_register_operand (operands[1], QImode))
4591 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4592 operands[0] = gen_lowpart (SImode, operands[0]);
4593 operands[1] = gen_lowpart (SImode, operands[1]);
4594 operands[2] = gen_reg_rtx (SImode);
4595 }"
4596)
f7fbdd4a 4597
25f905c2 4598(define_insn "*arm_extendqihi_insn"
b4e8a300 4599 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4600 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4601 "TARGET_ARM && arm_arch4"
25f905c2 4602 "ldr%(sb%)\\t%0, %1"
a2cd141b 4603 [(set_attr "type" "load_byte")
0d66636f 4604 (set_attr "predicable" "yes")
cffb2a26 4605 (set_attr "pool_range" "256")
4606 (set_attr "neg_pool_range" "244")]
4607)
3fc2009e 4608
b11cae9e 4609(define_expand "extendqisi2"
ef51b8e1 4610 [(set (match_operand:SI 0 "s_register_operand" "")
4611 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 4612 "TARGET_EITHER"
ef51b8e1 4613{
4614 if (!arm_arch4 && MEM_P (operands[1]))
4615 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4616
ef51b8e1 4617 if (!arm_arch6 && !MEM_P (operands[1]))
4618 {
4619 rtx t = gen_lowpart (SImode, operands[1]);
4620 rtx tmp = gen_reg_rtx (SImode);
4621 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4622 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4623 DONE;
4624 }
4625})
a2cd141b 4626
ef51b8e1 4627(define_split
4628 [(set (match_operand:SI 0 "register_operand" "")
4629 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4630 "!arm_arch6"
4631 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4632 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4633{
4634 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4635})
f7fbdd4a 4636
a2cd141b 4637(define_insn "*arm_extendqisi"
ef51b8e1 4638 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4639 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4640 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4641 "@
4642 #
4643 ldr%(sb%)\\t%0, %1"
4644 [(set_attr "length" "8,4")
4645 (set_attr "type" "alu_shift,load_byte")
0d66636f 4646 (set_attr "predicable" "yes")
ef51b8e1 4647 (set_attr "pool_range" "*,256")
4648 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4649)
3fc2009e 4650
a2cd141b 4651(define_insn "*arm_extendqisi_v6"
4652 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4653 (sign_extend:SI
4654 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4655 "TARGET_ARM && arm_arch6"
b4e8a300 4656 "@
4657 sxtb%?\\t%0, %1
25f905c2 4658 ldr%(sb%)\\t%0, %1"
a2cd141b 4659 [(set_attr "type" "alu_shift,load_byte")
4660 (set_attr "predicable" "yes")
a2cd141b 4661 (set_attr "pool_range" "*,256")
4662 (set_attr "neg_pool_range" "*,244")]
4663)
4664
4665(define_insn "*arm_extendqisi2addsi"
4666 [(set (match_operand:SI 0 "s_register_operand" "=r")
4667 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4668 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4669 "TARGET_INT_SIMD"
a2cd141b 4670 "sxtab%?\\t%0, %2, %1"
4671 [(set_attr "type" "alu_shift")
bcaec148 4672 (set_attr "insn" "xtab")
a2cd141b 4673 (set_attr "predicable" "yes")]
4674)
4675
ef51b8e1 4676(define_split
4677 [(set (match_operand:SI 0 "register_operand" "")
4678 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4679 "TARGET_THUMB1 && reload_completed"
4680 [(set (match_dup 0) (match_dup 2))
4681 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4682{
4683 rtx addr = XEXP (operands[1], 0);
cffb2a26 4684
ef51b8e1 4685 if (GET_CODE (addr) == CONST)
4686 addr = XEXP (addr, 0);
cffb2a26 4687
ef51b8e1 4688 if (GET_CODE (addr) == PLUS
4689 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4690 /* No split necessary. */
4691 FAIL;
4692
4693 if (GET_CODE (addr) == PLUS
4694 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4695 FAIL;
4696
4697 if (reg_overlap_mentioned_p (operands[0], addr))
4698 {
4699 rtx t = gen_lowpart (QImode, operands[0]);
4700 emit_move_insn (t, operands[1]);
4701 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4702 DONE;
4703 }
4704
4705 if (REG_P (addr))
4706 {
4707 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4708 operands[2] = const0_rtx;
4709 }
4710 else if (GET_CODE (addr) != PLUS)
4711 FAIL;
4712 else if (REG_P (XEXP (addr, 0)))
4713 {
4714 operands[2] = XEXP (addr, 1);
4715 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4716 }
4717 else
4718 {
4719 operands[2] = XEXP (addr, 0);
4720 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4721 }
cffb2a26 4722
ef51b8e1 4723 operands[3] = change_address (operands[1], QImode, addr);
4724})
4725
8a3b73a1 4726(define_peephole2
4727 [(set (match_operand:SI 0 "register_operand" "")
4728 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4729 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4730 (set (match_operand:SI 3 "register_operand" "")
4731 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4732 "TARGET_THUMB1
4733 && GET_CODE (XEXP (operands[4], 0)) == PLUS
4734 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4735 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4736 && (peep2_reg_dead_p (3, operands[0])
4737 || rtx_equal_p (operands[0], operands[3]))
4738 && (peep2_reg_dead_p (3, operands[2])
4739 || rtx_equal_p (operands[2], operands[3]))"
4740 [(set (match_dup 2) (match_dup 1))
4741 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4742{
4743 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4744 operands[4] = change_address (operands[4], QImode, addr);
4745})
4746
ef51b8e1 4747(define_insn "thumb1_extendqisi2"
a2cd141b 4748 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4749 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 4750 "TARGET_THUMB1"
4751{
4752 rtx addr;
a2cd141b 4753
ef51b8e1 4754 if (which_alternative == 0 && arm_arch6)
4755 return "sxtb\\t%0, %1";
4756 if (which_alternative == 0)
4757 return "#";
a2cd141b 4758
ef51b8e1 4759 addr = XEXP (operands[1], 0);
4760 if (GET_CODE (addr) == PLUS
4761 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4762 return "ldrsb\\t%0, %1";
a2cd141b 4763
ef51b8e1 4764 return "#";
4765}
4766 [(set_attr_alternative "length"
4767 [(if_then_else (eq_attr "is_arch6" "yes")
4768 (const_int 2) (const_int 4))
4769 (const_int 2)
4770 (if_then_else (eq_attr "is_arch6" "yes")
4771 (const_int 4) (const_int 6))])
4772 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 4773)
4774
caedf871 4775(define_expand "extendsfdf2"
4776 [(set (match_operand:DF 0 "s_register_operand" "")
4777 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4778 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4779 ""
4780)
9b8516be 4781
4782/* HFmode -> DFmode conversions have to go through SFmode. */
4783(define_expand "extendhfdf2"
4784 [(set (match_operand:DF 0 "general_operand" "")
4785 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4786 "TARGET_EITHER"
4787 "
4788 {
4789 rtx op1;
4790 op1 = convert_to_mode (SFmode, operands[1], 0);
4791 op1 = convert_to_mode (DFmode, op1, 0);
4792 emit_insn (gen_movdf (operands[0], op1));
4793 DONE;
4794 }"
4795)
b11cae9e 4796\f
4797;; Move insns (including loads and stores)
4798
4799;; XXX Just some ideas about movti.
9c08d1fa 4800;; I don't think these are a good idea on the arm, there just aren't enough
4801;; registers
b11cae9e 4802;;(define_expand "loadti"
9c08d1fa 4803;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4804;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4805;; "" "")
4806
4807;;(define_expand "storeti"
4808;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4809;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4810;; "" "")
4811
4812;;(define_expand "movti"
4813;; [(set (match_operand:TI 0 "general_operand" "")
4814;; (match_operand:TI 1 "general_operand" ""))]
4815;; ""
4816;; "
4817;;{
4818;; rtx insn;
4819;;
4820;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4821;; operands[1] = copy_to_reg (operands[1]);
4822;; if (GET_CODE (operands[0]) == MEM)
4823;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4824;; else if (GET_CODE (operands[1]) == MEM)
4825;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4826;; else
4827;; FAIL;
4828;;
4829;; emit_insn (insn);
4830;; DONE;
4831;;}")
4832
a2f10574 4833;; Recognize garbage generated above.
b11cae9e 4834
4835;;(define_insn ""
4836;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4837;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4838;; ""
4839;; "*
4840;; {
4841;; register mem = (which_alternative < 3);
0d66636f 4842;; register const char *template;
b11cae9e 4843;;
4844;; operands[mem] = XEXP (operands[mem], 0);
4845;; switch (which_alternative)
4846;; {
4847;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4848;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4849;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4850;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4851;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4852;; case 5: template = \"stmia\\t%0, %M1\"; break;
4853;; }
e2348bcb 4854;; output_asm_insn (template, operands);
4855;; return \"\";
b11cae9e 4856;; }")
4857
cffb2a26 4858(define_expand "movdi"
4859 [(set (match_operand:DI 0 "general_operand" "")
4860 (match_operand:DI 1 "general_operand" ""))]
4861 "TARGET_EITHER"
4862 "
e1ba4a27 4863 if (can_create_pseudo_p ())
cffb2a26 4864 {
b2778788 4865 if (GET_CODE (operands[0]) != REG)
4866 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4867 }
4868 "
4869)
b11cae9e 4870
cffb2a26 4871(define_insn "*arm_movdi"
d51f92df 4872 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4873 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 4874 "TARGET_32BIT
b2778788 4875 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4876 && !TARGET_IWMMXT
4877 && ( register_operand (operands[0], DImode)
4878 || register_operand (operands[1], DImode))"
b11cae9e 4879 "*
d51f92df 4880 switch (which_alternative)
4881 {
4882 case 0:
4883 case 1:
4884 case 2:
4885 return \"#\";
4886 default:
4887 return output_move_double (operands);
4888 }
cffb2a26 4889 "
359a6e9f 4890 [(set_attr "length" "8,12,16,8,8")
4891 (set_attr "type" "*,*,*,load2,store2")
cde1623a 4892 (set_attr "arm_pool_range" "*,*,*,1020,*")
4893 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
4894 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
4895 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 4896)
4897
d51f92df 4898(define_split
4899 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4900 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4901 "TARGET_32BIT
d51f92df 4902 && reload_completed
4903 && (arm_const_double_inline_cost (operands[1])
4904 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4905 [(const_int 0)]
4906 "
4907 arm_split_constant (SET, SImode, curr_insn,
4908 INTVAL (gen_lowpart (SImode, operands[1])),
4909 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4910 arm_split_constant (SET, SImode, curr_insn,
4911 INTVAL (gen_highpart_mode (SImode,
4912 GET_MODE (operands[0]),
4913 operands[1])),
4914 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4915 DONE;
4916 "
4917)
4918
e5ba9289 4919; If optimizing for size, or if we have load delay slots, then
4920; we want to split the constant into two separate operations.
4921; In both cases this may split a trivial part into a single data op
4922; leaving a single complex constant to load. We can also get longer
4923; offsets in a LDR which means we get better chances of sharing the pool
4924; entries. Finally, we can normally do a better job of scheduling
4925; LDR instructions than we can with LDM.
4926; This pattern will only match if the one above did not.
4927(define_split
4928 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4929 (match_operand:ANY64 1 "const_double_operand" ""))]
4930 "TARGET_ARM && reload_completed
4931 && arm_const_double_by_parts (operands[1])"
4932 [(set (match_dup 0) (match_dup 1))
4933 (set (match_dup 2) (match_dup 3))]
4934 "
4935 operands[2] = gen_highpart (SImode, operands[0]);
4936 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4937 operands[1]);
4938 operands[0] = gen_lowpart (SImode, operands[0]);
4939 operands[1] = gen_lowpart (SImode, operands[1]);
4940 "
4941)
4942
d51f92df 4943(define_split
4944 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4945 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4946 "TARGET_EITHER && reload_completed"
4947 [(set (match_dup 0) (match_dup 1))
4948 (set (match_dup 2) (match_dup 3))]
4949 "
4950 operands[2] = gen_highpart (SImode, operands[0]);
4951 operands[3] = gen_highpart (SImode, operands[1]);
4952 operands[0] = gen_lowpart (SImode, operands[0]);
4953 operands[1] = gen_lowpart (SImode, operands[1]);
4954
4955 /* Handle a partial overlap. */
4956 if (rtx_equal_p (operands[0], operands[3]))
4957 {
4958 rtx tmp0 = operands[0];
4959 rtx tmp1 = operands[1];
4960
4961 operands[0] = operands[2];
4962 operands[1] = operands[3];
4963 operands[2] = tmp0;
4964 operands[3] = tmp1;
4965 }
4966 "
4967)
4968
a8a3b539 4969;; We can't actually do base+index doubleword loads if the index and
4970;; destination overlap. Split here so that we at least have chance to
4971;; schedule.
4972(define_split
4973 [(set (match_operand:DI 0 "s_register_operand" "")
4974 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4975 (match_operand:SI 2 "s_register_operand" ""))))]
4976 "TARGET_LDRD
4977 && reg_overlap_mentioned_p (operands[0], operands[1])
4978 && reg_overlap_mentioned_p (operands[0], operands[2])"
4979 [(set (match_dup 4)
4980 (plus:SI (match_dup 1)
4981 (match_dup 2)))
4982 (set (match_dup 0)
4983 (mem:DI (match_dup 4)))]
4984 "
4985 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4986 "
4987)
4988
cffb2a26 4989;;; ??? This should have alternatives for constants.
4990;;; ??? This was originally identical to the movdf_insn pattern.
4991;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4992;;; thumb_reorg with a memory reference.
25f905c2 4993(define_insn "*thumb1_movdi_insn"
215b30b3 4994 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4995 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4996 "TARGET_THUMB1
a2cd141b 4997 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4998 && ( register_operand (operands[0], DImode)
4999 || register_operand (operands[1], DImode))"
5000 "*
5001 {
5002 switch (which_alternative)
5003 {
5004 default:
5005 case 0:
5006 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5007 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5008 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5009 case 1:
5010 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5011 case 2:
5012 operands[1] = GEN_INT (- INTVAL (operands[1]));
5013 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5014 case 3:
5015 return \"ldmia\\t%1, {%0, %H0}\";
5016 case 4:
5017 return \"stmia\\t%0, {%1, %H1}\";
5018 case 5:
5019 return thumb_load_double_from_address (operands);
5020 case 6:
1a83b3ff 5021 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5022 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5023 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5024 return \"\";
5025 case 7:
5026 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5027 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5028 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5029 }
5030 }"
5031 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5032 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5033 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5034 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5035)
b11cae9e 5036
9c08d1fa 5037(define_expand "movsi"
5038 [(set (match_operand:SI 0 "general_operand" "")
5039 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5040 "TARGET_EITHER"
9c08d1fa 5041 "
befb0bac 5042 {
e348ff3e 5043 rtx base, offset, tmp;
5044
25f905c2 5045 if (TARGET_32BIT)
9c08d1fa 5046 {
674a8f0b 5047 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5048 if (GET_CODE (operands[0]) == MEM)
5049 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5050 if (arm_general_register_operand (operands[0], SImode)
5051 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5052 && !(const_ok_for_arm (INTVAL (operands[1]))
5053 || const_ok_for_arm (~INTVAL (operands[1]))))
5054 {
96f57e36 5055 arm_split_constant (SET, SImode, NULL_RTX,
5056 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5057 optimize && can_create_pseudo_p ());
cffb2a26 5058 DONE;
5059 }
d0e6a121 5060
5061 if (TARGET_USE_MOVT && !target_word_relocations
5062 && GET_CODE (operands[1]) == SYMBOL_REF
5063 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5064 {
5065 arm_emit_movpair (operands[0], operands[1]);
5066 DONE;
5067 }
cffb2a26 5068 }
25f905c2 5069 else /* TARGET_THUMB1... */
cffb2a26 5070 {
e1ba4a27 5071 if (can_create_pseudo_p ())
cffb2a26 5072 {
5073 if (GET_CODE (operands[0]) != REG)
5074 operands[1] = force_reg (SImode, operands[1]);
5075 }
9c08d1fa 5076 }
f655717d 5077
e348ff3e 5078 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5079 {
5080 split_const (operands[1], &base, &offset);
5081 if (GET_CODE (base) == SYMBOL_REF
5082 && !offset_within_block_p (base, INTVAL (offset)))
5083 {
b308ddcf 5084 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5085 emit_move_insn (tmp, base);
5086 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5087 DONE;
5088 }
5089 }
5090
f655717d 5091 /* Recognize the case where operand[1] is a reference to thread-local
5092 data and load its address to a register. */
5093 if (arm_tls_referenced_p (operands[1]))
5094 {
5095 rtx tmp = operands[1];
5096 rtx addend = NULL;
5097
5098 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5099 {
5100 addend = XEXP (XEXP (tmp, 0), 1);
5101 tmp = XEXP (XEXP (tmp, 0), 0);
5102 }
5103
5104 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5105 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5106
e1ba4a27 5107 tmp = legitimize_tls_address (tmp,
5108 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5109 if (addend)
5110 {
5111 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5112 tmp = force_operand (tmp, operands[0]);
5113 }
5114 operands[1] = tmp;
5115 }
5116 else if (flag_pic
5117 && (CONSTANT_P (operands[1])
5118 || symbol_mentioned_p (operands[1])
5119 || label_mentioned_p (operands[1])))
5120 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5121 (!can_create_pseudo_p ()
5122 ? operands[0]
5123 : 0));
befb0bac 5124 }
215b30b3 5125 "
5126)
9c08d1fa 5127
d0e6a121 5128;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5129;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5130;; so this does not matter.
5131(define_insn "*arm_movt"
5132 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5133 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5134 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5135 "arm_arch_thumb2"
d0e6a121 5136 "movt%?\t%0, #:upper16:%c2"
5137 [(set_attr "predicable" "yes")
5138 (set_attr "length" "4")]
5139)
5140
cffb2a26 5141(define_insn "*arm_movsi_insn"
aaa37ad6 5142 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5143 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5144 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5145 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5146 && ( register_operand (operands[0], SImode)
5147 || register_operand (operands[1], SImode))"
f7fbdd4a 5148 "@
aaa37ad6 5149 mov%?\\t%0, %1
f7fbdd4a 5150 mov%?\\t%0, %1
5151 mvn%?\\t%0, #%B1
25f905c2 5152 movw%?\\t%0, %1
f7fbdd4a 5153 ldr%?\\t%0, %1
5154 str%?\\t%1, %0"
aaa37ad6 5155 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5156 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5157 (set_attr "predicable" "yes")
aaa37ad6 5158 (set_attr "pool_range" "*,*,*,*,4096,*")
5159 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5160)
87b22bf7 5161
5162(define_split
a2cd141b 5163 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5164 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5165 "TARGET_32BIT
215b30b3 5166 && (!(const_ok_for_arm (INTVAL (operands[1]))
5167 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5168 [(clobber (const_int 0))]
5169 "
96f57e36 5170 arm_split_constant (SET, SImode, NULL_RTX,
5171 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5172 DONE;
215b30b3 5173 "
5174)
9c08d1fa 5175
25f905c2 5176(define_insn "*thumb1_movsi_insn"
55a0d64c 5177 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5178 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 5179 "TARGET_THUMB1
cffb2a26 5180 && ( register_operand (operands[0], SImode)
5181 || register_operand (operands[1], SImode))"
5182 "@
5183 mov %0, %1
5184 mov %0, %1
5185 #
5186 #
5187 ldmia\\t%1, {%0}
5188 stmia\\t%0, {%1}
5189 ldr\\t%0, %1
5190 str\\t%1, %0
5191 mov\\t%0, %1"
5192 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5193 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5194 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5195 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5196
5197(define_split
5198 [(set (match_operand:SI 0 "register_operand" "")
5199 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5200 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5201 [(set (match_dup 2) (match_dup 1))
5202 (set (match_dup 0) (neg:SI (match_dup 2)))]
5203 "
5204 {
5205 operands[1] = GEN_INT (- INTVAL (operands[1]));
5206 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5207 }"
cffb2a26 5208)
5209
5210(define_split
5211 [(set (match_operand:SI 0 "register_operand" "")
5212 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5213 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5214 [(set (match_dup 2) (match_dup 1))
5215 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5216 "
5217 {
e4aeee53 5218 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5219 unsigned HOST_WIDE_INT mask = 0xff;
5220 int i;
5221
5222 for (i = 0; i < 25; i++)
5223 if ((val & (mask << i)) == val)
5224 break;
5225
1276f1b8 5226 /* Don't split if the shift is zero. */
cffb2a26 5227 if (i == 0)
5228 FAIL;
5229
5230 operands[1] = GEN_INT (val >> i);
1276f1b8 5231 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5232 operands[3] = GEN_INT (i);
cffb2a26 5233 }"
5234)
5235
67336bcf 5236;; When generating pic, we need to load the symbol offset into a register.
5237;; So that the optimizer does not confuse this with a normal symbol load
5238;; we use an unspec. The offset will be loaded from a constant pool entry,
5239;; since that is the only type of relocation we can use.
5240
94f8caca 5241;; Wrap calculation of the whole PIC address in a single pattern for the
5242;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5243;; a PIC address involves two loads from memory, so we want to CSE it
5244;; as often as possible.
5245;; This pattern will be split into one of the pic_load_addr_* patterns
5246;; and a move after GCSE optimizations.
5247;;
5248;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5249(define_expand "calculate_pic_address"
5250 [(set (match_operand:SI 0 "register_operand" "")
5251 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5252 (unspec:SI [(match_operand:SI 2 "" "")]
5253 UNSPEC_PIC_SYM))))]
5254 "flag_pic"
5255)
5256
5257;; Split calculate_pic_address into pic_load_addr_* and a move.
5258(define_split
5259 [(set (match_operand:SI 0 "register_operand" "")
5260 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5261 (unspec:SI [(match_operand:SI 2 "" "")]
5262 UNSPEC_PIC_SYM))))]
5263 "flag_pic"
5264 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5265 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5266 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5267)
5268
67336bcf 5269;; The rather odd constraints on the following are to force reload to leave
5270;; the insn alone, and to force the minipool generation pass to then move
5271;; the GOT symbol to memory.
849170fd 5272
b3cd5f55 5273(define_insn "pic_load_addr_32bit"
849170fd 5274 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5275 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5276 "TARGET_32BIT && flag_pic"
67336bcf 5277 "ldr%?\\t%0, %1"
a2cd141b 5278 [(set_attr "type" "load1")
b3cd5f55 5279 (set_attr "pool_range" "4096")
5280 (set (attr "neg_pool_range")
5281 (if_then_else (eq_attr "is_thumb" "no")
5282 (const_int 4084)
5283 (const_int 0)))]
8c4d8060 5284)
5285
25f905c2 5286(define_insn "pic_load_addr_thumb1"
8c4d8060 5287 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5288 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5289 "TARGET_THUMB1 && flag_pic"
8c4d8060 5290 "ldr\\t%0, %1"
a2cd141b 5291 [(set_attr "type" "load1")
8c4d8060 5292 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5293)
849170fd 5294
cffb2a26 5295(define_insn "pic_add_dot_plus_four"
15d5d060 5296 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5297 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5298 (const_int 4)
beef0fb5 5299 (match_operand 2 "" "")]
5300 UNSPEC_PIC_BASE))]
b3cd5f55 5301 "TARGET_THUMB"
cffb2a26 5302 "*
6cdcb15c 5303 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5304 INTVAL (operands[2]));
cffb2a26 5305 return \"add\\t%0, %|pc\";
5306 "
5307 [(set_attr "length" "2")]
5308)
849170fd 5309
5310(define_insn "pic_add_dot_plus_eight"
15d5d060 5311 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5312 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5313 (const_int 8)
beef0fb5 5314 (match_operand 2 "" "")]
5315 UNSPEC_PIC_BASE))]
f655717d 5316 "TARGET_ARM"
c4034607 5317 "*
6cdcb15c 5318 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5319 INTVAL (operands[2]));
15d5d060 5320 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5321 "
0d66636f 5322 [(set_attr "predicable" "yes")]
cffb2a26 5323)
849170fd 5324
f655717d 5325(define_insn "tls_load_dot_plus_eight"
cc071db6 5326 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5327 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5328 (const_int 8)
beef0fb5 5329 (match_operand 2 "" "")]
5330 UNSPEC_PIC_BASE)))]
f655717d 5331 "TARGET_ARM"
5332 "*
6cdcb15c 5333 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5334 INTVAL (operands[2]));
f655717d 5335 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5336 "
5337 [(set_attr "predicable" "yes")]
5338)
5339
5340;; PIC references to local variables can generate pic_add_dot_plus_eight
5341;; followed by a load. These sequences can be crunched down to
5342;; tls_load_dot_plus_eight by a peephole.
5343
5344(define_peephole2
c0c1fba5 5345 [(set (match_operand:SI 0 "register_operand" "")
5346 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5347 (const_int 8)
5348 (match_operand 1 "" "")]
5349 UNSPEC_PIC_BASE))
f655717d 5350 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5351 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5352 [(set (match_dup 2)
5353 (mem:SI (unspec:SI [(match_dup 3)
5354 (const_int 8)
5355 (match_dup 1)]
5356 UNSPEC_PIC_BASE)))]
f655717d 5357 ""
5358)
5359
bac7fc85 5360(define_insn "pic_offset_arm"
5361 [(set (match_operand:SI 0 "register_operand" "=r")
5362 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5363 (unspec:SI [(match_operand:SI 2 "" "X")]
5364 UNSPEC_PIC_OFFSET))))]
5365 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5366 "ldr%?\\t%0, [%1,%2]"
5367 [(set_attr "type" "load1")]
5368)
5369
95373f08 5370(define_expand "builtin_setjmp_receiver"
5371 [(label_ref (match_operand 0 "" ""))]
5372 "flag_pic"
5373 "
5374{
b935b306 5375 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5376 register. */
2cb7d577 5377 if (arm_pic_register != INVALID_REGNUM)
5378 arm_load_pic_register (1UL << 3);
95373f08 5379 DONE;
5380}")
5381
9c08d1fa 5382;; If copying one reg to another we can set the condition codes according to
5383;; its value. Such a move is common after a return from subroutine and the
5384;; result is being tested against zero.
5385
f7fbdd4a 5386(define_insn "*movsi_compare0"
bd5b4116 5387 [(set (reg:CC CC_REGNUM)
cffb2a26 5388 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5389 (const_int 0)))
5390 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5391 (match_dup 1))]
25f905c2 5392 "TARGET_32BIT"
e2348bcb 5393 "@
40dbec34 5394 cmp%?\\t%0, #0
25f905c2 5395 sub%.\\t%0, %1, #0"
cffb2a26 5396 [(set_attr "conds" "set")]
5397)
b11cae9e 5398
b11cae9e 5399;; Subroutine to store a half word from a register into memory.
5400;; Operand 0 is the source register (HImode)
c8f69309 5401;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5402
9c08d1fa 5403;; In both this routine and the next, we must be careful not to spill
01cc3b75 5404;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5405;; can generate unrecognizable rtl.
5406
b11cae9e 5407(define_expand "storehi"
c8f69309 5408 [;; store the low byte
f082f1c4 5409 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5410 ;; extract the high byte
c8f69309 5411 (set (match_dup 2)
5412 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5413 ;; store the high byte
787f8210 5414 (set (match_dup 4) (match_dup 5))]
cffb2a26 5415 "TARGET_ARM"
b11cae9e 5416 "
215b30b3 5417 {
537ffcfc 5418 rtx op1 = operands[1];
5419 rtx addr = XEXP (op1, 0);
215b30b3 5420 enum rtx_code code = GET_CODE (addr);
5421
5422 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5423 || code == MINUS)
537ffcfc 5424 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5425
537ffcfc 5426 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5427 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5428 operands[3] = gen_lowpart (QImode, operands[0]);
5429 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5430 operands[2] = gen_reg_rtx (SImode);
5431 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5432 }"
5433)
b11cae9e 5434
c7597b5d 5435(define_expand "storehi_bigend"
f082f1c4 5436 [(set (match_dup 4) (match_dup 3))
c7597b5d 5437 (set (match_dup 2)
5438 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5439 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5440 "TARGET_ARM"
b11cae9e 5441 "
215b30b3 5442 {
537ffcfc 5443 rtx op1 = operands[1];
5444 rtx addr = XEXP (op1, 0);
215b30b3 5445 enum rtx_code code = GET_CODE (addr);
5446
5447 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5448 || code == MINUS)
537ffcfc 5449 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5450
537ffcfc 5451 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5452 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5453 operands[3] = gen_lowpart (QImode, operands[0]);
5454 operands[0] = gen_lowpart (SImode, operands[0]);
5455 operands[2] = gen_reg_rtx (SImode);
787f8210 5456 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5457 }"
5458)
c7597b5d 5459
5460;; Subroutine to store a half word integer constant into memory.
5461(define_expand "storeinthi"
f082f1c4 5462 [(set (match_operand 0 "" "")
787f8210 5463 (match_operand 1 "" ""))
9e8503e6 5464 (set (match_dup 3) (match_dup 2))]
cffb2a26 5465 "TARGET_ARM"
c7597b5d 5466 "
215b30b3 5467 {
5468 HOST_WIDE_INT value = INTVAL (operands[1]);
5469 rtx addr = XEXP (operands[0], 0);
537ffcfc 5470 rtx op0 = operands[0];
215b30b3 5471 enum rtx_code code = GET_CODE (addr);
c7597b5d 5472
215b30b3 5473 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5474 || code == MINUS)
537ffcfc 5475 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5476
215b30b3 5477 operands[1] = gen_reg_rtx (SImode);
5478 if (BYTES_BIG_ENDIAN)
5479 {
5480 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5481 if ((value & 255) == ((value >> 8) & 255))
5482 operands[2] = operands[1];
5483 else
5484 {
5485 operands[2] = gen_reg_rtx (SImode);
5486 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5487 }
5488 }
5489 else
5490 {
5491 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5492 if ((value & 255) == ((value >> 8) & 255))
5493 operands[2] = operands[1];
5494 else
5495 {
5496 operands[2] = gen_reg_rtx (SImode);
5497 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5498 }
5499 }
c7597b5d 5500
537ffcfc 5501 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5502 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5503 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5504 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5505 }"
5506)
b11cae9e 5507
f7fbdd4a 5508(define_expand "storehi_single_op"
5509 [(set (match_operand:HI 0 "memory_operand" "")
5510 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5511 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5512 "
215b30b3 5513 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5514 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5515 "
5516)
f7fbdd4a 5517
b11cae9e 5518(define_expand "movhi"
5519 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5520 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5521 "TARGET_EITHER"
b11cae9e 5522 "
cffb2a26 5523 if (TARGET_ARM)
b11cae9e 5524 {
e1ba4a27 5525 if (can_create_pseudo_p ())
cffb2a26 5526 {
5527 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5528 {
cffb2a26 5529 if (arm_arch4)
5530 {
5531 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5532 DONE;
5533 }
5534 if (GET_CODE (operands[1]) == CONST_INT)
5535 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5536 else
cffb2a26 5537 {
5538 if (GET_CODE (operands[1]) == MEM)
5539 operands[1] = force_reg (HImode, operands[1]);
5540 if (BYTES_BIG_ENDIAN)
5541 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5542 else
5543 emit_insn (gen_storehi (operands[1], operands[0]));
5544 }
5545 DONE;
b11cae9e 5546 }
cffb2a26 5547 /* Sign extend a constant, and keep it in an SImode reg. */
5548 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5549 {
cffb2a26 5550 rtx reg = gen_reg_rtx (SImode);
5551 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5552
5553 /* If the constant is already valid, leave it alone. */
215b30b3 5554 if (!const_ok_for_arm (val))
cffb2a26 5555 {
5556 /* If setting all the top bits will make the constant
5557 loadable in a single instruction, then set them.
5558 Otherwise, sign extend the number. */
5559
215b30b3 5560 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5561 val |= ~0xffff;
5562 else if (val & 0x8000)
5563 val |= ~0xffff;
5564 }
5565
5566 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5567 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5568 }
e1ba4a27 5569 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5570 && GET_CODE (operands[1]) == MEM)
5571 {
5572 rtx reg = gen_reg_rtx (SImode);
5573
5574 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5575 operands[1] = gen_lowpart (HImode, reg);
5576 }
215b30b3 5577 else if (!arm_arch4)
f7fbdd4a 5578 {
cffb2a26 5579 if (GET_CODE (operands[1]) == MEM)
5580 {
c1a66faf 5581 rtx base;
5582 rtx offset = const0_rtx;
5583 rtx reg = gen_reg_rtx (SImode);
5584
5585 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5586 || (GET_CODE (base) == PLUS
5587 && (GET_CODE (offset = XEXP (base, 1))
5588 == CONST_INT)
5589 && ((INTVAL(offset) & 1) != 1)
5590 && GET_CODE (base = XEXP (base, 0)) == REG))
5591 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5592 {
8deb3959 5593 rtx new_rtx;
c1a66faf 5594
8deb3959 5595 new_rtx = widen_memory_access (operands[1], SImode,
5596 ((INTVAL (offset) & ~3)
5597 - INTVAL (offset)));
5598 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5599 if (((INTVAL (offset) & 2) != 0)
5600 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5601 {
5602 rtx reg2 = gen_reg_rtx (SImode);
5603
5604 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5605 reg = reg2;
5606 }
206ee9a2 5607 }
c1a66faf 5608 else
5609 emit_insn (gen_movhi_bytes (reg, operands[1]));
5610
5611 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5612 }
5613 }
5614 }
674a8f0b 5615 /* Handle loading a large integer during reload. */
cffb2a26 5616 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5617 && !const_ok_for_arm (INTVAL (operands[1]))
5618 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5619 {
5620 /* Writing a constant to memory needs a scratch, which should
5621 be handled with SECONDARY_RELOADs. */
ed29c566 5622 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5623
5624 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5625 emit_insn (gen_movsi (operands[0], operands[1]));
5626 DONE;
5627 }
5628 }
25f905c2 5629 else if (TARGET_THUMB2)
5630 {
5631 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5632 if (can_create_pseudo_p ())
25f905c2 5633 {
5634 if (GET_CODE (operands[0]) != REG)
5635 operands[1] = force_reg (HImode, operands[1]);
5636 /* Zero extend a constant, and keep it in an SImode reg. */
5637 else if (GET_CODE (operands[1]) == CONST_INT)
5638 {
5639 rtx reg = gen_reg_rtx (SImode);
5640 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5641
5642 emit_insn (gen_movsi (reg, GEN_INT (val)));
5643 operands[1] = gen_lowpart (HImode, reg);
5644 }
5645 }
5646 }
5647 else /* TARGET_THUMB1 */
cffb2a26 5648 {
e1ba4a27 5649 if (can_create_pseudo_p ())
cffb2a26 5650 {
6cffc037 5651 if (GET_CODE (operands[1]) == CONST_INT)
5652 {
5653 rtx reg = gen_reg_rtx (SImode);
5654
5655 emit_insn (gen_movsi (reg, operands[1]));
5656 operands[1] = gen_lowpart (HImode, reg);
5657 }
cffb2a26 5658
5659 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5660 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5661 virtual register (also rejected as illegitimate for HImode/QImode)
5662 relative address. */
cffb2a26 5663 /* ??? This should perhaps be fixed elsewhere, for instance, in
5664 fixup_stack_1, by checking for other kinds of invalid addresses,
5665 e.g. a bare reference to a virtual register. This may confuse the
5666 alpha though, which must handle this case differently. */
5667 if (GET_CODE (operands[0]) == MEM
215b30b3 5668 && !memory_address_p (GET_MODE (operands[0]),
5669 XEXP (operands[0], 0)))
537ffcfc 5670 operands[0]
5671 = replace_equiv_address (operands[0],
5672 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5673
5674 if (GET_CODE (operands[1]) == MEM
215b30b3 5675 && !memory_address_p (GET_MODE (operands[1]),
5676 XEXP (operands[1], 0)))
537ffcfc 5677 operands[1]
5678 = replace_equiv_address (operands[1],
5679 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5680
5681 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5682 {
5683 rtx reg = gen_reg_rtx (SImode);
5684
5685 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5686 operands[1] = gen_lowpart (HImode, reg);
5687 }
5688
5689 if (GET_CODE (operands[0]) == MEM)
5690 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5691 }
cffb2a26 5692 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5693 && !satisfies_constraint_I (operands[1]))
cffb2a26 5694 {
6cffc037 5695 /* Handle loading a large integer during reload. */
5696
cffb2a26 5697 /* Writing a constant to memory needs a scratch, which should
5698 be handled with SECONDARY_RELOADs. */
ed29c566 5699 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5700
1a83b3ff 5701 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5702 emit_insn (gen_movsi (operands[0], operands[1]));
5703 DONE;
5704 }
b11cae9e 5705 }
cffb2a26 5706 "
5707)
5708
25f905c2 5709(define_insn "*thumb1_movhi_insn"
a941568e 5710 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5711 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5712 "TARGET_THUMB1
cffb2a26 5713 && ( register_operand (operands[0], HImode)
5714 || register_operand (operands[1], HImode))"
5715 "*
5716 switch (which_alternative)
d79300ac 5717 {
cffb2a26 5718 case 0: return \"add %0, %1, #0\";
5719 case 2: return \"strh %1, %0\";
5720 case 3: return \"mov %0, %1\";
5721 case 4: return \"mov %0, %1\";
5722 case 5: return \"mov %0, %1\";
ed29c566 5723 default: gcc_unreachable ();
cffb2a26 5724 case 1:
5725 /* The stack pointer can end up being taken as an index register.
5726 Catch this case here and deal with it. */
5727 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5728 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5729 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5730 {
5731 rtx ops[2];
5732 ops[0] = operands[0];
5733 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5734
5735 output_asm_insn (\"mov %0, %1\", ops);
5736
5737 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5738
5739 }
5740 return \"ldrh %0, %1\";
5741 }"
5742 [(set_attr "length" "2,4,2,2,2,2")
747b7458 5743 (set_attr "type" "*,load1,store1,*,*,*")
5744 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 5745
b11cae9e 5746
25f7a26e 5747(define_expand "movhi_bytes"
eab14235 5748 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5749 (set (match_dup 3)
eab14235 5750 (zero_extend:SI (match_dup 6)))
25f7a26e 5751 (set (match_operand:SI 0 "" "")
5752 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5753 "TARGET_ARM"
25f7a26e 5754 "
215b30b3 5755 {
5756 rtx mem1, mem2;
5757 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5758
788fcce0 5759 mem1 = change_address (operands[1], QImode, addr);
5760 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5761 operands[0] = gen_lowpart (SImode, operands[0]);
5762 operands[1] = mem1;
5763 operands[2] = gen_reg_rtx (SImode);
5764 operands[3] = gen_reg_rtx (SImode);
5765 operands[6] = mem2;
25f7a26e 5766
215b30b3 5767 if (BYTES_BIG_ENDIAN)
5768 {
5769 operands[4] = operands[2];
5770 operands[5] = operands[3];
5771 }
5772 else
5773 {
5774 operands[4] = operands[3];
5775 operands[5] = operands[2];
5776 }
5777 }"
5778)
25f7a26e 5779
c7597b5d 5780(define_expand "movhi_bigend"
5781 [(set (match_dup 2)
5782 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5783 (const_int 16)))
5784 (set (match_dup 3)
5785 (ashiftrt:SI (match_dup 2) (const_int 16)))
5786 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5787 (match_dup 4))]
cffb2a26 5788 "TARGET_ARM"
c7597b5d 5789 "
5790 operands[2] = gen_reg_rtx (SImode);
5791 operands[3] = gen_reg_rtx (SImode);
787f8210 5792 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5793 "
5794)
b11cae9e 5795
a2f10574 5796;; Pattern to recognize insn generated default case above
f7fbdd4a 5797(define_insn "*movhi_insn_arch4"
cde1623a 5798 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 5799 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 5800 "TARGET_ARM
5801 && arm_arch4
85e02ccb 5802 && (register_operand (operands[0], HImode)
5803 || register_operand (operands[1], HImode))"
f7fbdd4a 5804 "@
5805 mov%?\\t%0, %1\\t%@ movhi
5806 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5807 str%(h%)\\t%1, %0\\t%@ movhi
5808 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5809 [(set_attr "type" "*,*,store1,load1")
0d66636f 5810 (set_attr "predicable" "yes")
d2a518d1 5811 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 5812 (set_attr "pool_range" "*,*,*,256")
5813 (set_attr "neg_pool_range" "*,*,*,244")]
5814)
f7fbdd4a 5815
f7fbdd4a 5816(define_insn "*movhi_bytes"
25f7a26e 5817 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5818 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5819 "TARGET_ARM"
25f7a26e 5820 "@
5821 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5822 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 5823 [(set_attr "predicable" "yes")
5824 (set_attr "insn" "mov,mvn")]
0d66636f 5825)
25f7a26e 5826
f90b51f1 5827(define_expand "thumb_movhi_clobber"
5828 [(set (match_operand:HI 0 "memory_operand" "")
5829 (match_operand:HI 1 "register_operand" ""))
5830 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5831 "TARGET_THUMB1"
f90b51f1 5832 "
5833 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5834 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5835 {
5836 emit_insn (gen_movhi (operands[0], operands[1]));
5837 DONE;
5838 }
5839 /* XXX Fixme, need to handle other cases here as well. */
5840 gcc_unreachable ();
5841 "
cffb2a26 5842)
5843
bc5c7e08 5844;; We use a DImode scratch because we may occasionally need an additional
5845;; temporary if the address isn't offsettable -- push_reload doesn't seem
5846;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5847(define_expand "reload_outhi"
cffb2a26 5848 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5849 (match_operand:HI 1 "s_register_operand" "r")
5850 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5851 "TARGET_EITHER"
5852 "if (TARGET_ARM)
5853 arm_reload_out_hi (operands);
5854 else
5855 thumb_reload_out_hi (operands);
d3373b54 5856 DONE;
cffb2a26 5857 "
5858)
d3373b54 5859
25f7a26e 5860(define_expand "reload_inhi"
5861 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5862 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5863 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5864 "TARGET_EITHER"
25f7a26e 5865 "
cffb2a26 5866 if (TARGET_ARM)
5867 arm_reload_in_hi (operands);
5868 else
5869 thumb_reload_out_hi (operands);
25f7a26e 5870 DONE;
5871")
5872
9c08d1fa 5873(define_expand "movqi"
5874 [(set (match_operand:QI 0 "general_operand" "")
5875 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5876 "TARGET_EITHER"
9c08d1fa 5877 "
6cffc037 5878 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5879
e1ba4a27 5880 if (can_create_pseudo_p ())
cffb2a26 5881 {
6cffc037 5882 if (GET_CODE (operands[1]) == CONST_INT)
5883 {
5884 rtx reg = gen_reg_rtx (SImode);
5885
03770691 5886 /* For thumb we want an unsigned immediate, then we are more likely
5887 to be able to use a movs insn. */
5888 if (TARGET_THUMB)
5889 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5890
6cffc037 5891 emit_insn (gen_movsi (reg, operands[1]));
5892 operands[1] = gen_lowpart (QImode, reg);
5893 }
cffb2a26 5894
6cffc037 5895 if (TARGET_THUMB)
5896 {
cffb2a26 5897 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5898 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5899 virtual register (also rejected as illegitimate for HImode/QImode)
5900 relative address. */
cffb2a26 5901 /* ??? This should perhaps be fixed elsewhere, for instance, in
5902 fixup_stack_1, by checking for other kinds of invalid addresses,
5903 e.g. a bare reference to a virtual register. This may confuse the
5904 alpha though, which must handle this case differently. */
5905 if (GET_CODE (operands[0]) == MEM
215b30b3 5906 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5907 XEXP (operands[0], 0)))
537ffcfc 5908 operands[0]
5909 = replace_equiv_address (operands[0],
5910 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5911 if (GET_CODE (operands[1]) == MEM
5912 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5913 XEXP (operands[1], 0)))
537ffcfc 5914 operands[1]
5915 = replace_equiv_address (operands[1],
5916 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5917 }
5918
5919 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5920 {
5921 rtx reg = gen_reg_rtx (SImode);
5922
5923 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5924 operands[1] = gen_lowpart (QImode, reg);
5925 }
5926
5927 if (GET_CODE (operands[0]) == MEM)
5928 operands[1] = force_reg (QImode, operands[1]);
5929 }
5930 else if (TARGET_THUMB
5931 && GET_CODE (operands[1]) == CONST_INT
234f6557 5932 && !satisfies_constraint_I (operands[1]))
6cffc037 5933 {
674a8f0b 5934 /* Handle loading a large integer during reload. */
cffb2a26 5935
6cffc037 5936 /* Writing a constant to memory needs a scratch, which should
5937 be handled with SECONDARY_RELOADs. */
5938 gcc_assert (GET_CODE (operands[0]) == REG);
5939
5940 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5941 emit_insn (gen_movsi (operands[0], operands[1]));
5942 DONE;
cffb2a26 5943 }
5944 "
5945)
b11cae9e 5946
9c08d1fa 5947
cffb2a26 5948(define_insn "*arm_movqi_insn"
5949 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5950 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5951 "TARGET_32BIT
cffb2a26 5952 && ( register_operand (operands[0], QImode)
5953 || register_operand (operands[1], QImode))"
5565501b 5954 "@
5955 mov%?\\t%0, %1
5956 mvn%?\\t%0, #%B1
25f905c2 5957 ldr%(b%)\\t%0, %1
5958 str%(b%)\\t%1, %0"
a2cd141b 5959 [(set_attr "type" "*,*,load1,store1")
d2a518d1 5960 (set_attr "insn" "mov,mvn,*,*")
0d66636f 5961 (set_attr "predicable" "yes")]
cffb2a26 5962)
5963
25f905c2 5964(define_insn "*thumb1_movqi_insn"
cffb2a26 5965 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5966 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5967 "TARGET_THUMB1
cffb2a26 5968 && ( register_operand (operands[0], QImode)
5969 || register_operand (operands[1], QImode))"
5970 "@
5971 add\\t%0, %1, #0
5972 ldrb\\t%0, %1
5973 strb\\t%1, %0
5974 mov\\t%0, %1
5975 mov\\t%0, %1
5976 mov\\t%0, %1"
5977 [(set_attr "length" "2")
a2cd141b 5978 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 5979 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 5980 (set_attr "pool_range" "*,32,*,*,*,*")
5981 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 5982
9b8516be 5983;; HFmode moves
5984(define_expand "movhf"
5985 [(set (match_operand:HF 0 "general_operand" "")
5986 (match_operand:HF 1 "general_operand" ""))]
5987 "TARGET_EITHER"
5988 "
5989 if (TARGET_32BIT)
5990 {
5991 if (GET_CODE (operands[0]) == MEM)
5992 operands[1] = force_reg (HFmode, operands[1]);
5993 }
5994 else /* TARGET_THUMB1 */
5995 {
5996 if (can_create_pseudo_p ())
5997 {
5998 if (GET_CODE (operands[0]) != REG)
5999 operands[1] = force_reg (HFmode, operands[1]);
6000 }
6001 }
6002 "
6003)
6004
6005(define_insn "*arm32_movhf"
6006 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6007 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 6008 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6009 && ( s_register_operand (operands[0], HFmode)
6010 || s_register_operand (operands[1], HFmode))"
6011 "*
6012 switch (which_alternative)
6013 {
6014 case 0: /* ARM register from memory */
6015 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6016 case 1: /* memory from ARM register */
6017 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6018 case 2: /* ARM register from ARM register */
6019 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6020 case 3: /* ARM register from constant */
6021 {
6022 REAL_VALUE_TYPE r;
6023 long bits;
6024 rtx ops[4];
6025
6026 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6027 bits = real_to_target (NULL, &r, HFmode);
6028 ops[0] = operands[0];
6029 ops[1] = GEN_INT (bits);
6030 ops[2] = GEN_INT (bits & 0xff00);
6031 ops[3] = GEN_INT (bits & 0x00ff);
6032
6033 if (arm_arch_thumb2)
6034 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6035 else
6036 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6037 return \"\";
6038 }
6039 default:
6040 gcc_unreachable ();
6041 }
6042 "
6043 [(set_attr "conds" "unconditional")
6044 (set_attr "type" "load1,store1,*,*")
d2a518d1 6045 (set_attr "insn" "*,*,mov,mov")
9b8516be 6046 (set_attr "length" "4,4,4,8")
d2a518d1 6047 (set_attr "predicable" "yes")]
9b8516be 6048)
6049
6050(define_insn "*thumb1_movhf"
6051 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6052 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6053 "TARGET_THUMB1
6054 && ( s_register_operand (operands[0], HFmode)
6055 || s_register_operand (operands[1], HFmode))"
6056 "*
6057 switch (which_alternative)
6058 {
6059 case 1:
6060 {
6061 rtx addr;
6062 gcc_assert (GET_CODE(operands[1]) == MEM);
6063 addr = XEXP (operands[1], 0);
6064 if (GET_CODE (addr) == LABEL_REF
6065 || (GET_CODE (addr) == CONST
6066 && GET_CODE (XEXP (addr, 0)) == PLUS
6067 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6068 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6069 {
6070 /* Constant pool entry. */
6071 return \"ldr\\t%0, %1\";
6072 }
6073 return \"ldrh\\t%0, %1\";
6074 }
6075 case 2: return \"strh\\t%1, %0\";
6076 default: return \"mov\\t%0, %1\";
6077 }
6078 "
6079 [(set_attr "length" "2")
6080 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6081 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6082 (set_attr "pool_range" "*,1020,*,*,*")
6083 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6084
87b22bf7 6085(define_expand "movsf"
6086 [(set (match_operand:SF 0 "general_operand" "")
6087 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6088 "TARGET_EITHER"
87b22bf7 6089 "
25f905c2 6090 if (TARGET_32BIT)
cffb2a26 6091 {
6092 if (GET_CODE (operands[0]) == MEM)
6093 operands[1] = force_reg (SFmode, operands[1]);
6094 }
25f905c2 6095 else /* TARGET_THUMB1 */
cffb2a26 6096 {
e1ba4a27 6097 if (can_create_pseudo_p ())
cffb2a26 6098 {
6099 if (GET_CODE (operands[0]) != REG)
6100 operands[1] = force_reg (SFmode, operands[1]);
6101 }
6102 }
6103 "
6104)
6105
03d440a6 6106;; Transform a floating-point move of a constant into a core register into
6107;; an SImode operation.
cffb2a26 6108(define_split
03d440a6 6109 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6110 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6111 "TARGET_EITHER
cffb2a26 6112 && reload_completed
6113 && GET_CODE (operands[1]) == CONST_DOUBLE"
6114 [(set (match_dup 2) (match_dup 3))]
6115 "
6116 operands[2] = gen_lowpart (SImode, operands[0]);
6117 operands[3] = gen_lowpart (SImode, operands[1]);
6118 if (operands[2] == 0 || operands[3] == 0)
6119 FAIL;
215b30b3 6120 "
6121)
87b22bf7 6122
cffb2a26 6123(define_insn "*arm_movsf_soft_insn"
6124 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6125 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6126 "TARGET_32BIT
cffb2a26 6127 && TARGET_SOFT_FLOAT
215b30b3 6128 && (GET_CODE (operands[0]) != MEM
6129 || register_operand (operands[1], SFmode))"
9a1112d7 6130 "@
6131 mov%?\\t%0, %1
6132 ldr%?\\t%0, %1\\t%@ float
6133 str%?\\t%1, %0\\t%@ float"
cde1623a 6134 [(set_attr "predicable" "yes")
a2cd141b 6135 (set_attr "type" "*,load1,store1")
d2a518d1 6136 (set_attr "insn" "mov,*,*")
cffb2a26 6137 (set_attr "pool_range" "*,4096,*")
cde1623a 6138 (set_attr "arm_neg_pool_range" "*,4084,*")
6139 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6140)
6141
6142;;; ??? This should have alternatives for constants.
25f905c2 6143(define_insn "*thumb1_movsf_insn"
215b30b3 6144 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6145 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6146 "TARGET_THUMB1
cffb2a26 6147 && ( register_operand (operands[0], SFmode)
6148 || register_operand (operands[1], SFmode))"
6149 "@
6150 add\\t%0, %1, #0
6151 ldmia\\t%1, {%0}
6152 stmia\\t%0, {%1}
6153 ldr\\t%0, %1
6154 str\\t%1, %0
6155 mov\\t%0, %1
6156 mov\\t%0, %1"
6157 [(set_attr "length" "2")
a2cd141b 6158 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6159 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6160 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6161 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6162)
9a1112d7 6163
9c08d1fa 6164(define_expand "movdf"
87b22bf7 6165 [(set (match_operand:DF 0 "general_operand" "")
6166 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6167 "TARGET_EITHER"
9c08d1fa 6168 "
25f905c2 6169 if (TARGET_32BIT)
cffb2a26 6170 {
6171 if (GET_CODE (operands[0]) == MEM)
6172 operands[1] = force_reg (DFmode, operands[1]);
6173 }
6174 else /* TARGET_THUMB */
6175 {
e1ba4a27 6176 if (can_create_pseudo_p ())
cffb2a26 6177 {
6178 if (GET_CODE (operands[0]) != REG)
6179 operands[1] = force_reg (DFmode, operands[1]);
6180 }
6181 }
6182 "
6183)
b11cae9e 6184
9c08d1fa 6185;; Reloading a df mode value stored in integer regs to memory can require a
6186;; scratch reg.
6187(define_expand "reload_outdf"
cffb2a26 6188 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6189 (match_operand:DF 1 "s_register_operand" "r")
6190 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6191 "TARGET_32BIT"
87b22bf7 6192 "
215b30b3 6193 {
6194 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6195
215b30b3 6196 if (code == REG)
6197 operands[2] = XEXP (operands[0], 0);
6198 else if (code == POST_INC || code == PRE_DEC)
6199 {
6200 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6201 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6202 emit_insn (gen_movdi (operands[0], operands[1]));
6203 DONE;
6204 }
6205 else if (code == PRE_INC)
6206 {
6207 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6208
215b30b3 6209 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6210 operands[2] = reg;
6211 }
6212 else if (code == POST_DEC)
6213 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6214 else
6215 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6216 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6217
788fcce0 6218 emit_insn (gen_rtx_SET (VOIDmode,
6219 replace_equiv_address (operands[0], operands[2]),
215b30b3 6220 operands[1]));
f7fbdd4a 6221
215b30b3 6222 if (code == POST_DEC)
6223 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6224
6225 DONE;
6226 }"
6227)
9c08d1fa 6228
9a1112d7 6229(define_insn "*movdf_soft_insn"
359a6e9f 6230 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6231 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6232 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6233 && ( register_operand (operands[0], DFmode)
6234 || register_operand (operands[1], DFmode))"
d51f92df 6235 "*
6236 switch (which_alternative)
6237 {
6238 case 0:
6239 case 1:
6240 case 2:
6241 return \"#\";
6242 default:
6243 return output_move_double (operands);
6244 }
6245 "
359a6e9f 6246 [(set_attr "length" "8,12,16,8,8")
6247 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6248 (set_attr "pool_range" "*,*,*,1020,*")
6249 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6250 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6251)
6252
6253;;; ??? This should have alternatives for constants.
6254;;; ??? This was originally identical to the movdi_insn pattern.
6255;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6256;;; thumb_reorg with a memory reference.
6257(define_insn "*thumb_movdf_insn"
215b30b3 6258 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6259 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6260 "TARGET_THUMB1
cffb2a26 6261 && ( register_operand (operands[0], DFmode)
6262 || register_operand (operands[1], DFmode))"
6263 "*
6264 switch (which_alternative)
6265 {
6266 default:
6267 case 0:
6268 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6269 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6270 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6271 case 1:
6272 return \"ldmia\\t%1, {%0, %H0}\";
6273 case 2:
6274 return \"stmia\\t%0, {%1, %H1}\";
6275 case 3:
6276 return thumb_load_double_from_address (operands);
6277 case 4:
1a83b3ff 6278 operands[2] = gen_rtx_MEM (SImode,
6279 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6280 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6281 return \"\";
6282 case 5:
6283 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6284 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6285 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6286 }
6287 "
6288 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6289 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6290 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6291 (set_attr "pool_range" "*,*,*,1020,*,*")]
6292)
755eb2b4 6293
ccd90aaa 6294(define_expand "movxf"
6295 [(set (match_operand:XF 0 "general_operand" "")
6296 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6297 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6298 "
6299 if (GET_CODE (operands[0]) == MEM)
6300 operands[1] = force_reg (XFmode, operands[1]);
6301 "
6302)
6303
b11cae9e 6304\f
b11cae9e 6305
9c08d1fa 6306;; load- and store-multiple insns
6307;; The arm can load/store any set of registers, provided that they are in
320ea44d 6308;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6309
9c08d1fa 6310(define_expand "load_multiple"
6311 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6312 (match_operand:SI 1 "" ""))
6313 (use (match_operand:SI 2 "" ""))])]
25f905c2 6314 "TARGET_32BIT"
9580c25f 6315{
6316 HOST_WIDE_INT offset = 0;
6317
bd5b4116 6318 /* Support only fixed point registers. */
9c08d1fa 6319 if (GET_CODE (operands[2]) != CONST_INT
6320 || INTVAL (operands[2]) > 14
6321 || INTVAL (operands[2]) < 2
6322 || GET_CODE (operands[1]) != MEM
6323 || GET_CODE (operands[0]) != REG
bd5b4116 6324 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6325 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6326 FAIL;
6327
6328 operands[3]
320ea44d 6329 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6330 INTVAL (operands[2]),
f082f1c4 6331 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6332 FALSE, operands[1], &offset);
9580c25f 6333})
b11cae9e 6334
9c08d1fa 6335(define_expand "store_multiple"
6336 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6337 (match_operand:SI 1 "" ""))
6338 (use (match_operand:SI 2 "" ""))])]
25f905c2 6339 "TARGET_32BIT"
9580c25f 6340{
6341 HOST_WIDE_INT offset = 0;
6342
674a8f0b 6343 /* Support only fixed point registers. */
9c08d1fa 6344 if (GET_CODE (operands[2]) != CONST_INT
6345 || INTVAL (operands[2]) > 14
6346 || INTVAL (operands[2]) < 2
6347 || GET_CODE (operands[1]) != REG
6348 || GET_CODE (operands[0]) != MEM
bd5b4116 6349 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6350 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6351 FAIL;
6352
6353 operands[3]
320ea44d 6354 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6355 INTVAL (operands[2]),
f082f1c4 6356 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6357 FALSE, operands[0], &offset);
9580c25f 6358})
b11cae9e 6359
9c08d1fa 6360
6361;; Move a block of memory if it is word aligned and MORE than 2 words long.
6362;; We could let this apply for blocks of less than this, but it clobbers so
6363;; many registers that there is then probably a better way.
6364
008c057d 6365(define_expand "movmemqi"
34191dd1 6366 [(match_operand:BLK 0 "general_operand" "")
6367 (match_operand:BLK 1 "general_operand" "")
6368 (match_operand:SI 2 "const_int_operand" "")
6369 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6370 "TARGET_EITHER"
9c08d1fa 6371 "
25f905c2 6372 if (TARGET_32BIT)
cffb2a26 6373 {
008c057d 6374 if (arm_gen_movmemqi (operands))
cffb2a26 6375 DONE;
6376 FAIL;
6377 }
25f905c2 6378 else /* TARGET_THUMB1 */
cffb2a26 6379 {
6380 if ( INTVAL (operands[3]) != 4
6381 || INTVAL (operands[2]) > 48)
6382 FAIL;
6383
008c057d 6384 thumb_expand_movmemqi (operands);
cffb2a26 6385 DONE;
6386 }
6387 "
6388)
6389
2162064c 6390;; Thumb block-move insns
cffb2a26 6391
6392(define_insn "movmem12b"
960f3acf 6393 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6394 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6395 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6396 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6397 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6398 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6399 (set (match_operand:SI 0 "register_operand" "=l")
6400 (plus:SI (match_dup 2) (const_int 12)))
6401 (set (match_operand:SI 1 "register_operand" "=l")
6402 (plus:SI (match_dup 3) (const_int 12)))
6403 (clobber (match_scratch:SI 4 "=&l"))
6404 (clobber (match_scratch:SI 5 "=&l"))
6405 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6406 "TARGET_THUMB1"
cffb2a26 6407 "* return thumb_output_move_mem_multiple (3, operands);"
6408 [(set_attr "length" "4")
215b30b3 6409 ; This isn't entirely accurate... It loads as well, but in terms of
6410 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6411 (set_attr "type" "store3")]
6412)
6413
6414(define_insn "movmem8b"
960f3acf 6415 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6416 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6417 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6418 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6419 (set (match_operand:SI 0 "register_operand" "=l")
6420 (plus:SI (match_dup 2) (const_int 8)))
6421 (set (match_operand:SI 1 "register_operand" "=l")
6422 (plus:SI (match_dup 3) (const_int 8)))
6423 (clobber (match_scratch:SI 4 "=&l"))
6424 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6425 "TARGET_THUMB1"
cffb2a26 6426 "* return thumb_output_move_mem_multiple (2, operands);"
6427 [(set_attr "length" "4")
215b30b3 6428 ; This isn't entirely accurate... It loads as well, but in terms of
6429 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6430 (set_attr "type" "store2")]
6431)
6432
9c08d1fa 6433\f
b11cae9e 6434
341940e8 6435;; Compare & branch insns
8d232dc7 6436;; The range calculations are based as follows:
341940e8 6437;; For forward branches, the address calculation returns the address of
6438;; the next instruction. This is 2 beyond the branch instruction.
6439;; For backward branches, the address calculation returns the address of
6440;; the first instruction in this pattern (cmp). This is 2 before the branch
6441;; instruction for the shortest sequence, and 4 before the branch instruction
6442;; if we have to jump around an unconditional branch.
6443;; To the basic branch range the PC offset must be added (this is +4).
6444;; So for forward branches we have
6445;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6446;; And for backward branches we have
6447;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6448;;
6449;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6450;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6451
aeac46d4 6452(define_expand "cbranchsi4"
6453 [(set (pc) (if_then_else
6454 (match_operator 0 "arm_comparison_operator"
6455 [(match_operand:SI 1 "s_register_operand" "")
6456 (match_operand:SI 2 "nonmemory_operand" "")])
6457 (label_ref (match_operand 3 "" ""))
6458 (pc)))]
74f4459c 6459 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6460 "
74f4459c 6461 if (!TARGET_THUMB1)
6462 {
6463 if (!arm_add_operand (operands[2], SImode))
6464 operands[2] = force_reg (SImode, operands[2]);
6465 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6466 operands[3]));
6467 DONE;
6468 }
25f905c2 6469 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6470 {
6471 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6472 operands[3], operands[0]));
6473 DONE;
6474 }
25f905c2 6475 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6476 operands[2] = force_reg (SImode, operands[2]);
6477 ")
6478
a8e6c15d 6479;; A pattern to recognize a special situation and optimize for it.
6480;; On the thumb, zero-extension from memory is preferrable to sign-extension
6481;; due to the available addressing modes. Hence, convert a signed comparison
6482;; with zero into an unsigned comparison with 127 if possible.
6483(define_expand "cbranchqi4"
6484 [(set (pc) (if_then_else
6485 (match_operator 0 "lt_ge_comparison_operator"
6486 [(match_operand:QI 1 "memory_operand" "")
6487 (match_operand:QI 2 "const0_operand" "")])
6488 (label_ref (match_operand 3 "" ""))
6489 (pc)))]
6490 "TARGET_THUMB1"
6491{
d0f6c30d 6492 rtx xops[4];
a8e6c15d 6493 xops[1] = gen_reg_rtx (SImode);
6494 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6495 xops[2] = GEN_INT (127);
6496 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6497 VOIDmode, xops[1], xops[2]);
6498 xops[3] = operands[3];
6499 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6500 DONE;
6501})
6502
74f4459c 6503(define_expand "cbranchsf4"
6504 [(set (pc) (if_then_else
6505 (match_operator 0 "arm_comparison_operator"
6506 [(match_operand:SF 1 "s_register_operand" "")
6507 (match_operand:SF 2 "arm_float_compare_operand" "")])
6508 (label_ref (match_operand 3 "" ""))
6509 (pc)))]
6510 "TARGET_32BIT && TARGET_HARD_FLOAT"
6511 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6512 operands[3])); DONE;"
6513)
6514
6515(define_expand "cbranchdf4"
6516 [(set (pc) (if_then_else
6517 (match_operator 0 "arm_comparison_operator"
6518 [(match_operand:DF 1 "s_register_operand" "")
6519 (match_operand:DF 2 "arm_float_compare_operand" "")])
6520 (label_ref (match_operand 3 "" ""))
6521 (pc)))]
a50d7267 6522 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6523 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6524 operands[3])); DONE;"
6525)
6526
74f4459c 6527(define_expand "cbranchdi4"
6528 [(set (pc) (if_then_else
6529 (match_operator 0 "arm_comparison_operator"
a8045a4f 6530 [(match_operand:DI 1 "cmpdi_operand" "")
6531 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6532 (label_ref (match_operand 3 "" ""))
6533 (pc)))]
a8045a4f 6534 "TARGET_32BIT"
6535 "{
6536 rtx swap = NULL_RTX;
6537 enum rtx_code code = GET_CODE (operands[0]);
6538
6539 /* We should not have two constants. */
6540 gcc_assert (GET_MODE (operands[1]) == DImode
6541 || GET_MODE (operands[2]) == DImode);
6542
6543 /* Flip unimplemented DImode comparisons to a form that
6544 arm_gen_compare_reg can handle. */
6545 switch (code)
6546 {
6547 case GT:
6548 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6549 case LE:
6550 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6551 case GTU:
6552 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6553 case LEU:
6554 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6555 default:
6556 break;
6557 }
6558 if (swap)
6559 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6560 operands[3]));
6561 else
6562 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6563 operands[3]));
6564 DONE;
6565 }"
74f4459c 6566)
6567
d60047aa 6568(define_insn "cbranchsi4_insn"
aeac46d4 6569 [(set (pc) (if_then_else
6570 (match_operator 0 "arm_comparison_operator"
747b7458 6571 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 6572 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6573 (label_ref (match_operand 3 "" ""))
6574 (pc)))]
25f905c2 6575 "TARGET_THUMB1"
747b7458 6576{
6577 rtx t = cfun->machine->thumb1_cc_insn;
6578 if (t != NULL_RTX)
d60047aa 6579 {
747b7458 6580 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6581 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6582 t = NULL_RTX;
6583 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6584 {
6585 if (!noov_comparison_operator (operands[0], VOIDmode))
6586 t = NULL_RTX;
6587 }
6588 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 6589 t = NULL_RTX;
6590 }
d60047aa 6591 if (t == NULL_RTX)
747b7458 6592 {
6593 output_asm_insn ("cmp\t%1, %2", operands);
6594 cfun->machine->thumb1_cc_insn = insn;
6595 cfun->machine->thumb1_cc_op0 = operands[1];
6596 cfun->machine->thumb1_cc_op1 = operands[2];
6597 cfun->machine->thumb1_cc_mode = CCmode;
6598 }
6599 else
6600 /* Ensure we emit the right type of condition code on the jump. */
6601 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6602 CC_REGNUM);
aeac46d4 6603
cffb2a26 6604 switch (get_attr_length (insn))
6605 {
6606 case 4: return \"b%d0\\t%l3\";
6607 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6608 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6609 }
747b7458 6610}
cffb2a26 6611 [(set (attr "far_jump")
6612 (if_then_else
6613 (eq_attr "length" "8")
6614 (const_string "yes")
6615 (const_string "no")))
6616 (set (attr "length")
6617 (if_then_else
6618 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6619 (le (minus (match_dup 3) (pc)) (const_int 256)))
6620 (const_int 4)
6621 (if_then_else
6622 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6623 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6624 (const_int 6)
6625 (const_int 8))))]
6626)
6627
aeac46d4 6628(define_insn "cbranchsi4_scratch"
6629 [(set (pc) (if_then_else
6630 (match_operator 4 "arm_comparison_operator"
6631 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6632 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6633 (label_ref (match_operand 3 "" ""))
6634 (pc)))
6635 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6636 "TARGET_THUMB1"
aeac46d4 6637 "*
6638 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6639
6640 switch (get_attr_length (insn))
6641 {
6642 case 4: return \"b%d4\\t%l3\";
6643 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6644 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6645 }
6646 "
6647 [(set (attr "far_jump")
6648 (if_then_else
6649 (eq_attr "length" "8")
6650 (const_string "yes")
6651 (const_string "no")))
6652 (set (attr "length")
6653 (if_then_else
6654 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6655 (le (minus (match_dup 3) (pc)) (const_int 256)))
6656 (const_int 4)
6657 (if_then_else
6658 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6659 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6660 (const_int 6)
6661 (const_int 8))))]
6662)
446a1e96 6663
747b7458 6664;; Two peepholes to generate subtract of 0 instead of a move if the
6665;; condition codes will be useful.
446a1e96 6666(define_peephole2
6667 [(set (match_operand:SI 0 "low_register_operand" "")
6668 (match_operand:SI 1 "low_register_operand" ""))
6669 (set (pc)
6670 (if_then_else (match_operator 2 "arm_comparison_operator"
6671 [(match_dup 1) (const_int 0)])
6672 (label_ref (match_operand 3 "" ""))
6673 (pc)))]
6674 "TARGET_THUMB1"
747b7458 6675 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6676 (set (pc)
6677 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6678 (label_ref (match_dup 3))
747b7458 6679 (pc)))]
6680 "")
446a1e96 6681
6682;; Sigh! This variant shouldn't be needed, but combine often fails to
6683;; merge cases like this because the op1 is a hard register in
07d32235 6684;; arm_class_likely_spilled_p.
446a1e96 6685(define_peephole2
6686 [(set (match_operand:SI 0 "low_register_operand" "")
6687 (match_operand:SI 1 "low_register_operand" ""))
6688 (set (pc)
6689 (if_then_else (match_operator 2 "arm_comparison_operator"
6690 [(match_dup 0) (const_int 0)])
6691 (label_ref (match_operand 3 "" ""))
6692 (pc)))]
6693 "TARGET_THUMB1"
747b7458 6694 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6695 (set (pc)
6696 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6697 (label_ref (match_dup 3))
747b7458 6698 (pc)))]
6699 "")
446a1e96 6700
cffb2a26 6701(define_insn "*negated_cbranchsi4"
6702 [(set (pc)
6703 (if_then_else
aed179ae 6704 (match_operator 0 "equality_operator"
aeac46d4 6705 [(match_operand:SI 1 "s_register_operand" "l")
6706 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6707 (label_ref (match_operand 3 "" ""))
215b30b3 6708 (pc)))]
25f905c2 6709 "TARGET_THUMB1"
cffb2a26 6710 "*
6711 output_asm_insn (\"cmn\\t%1, %2\", operands);
6712 switch (get_attr_length (insn))
6713 {
6714 case 4: return \"b%d0\\t%l3\";
6715 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6716 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6717 }
6718 "
6719 [(set (attr "far_jump")
6720 (if_then_else
6721 (eq_attr "length" "8")
6722 (const_string "yes")
6723 (const_string "no")))
6724 (set (attr "length")
6725 (if_then_else
6726 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6727 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6728 (const_int 4)
6729 (if_then_else
341940e8 6730 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6731 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6732 (const_int 6)
6733 (const_int 8))))]
6734)
6735
58d6528b 6736(define_insn "*tbit_cbranch"
6737 [(set (pc)
6738 (if_then_else
6739 (match_operator 0 "equality_operator"
6740 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6741 (const_int 1)
6742 (match_operand:SI 2 "const_int_operand" "i"))
6743 (const_int 0)])
6744 (label_ref (match_operand 3 "" ""))
6745 (pc)))
6746 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6747 "TARGET_THUMB1"
58d6528b 6748 "*
6749 {
6750 rtx op[3];
6751 op[0] = operands[4];
6752 op[1] = operands[1];
6753 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6754
86efa74d 6755 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6756 switch (get_attr_length (insn))
6757 {
6758 case 4: return \"b%d0\\t%l3\";
6759 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6760 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6761 }
6762 }"
6763 [(set (attr "far_jump")
6764 (if_then_else
6765 (eq_attr "length" "8")
6766 (const_string "yes")
6767 (const_string "no")))
6768 (set (attr "length")
6769 (if_then_else
6770 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6771 (le (minus (match_dup 3) (pc)) (const_int 256)))
6772 (const_int 4)
6773 (if_then_else
6774 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6775 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6776 (const_int 6)
6777 (const_int 8))))]
6778)
6779
6780(define_insn "*tlobits_cbranch"
6781 [(set (pc)
6782 (if_then_else
6783 (match_operator 0 "equality_operator"
6784 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6785 (match_operand:SI 2 "const_int_operand" "i")
6786 (const_int 0))
6787 (const_int 0)])
6788 (label_ref (match_operand 3 "" ""))
6789 (pc)))
6790 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6791 "TARGET_THUMB1"
86efa74d 6792 "*
6793 {
6794 rtx op[3];
6795 op[0] = operands[4];
6796 op[1] = operands[1];
6797 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6798
58d6528b 6799 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6800 switch (get_attr_length (insn))
6801 {
6802 case 4: return \"b%d0\\t%l3\";
6803 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6804 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6805 }
6806 }"
6807 [(set (attr "far_jump")
6808 (if_then_else
6809 (eq_attr "length" "8")
6810 (const_string "yes")
6811 (const_string "no")))
6812 (set (attr "length")
6813 (if_then_else
6814 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6815 (le (minus (match_dup 3) (pc)) (const_int 256)))
6816 (const_int 4)
6817 (if_then_else
6818 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6819 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6820 (const_int 6)
6821 (const_int 8))))]
6822)
747b7458 6823
aeac46d4 6824(define_insn "*tstsi3_cbranch"
58d6528b 6825 [(set (pc)
6826 (if_then_else
aeac46d4 6827 (match_operator 3 "equality_operator"
6828 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6829 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6830 (const_int 0)])
aeac46d4 6831 (label_ref (match_operand 2 "" ""))
6832 (pc)))]
25f905c2 6833 "TARGET_THUMB1"
58d6528b 6834 "*
6835 {
aeac46d4 6836 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6837 switch (get_attr_length (insn))
6838 {
aeac46d4 6839 case 4: return \"b%d3\\t%l2\";
6840 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6841 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6842 }
6843 }"
6844 [(set (attr "far_jump")
6845 (if_then_else
6846 (eq_attr "length" "8")
6847 (const_string "yes")
6848 (const_string "no")))
6849 (set (attr "length")
6850 (if_then_else
aeac46d4 6851 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6852 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6853 (const_int 4)
6854 (if_then_else
aeac46d4 6855 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6856 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6857 (const_int 6)
6858 (const_int 8))))]
6859)
6860
203c488f 6861(define_insn "*cbranchne_decr1"
6862 [(set (pc)
6863 (if_then_else (match_operator 3 "equality_operator"
6864 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6865 (const_int 0)])
6866 (label_ref (match_operand 4 "" ""))
6867 (pc)))
aeac46d4 6868 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6869 (plus:SI (match_dup 2) (const_int -1)))
6870 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6871 "TARGET_THUMB1"
203c488f 6872 "*
6873 {
6874 rtx cond[2];
6875 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6876 ? GEU : LTU),
58d6528b 6877 VOIDmode, operands[2], const1_rtx);
203c488f 6878 cond[1] = operands[4];
6879
6880 if (which_alternative == 0)
6881 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6882 else if (which_alternative == 1)
6883 {
6884 /* We must provide an alternative for a hi reg because reload
6885 cannot handle output reloads on a jump instruction, but we
6886 can't subtract into that. Fortunately a mov from lo to hi
6887 does not clobber the condition codes. */
6888 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6889 output_asm_insn (\"mov\\t%0, %1\", operands);
6890 }
6891 else
6892 {
6893 /* Similarly, but the target is memory. */
6894 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6895 output_asm_insn (\"str\\t%1, %0\", operands);
6896 }
6897
6898 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6899 {
6900 case 4:
8aea555f 6901 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6902 return \"\";
6903 case 6:
8aea555f 6904 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6905 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6906 default:
8aea555f 6907 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6908 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6909 }
6910 }
6911 "
6912 [(set (attr "far_jump")
6913 (if_then_else
6914 (ior (and (eq (symbol_ref ("which_alternative"))
6915 (const_int 0))
6916 (eq_attr "length" "8"))
6917 (eq_attr "length" "10"))
6918 (const_string "yes")
6919 (const_string "no")))
6920 (set_attr_alternative "length"
6921 [
6922 ;; Alternative 0
6923 (if_then_else
6924 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6925 (le (minus (match_dup 4) (pc)) (const_int 256)))
6926 (const_int 4)
6927 (if_then_else
6928 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6929 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6930 (const_int 6)
6931 (const_int 8)))
6932 ;; Alternative 1
6933 (if_then_else
6934 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6935 (le (minus (match_dup 4) (pc)) (const_int 256)))
6936 (const_int 6)
6937 (if_then_else
6938 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6939 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6940 (const_int 8)
6941 (const_int 10)))
6942 ;; Alternative 2
6943 (if_then_else
6944 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6945 (le (minus (match_dup 4) (pc)) (const_int 256)))
6946 (const_int 6)
6947 (if_then_else
6948 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6949 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6950 (const_int 8)
6951 (const_int 10)))
6952 ;; Alternative 3
6953 (if_then_else
6954 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6955 (le (minus (match_dup 4) (pc)) (const_int 256)))
6956 (const_int 6)
6957 (if_then_else
6958 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6959 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6960 (const_int 8)
6961 (const_int 10)))])]
6962)
cffb2a26 6963
58d6528b 6964(define_insn "*addsi3_cbranch"
6965 [(set (pc)
6966 (if_then_else
b0694be0 6967 (match_operator 4 "arm_comparison_operator"
58d6528b 6968 [(plus:SI
e54011cb 6969 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
6970 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 6971 (const_int 0)])
6972 (label_ref (match_operand 5 "" ""))
6973 (pc)))
aeac46d4 6974 (set
6975 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6976 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 6977 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 6978 "TARGET_THUMB1
58d6528b 6979 && (GET_CODE (operands[4]) == EQ
6980 || GET_CODE (operands[4]) == NE
6981 || GET_CODE (operands[4]) == GE
6982 || GET_CODE (operands[4]) == LT)"
6983 "*
6984 {
6985 rtx cond[3];
6986
956a6170 6987 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 6988 cond[1] = operands[2];
6989 cond[2] = operands[3];
6990
6991 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6992 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6993 else
6994 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6995
956a6170 6996 if (which_alternative >= 2
58d6528b 6997 && which_alternative < 4)
6998 output_asm_insn (\"mov\\t%0, %1\", operands);
6999 else if (which_alternative >= 4)
7000 output_asm_insn (\"str\\t%1, %0\", operands);
7001
d0f6c30d 7002 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 7003 {
7004 case 4:
7005 return \"b%d4\\t%l5\";
7006 case 6:
7007 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7008 default:
7009 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7010 }
7011 }
7012 "
7013 [(set (attr "far_jump")
7014 (if_then_else
7015 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7016 (const_int 2))
58d6528b 7017 (eq_attr "length" "8"))
7018 (eq_attr "length" "10"))
7019 (const_string "yes")
7020 (const_string "no")))
7021 (set (attr "length")
7022 (if_then_else
7023 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7024 (const_int 2))
58d6528b 7025 (if_then_else
7026 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7027 (le (minus (match_dup 5) (pc)) (const_int 256)))
7028 (const_int 4)
7029 (if_then_else
7030 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7031 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7032 (const_int 6)
7033 (const_int 8)))
7034 (if_then_else
7035 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7036 (le (minus (match_dup 5) (pc)) (const_int 256)))
7037 (const_int 6)
7038 (if_then_else
7039 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7040 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7041 (const_int 8)
7042 (const_int 10)))))]
7043)
7044
7045(define_insn "*addsi3_cbranch_scratch"
7046 [(set (pc)
7047 (if_then_else
b0694be0 7048 (match_operator 3 "arm_comparison_operator"
58d6528b 7049 [(plus:SI
7050 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7051 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7052 (const_int 0)])
7053 (label_ref (match_operand 4 "" ""))
7054 (pc)))
7055 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7056 "TARGET_THUMB1
58d6528b 7057 && (GET_CODE (operands[3]) == EQ
7058 || GET_CODE (operands[3]) == NE
7059 || GET_CODE (operands[3]) == GE
7060 || GET_CODE (operands[3]) == LT)"
7061 "*
7062 {
7063 switch (which_alternative)
7064 {
7065 case 0:
7066 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7067 break;
7068 case 1:
7069 output_asm_insn (\"cmn\t%1, %2\", operands);
7070 break;
0f5e9701 7071 case 2:
3a445a04 7072 if (INTVAL (operands[2]) < 0)
7073 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7074 else
7075 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7076 break;
0f5e9701 7077 case 3:
3a445a04 7078 if (INTVAL (operands[2]) < 0)
7079 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7080 else
7081 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7082 break;
7083 }
7084
7085 switch (get_attr_length (insn))
7086 {
7087 case 4:
7088 return \"b%d3\\t%l4\";
7089 case 6:
7090 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7091 default:
7092 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7093 }
7094 }
7095 "
7096 [(set (attr "far_jump")
7097 (if_then_else
7098 (eq_attr "length" "8")
7099 (const_string "yes")
7100 (const_string "no")))
7101 (set (attr "length")
7102 (if_then_else
7103 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7104 (le (minus (match_dup 4) (pc)) (const_int 256)))
7105 (const_int 4)
7106 (if_then_else
7107 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7108 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7109 (const_int 6)
7110 (const_int 8))))]
7111)
7112
58d6528b 7113
9c08d1fa 7114;; Comparison and test insns
7115
cffb2a26 7116(define_insn "*arm_cmpsi_insn"
bd5b4116 7117 [(set (reg:CC CC_REGNUM)
a6864a24 7118 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7119 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
25f905c2 7120 "TARGET_32BIT"
5565501b 7121 "@
a6864a24 7122 cmp%?\\t%0, %1
7123 cmp%?\\t%0, %1
aea4c774 7124 cmp%?\\t%0, %1
7125 cmn%?\\t%0, #%n1"
a6864a24 7126 [(set_attr "conds" "set")
7127 (set_attr "arch" "t2,t2,any,any")
7128 (set_attr "length" "2,2,4,4")]
cffb2a26 7129)
b11cae9e 7130
d5d4dc8d 7131(define_insn "*cmpsi_shiftsi"
bd5b4116 7132 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7133 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7134 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7135 [(match_operand:SI 1 "s_register_operand" "r,r")
7136 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7137 "TARGET_32BIT"
aea4c774 7138 "cmp%?\\t%0, %1%S3"
344495ea 7139 [(set_attr "conds" "set")
331beb1a 7140 (set_attr "shift" "1")
d5d4dc8d 7141 (set_attr "arch" "32,a")
7142 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7143
d5d4dc8d 7144(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7145 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7146 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7147 [(match_operand:SI 1 "s_register_operand" "r,r")
7148 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7149 (match_operand:SI 0 "s_register_operand" "r,r")))]
7150 "TARGET_32BIT"
aea4c774 7151 "cmp%?\\t%0, %1%S3"
344495ea 7152 [(set_attr "conds" "set")
331beb1a 7153 (set_attr "shift" "1")
d5d4dc8d 7154 (set_attr "arch" "32,a")
7155 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7156
25f905c2 7157(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7158 [(set (reg:CC_Z CC_REGNUM)
7159 (compare:CC_Z
7160 (neg:SI (match_operator:SI 1 "shift_operator"
7161 [(match_operand:SI 2 "s_register_operand" "r")
7162 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7163 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7164 "TARGET_ARM"
aed179ae 7165 "cmn%?\\t%0, %2%S1"
344495ea 7166 [(set_attr "conds" "set")
aed179ae 7167 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7168 (const_string "alu_shift")
7169 (const_string "alu_shift_reg")))]
0d66636f 7170)
b11cae9e 7171
a8045a4f 7172;; DImode comparisons. The generic code generates branches that
7173;; if-conversion can not reduce to a conditional compare, so we do
7174;; that directly.
7175
7176(define_insn "*arm_cmpdi_insn"
7177 [(set (reg:CC_NCV CC_REGNUM)
7178 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7179 (match_operand:DI 1 "arm_di_operand" "rDi")))
7180 (clobber (match_scratch:SI 2 "=r"))]
7181 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7182 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7183 [(set_attr "conds" "set")
7184 (set_attr "length" "8")]
7185)
7186
7187(define_insn "*arm_cmpdi_unsigned"
7188 [(set (reg:CC_CZ CC_REGNUM)
7189 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7190 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7191 "TARGET_ARM"
7192 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7193 [(set_attr "conds" "set")
7194 (set_attr "length" "8")]
7195)
7196
7197(define_insn "*arm_cmpdi_zero"
7198 [(set (reg:CC_Z CC_REGNUM)
7199 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7200 (const_int 0)))
7201 (clobber (match_scratch:SI 1 "=r"))]
7202 "TARGET_32BIT"
7203 "orr%.\\t%1, %Q0, %R0"
7204 [(set_attr "conds" "set")]
7205)
7206
7207(define_insn "*thumb_cmpdi_zero"
7208 [(set (reg:CC_Z CC_REGNUM)
7209 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7210 (const_int 0)))
7211 (clobber (match_scratch:SI 1 "=l"))]
7212 "TARGET_THUMB1"
7213 "orr\\t%1, %Q0, %R0"
7214 [(set_attr "conds" "set")
7215 (set_attr "length" "2")]
7216)
7217
7d57ec45 7218;; Cirrus SF compare instruction
7219(define_insn "*cirrus_cmpsf"
7220 [(set (reg:CCFP CC_REGNUM)
7221 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7222 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7223 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7224 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7225 [(set_attr "type" "mav_farith")
7d57ec45 7226 (set_attr "cirrus" "compare")]
7227)
7228
7229;; Cirrus DF compare instruction
7230(define_insn "*cirrus_cmpdf"
7231 [(set (reg:CCFP CC_REGNUM)
7232 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7233 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7234 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7235 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7236 [(set_attr "type" "mav_farith")
7d57ec45 7237 (set_attr "cirrus" "compare")]
7238)
7239
7d57ec45 7240(define_insn "*cirrus_cmpdi"
7241 [(set (reg:CC CC_REGNUM)
7242 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7243 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7244 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7245 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7246 [(set_attr "type" "mav_farith")
7d57ec45 7247 (set_attr "cirrus" "compare")]
7248)
7249
9c08d1fa 7250; This insn allows redundant compares to be removed by cse, nothing should
7251; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7252; is deleted later on. The match_dup will match the mode here, so that
7253; mode changes of the condition codes aren't lost by this even though we don't
7254; specify what they are.
7255
8a18b90c 7256(define_insn "*deleted_compare"
9c08d1fa 7257 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7258 "TARGET_32BIT"
40dbec34 7259 "\\t%@ deleted compare"
cffb2a26 7260 [(set_attr "conds" "set")
7261 (set_attr "length" "0")]
7262)
9c08d1fa 7263
7264\f
7265;; Conditional branch insns
7266
74f4459c 7267(define_expand "cbranch_cc"
9c08d1fa 7268 [(set (pc)
74f4459c 7269 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7270 (match_operand 2 "" "")])
7271 (label_ref (match_operand 3 "" ""))
9c08d1fa 7272 (pc)))]
25f905c2 7273 "TARGET_32BIT"
74f4459c 7274 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7275 operands[1], operands[2]);
7276 operands[2] = const0_rtx;"
8fa3ba89 7277)
7278
7279;;
7280;; Patterns to match conditional branch insns.
7281;;
7282
cffb2a26 7283(define_insn "*arm_cond_branch"
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 (label_ref (match_operand 0 "" ""))
7288 (pc)))]
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")
a6864a24 7299 (set_attr "type" "branch")
7300 (set (attr "length")
7301 (if_then_else
7302 (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7303 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7304 (le (minus (match_dup 0) (pc)) (const_int 256))))
7305 (const_int 2)
7306 (const_int 4)))]
cffb2a26 7307)
d75350ce 7308
cffb2a26 7309(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7310 [(set (pc)
8fa3ba89 7311 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7312 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7313 (pc)
7314 (label_ref (match_operand 0 "" ""))))]
25f905c2 7315 "TARGET_32BIT"
d75350ce 7316 "*
9c08d1fa 7317 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7318 {
7319 arm_ccfsm_state += 2;
7320 return \"\";
7321 }
e2348bcb 7322 return \"b%D1\\t%l0\";
cffb2a26 7323 "
a2cd141b 7324 [(set_attr "conds" "use")
a6864a24 7325 (set_attr "type" "branch")
7326 (set (attr "length")
7327 (if_then_else
7328 (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7329 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7330 (le (minus (match_dup 0) (pc)) (const_int 256))))
7331 (const_int 2)
7332 (const_int 4)))]
cffb2a26 7333)
7334
b11cae9e 7335\f
9c08d1fa 7336
7337; scc insns
7338
74f4459c 7339(define_expand "cstore_cc"
7db9af5d 7340 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7341 (match_operator:SI 1 "" [(match_operand 2 "" "")
7342 (match_operand 3 "" "")]))]
25f905c2 7343 "TARGET_32BIT"
74f4459c 7344 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7345 operands[2], operands[3]);
7346 operands[3] = const0_rtx;"
8fa3ba89 7347)
7348
f7fbdd4a 7349(define_insn "*mov_scc"
9c08d1fa 7350 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7351 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7352 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7353 "TARGET_ARM"
4d61e570 7354 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7355 [(set_attr "conds" "use")
d2a518d1 7356 (set_attr "insn" "mov")
cffb2a26 7357 (set_attr "length" "8")]
7358)
9c08d1fa 7359
f7fbdd4a 7360(define_insn "*mov_negscc"
9c08d1fa 7361 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7362 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7363 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7364 "TARGET_ARM"
4d61e570 7365 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7366 [(set_attr "conds" "use")
d2a518d1 7367 (set_attr "insn" "mov")
cffb2a26 7368 (set_attr "length" "8")]
7369)
9c08d1fa 7370
f7fbdd4a 7371(define_insn "*mov_notscc"
9c08d1fa 7372 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7373 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7374 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7375 "TARGET_ARM"
4d61e570 7376 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7377 [(set_attr "conds" "use")
d2a518d1 7378 (set_attr "insn" "mov")
cffb2a26 7379 (set_attr "length" "8")]
7380)
9c08d1fa 7381
595d88b5 7382(define_expand "cstoresi4"
7383 [(set (match_operand:SI 0 "s_register_operand" "")
7384 (match_operator:SI 1 "arm_comparison_operator"
7385 [(match_operand:SI 2 "s_register_operand" "")
7386 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7387 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7388 "{
7389 rtx op3, scratch, scratch2;
7390
74f4459c 7391 if (!TARGET_THUMB1)
7392 {
7393 if (!arm_add_operand (operands[3], SImode))
7394 operands[3] = force_reg (SImode, operands[3]);
7395 emit_insn (gen_cstore_cc (operands[0], operands[1],
7396 operands[2], operands[3]));
7397 DONE;
7398 }
7399
595d88b5 7400 if (operands[3] == const0_rtx)
7401 {
7402 switch (GET_CODE (operands[1]))
7403 {
7404 case EQ:
25f905c2 7405 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7406 break;
7407
7408 case NE:
25f905c2 7409 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7410 break;
7411
7412 case LE:
7413 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7414 NULL_RTX, 0, OPTAB_WIDEN);
7415 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7416 NULL_RTX, 0, OPTAB_WIDEN);
7417 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7418 operands[0], 1, OPTAB_WIDEN);
7419 break;
7420
7421 case GE:
7422 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7423 NULL_RTX, 1);
7424 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7425 NULL_RTX, 1, OPTAB_WIDEN);
7426 break;
7427
7428 case GT:
7429 scratch = expand_binop (SImode, ashr_optab, operands[2],
7430 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7431 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7432 NULL_RTX, 0, OPTAB_WIDEN);
7433 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7434 0, OPTAB_WIDEN);
7435 break;
7436
7437 /* LT is handled by generic code. No need for unsigned with 0. */
7438 default:
7439 FAIL;
7440 }
7441 DONE;
7442 }
7443
7444 switch (GET_CODE (operands[1]))
7445 {
7446 case EQ:
7447 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7448 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7449 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7450 break;
7451
7452 case NE:
7453 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7454 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7455 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7456 break;
7457
7458 case LE:
7459 op3 = force_reg (SImode, operands[3]);
7460
7461 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7462 NULL_RTX, 1, OPTAB_WIDEN);
7463 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7464 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7465 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7466 op3, operands[2]));
7467 break;
7468
7469 case GE:
7470 op3 = operands[3];
25f905c2 7471 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7472 op3 = force_reg (SImode, op3);
7473 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7474 NULL_RTX, 0, OPTAB_WIDEN);
7475 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7476 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7477 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7478 operands[2], op3));
7479 break;
7480
7481 case LEU:
7482 op3 = force_reg (SImode, operands[3]);
7483 scratch = force_reg (SImode, const0_rtx);
25f905c2 7484 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7485 op3, operands[2]));
7486 break;
7487
7488 case GEU:
7489 op3 = operands[3];
25f905c2 7490 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7491 op3 = force_reg (SImode, op3);
7492 scratch = force_reg (SImode, const0_rtx);
25f905c2 7493 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7494 operands[2], op3));
7495 break;
7496
7497 case LTU:
7498 op3 = operands[3];
25f905c2 7499 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7500 op3 = force_reg (SImode, op3);
7501 scratch = gen_reg_rtx (SImode);
408b7ae5 7502 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7503 break;
7504
7505 case GTU:
7506 op3 = force_reg (SImode, operands[3]);
7507 scratch = gen_reg_rtx (SImode);
408b7ae5 7508 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7509 break;
7510
7511 /* No good sequences for GT, LT. */
7512 default:
7513 FAIL;
7514 }
7515 DONE;
7516}")
7517
74f4459c 7518(define_expand "cstoresf4"
7519 [(set (match_operand:SI 0 "s_register_operand" "")
7520 (match_operator:SI 1 "arm_comparison_operator"
7521 [(match_operand:SF 2 "s_register_operand" "")
7522 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7523 "TARGET_32BIT && TARGET_HARD_FLOAT"
7524 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7525 operands[2], operands[3])); DONE;"
7526)
7527
7528(define_expand "cstoredf4"
7529 [(set (match_operand:SI 0 "s_register_operand" "")
7530 (match_operator:SI 1 "arm_comparison_operator"
7531 [(match_operand:DF 2 "s_register_operand" "")
7532 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7533 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7534 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7535 operands[2], operands[3])); DONE;"
7536)
7537
74f4459c 7538(define_expand "cstoredi4"
7539 [(set (match_operand:SI 0 "s_register_operand" "")
7540 (match_operator:SI 1 "arm_comparison_operator"
a8045a4f 7541 [(match_operand:DI 2 "cmpdi_operand" "")
7542 (match_operand:DI 3 "cmpdi_operand" "")]))]
7543 "TARGET_32BIT"
7544 "{
7545 rtx swap = NULL_RTX;
7546 enum rtx_code code = GET_CODE (operands[1]);
7547
7548 /* We should not have two constants. */
7549 gcc_assert (GET_MODE (operands[2]) == DImode
7550 || GET_MODE (operands[3]) == DImode);
7551
7552 /* Flip unimplemented DImode comparisons to a form that
7553 arm_gen_compare_reg can handle. */
7554 switch (code)
7555 {
7556 case GT:
7557 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7558 case LE:
7559 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7560 case GTU:
7561 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7562 case LEU:
7563 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7564 default:
7565 break;
7566 }
7567 if (swap)
7568 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7569 operands[2]));
7570 else
7571 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7572 operands[3]));
7573 DONE;
7574 }"
74f4459c 7575)
7576
25f905c2 7577(define_expand "cstoresi_eq0_thumb1"
595d88b5 7578 [(parallel
7579 [(set (match_operand:SI 0 "s_register_operand" "")
7580 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7581 (const_int 0)))
7582 (clobber (match_dup:SI 2))])]
25f905c2 7583 "TARGET_THUMB1"
595d88b5 7584 "operands[2] = gen_reg_rtx (SImode);"
7585)
7586
25f905c2 7587(define_expand "cstoresi_ne0_thumb1"
595d88b5 7588 [(parallel
7589 [(set (match_operand:SI 0 "s_register_operand" "")
7590 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7591 (const_int 0)))
7592 (clobber (match_dup:SI 2))])]
25f905c2 7593 "TARGET_THUMB1"
595d88b5 7594 "operands[2] = gen_reg_rtx (SImode);"
7595)
7596
25f905c2 7597(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7598 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7599 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7600 (const_int 0)))
7601 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7602 "TARGET_THUMB1"
595d88b5 7603 "@
7604 neg\\t%0, %1\;adc\\t%0, %0, %1
7605 neg\\t%2, %1\;adc\\t%0, %1, %2"
7606 [(set_attr "length" "4")]
7607)
7608
25f905c2 7609(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7610 [(set (match_operand:SI 0 "s_register_operand" "=l")
7611 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7612 (const_int 0)))
7613 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7614 "TARGET_THUMB1"
595d88b5 7615 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7616 [(set_attr "length" "4")]
7617)
7618
408b7ae5 7619;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 7620(define_insn "cstoresi_nltu_thumb1"
595d88b5 7621 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7622 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7623 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7624 "TARGET_THUMB1"
595d88b5 7625 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7626 [(set_attr "length" "4")]
7627)
7628
408b7ae5 7629(define_insn_and_split "cstoresi_ltu_thumb1"
7630 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7631 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7632 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7633 "TARGET_THUMB1"
7634 "#"
7635 "TARGET_THUMB1"
7636 [(set (match_dup 3)
7637 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7638 (set (match_dup 0) (neg:SI (match_dup 3)))]
7639 "operands[3] = gen_reg_rtx (SImode);"
7640 [(set_attr "length" "4")]
7641)
7642
595d88b5 7643;; Used as part of the expansion of thumb les sequence.
25f905c2 7644(define_insn "thumb1_addsi3_addgeu"
595d88b5 7645 [(set (match_operand:SI 0 "s_register_operand" "=l")
7646 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7647 (match_operand:SI 2 "s_register_operand" "l"))
7648 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 7649 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7650 "TARGET_THUMB1"
595d88b5 7651 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7652 [(set_attr "length" "4")]
7653)
7654
9c08d1fa 7655\f
39b5e676 7656;; Conditional move insns
7657
7658(define_expand "movsicc"
8a18b90c 7659 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7660 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7661 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7662 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7663 "TARGET_32BIT"
39b5e676 7664 "
215b30b3 7665 {
7666 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7667 rtx ccreg;
7668
7669 if (code == UNEQ || code == LTGT)
7670 FAIL;
39b5e676 7671
74f4459c 7672 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7673 XEXP (operands[1], 1));
29bb088d 7674 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7675 }"
7676)
39b5e676 7677
7678(define_expand "movsfcc"
8a18b90c 7679 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7680 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7681 (match_operand:SF 2 "s_register_operand" "")
7682 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 7683 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7684 "
215b30b3 7685 {
7686 enum rtx_code code = GET_CODE (operands[1]);
7687 rtx ccreg;
f082f1c4 7688
278b301d 7689 if (code == UNEQ || code == LTGT)
7690 FAIL;
7691
215b30b3 7692 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7693 Otherwise, ensure it is a valid FP add operand */
7694 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7695 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7696 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7697
74f4459c 7698 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7699 XEXP (operands[1], 1));
29bb088d 7700 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7701 }"
7702)
39b5e676 7703
7704(define_expand "movdfcc"
8a18b90c 7705 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7706 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7707 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7708 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 7709 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 7710 "
215b30b3 7711 {
7712 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7713 rtx ccreg;
39b5e676 7714
278b301d 7715 if (code == UNEQ || code == LTGT)
7716 FAIL;
7717
74f4459c 7718 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7719 XEXP (operands[1], 1));
29bb088d 7720 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7721 }"
7722)
39b5e676 7723
7724(define_insn "*movsicc_insn"
f082f1c4 7725 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7726 (if_then_else:SI
8fa3ba89 7727 (match_operator 3 "arm_comparison_operator"
8a18b90c 7728 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7729 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7730 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7731 "TARGET_ARM"
39b5e676 7732 "@
8a18b90c 7733 mov%D3\\t%0, %2
7734 mvn%D3\\t%0, #%B2
f082f1c4 7735 mov%d3\\t%0, %1
7736 mvn%d3\\t%0, #%B1
8a18b90c 7737 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7738 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7739 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7740 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7741 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7742 (set_attr "conds" "use")
7743 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 7744)
39b5e676 7745
39b5e676 7746(define_insn "*movsfcc_soft_insn"
f082f1c4 7747 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7748 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7749 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7750 (match_operand:SF 1 "s_register_operand" "0,r")
7751 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7752 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7753 "@
7754 mov%D3\\t%0, %2
7755 mov%d3\\t%0, %1"
d2a518d1 7756 [(set_attr "conds" "use")
7757 (set_attr "insn" "mov")]
8fa3ba89 7758)
39b5e676 7759
39b5e676 7760\f
9c08d1fa 7761;; Jump and linkage insns
7762
cffb2a26 7763(define_expand "jump"
9c08d1fa 7764 [(set (pc)
7765 (label_ref (match_operand 0 "" "")))]
cffb2a26 7766 "TARGET_EITHER"
9c08d1fa 7767 ""
cffb2a26 7768)
7769
7770(define_insn "*arm_jump"
7771 [(set (pc)
7772 (label_ref (match_operand 0 "" "")))]
25f905c2 7773 "TARGET_32BIT"
9c08d1fa 7774 "*
0d66636f 7775 {
7776 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7777 {
7778 arm_ccfsm_state += 2;
7779 return \"\";
7780 }
7781 return \"b%?\\t%l0\";
7782 }
7783 "
a6864a24 7784 [(set_attr "predicable" "yes")
7785 (set (attr "length")
7786 (if_then_else
7787 (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7788 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7789 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7790 (const_int 2)
7791 (const_int 4)))]
0d66636f 7792)
9c08d1fa 7793
cffb2a26 7794(define_insn "*thumb_jump"
7795 [(set (pc)
7796 (label_ref (match_operand 0 "" "")))]
25f905c2 7797 "TARGET_THUMB1"
cffb2a26 7798 "*
7799 if (get_attr_length (insn) == 2)
7800 return \"b\\t%l0\";
7801 return \"bl\\t%l0\\t%@ far jump\";
7802 "
7803 [(set (attr "far_jump")
7804 (if_then_else
7805 (eq_attr "length" "4")
7806 (const_string "yes")
7807 (const_string "no")))
7808 (set (attr "length")
7809 (if_then_else
911ed8af 7810 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7811 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7812 (const_int 2)
7813 (const_int 4)))]
7814)
7815
d3373b54 7816(define_expand "call"
7817 [(parallel [(call (match_operand 0 "memory_operand" "")
7818 (match_operand 1 "general_operand" ""))
cffb2a26 7819 (use (match_operand 2 "" ""))
bd5b4116 7820 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7821 "TARGET_EITHER"
6c4c2133 7822 "
7823 {
bac7fc85 7824 rtx callee, pat;
bbe777ea 7825
bbe777ea 7826 /* In an untyped call, we can get NULL for operand 2. */
7827 if (operands[2] == NULL_RTX)
7828 operands[2] = const0_rtx;
7829
de55252a 7830 /* Decide if we should generate indirect calls by loading the
85c36fd1 7831 32-bit address of the callee into a register before performing the
de55252a 7832 branch and link. */
7833 callee = XEXP (operands[0], 0);
7834 if (GET_CODE (callee) == SYMBOL_REF
7835 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7836 : !REG_P (callee))
bbe777ea 7837 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7838
7839 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7840 arm_emit_call_insn (pat, XEXP (operands[0], 0));
7841 DONE;
6c4c2133 7842 }"
7843)
d3373b54 7844
bac7fc85 7845(define_expand "call_internal"
7846 [(parallel [(call (match_operand 0 "memory_operand" "")
7847 (match_operand 1 "general_operand" ""))
7848 (use (match_operand 2 "" ""))
7849 (clobber (reg:SI LR_REGNUM))])])
7850
f1039640 7851(define_insn "*call_reg_armv5"
d3373b54 7852 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7853 (match_operand 1 "" ""))
7854 (use (match_operand 2 "" ""))
bd5b4116 7855 (clobber (reg:SI LR_REGNUM))]
f1039640 7856 "TARGET_ARM && arm_arch5"
7857 "blx%?\\t%0"
7858 [(set_attr "type" "call")]
7859)
7860
7861(define_insn "*call_reg_arm"
7862 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7863 (match_operand 1 "" ""))
7864 (use (match_operand 2 "" ""))
7865 (clobber (reg:SI LR_REGNUM))]
7866 "TARGET_ARM && !arm_arch5"
9c08d1fa 7867 "*
5565501b 7868 return output_call (operands);
cffb2a26 7869 "
7870 ;; length is worst case, normally it is only two
7871 [(set_attr "length" "12")
7872 (set_attr "type" "call")]
7873)
9c08d1fa 7874
89504fc1 7875
7876;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7877;; considered a function call by the branch predictor of some cores (PR40887).
7878;; Falls back to blx rN (*call_reg_armv5).
7879
f7fbdd4a 7880(define_insn "*call_mem"
a3c63a9d 7881 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7882 (match_operand 1 "" ""))
7883 (use (match_operand 2 "" ""))
bd5b4116 7884 (clobber (reg:SI LR_REGNUM))]
89504fc1 7885 "TARGET_ARM && !arm_arch5"
9c08d1fa 7886 "*
5565501b 7887 return output_call_mem (operands);
cffb2a26 7888 "
7889 [(set_attr "length" "12")
7890 (set_attr "type" "call")]
7891)
7892
25f905c2 7893(define_insn "*call_reg_thumb1_v5"
cffb2a26 7894 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7895 (match_operand 1 "" ""))
7896 (use (match_operand 2 "" ""))
bd5b4116 7897 (clobber (reg:SI LR_REGNUM))]
25f905c2 7898 "TARGET_THUMB1 && arm_arch5"
f1039640 7899 "blx\\t%0"
7900 [(set_attr "length" "2")
7901 (set_attr "type" "call")]
cffb2a26 7902)
7903
25f905c2 7904(define_insn "*call_reg_thumb1"
f1039640 7905 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7906 (match_operand 1 "" ""))
7907 (use (match_operand 2 "" ""))
bd5b4116 7908 (clobber (reg:SI LR_REGNUM))]
25f905c2 7909 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 7910 "*
7911 {
150502c9 7912 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7913 return thumb_call_via_reg (operands[0]);
150502c9 7914 else if (operands[1] == const0_rtx)
f1039640 7915 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7916 else if (frame_pointer_needed)
7917 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7918 else
150502c9 7919 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7920 }"
7921 [(set_attr "type" "call")]
7922)
9c08d1fa 7923
d3373b54 7924(define_expand "call_value"
e0698af7 7925 [(parallel [(set (match_operand 0 "" "")
7926 (call (match_operand 1 "memory_operand" "")
7927 (match_operand 2 "general_operand" "")))
cffb2a26 7928 (use (match_operand 3 "" ""))
bd5b4116 7929 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7930 "TARGET_EITHER"
6c4c2133 7931 "
7932 {
bac7fc85 7933 rtx pat, callee;
bbe777ea 7934
7935 /* In an untyped call, we can get NULL for operand 2. */
7936 if (operands[3] == 0)
7937 operands[3] = const0_rtx;
7938
de55252a 7939 /* Decide if we should generate indirect calls by loading the
7940 32-bit address of the callee into a register before performing the
7941 branch and link. */
7942 callee = XEXP (operands[1], 0);
7943 if (GET_CODE (callee) == SYMBOL_REF
7944 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7945 : !REG_P (callee))
78fe751b 7946 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7947
7948 pat = gen_call_value_internal (operands[0], operands[1],
7949 operands[2], operands[3]);
7950 arm_emit_call_insn (pat, XEXP (operands[1], 0));
7951 DONE;
6c4c2133 7952 }"
7953)
d3373b54 7954
bac7fc85 7955(define_expand "call_value_internal"
7956 [(parallel [(set (match_operand 0 "" "")
7957 (call (match_operand 1 "memory_operand" "")
7958 (match_operand 2 "general_operand" "")))
7959 (use (match_operand 3 "" ""))
7960 (clobber (reg:SI LR_REGNUM))])])
7961
f1039640 7962(define_insn "*call_value_reg_armv5"
27ed6835 7963 [(set (match_operand 0 "" "")
755eb2b4 7964 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7965 (match_operand 2 "" "")))
bbe777ea 7966 (use (match_operand 3 "" ""))
bd5b4116 7967 (clobber (reg:SI LR_REGNUM))]
f1039640 7968 "TARGET_ARM && arm_arch5"
7969 "blx%?\\t%1"
7970 [(set_attr "type" "call")]
7971)
7972
7973(define_insn "*call_value_reg_arm"
7974 [(set (match_operand 0 "" "")
7975 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7976 (match_operand 2 "" "")))
7977 (use (match_operand 3 "" ""))
7978 (clobber (reg:SI LR_REGNUM))]
7979 "TARGET_ARM && !arm_arch5"
9c08d1fa 7980 "*
215b30b3 7981 return output_call (&operands[1]);
cffb2a26 7982 "
7983 [(set_attr "length" "12")
7984 (set_attr "type" "call")]
7985)
9c08d1fa 7986
89504fc1 7987;; Note: see *call_mem
7988
f7fbdd4a 7989(define_insn "*call_value_mem"
27ed6835 7990 [(set (match_operand 0 "" "")
a3c63a9d 7991 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7992 (match_operand 2 "" "")))
bbe777ea 7993 (use (match_operand 3 "" ""))
bd5b4116 7994 (clobber (reg:SI LR_REGNUM))]
89504fc1 7995 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7996 "*
215b30b3 7997 return output_call_mem (&operands[1]);
cffb2a26 7998 "
7999 [(set_attr "length" "12")
8000 (set_attr "type" "call")]
8001)
9c08d1fa 8002
25f905c2 8003(define_insn "*call_value_reg_thumb1_v5"
f1039640 8004 [(set (match_operand 0 "" "")
8005 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8006 (match_operand 2 "" "")))
8007 (use (match_operand 3 "" ""))
8008 (clobber (reg:SI LR_REGNUM))]
25f905c2 8009 "TARGET_THUMB1 && arm_arch5"
f1039640 8010 "blx\\t%1"
8011 [(set_attr "length" "2")
8012 (set_attr "type" "call")]
8013)
8014
25f905c2 8015(define_insn "*call_value_reg_thumb1"
f1039640 8016 [(set (match_operand 0 "" "")
8017 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8018 (match_operand 2 "" "")))
8019 (use (match_operand 3 "" ""))
8020 (clobber (reg:SI LR_REGNUM))]
25f905c2 8021 "TARGET_THUMB1 && !arm_arch5"
f1039640 8022 "*
8023 {
150502c9 8024 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8025 return thumb_call_via_reg (operands[1]);
150502c9 8026 else if (operands[2] == const0_rtx)
f1039640 8027 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8028 else if (frame_pointer_needed)
8029 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8030 else
150502c9 8031 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8032 }"
8033 [(set_attr "type" "call")]
8034)
8035
9c08d1fa 8036;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8037;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8038
f7fbdd4a 8039(define_insn "*call_symbol"
27ed6835 8040 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8041 (match_operand 1 "" ""))
bbe777ea 8042 (use (match_operand 2 "" ""))
bd5b4116 8043 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8044 "TARGET_32BIT
cffb2a26 8045 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8046 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8047 "*
8048 {
55c1e470 8049 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8050 }"
cffb2a26 8051 [(set_attr "type" "call")]
8052)
9c08d1fa 8053
f7fbdd4a 8054(define_insn "*call_value_symbol"
ccd90aaa 8055 [(set (match_operand 0 "" "")
27ed6835 8056 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8057 (match_operand:SI 2 "" "")))
bbe777ea 8058 (use (match_operand 3 "" ""))
bd5b4116 8059 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8060 "TARGET_32BIT
cffb2a26 8061 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8062 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8063 "*
8064 {
55c1e470 8065 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8066 }"
cffb2a26 8067 [(set_attr "type" "call")]
8068)
8069
8070(define_insn "*call_insn"
27ed6835 8071 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8072 (match_operand:SI 1 "" ""))
8073 (use (match_operand 2 "" ""))
bd5b4116 8074 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8075 "TARGET_THUMB1
1675c6e9 8076 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8077 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8078 "bl\\t%a0"
8079 [(set_attr "length" "4")
8080 (set_attr "type" "call")]
8081)
8082
8083(define_insn "*call_value_insn"
ccd90aaa 8084 [(set (match_operand 0 "" "")
27ed6835 8085 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8086 (match_operand 2 "" "")))
8087 (use (match_operand 3 "" ""))
bd5b4116 8088 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8089 "TARGET_THUMB1
1675c6e9 8090 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8091 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8092 "bl\\t%a1"
8093 [(set_attr "length" "4")
8094 (set_attr "type" "call")]
8095)
9c08d1fa 8096
1c494086 8097;; We may also be able to do sibcalls for Thumb, but it's much harder...
8098(define_expand "sibcall"
8099 [(parallel [(call (match_operand 0 "memory_operand" "")
8100 (match_operand 1 "general_operand" ""))
2ba80634 8101 (return)
8102 (use (match_operand 2 "" ""))])]
d68c2c10 8103 "TARGET_32BIT"
1c494086 8104 "
8105 {
8106 if (operands[2] == NULL_RTX)
8107 operands[2] = const0_rtx;
1c494086 8108 }"
8109)
8110
8111(define_expand "sibcall_value"
ccd90aaa 8112 [(parallel [(set (match_operand 0 "" "")
1c494086 8113 (call (match_operand 1 "memory_operand" "")
8114 (match_operand 2 "general_operand" "")))
2ba80634 8115 (return)
8116 (use (match_operand 3 "" ""))])]
d68c2c10 8117 "TARGET_32BIT"
1c494086 8118 "
8119 {
8120 if (operands[3] == NULL_RTX)
8121 operands[3] = const0_rtx;
1c494086 8122 }"
8123)
8124
8125(define_insn "*sibcall_insn"
8126 [(call (mem:SI (match_operand:SI 0 "" "X"))
8127 (match_operand 1 "" ""))
2ba80634 8128 (return)
8129 (use (match_operand 2 "" ""))]
d68c2c10 8130 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8131 "*
8132 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8133 "
8134 [(set_attr "type" "call")]
8135)
8136
8137(define_insn "*sibcall_value_insn"
ccd90aaa 8138 [(set (match_operand 0 "" "")
755eb2b4 8139 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8140 (match_operand 2 "" "")))
2ba80634 8141 (return)
8142 (use (match_operand 3 "" ""))]
d68c2c10 8143 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8144 "*
8145 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8146 "
8147 [(set_attr "type" "call")]
8148)
8149
d68c2c10 8150(define_expand "return"
8151 [(return)]
8152 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8153 "")
8154
9c08d1fa 8155;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8156(define_insn "*arm_return"
9c08d1fa 8157 [(return)]
cffb2a26 8158 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8159 "*
9c08d1fa 8160 {
cffb2a26 8161 if (arm_ccfsm_state == 2)
8162 {
8163 arm_ccfsm_state += 2;
8164 return \"\";
8165 }
5db468b7 8166 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8167 }"
a2cd141b 8168 [(set_attr "type" "load1")
755eb2b4 8169 (set_attr "length" "12")
0d66636f 8170 (set_attr "predicable" "yes")]
cffb2a26 8171)
9c08d1fa 8172
f7fbdd4a 8173(define_insn "*cond_return"
9c08d1fa 8174 [(set (pc)
8fa3ba89 8175 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8176 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8177 (return)
8178 (pc)))]
cffb2a26 8179 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8180 "*
8fa3ba89 8181 {
8182 if (arm_ccfsm_state == 2)
8183 {
8184 arm_ccfsm_state += 2;
8185 return \"\";
8186 }
8187 return output_return_instruction (operands[0], TRUE, FALSE);
8188 }"
8189 [(set_attr "conds" "use")
755eb2b4 8190 (set_attr "length" "12")
a2cd141b 8191 (set_attr "type" "load1")]
8fa3ba89 8192)
9c08d1fa 8193
f7fbdd4a 8194(define_insn "*cond_return_inverted"
9c08d1fa 8195 [(set (pc)
8fa3ba89 8196 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8197 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8198 (pc)
8199 (return)))]
cffb2a26 8200 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8201 "*
8fa3ba89 8202 {
8203 if (arm_ccfsm_state == 2)
8204 {
8205 arm_ccfsm_state += 2;
8206 return \"\";
8207 }
8208 return output_return_instruction (operands[0], TRUE, TRUE);
8209 }"
8210 [(set_attr "conds" "use")
37a1317b 8211 (set_attr "length" "12")
a2cd141b 8212 (set_attr "type" "load1")]
8fa3ba89 8213)
9c08d1fa 8214
68121397 8215;; Generate a sequence of instructions to determine if the processor is
8216;; in 26-bit or 32-bit mode, and return the appropriate return address
8217;; mask.
8218
8219(define_expand "return_addr_mask"
8220 [(set (match_dup 1)
8221 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8222 (const_int 0)))
8223 (set (match_operand:SI 0 "s_register_operand" "")
8224 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8225 (const_int -1)
8226 (const_int 67108860)))] ; 0x03fffffc
8227 "TARGET_ARM"
8228 "
62eddbd4 8229 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8230 ")
8231
8232(define_insn "*check_arch2"
8233 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8234 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8235 (const_int 0)))]
8236 "TARGET_ARM"
8237 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8238 [(set_attr "length" "8")
8239 (set_attr "conds" "set")]
8240)
8241
9c08d1fa 8242;; Call subroutine returning any type.
8243
8244(define_expand "untyped_call"
8245 [(parallel [(call (match_operand 0 "" "")
8246 (const_int 0))
8247 (match_operand 1 "" "")
8248 (match_operand 2 "" "")])]
ccd90aaa 8249 "TARGET_EITHER"
9c08d1fa 8250 "
215b30b3 8251 {
8252 int i;
ccd90aaa 8253 rtx par = gen_rtx_PARALLEL (VOIDmode,
8254 rtvec_alloc (XVECLEN (operands[2], 0)));
8255 rtx addr = gen_reg_rtx (Pmode);
8256 rtx mem;
8257 int size = 0;
9c08d1fa 8258
ccd90aaa 8259 emit_move_insn (addr, XEXP (operands[1], 0));
8260 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8261
215b30b3 8262 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8263 {
ccd90aaa 8264 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8265
ccd90aaa 8266 /* Default code only uses r0 as a return value, but we could
8267 be using anything up to 4 registers. */
8268 if (REGNO (src) == R0_REGNUM)
8269 src = gen_rtx_REG (TImode, R0_REGNUM);
8270
8271 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8272 GEN_INT (size));
8273 size += GET_MODE_SIZE (GET_MODE (src));
8274 }
8275
8276 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8277 const0_rtx));
8278
8279 size = 0;
8280
8281 for (i = 0; i < XVECLEN (par, 0); i++)
8282 {
8283 HOST_WIDE_INT offset = 0;
8284 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8285
8286 if (size != 0)
8287 emit_move_insn (addr, plus_constant (addr, size));
8288
8289 mem = change_address (mem, GET_MODE (reg), NULL);
8290 if (REGNO (reg) == R0_REGNUM)
8291 {
8292 /* On thumb we have to use a write-back instruction. */
320ea44d 8293 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8294 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8295 size = TARGET_ARM ? 16 : 0;
8296 }
8297 else
8298 {
8299 emit_move_insn (mem, reg);
8300 size = GET_MODE_SIZE (GET_MODE (reg));
8301 }
215b30b3 8302 }
9c08d1fa 8303
215b30b3 8304 /* The optimizer does not know that the call sets the function value
8305 registers we stored in the result block. We avoid problems by
8306 claiming that all hard registers are used and clobbered at this
8307 point. */
8308 emit_insn (gen_blockage ());
8309
8310 DONE;
8311 }"
8312)
9c08d1fa 8313
ccd90aaa 8314(define_expand "untyped_return"
8315 [(match_operand:BLK 0 "memory_operand" "")
8316 (match_operand 1 "" "")]
8317 "TARGET_EITHER"
8318 "
8319 {
8320 int i;
8321 rtx addr = gen_reg_rtx (Pmode);
8322 rtx mem;
8323 int size = 0;
8324
8325 emit_move_insn (addr, XEXP (operands[0], 0));
8326 mem = change_address (operands[0], BLKmode, addr);
8327
8328 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8329 {
8330 HOST_WIDE_INT offset = 0;
8331 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8332
8333 if (size != 0)
8334 emit_move_insn (addr, plus_constant (addr, size));
8335
8336 mem = change_address (mem, GET_MODE (reg), NULL);
8337 if (REGNO (reg) == R0_REGNUM)
8338 {
8339 /* On thumb we have to use a write-back instruction. */
320ea44d 8340 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8341 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8342 size = TARGET_ARM ? 16 : 0;
8343 }
8344 else
8345 {
8346 emit_move_insn (reg, mem);
8347 size = GET_MODE_SIZE (GET_MODE (reg));
8348 }
8349 }
8350
8351 /* Emit USE insns before the return. */
8352 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8353 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8354
8355 /* Construct the return. */
8356 expand_naked_return ();
8357
8358 DONE;
8359 }"
8360)
8361
9c08d1fa 8362;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8363;; all of memory. This blocks insns from being moved across this point.
8364
8365(define_insn "blockage"
e1159bbe 8366 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8367 "TARGET_EITHER"
9c08d1fa 8368 ""
cffb2a26 8369 [(set_attr "length" "0")
8370 (set_attr "type" "block")]
8371)
9c08d1fa 8372
f7fbdd4a 8373(define_expand "casesi"
8374 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8375 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8376 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8377 (match_operand:SI 3 "" "") ; table label
8378 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8379 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8380 "
215b30b3 8381 {
e6ac8414 8382 enum insn_code code;
215b30b3 8383 if (operands[1] != const0_rtx)
8384 {
e6ac8414 8385 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8386
215b30b3 8387 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8388 gen_int_mode (-INTVAL (operands[1]),
8389 SImode)));
215b30b3 8390 operands[0] = reg;
8391 }
9c08d1fa 8392
25f905c2 8393 if (TARGET_ARM)
e6ac8414 8394 code = CODE_FOR_arm_casesi_internal;
3db2019b 8395 else if (TARGET_THUMB1)
e6ac8414 8396 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8397 else if (flag_pic)
e6ac8414 8398 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8399 else
e6ac8414 8400 code = CODE_FOR_thumb2_casesi_internal;
8401
8402 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8403 operands[2] = force_reg (SImode, operands[2]);
8404
8405 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8406 operands[3], operands[4]));
215b30b3 8407 DONE;
8408 }"
8409)
f7fbdd4a 8410
f082f1c4 8411;; The USE in this pattern is needed to tell flow analysis that this is
8412;; a CASESI insn. It has no other purpose.
25f905c2 8413(define_insn "arm_casesi_internal"
f082f1c4 8414 [(parallel [(set (pc)
8415 (if_then_else
8416 (leu (match_operand:SI 0 "s_register_operand" "r")
8417 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8418 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8419 (label_ref (match_operand 2 "" ""))))
8420 (label_ref (match_operand 3 "" ""))))
bd5b4116 8421 (clobber (reg:CC CC_REGNUM))
f082f1c4 8422 (use (label_ref (match_dup 2)))])]
cffb2a26 8423 "TARGET_ARM"
f7fbdd4a 8424 "*
0d66636f 8425 if (flag_pic)
8426 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8427 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8428 "
8429 [(set_attr "conds" "clob")
8430 (set_attr "length" "12")]
8431)
9c08d1fa 8432
e6ac8414 8433(define_expand "thumb1_casesi_internal_pic"
8434 [(match_operand:SI 0 "s_register_operand" "")
8435 (match_operand:SI 1 "thumb1_cmp_operand" "")
8436 (match_operand 2 "" "")
8437 (match_operand 3 "" "")]
3db2019b 8438 "TARGET_THUMB1"
e6ac8414 8439 {
8440 rtx reg0;
8441 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8442 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8443 operands[3]));
8444 reg0 = gen_rtx_REG (SImode, 0);
8445 emit_move_insn (reg0, operands[0]);
8446 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8447 DONE;
8448 }
8449)
8450
8451(define_insn "thumb1_casesi_dispatch"
8452 [(parallel [(set (pc) (unspec [(reg:SI 0)
8453 (label_ref (match_operand 0 "" ""))
8454;; (label_ref (match_operand 1 "" ""))
8455]
8456 UNSPEC_THUMB1_CASESI))
8457 (clobber (reg:SI IP_REGNUM))
8458 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8459 "TARGET_THUMB1"
e6ac8414 8460 "* return thumb1_output_casesi(operands);"
8461 [(set_attr "length" "4")]
8462)
8463
cffb2a26 8464(define_expand "indirect_jump"
9c08d1fa 8465 [(set (pc)
cffb2a26 8466 (match_operand:SI 0 "s_register_operand" ""))]
8467 "TARGET_EITHER"
25f905c2 8468 "
8469 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8470 address and use bx. */
8471 if (TARGET_THUMB2)
8472 {
8473 rtx tmp;
8474 tmp = gen_reg_rtx (SImode);
8475 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8476 operands[0] = tmp;
8477 }
8478 "
cffb2a26 8479)
8480
f1039640 8481;; NB Never uses BX.
cffb2a26 8482(define_insn "*arm_indirect_jump"
8483 [(set (pc)
8484 (match_operand:SI 0 "s_register_operand" "r"))]
8485 "TARGET_ARM"
8486 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8487 [(set_attr "predicable" "yes")]
cffb2a26 8488)
9c08d1fa 8489
f7fbdd4a 8490(define_insn "*load_indirect_jump"
9c08d1fa 8491 [(set (pc)
8492 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8493 "TARGET_ARM"
8494 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8495 [(set_attr "type" "load1")
61a2d04c 8496 (set_attr "pool_range" "4096")
8497 (set_attr "neg_pool_range" "4084")
0d66636f 8498 (set_attr "predicable" "yes")]
cffb2a26 8499)
8500
f1039640 8501;; NB Never uses BX.
25f905c2 8502(define_insn "*thumb1_indirect_jump"
cffb2a26 8503 [(set (pc)
8504 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8505 "TARGET_THUMB1"
cffb2a26 8506 "mov\\tpc, %0"
8507 [(set_attr "conds" "clob")
8508 (set_attr "length" "2")]
8509)
8510
9c08d1fa 8511\f
8512;; Misc insns
8513
8514(define_insn "nop"
8515 [(const_int 0)]
cffb2a26 8516 "TARGET_EITHER"
8517 "*
25f905c2 8518 if (TARGET_UNIFIED_ASM)
8519 return \"nop\";
cffb2a26 8520 if (TARGET_ARM)
8521 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8522 return \"mov\\tr8, r8\";
8523 "
8524 [(set (attr "length")
8525 (if_then_else (eq_attr "is_thumb" "yes")
8526 (const_int 2)
8527 (const_int 4)))]
8528)
8529
9c08d1fa 8530\f
8531;; Patterns to allow combination of arithmetic, cond code and shifts
8532
f7fbdd4a 8533(define_insn "*arith_shiftsi"
d5d4dc8d 8534 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8535 (match_operator:SI 1 "shiftable_operator"
8536 [(match_operator:SI 3 "shift_operator"
d5d4dc8d 8537 [(match_operand:SI 4 "s_register_operand" "r,r")
8538 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8539 (match_operand:SI 2 "s_register_operand" "rk,rk")]))]
8540 "TARGET_32BIT"
6c4c2133 8541 "%i1%?\\t%0, %2, %4%S3"
344495ea 8542 [(set_attr "predicable" "yes")
331beb1a 8543 (set_attr "shift" "4")
d5d4dc8d 8544 (set_attr "arch" "32,a")
8545 ;; We have to make sure to disable the second alternative if
8546 ;; the shift_operator is MULT, since otherwise the insn will
8547 ;; also match a multiply_accumulate pattern and validate_change
8548 ;; will allow a replacement of the constant with a register
8549 ;; despite the checks done in shift_operator.
8550 (set_attr_alternative "insn_enabled"
8551 [(const_string "yes")
8552 (if_then_else
8553 (match_operand:SI 3 "mult_operator" "")
8554 (const_string "no") (const_string "yes"))])
8555 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8556
d7863cfe 8557(define_split
8558 [(set (match_operand:SI 0 "s_register_operand" "")
8559 (match_operator:SI 1 "shiftable_operator"
8560 [(match_operator:SI 2 "shiftable_operator"
8561 [(match_operator:SI 3 "shift_operator"
8562 [(match_operand:SI 4 "s_register_operand" "")
8563 (match_operand:SI 5 "reg_or_int_operand" "")])
8564 (match_operand:SI 6 "s_register_operand" "")])
8565 (match_operand:SI 7 "arm_rhs_operand" "")]))
8566 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8567 "TARGET_32BIT"
d7863cfe 8568 [(set (match_dup 8)
8569 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8570 (match_dup 6)]))
8571 (set (match_dup 0)
8572 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8573 "")
8574
f7fbdd4a 8575(define_insn "*arith_shiftsi_compare0"
bd5b4116 8576 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8577 (compare:CC_NOOV
8578 (match_operator:SI 1 "shiftable_operator"
8579 [(match_operator:SI 3 "shift_operator"
8580 [(match_operand:SI 4 "s_register_operand" "r,r")
8581 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8582 (match_operand:SI 2 "s_register_operand" "r,r")])
8583 (const_int 0)))
8584 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8585 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8586 (match_dup 2)]))]
d5d4dc8d 8587 "TARGET_32BIT"
25f905c2 8588 "%i1%.\\t%0, %2, %4%S3"
344495ea 8589 [(set_attr "conds" "set")
331beb1a 8590 (set_attr "shift" "4")
d5d4dc8d 8591 (set_attr "arch" "32,a")
8592 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8593
f7fbdd4a 8594(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8595 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8596 (compare:CC_NOOV
8597 (match_operator:SI 1 "shiftable_operator"
8598 [(match_operator:SI 3 "shift_operator"
8599 [(match_operand:SI 4 "s_register_operand" "r,r")
8600 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8601 (match_operand:SI 2 "s_register_operand" "r,r")])
8602 (const_int 0)))
8603 (clobber (match_scratch:SI 0 "=r,r"))]
8604 "TARGET_32BIT"
25f905c2 8605 "%i1%.\\t%0, %2, %4%S3"
344495ea 8606 [(set_attr "conds" "set")
331beb1a 8607 (set_attr "shift" "4")
d5d4dc8d 8608 (set_attr "arch" "32,a")
8609 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8610
f7fbdd4a 8611(define_insn "*sub_shiftsi"
d5d4dc8d 8612 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8613 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8614 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8615 [(match_operand:SI 3 "s_register_operand" "r,r")
8616 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8617 "TARGET_32BIT"
6c4c2133 8618 "sub%?\\t%0, %1, %3%S2"
344495ea 8619 [(set_attr "predicable" "yes")
331beb1a 8620 (set_attr "shift" "3")
d5d4dc8d 8621 (set_attr "arch" "32,a")
8622 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8623
f7fbdd4a 8624(define_insn "*sub_shiftsi_compare0"
bd5b4116 8625 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8626 (compare:CC_NOOV
d5d4dc8d 8627 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8628 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8629 [(match_operand:SI 3 "s_register_operand" "r,r")
8630 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8631 (const_int 0)))
d5d4dc8d 8632 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8633 (minus:SI (match_dup 1)
8634 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8635 "TARGET_32BIT"
25f905c2 8636 "sub%.\\t%0, %1, %3%S2"
344495ea 8637 [(set_attr "conds" "set")
a2cd141b 8638 (set_attr "shift" "3")
d5d4dc8d 8639 (set_attr "arch" "32,a")
8640 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8641
f7fbdd4a 8642(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8643 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8644 (compare:CC_NOOV
d5d4dc8d 8645 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8646 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8647 [(match_operand:SI 3 "s_register_operand" "r,r")
8648 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8649 (const_int 0)))
d5d4dc8d 8650 (clobber (match_scratch:SI 0 "=r,r"))]
8651 "TARGET_32BIT"
25f905c2 8652 "sub%.\\t%0, %1, %3%S2"
344495ea 8653 [(set_attr "conds" "set")
a2cd141b 8654 (set_attr "shift" "3")
d5d4dc8d 8655 (set_attr "arch" "32,a")
8656 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8657\f
8658
f7fbdd4a 8659(define_insn "*and_scc"
9c08d1fa 8660 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8661 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8662 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8663 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8664 "TARGET_ARM"
e2348bcb 8665 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8666 [(set_attr "conds" "use")
d2a518d1 8667 (set_attr "insn" "mov")
8fa3ba89 8668 (set_attr "length" "8")]
8669)
9c08d1fa 8670
f7fbdd4a 8671(define_insn "*ior_scc"
9c08d1fa 8672 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8673 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8674 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8675 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8676 "TARGET_ARM"
e2348bcb 8677 "@
899850b0 8678 orr%d2\\t%0, %1, #1
8679 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8680 [(set_attr "conds" "use")
8681 (set_attr "length" "4,8")]
8682)
9c08d1fa 8683
2df9477b 8684; A series of splitters for the compare_scc pattern below. Note that
8685; order is important.
8686(define_split
8687 [(set (match_operand:SI 0 "s_register_operand" "")
8688 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8689 (const_int 0)))
8690 (clobber (reg:CC CC_REGNUM))]
8691 "TARGET_32BIT && reload_completed"
8692 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8693
8694(define_split
8695 [(set (match_operand:SI 0 "s_register_operand" "")
8696 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8697 (const_int 0)))
8698 (clobber (reg:CC CC_REGNUM))]
8699 "TARGET_32BIT && reload_completed"
8700 [(set (match_dup 0) (not:SI (match_dup 1)))
8701 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8702
8703(define_split
8704 [(set (match_operand:SI 0 "s_register_operand" "")
8705 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8706 (const_int 0)))
8707 (clobber (reg:CC CC_REGNUM))]
8708 "TARGET_32BIT && reload_completed"
8709 [(parallel
080c0b9a 8710 [(set (reg:CC CC_REGNUM)
8711 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8712 (set (match_dup 0)
8713 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8714 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8715 (set (match_dup 0) (const_int 0)))])
8716
8717(define_split
8718 [(set (match_operand:SI 0 "s_register_operand" "")
8719 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8720 (match_operand:SI 2 "const_int_operand" "")))
8721 (clobber (reg:CC CC_REGNUM))]
8722 "TARGET_32BIT && reload_completed"
8723 [(parallel
8724 [(set (reg:CC CC_REGNUM)
8725 (compare:CC (match_dup 1) (match_dup 2)))
8726 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8727 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8728 (set (match_dup 0) (const_int 1)))]
8729{
8730 operands[3] = GEN_INT (-INTVAL (operands[2]));
8731})
8732
8733(define_split
8734 [(set (match_operand:SI 0 "s_register_operand" "")
8735 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8736 (match_operand:SI 2 "arm_add_operand" "")))
8737 (clobber (reg:CC CC_REGNUM))]
8738 "TARGET_32BIT && reload_completed"
8739 [(parallel
8740 [(set (reg:CC_NOOV CC_REGNUM)
8741 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8742 (const_int 0)))
8743 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8744 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8745 (set (match_dup 0) (const_int 1)))])
8746
8747(define_insn_and_split "*compare_scc"
5565501b 8748 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8749 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8750 [(match_operand:SI 2 "s_register_operand" "r,r")
8751 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8752 (clobber (reg:CC CC_REGNUM))]
2df9477b 8753 "TARGET_32BIT"
8754 "#"
8755 "&& reload_completed"
8756 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8757 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8758 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8759{
8760 rtx tmp1;
8761 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8762 operands[2], operands[3]);
8763 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8764
2df9477b 8765 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8766
2df9477b 8767 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8768 if (mode == CCFPmode || mode == CCFPEmode)
8769 rc = reverse_condition_maybe_unordered (rc);
8770 else
8771 rc = reverse_condition (rc);
8772 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8773})
9c08d1fa 8774
080c0b9a 8775;; Attempt to improve the sequence generated by the compare_scc splitters
8776;; not to use conditional execution.
8777(define_peephole2
8778 [(set (reg:CC CC_REGNUM)
8779 (compare:CC (match_operand:SI 1 "register_operand" "")
8780 (match_operand:SI 2 "arm_rhs_operand" "")))
8781 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8782 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8783 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8784 (set (match_dup 0) (const_int 1)))
8785 (match_scratch:SI 3 "r")]
8786 "TARGET_32BIT"
8787 [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
8788 (parallel
8789 [(set (reg:CC CC_REGNUM)
8790 (compare:CC (const_int 0) (match_dup 3)))
8791 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8792 (set (match_dup 0)
8793 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8794 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
8795
f7fbdd4a 8796(define_insn "*cond_move"
9c08d1fa 8797 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8798 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8799 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8800 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8801 (const_int 0)])
8802 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8803 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8804 "TARGET_ARM"
9c08d1fa 8805 "*
8fa3ba89 8806 if (GET_CODE (operands[3]) == NE)
8807 {
8808 if (which_alternative != 1)
8809 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8810 if (which_alternative != 0)
8811 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8812 return \"\";
8813 }
8814 if (which_alternative != 0)
8815 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8816 if (which_alternative != 1)
8817 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8818 return \"\";
8819 "
8820 [(set_attr "conds" "use")
d2a518d1 8821 (set_attr "insn" "mov")
8fa3ba89 8822 (set_attr "length" "4,4,8")]
8823)
9c08d1fa 8824
f7fbdd4a 8825(define_insn "*cond_arith"
9c08d1fa 8826 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8827 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8828 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8829 [(match_operand:SI 2 "s_register_operand" "r,r")
8830 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8831 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8832 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8833 "TARGET_ARM"
9c08d1fa 8834 "*
8fa3ba89 8835 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8836 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8837
8fa3ba89 8838 output_asm_insn (\"cmp\\t%2, %3\", operands);
8839 if (GET_CODE (operands[5]) == AND)
8840 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8841 else if (GET_CODE (operands[5]) == MINUS)
8842 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8843 else if (which_alternative != 0)
8844 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8845 return \"%i5%d4\\t%0, %1, #1\";
8846 "
8847 [(set_attr "conds" "clob")
8848 (set_attr "length" "12")]
8849)
9c08d1fa 8850
f7fbdd4a 8851(define_insn "*cond_sub"
9c08d1fa 8852 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8853 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8854 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8855 [(match_operand:SI 2 "s_register_operand" "r,r")
8856 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8857 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8858 "TARGET_ARM"
9c08d1fa 8859 "*
8fa3ba89 8860 output_asm_insn (\"cmp\\t%2, %3\", operands);
8861 if (which_alternative != 0)
8862 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8863 return \"sub%d4\\t%0, %1, #1\";
8864 "
8865 [(set_attr "conds" "clob")
8866 (set_attr "length" "8,12")]
8867)
9c08d1fa 8868
25f905c2 8869;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 8870(define_insn "*cmp_ite0"
cffb2a26 8871 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8872 (compare
8873 (if_then_else:SI
8fa3ba89 8874 (match_operator 4 "arm_comparison_operator"
aea4c774 8875 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8876 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8877 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8878 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8879 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8880 (const_int 0))
8881 (const_int 0)))]
cffb2a26 8882 "TARGET_ARM"
9c08d1fa 8883 "*
aea4c774 8884 {
8fa3ba89 8885 static const char * const opcodes[4][2] =
8886 {
8887 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8888 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8889 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8890 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8891 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8892 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8893 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8894 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8895 };
8896 int swap =
8897 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8898
8899 return opcodes[which_alternative][swap];
8900 }"
8901 [(set_attr "conds" "set")
8902 (set_attr "length" "8")]
8903)
9c08d1fa 8904
aea4c774 8905(define_insn "*cmp_ite1"
cffb2a26 8906 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8907 (compare
8908 (if_then_else:SI
8fa3ba89 8909 (match_operator 4 "arm_comparison_operator"
aea4c774 8910 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8911 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8912 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8913 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8914 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8915 (const_int 1))
8916 (const_int 0)))]
cffb2a26 8917 "TARGET_ARM"
9c08d1fa 8918 "*
9c08d1fa 8919 {
215b30b3 8920 static const char * const opcodes[4][2] =
8921 {
8922 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8923 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8924 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8925 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8926 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8927 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8928 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8929 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8930 };
8931 int swap =
8932 comparison_dominates_p (GET_CODE (operands[5]),
8933 reverse_condition (GET_CODE (operands[4])));
8934
8935 return opcodes[which_alternative][swap];
8936 }"
8fa3ba89 8937 [(set_attr "conds" "set")
8938 (set_attr "length" "8")]
8939)
9c08d1fa 8940
f6c53574 8941(define_insn "*cmp_and"
8942 [(set (match_operand 6 "dominant_cc_register" "")
8943 (compare
8944 (and:SI
8945 (match_operator 4 "arm_comparison_operator"
8946 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8947 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8948 (match_operator:SI 5 "arm_comparison_operator"
8949 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8950 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8951 (const_int 0)))]
8952 "TARGET_ARM"
8953 "*
8954 {
35823b64 8955 static const char *const opcodes[4][2] =
f6c53574 8956 {
8957 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8958 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8959 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8960 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8961 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8962 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8963 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8964 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8965 };
8966 int swap =
8967 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8968
8969 return opcodes[which_alternative][swap];
8970 }"
8971 [(set_attr "conds" "set")
8972 (set_attr "predicable" "no")
8973 (set_attr "length" "8")]
8974)
8975
8976(define_insn "*cmp_ior"
8977 [(set (match_operand 6 "dominant_cc_register" "")
8978 (compare
8979 (ior:SI
8980 (match_operator 4 "arm_comparison_operator"
8981 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8982 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8983 (match_operator:SI 5 "arm_comparison_operator"
8984 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8985 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8986 (const_int 0)))]
8987 "TARGET_ARM"
8988 "*
8989{
35823b64 8990 static const char *const opcodes[4][2] =
f6c53574 8991 {
8992 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8993 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8994 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8995 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8996 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8997 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8998 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8999 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9000 };
9001 int swap =
9002 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9003
9004 return opcodes[which_alternative][swap];
9005}
9006"
9007 [(set_attr "conds" "set")
9008 (set_attr "length" "8")]
9009)
9010
3c5afce6 9011(define_insn_and_split "*ior_scc_scc"
9012 [(set (match_operand:SI 0 "s_register_operand" "=r")
9013 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9014 [(match_operand:SI 1 "s_register_operand" "r")
9015 (match_operand:SI 2 "arm_add_operand" "rIL")])
9016 (match_operator:SI 6 "arm_comparison_operator"
9017 [(match_operand:SI 4 "s_register_operand" "r")
9018 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9019 (clobber (reg:CC CC_REGNUM))]
9020 "TARGET_ARM
9021 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9022 != CCmode)"
9023 "#"
9024 "TARGET_ARM && reload_completed"
9025 [(set (match_dup 7)
9026 (compare
9027 (ior:SI
9028 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9029 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9030 (const_int 0)))
9031 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9032 "operands[7]
9033 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9034 DOM_CC_X_OR_Y),
601f584c 9035 CC_REGNUM);"
9036 [(set_attr "conds" "clob")
9037 (set_attr "length" "16")])
9038
9039; If the above pattern is followed by a CMP insn, then the compare is
9040; redundant, since we can rework the conditional instruction that follows.
9041(define_insn_and_split "*ior_scc_scc_cmp"
9042 [(set (match_operand 0 "dominant_cc_register" "")
9043 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9044 [(match_operand:SI 1 "s_register_operand" "r")
9045 (match_operand:SI 2 "arm_add_operand" "rIL")])
9046 (match_operator:SI 6 "arm_comparison_operator"
9047 [(match_operand:SI 4 "s_register_operand" "r")
9048 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9049 (const_int 0)))
9050 (set (match_operand:SI 7 "s_register_operand" "=r")
9051 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9052 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9053 "TARGET_ARM"
9054 "#"
9055 "TARGET_ARM && reload_completed"
9056 [(set (match_dup 0)
9057 (compare
9058 (ior:SI
9059 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9060 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9061 (const_int 0)))
9062 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9063 ""
9064 [(set_attr "conds" "set")
9065 (set_attr "length" "16")])
3c5afce6 9066
9067(define_insn_and_split "*and_scc_scc"
9068 [(set (match_operand:SI 0 "s_register_operand" "=r")
9069 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9070 [(match_operand:SI 1 "s_register_operand" "r")
9071 (match_operand:SI 2 "arm_add_operand" "rIL")])
9072 (match_operator:SI 6 "arm_comparison_operator"
9073 [(match_operand:SI 4 "s_register_operand" "r")
9074 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9075 (clobber (reg:CC CC_REGNUM))]
9076 "TARGET_ARM
9077 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9078 != CCmode)"
9079 "#"
601f584c 9080 "TARGET_ARM && reload_completed
9081 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9082 != CCmode)"
3c5afce6 9083 [(set (match_dup 7)
9084 (compare
9085 (and:SI
9086 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9087 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9088 (const_int 0)))
9089 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9090 "operands[7]
9091 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9092 DOM_CC_X_AND_Y),
601f584c 9093 CC_REGNUM);"
9094 [(set_attr "conds" "clob")
9095 (set_attr "length" "16")])
9096
9097; If the above pattern is followed by a CMP insn, then the compare is
9098; redundant, since we can rework the conditional instruction that follows.
9099(define_insn_and_split "*and_scc_scc_cmp"
9100 [(set (match_operand 0 "dominant_cc_register" "")
9101 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9102 [(match_operand:SI 1 "s_register_operand" "r")
9103 (match_operand:SI 2 "arm_add_operand" "rIL")])
9104 (match_operator:SI 6 "arm_comparison_operator"
9105 [(match_operand:SI 4 "s_register_operand" "r")
9106 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9107 (const_int 0)))
9108 (set (match_operand:SI 7 "s_register_operand" "=r")
9109 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9110 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9111 "TARGET_ARM"
9112 "#"
9113 "TARGET_ARM && reload_completed"
9114 [(set (match_dup 0)
9115 (compare
9116 (and:SI
9117 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9118 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9119 (const_int 0)))
9120 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9121 ""
9122 [(set_attr "conds" "set")
9123 (set_attr "length" "16")])
9124
9125;; If there is no dominance in the comparison, then we can still save an
9126;; instruction in the AND case, since we can know that the second compare
9127;; need only zero the value if false (if true, then the value is already
9128;; correct).
9129(define_insn_and_split "*and_scc_scc_nodom"
9130 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9131 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9132 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9133 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9134 (match_operator:SI 6 "arm_comparison_operator"
9135 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9136 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9137 (clobber (reg:CC CC_REGNUM))]
9138 "TARGET_ARM
9139 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9140 == CCmode)"
9141 "#"
9142 "TARGET_ARM && reload_completed"
9143 [(parallel [(set (match_dup 0)
9144 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9145 (clobber (reg:CC CC_REGNUM))])
9146 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9147 (set (match_dup 0)
9148 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9149 (match_dup 0)
9150 (const_int 0)))]
9151 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9152 operands[4], operands[5]),
9153 CC_REGNUM);
9154 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9155 operands[5]);"
9156 [(set_attr "conds" "clob")
9157 (set_attr "length" "20")])
3c5afce6 9158
3a0bdee0 9159(define_split
9160 [(set (reg:CC_NOOV CC_REGNUM)
9161 (compare:CC_NOOV (ior:SI
9162 (and:SI (match_operand:SI 0 "s_register_operand" "")
9163 (const_int 1))
b0694be0 9164 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9165 [(match_operand:SI 2 "s_register_operand" "")
9166 (match_operand:SI 3 "arm_add_operand" "")]))
9167 (const_int 0)))
9168 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9169 "TARGET_ARM"
9170 [(set (match_dup 4)
9171 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9172 (match_dup 0)))
9173 (set (reg:CC_NOOV CC_REGNUM)
9174 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9175 (const_int 0)))]
9176 "")
9177
9178(define_split
9179 [(set (reg:CC_NOOV CC_REGNUM)
9180 (compare:CC_NOOV (ior:SI
b0694be0 9181 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9182 [(match_operand:SI 2 "s_register_operand" "")
9183 (match_operand:SI 3 "arm_add_operand" "")])
9184 (and:SI (match_operand:SI 0 "s_register_operand" "")
9185 (const_int 1)))
9186 (const_int 0)))
9187 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9188 "TARGET_ARM"
9189 [(set (match_dup 4)
9190 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9191 (match_dup 0)))
9192 (set (reg:CC_NOOV CC_REGNUM)
9193 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9194 (const_int 0)))]
9195 "")
25f905c2 9196;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9197
f7fbdd4a 9198(define_insn "*negscc"
9c08d1fa 9199 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9200 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9201 [(match_operand:SI 1 "s_register_operand" "r")
9202 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9203 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9204 "TARGET_ARM"
9c08d1fa 9205 "*
2ca2ec2e 9206 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9207 return \"mov\\t%0, %1, asr #31\";
9208
9c08d1fa 9209 if (GET_CODE (operands[3]) == NE)
e2348bcb 9210 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9211
e2348bcb 9212 output_asm_insn (\"cmp\\t%1, %2\", operands);
9213 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9214 return \"mvn%d3\\t%0, #0\";
215b30b3 9215 "
8fa3ba89 9216 [(set_attr "conds" "clob")
9217 (set_attr "length" "12")]
9218)
9c08d1fa 9219
9220(define_insn "movcond"
9221 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9222 (if_then_else:SI
8fa3ba89 9223 (match_operator 5 "arm_comparison_operator"
5565501b 9224 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9225 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9226 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9227 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9228 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9229 "TARGET_ARM"
9c08d1fa 9230 "*
9231 if (GET_CODE (operands[5]) == LT
9232 && (operands[4] == const0_rtx))
9233 {
5565501b 9234 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9235 {
9c08d1fa 9236 if (operands[2] == const0_rtx)
e2348bcb 9237 return \"and\\t%0, %1, %3, asr #31\";
9238 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9239 }
9240 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9241 {
9c08d1fa 9242 if (operands[1] == const0_rtx)
e2348bcb 9243 return \"bic\\t%0, %2, %3, asr #31\";
9244 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9245 }
9246 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9247 are constants. */
9c08d1fa 9248 }
e2348bcb 9249
9c08d1fa 9250 if (GET_CODE (operands[5]) == GE
9251 && (operands[4] == const0_rtx))
9252 {
9253 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9254 {
9c08d1fa 9255 if (operands[2] == const0_rtx)
e2348bcb 9256 return \"bic\\t%0, %1, %3, asr #31\";
9257 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9258 }
9259 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9260 {
9c08d1fa 9261 if (operands[1] == const0_rtx)
e2348bcb 9262 return \"and\\t%0, %2, %3, asr #31\";
9263 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9264 }
9265 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9266 are constants. */
9c08d1fa 9267 }
9268 if (GET_CODE (operands[4]) == CONST_INT
9269 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9270 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9271 else
e2348bcb 9272 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9273 if (which_alternative != 0)
e2348bcb 9274 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9275 if (which_alternative != 1)
e2348bcb 9276 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9277 return \"\";
215b30b3 9278 "
8fa3ba89 9279 [(set_attr "conds" "clob")
9280 (set_attr "length" "8,8,12")]
9281)
9c08d1fa 9282
25f905c2 9283;; ??? The patterns below need checking for Thumb-2 usefulness.
9284
8a18b90c 9285(define_insn "*ifcompare_plus_move"
9286 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9287 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9288 [(match_operand:SI 4 "s_register_operand" "r,r")
9289 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9290 (plus:SI
9291 (match_operand:SI 2 "s_register_operand" "r,r")
9292 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9293 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9294 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9295 "TARGET_ARM"
8a18b90c 9296 "#"
8fa3ba89 9297 [(set_attr "conds" "clob")
9298 (set_attr "length" "8,12")]
9299)
8a18b90c 9300
9301(define_insn "*if_plus_move"
129a2fe4 9302 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9303 (if_then_else:SI
8fa3ba89 9304 (match_operator 4 "arm_comparison_operator"
8a18b90c 9305 [(match_operand 5 "cc_register" "") (const_int 0)])
9306 (plus:SI
129a2fe4 9307 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9308 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9309 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9310 "TARGET_ARM"
8a18b90c 9311 "@
9312 add%d4\\t%0, %2, %3
9313 sub%d4\\t%0, %2, #%n3
9314 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9315 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9316 [(set_attr "conds" "use")
9317 (set_attr "length" "4,4,8,8")
9318 (set_attr "type" "*,*,*,*")]
9319)
8a18b90c 9320
9321(define_insn "*ifcompare_move_plus"
5565501b 9322 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9323 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9324 [(match_operand:SI 4 "s_register_operand" "r,r")
9325 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9326 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9327 (plus:SI
9328 (match_operand:SI 2 "s_register_operand" "r,r")
9329 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9330 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9331 "TARGET_ARM"
8a18b90c 9332 "#"
8fa3ba89 9333 [(set_attr "conds" "clob")
9334 (set_attr "length" "8,12")]
9335)
8a18b90c 9336
9337(define_insn "*if_move_plus"
129a2fe4 9338 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9339 (if_then_else:SI
8fa3ba89 9340 (match_operator 4 "arm_comparison_operator"
8a18b90c 9341 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9342 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9343 (plus:SI
129a2fe4 9344 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9345 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9346 "TARGET_ARM"
8a18b90c 9347 "@
9348 add%D4\\t%0, %2, %3
9349 sub%D4\\t%0, %2, #%n3
9350 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9351 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9352 [(set_attr "conds" "use")
9353 (set_attr "length" "4,4,8,8")
9354 (set_attr "type" "*,*,*,*")]
9355)
8a18b90c 9356
9357(define_insn "*ifcompare_arith_arith"
9358 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9359 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9360 [(match_operand:SI 5 "s_register_operand" "r")
9361 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9362 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9363 [(match_operand:SI 1 "s_register_operand" "r")
9364 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9365 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9366 [(match_operand:SI 3 "s_register_operand" "r")
9367 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9368 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9369 "TARGET_ARM"
8a18b90c 9370 "#"
8fa3ba89 9371 [(set_attr "conds" "clob")
9372 (set_attr "length" "12")]
9373)
9c08d1fa 9374
8a18b90c 9375(define_insn "*if_arith_arith"
9376 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9377 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9378 [(match_operand 8 "cc_register" "") (const_int 0)])
9379 (match_operator:SI 6 "shiftable_operator"
9380 [(match_operand:SI 1 "s_register_operand" "r")
9381 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9382 (match_operator:SI 7 "shiftable_operator"
9383 [(match_operand:SI 3 "s_register_operand" "r")
9384 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9385 "TARGET_ARM"
8a18b90c 9386 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9387 [(set_attr "conds" "use")
9388 (set_attr "length" "8")]
9389)
8a18b90c 9390
f7fbdd4a 9391(define_insn "*ifcompare_arith_move"
9c08d1fa 9392 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9393 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9394 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9395 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9396 (match_operator:SI 7 "shiftable_operator"
9397 [(match_operand:SI 4 "s_register_operand" "r,r")
9398 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9399 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9400 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9401 "TARGET_ARM"
9c08d1fa 9402 "*
9c08d1fa 9403 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9404 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9405 everything is in registers then we can do this in two instructions. */
9c08d1fa 9406 if (operands[3] == const0_rtx
9407 && GET_CODE (operands[7]) != AND
9408 && GET_CODE (operands[5]) == REG
9409 && GET_CODE (operands[1]) == REG
9410 && REGNO (operands[1]) == REGNO (operands[4])
9411 && REGNO (operands[4]) != REGNO (operands[0]))
9412 {
9413 if (GET_CODE (operands[6]) == LT)
40dbec34 9414 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9415 else if (GET_CODE (operands[6]) == GE)
40dbec34 9416 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9417 }
9418 if (GET_CODE (operands[3]) == CONST_INT
9419 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9420 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9421 else
e2348bcb 9422 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9423 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9424 if (which_alternative != 0)
129a2fe4 9425 return \"mov%D6\\t%0, %1\";
9c08d1fa 9426 return \"\";
215b30b3 9427 "
8fa3ba89 9428 [(set_attr "conds" "clob")
9429 (set_attr "length" "8,12")]
9430)
9c08d1fa 9431
8a18b90c 9432(define_insn "*if_arith_move"
129a2fe4 9433 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9434 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9435 [(match_operand 6 "cc_register" "") (const_int 0)])
9436 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9437 [(match_operand:SI 2 "s_register_operand" "r,r")
9438 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9439 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9440 "TARGET_ARM"
8a18b90c 9441 "@
9442 %I5%d4\\t%0, %2, %3
129a2fe4 9443 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9444 [(set_attr "conds" "use")
9445 (set_attr "length" "4,8")
9446 (set_attr "type" "*,*")]
9447)
8a18b90c 9448
f7fbdd4a 9449(define_insn "*ifcompare_move_arith"
9c08d1fa 9450 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9451 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9452 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9453 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9454 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9455 (match_operator:SI 7 "shiftable_operator"
9456 [(match_operand:SI 2 "s_register_operand" "r,r")
9457 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9458 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9459 "TARGET_ARM"
9c08d1fa 9460 "*
9c08d1fa 9461 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9462 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9463 everything is in registers then we can do this in two instructions */
9464 if (operands[5] == const0_rtx
9465 && GET_CODE (operands[7]) != AND
9466 && GET_CODE (operands[3]) == REG
9467 && GET_CODE (operands[1]) == REG
9468 && REGNO (operands[1]) == REGNO (operands[2])
9469 && REGNO (operands[2]) != REGNO (operands[0]))
9470 {
9471 if (GET_CODE (operands[6]) == GE)
40dbec34 9472 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9473 else if (GET_CODE (operands[6]) == LT)
40dbec34 9474 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9475 }
40dbec34 9476
9c08d1fa 9477 if (GET_CODE (operands[5]) == CONST_INT
9478 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9479 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9480 else
e2348bcb 9481 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9482
9c08d1fa 9483 if (which_alternative != 0)
129a2fe4 9484 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9485 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9486 "
8fa3ba89 9487 [(set_attr "conds" "clob")
9488 (set_attr "length" "8,12")]
9489)
9c08d1fa 9490
8a18b90c 9491(define_insn "*if_move_arith"
129a2fe4 9492 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9493 (if_then_else:SI
8fa3ba89 9494 (match_operator 4 "arm_comparison_operator"
8a18b90c 9495 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9496 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9497 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9498 [(match_operand:SI 2 "s_register_operand" "r,r")
9499 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9500 "TARGET_ARM"
8a18b90c 9501 "@
9502 %I5%D4\\t%0, %2, %3
129a2fe4 9503 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9504 [(set_attr "conds" "use")
9505 (set_attr "length" "4,8")
9506 (set_attr "type" "*,*")]
9507)
8a18b90c 9508
9509(define_insn "*ifcompare_move_not"
9c08d1fa 9510 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9511 (if_then_else:SI
8fa3ba89 9512 (match_operator 5 "arm_comparison_operator"
8a18b90c 9513 [(match_operand:SI 3 "s_register_operand" "r,r")
9514 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9515 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9516 (not:SI
9517 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9518 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9519 "TARGET_ARM"
8a18b90c 9520 "#"
8fa3ba89 9521 [(set_attr "conds" "clob")
9522 (set_attr "length" "8,12")]
9523)
9c08d1fa 9524
8a18b90c 9525(define_insn "*if_move_not"
9526 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9527 (if_then_else:SI
8fa3ba89 9528 (match_operator 4 "arm_comparison_operator"
8a18b90c 9529 [(match_operand 3 "cc_register" "") (const_int 0)])
9530 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9531 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9532 "TARGET_ARM"
8a18b90c 9533 "@
9534 mvn%D4\\t%0, %2
9535 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9536 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9537 [(set_attr "conds" "use")
d2a518d1 9538 (set_attr "insn" "mvn")
8fa3ba89 9539 (set_attr "length" "4,8,8")]
9540)
8a18b90c 9541
9542(define_insn "*ifcompare_not_move"
9c08d1fa 9543 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9544 (if_then_else:SI
8fa3ba89 9545 (match_operator 5 "arm_comparison_operator"
8a18b90c 9546 [(match_operand:SI 3 "s_register_operand" "r,r")
9547 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9548 (not:SI
9549 (match_operand:SI 2 "s_register_operand" "r,r"))
9550 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9551 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9552 "TARGET_ARM"
8a18b90c 9553 "#"
8fa3ba89 9554 [(set_attr "conds" "clob")
9555 (set_attr "length" "8,12")]
9556)
9c08d1fa 9557
8a18b90c 9558(define_insn "*if_not_move"
9559 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9560 (if_then_else:SI
8fa3ba89 9561 (match_operator 4 "arm_comparison_operator"
8a18b90c 9562 [(match_operand 3 "cc_register" "") (const_int 0)])
9563 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9564 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9565 "TARGET_ARM"
8a18b90c 9566 "@
9567 mvn%d4\\t%0, %2
9568 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9569 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9570 [(set_attr "conds" "use")
d2a518d1 9571 (set_attr "insn" "mvn")
8fa3ba89 9572 (set_attr "length" "4,8,8")]
9573)
8a18b90c 9574
9575(define_insn "*ifcompare_shift_move"
9c08d1fa 9576 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9577 (if_then_else:SI
8fa3ba89 9578 (match_operator 6 "arm_comparison_operator"
8a18b90c 9579 [(match_operand:SI 4 "s_register_operand" "r,r")
9580 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9581 (match_operator:SI 7 "shift_operator"
9582 [(match_operand:SI 2 "s_register_operand" "r,r")
9583 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9584 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9585 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9586 "TARGET_ARM"
9c08d1fa 9587 "#"
8fa3ba89 9588 [(set_attr "conds" "clob")
9589 (set_attr "length" "8,12")]
9590)
9c08d1fa 9591
8a18b90c 9592(define_insn "*if_shift_move"
9593 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9594 (if_then_else:SI
8fa3ba89 9595 (match_operator 5 "arm_comparison_operator"
8a18b90c 9596 [(match_operand 6 "cc_register" "") (const_int 0)])
9597 (match_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")])
9600 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9601 "TARGET_ARM"
5565501b 9602 "@
8a18b90c 9603 mov%d5\\t%0, %2%S4
9604 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9605 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9606 [(set_attr "conds" "use")
331beb1a 9607 (set_attr "shift" "2")
a2cd141b 9608 (set_attr "length" "4,8,8")
d2a518d1 9609 (set_attr "insn" "mov")
a2cd141b 9610 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9611 (const_string "alu_shift")
9612 (const_string "alu_shift_reg")))]
8fa3ba89 9613)
5565501b 9614
8a18b90c 9615(define_insn "*ifcompare_move_shift"
9616 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9617 (if_then_else:SI
8fa3ba89 9618 (match_operator 6 "arm_comparison_operator"
8a18b90c 9619 [(match_operand:SI 4 "s_register_operand" "r,r")
9620 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9621 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9622 (match_operator:SI 7 "shift_operator"
8a18b90c 9623 [(match_operand:SI 2 "s_register_operand" "r,r")
9624 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9625 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9626 "TARGET_ARM"
8a18b90c 9627 "#"
8fa3ba89 9628 [(set_attr "conds" "clob")
9629 (set_attr "length" "8,12")]
9630)
5565501b 9631
8a18b90c 9632(define_insn "*if_move_shift"
9633 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9634 (if_then_else:SI
8fa3ba89 9635 (match_operator 5 "arm_comparison_operator"
8a18b90c 9636 [(match_operand 6 "cc_register" "") (const_int 0)])
9637 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9638 (match_operator:SI 4 "shift_operator"
9639 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9640 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9641 "TARGET_ARM"
5565501b 9642 "@
8a18b90c 9643 mov%D5\\t%0, %2%S4
9644 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9645 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9646 [(set_attr "conds" "use")
331beb1a 9647 (set_attr "shift" "2")
a2cd141b 9648 (set_attr "length" "4,8,8")
d2a518d1 9649 (set_attr "insn" "mov")
a2cd141b 9650 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9651 (const_string "alu_shift")
9652 (const_string "alu_shift_reg")))]
8fa3ba89 9653)
9c08d1fa 9654
f7fbdd4a 9655(define_insn "*ifcompare_shift_shift"
8a18b90c 9656 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9657 (if_then_else:SI
8fa3ba89 9658 (match_operator 7 "arm_comparison_operator"
8a18b90c 9659 [(match_operand:SI 5 "s_register_operand" "r")
9660 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9661 (match_operator:SI 8 "shift_operator"
8a18b90c 9662 [(match_operand:SI 1 "s_register_operand" "r")
9663 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9664 (match_operator:SI 9 "shift_operator"
8a18b90c 9665 [(match_operand:SI 3 "s_register_operand" "r")
9666 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
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_shift_shift"
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 8 "cc_register" "") (const_int 0)])
9679 (match_operator:SI 6 "shift_operator"
9680 [(match_operand:SI 1 "s_register_operand" "r")
9681 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9682 (match_operator:SI 7 "shift_operator"
9683 [(match_operand:SI 3 "s_register_operand" "r")
9684 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9685 "TARGET_ARM"
8a18b90c 9686 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9687 [(set_attr "conds" "use")
331beb1a 9688 (set_attr "shift" "1")
a2cd141b 9689 (set_attr "length" "8")
d2a518d1 9690 (set_attr "insn" "mov")
a2cd141b 9691 (set (attr "type") (if_then_else
9692 (and (match_operand 2 "const_int_operand" "")
9693 (match_operand 4 "const_int_operand" ""))
9694 (const_string "alu_shift")
9695 (const_string "alu_shift_reg")))]
8fa3ba89 9696)
8a18b90c 9697
f7fbdd4a 9698(define_insn "*ifcompare_not_arith"
8a18b90c 9699 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9700 (if_then_else:SI
8fa3ba89 9701 (match_operator 6 "arm_comparison_operator"
8a18b90c 9702 [(match_operand:SI 4 "s_register_operand" "r")
9703 (match_operand:SI 5 "arm_add_operand" "rIL")])
9704 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9705 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9706 [(match_operand:SI 2 "s_register_operand" "r")
9707 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9708 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9709 "TARGET_ARM"
8a18b90c 9710 "#"
8fa3ba89 9711 [(set_attr "conds" "clob")
9712 (set_attr "length" "12")]
9713)
9c08d1fa 9714
8a18b90c 9715(define_insn "*if_not_arith"
9716 [(set (match_operand:SI 0 "s_register_operand" "=r")
9717 (if_then_else:SI
8fa3ba89 9718 (match_operator 5 "arm_comparison_operator"
8a18b90c 9719 [(match_operand 4 "cc_register" "") (const_int 0)])
9720 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9721 (match_operator:SI 6 "shiftable_operator"
9722 [(match_operand:SI 2 "s_register_operand" "r")
9723 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9724 "TARGET_ARM"
8a18b90c 9725 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9726 [(set_attr "conds" "use")
d2a518d1 9727 (set_attr "insn" "mvn")
8fa3ba89 9728 (set_attr "length" "8")]
9729)
8a18b90c 9730
9731(define_insn "*ifcompare_arith_not"
9732 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9733 (if_then_else:SI
8fa3ba89 9734 (match_operator 6 "arm_comparison_operator"
8a18b90c 9735 [(match_operand:SI 4 "s_register_operand" "r")
9736 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9737 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9738 [(match_operand:SI 2 "s_register_operand" "r")
9739 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9740 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9741 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9742 "TARGET_ARM"
8a18b90c 9743 "#"
8fa3ba89 9744 [(set_attr "conds" "clob")
9745 (set_attr "length" "12")]
9746)
9c08d1fa 9747
8a18b90c 9748(define_insn "*if_arith_not"
9749 [(set (match_operand:SI 0 "s_register_operand" "=r")
9750 (if_then_else:SI
8fa3ba89 9751 (match_operator 5 "arm_comparison_operator"
8a18b90c 9752 [(match_operand 4 "cc_register" "") (const_int 0)])
9753 (match_operator:SI 6 "shiftable_operator"
9754 [(match_operand:SI 2 "s_register_operand" "r")
9755 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9756 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9757 "TARGET_ARM"
8a18b90c 9758 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9759 [(set_attr "conds" "use")
d2a518d1 9760 (set_attr "insn" "mvn")
8fa3ba89 9761 (set_attr "length" "8")]
9762)
8a18b90c 9763
f7fbdd4a 9764(define_insn "*ifcompare_neg_move"
8a18b90c 9765 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9766 (if_then_else:SI
8fa3ba89 9767 (match_operator 5 "arm_comparison_operator"
8a18b90c 9768 [(match_operand:SI 3 "s_register_operand" "r,r")
9769 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9770 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9771 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9772 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9773 "TARGET_ARM"
8a18b90c 9774 "#"
8fa3ba89 9775 [(set_attr "conds" "clob")
9776 (set_attr "length" "8,12")]
9777)
8a18b90c 9778
9779(define_insn "*if_neg_move"
9780 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9781 (if_then_else:SI
8fa3ba89 9782 (match_operator 4 "arm_comparison_operator"
8a18b90c 9783 [(match_operand 3 "cc_register" "") (const_int 0)])
9784 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9785 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9786 "TARGET_ARM"
8a18b90c 9787 "@
9788 rsb%d4\\t%0, %2, #0
9789 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9790 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9791 [(set_attr "conds" "use")
9792 (set_attr "length" "4,8,8")]
9793)
9c08d1fa 9794
f7fbdd4a 9795(define_insn "*ifcompare_move_neg"
8a18b90c 9796 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9797 (if_then_else:SI
8fa3ba89 9798 (match_operator 5 "arm_comparison_operator"
8a18b90c 9799 [(match_operand:SI 3 "s_register_operand" "r,r")
9800 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9801 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9802 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9803 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9804 "TARGET_ARM"
8a18b90c 9805 "#"
8fa3ba89 9806 [(set_attr "conds" "clob")
9807 (set_attr "length" "8,12")]
9808)
8a18b90c 9809
9810(define_insn "*if_move_neg"
9811 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9812 (if_then_else:SI
8fa3ba89 9813 (match_operator 4 "arm_comparison_operator"
8a18b90c 9814 [(match_operand 3 "cc_register" "") (const_int 0)])
9815 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9816 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9817 "TARGET_ARM"
8a18b90c 9818 "@
9819 rsb%D4\\t%0, %2, #0
9820 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9821 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9822 [(set_attr "conds" "use")
9823 (set_attr "length" "4,8,8")]
9824)
9c08d1fa 9825
f7fbdd4a 9826(define_insn "*arith_adjacentmem"
9c08d1fa 9827 [(set (match_operand:SI 0 "s_register_operand" "=r")
9828 (match_operator:SI 1 "shiftable_operator"
9829 [(match_operand:SI 2 "memory_operand" "m")
9830 (match_operand:SI 3 "memory_operand" "m")]))
9831 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9832 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9833 "*
215b30b3 9834 {
9835 rtx ldm[3];
9836 rtx arith[4];
94dee231 9837 rtx base_reg;
9838 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9839
215b30b3 9840 if (REGNO (operands[0]) > REGNO (operands[4]))
9841 {
9842 ldm[1] = operands[4];
9843 ldm[2] = operands[0];
9844 }
9845 else
9846 {
9847 ldm[1] = operands[0];
9848 ldm[2] = operands[4];
9849 }
94dee231 9850
9851 base_reg = XEXP (operands[2], 0);
9852
9853 if (!REG_P (base_reg))
9854 {
9855 val1 = INTVAL (XEXP (base_reg, 1));
9856 base_reg = XEXP (base_reg, 0);
9857 }
9858
9859 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9860 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9861
215b30b3 9862 arith[0] = operands[0];
9863 arith[3] = operands[1];
94dee231 9864
215b30b3 9865 if (val1 < val2)
9866 {
9867 arith[1] = ldm[1];
9868 arith[2] = ldm[2];
9869 }
9870 else
9871 {
9872 arith[1] = ldm[2];
9873 arith[2] = ldm[1];
9874 }
94dee231 9875
9876 ldm[0] = base_reg;
9877 if (val1 !=0 && val2 != 0)
215b30b3 9878 {
cdb1295a 9879 rtx ops[3];
9880
94dee231 9881 if (val1 == 4 || val2 == 4)
9882 /* Other val must be 8, since we know they are adjacent and neither
9883 is zero. */
25f905c2 9884 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 9885 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 9886 {
94dee231 9887 ldm[0] = ops[0] = operands[4];
9888 ops[1] = base_reg;
9889 ops[2] = GEN_INT (val1);
9890 output_add_immediate (ops);
9891 if (val1 < val2)
25f905c2 9892 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 9893 else
25f905c2 9894 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 9895 }
cdb1295a 9896 else
9897 {
9898 /* Offset is out of range for a single add, so use two ldr. */
9899 ops[0] = ldm[1];
9900 ops[1] = base_reg;
9901 ops[2] = GEN_INT (val1);
9902 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9903 ops[0] = ldm[2];
9904 ops[2] = GEN_INT (val2);
9905 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9906 }
215b30b3 9907 }
94dee231 9908 else if (val1 != 0)
215b30b3 9909 {
215b30b3 9910 if (val1 < val2)
25f905c2 9911 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9912 else
25f905c2 9913 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9914 }
9915 else
9916 {
215b30b3 9917 if (val1 < val2)
25f905c2 9918 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9919 else
25f905c2 9920 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9921 }
9922 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9923 return \"\";
9924 }"
9925 [(set_attr "length" "12")
9926 (set_attr "predicable" "yes")
a2cd141b 9927 (set_attr "type" "load1")]
215b30b3 9928)
9c08d1fa 9929
9c08d1fa 9930; This pattern is never tried by combine, so do it as a peephole
9931
a0f94409 9932(define_peephole2
372575c7 9933 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9934 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9935 (set (reg:CC CC_REGNUM)
aea4c774 9936 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9937 "TARGET_ARM"
a0f94409 9938 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9939 (set (match_dup 0) (match_dup 1))])]
9940 ""
0d66636f 9941)
9c08d1fa 9942
9c08d1fa 9943(define_split
9944 [(set (match_operand:SI 0 "s_register_operand" "")
9945 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9946 (const_int 0))
8fa3ba89 9947 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9948 [(match_operand:SI 3 "s_register_operand" "")
9949 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9950 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9951 "TARGET_ARM"
9c08d1fa 9952 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9953 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9954 (match_dup 5)))]
215b30b3 9955 ""
9956)
9c08d1fa 9957
aea4c774 9958;; This split can be used because CC_Z mode implies that the following
9959;; branch will be an equality, or an unsigned inequality, so the sign
9960;; extension is not needed.
9c08d1fa 9961
aea4c774 9962(define_split
bd5b4116 9963 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9964 (compare:CC_Z
9965 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9966 (const_int 24))
aea4c774 9967 (match_operand 1 "const_int_operand" "")))
9968 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9969 "TARGET_ARM
9970 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9971 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9972 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9973 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9974 "
9c08d1fa 9975 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9976 "
9977)
25f905c2 9978;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 9979
87b22bf7 9980(define_expand "prologue"
9981 [(clobber (const_int 0))]
cffb2a26 9982 "TARGET_EITHER"
25f905c2 9983 "if (TARGET_32BIT)
cffb2a26 9984 arm_expand_prologue ();
9985 else
25f905c2 9986 thumb1_expand_prologue ();
87b22bf7 9987 DONE;
cffb2a26 9988 "
9989)
87b22bf7 9990
56d27660 9991(define_expand "epilogue"
4c44712e 9992 [(clobber (const_int 0))]
cffb2a26 9993 "TARGET_EITHER"
56d27660 9994 "
18d50ae6 9995 if (crtl->calls_eh_return)
4c44712e 9996 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 9997 if (TARGET_THUMB1)
9998 thumb1_expand_epilogue ();
cffb2a26 9999 else if (USE_RETURN_INSN (FALSE))
56d27660 10000 {
10001 emit_jump_insn (gen_return ());
10002 DONE;
10003 }
cffb2a26 10004 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10005 gen_rtvec (1,
10006 gen_rtx_RETURN (VOIDmode)),
e1159bbe 10007 VUNSPEC_EPILOGUE));
cffb2a26 10008 DONE;
10009 "
10010)
56d27660 10011
ef5651d0 10012;; Note - although unspec_volatile's USE all hard registers,
10013;; USEs are ignored after relaod has completed. Thus we need
10014;; to add an unspec of the link register to ensure that flow
10015;; does not think that it is unused by the sibcall branch that
10016;; will replace the standard function epilogue.
1c494086 10017(define_insn "sibcall_epilogue"
ef5651d0 10018 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10019 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10020 "TARGET_32BIT"
1c494086 10021 "*
ffc9d00c 10022 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10023 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10024 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10025 "
10026;; Length is absolute worst case
10027 [(set_attr "length" "44")
defc47cf 10028 (set_attr "type" "block")
10029 ;; We don't clobber the conditions, but the potential length of this
10030 ;; operation is sufficient to make conditionalizing the sequence
10031 ;; unlikely to be profitable.
10032 (set_attr "conds" "clob")]
1c494086 10033)
10034
cffb2a26 10035(define_insn "*epilogue_insns"
e1159bbe 10036 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10037 "TARGET_EITHER"
56d27660 10038 "*
25f905c2 10039 if (TARGET_32BIT)
ffc9d00c 10040 return arm_output_epilogue (NULL);
25f905c2 10041 else /* TARGET_THUMB1 */
cffb2a26 10042 return thumb_unexpanded_epilogue ();
10043 "
215b30b3 10044 ; Length is absolute worst case
cffb2a26 10045 [(set_attr "length" "44")
defc47cf 10046 (set_attr "type" "block")
10047 ;; We don't clobber the conditions, but the potential length of this
10048 ;; operation is sufficient to make conditionalizing the sequence
10049 ;; unlikely to be profitable.
10050 (set_attr "conds" "clob")]
cffb2a26 10051)
10052
10053(define_expand "eh_epilogue"
7db9af5d 10054 [(use (match_operand:SI 0 "register_operand" ""))
10055 (use (match_operand:SI 1 "register_operand" ""))
10056 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10057 "TARGET_EITHER"
10058 "
215b30b3 10059 {
10060 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10061 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10062 {
10063 rtx ra = gen_rtx_REG (Pmode, 2);
10064
10065 emit_move_insn (ra, operands[2]);
10066 operands[2] = ra;
10067 }
5cf3595a 10068 /* This is a hack -- we may have crystalized the function type too
10069 early. */
10070 cfun->machine->func_type = 0;
215b30b3 10071 }"
10072)
56d27660 10073
9c08d1fa 10074;; This split is only used during output to reduce the number of patterns
10075;; that need assembler instructions adding to them. We allowed the setting
10076;; of the conditions to be implicit during rtl generation so that
10077;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10078;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10079;; up again here.
10080
25f905c2 10081;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10082;; conditional execution sufficient?
10083
9c08d1fa 10084(define_split
10085 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10086 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10087 [(match_operand 2 "" "") (match_operand 3 "" "")])
10088 (match_dup 0)
10089 (match_operand 4 "" "")))
bd5b4116 10090 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10091 "TARGET_ARM && reload_completed"
8fa3ba89 10092 [(set (match_dup 5) (match_dup 6))
10093 (cond_exec (match_dup 7)
10094 (set (match_dup 0) (match_dup 4)))]
10095 "
10096 {
10097 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10098 operands[2], operands[3]);
10099 enum rtx_code rc = GET_CODE (operands[1]);
10100
bd5b4116 10101 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10102 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10103 if (mode == CCFPmode || mode == CCFPEmode)
10104 rc = reverse_condition_maybe_unordered (rc);
10105 else
10106 rc = reverse_condition (rc);
10107
10108 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10109 }"
10110)
10111
10112(define_split
10113 [(set (match_operand:SI 0 "s_register_operand" "")
10114 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10115 [(match_operand 2 "" "") (match_operand 3 "" "")])
10116 (match_operand 4 "" "")
10117 (match_dup 0)))
bd5b4116 10118 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10119 "TARGET_ARM && reload_completed"
8fa3ba89 10120 [(set (match_dup 5) (match_dup 6))
10121 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10122 (set (match_dup 0) (match_dup 4)))]
10123 "
10124 {
10125 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10126 operands[2], operands[3]);
10127
bd5b4116 10128 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10129 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10130 }"
10131)
10132
10133(define_split
10134 [(set (match_operand:SI 0 "s_register_operand" "")
10135 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10136 [(match_operand 2 "" "") (match_operand 3 "" "")])
10137 (match_operand 4 "" "")
10138 (match_operand 5 "" "")))
bd5b4116 10139 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10140 "TARGET_ARM && reload_completed"
8fa3ba89 10141 [(set (match_dup 6) (match_dup 7))
10142 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10143 (set (match_dup 0) (match_dup 4)))
10144 (cond_exec (match_dup 8)
10145 (set (match_dup 0) (match_dup 5)))]
10146 "
10147 {
10148 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10149 operands[2], operands[3]);
10150 enum rtx_code rc = GET_CODE (operands[1]);
10151
bd5b4116 10152 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10153 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10154 if (mode == CCFPmode || mode == CCFPEmode)
10155 rc = reverse_condition_maybe_unordered (rc);
10156 else
10157 rc = reverse_condition (rc);
10158
10159 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10160 }"
10161)
10162
cffb2a26 10163(define_split
10164 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10165 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10166 [(match_operand:SI 2 "s_register_operand" "")
10167 (match_operand:SI 3 "arm_add_operand" "")])
10168 (match_operand:SI 4 "arm_rhs_operand" "")
10169 (not:SI
10170 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10171 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10172 "TARGET_ARM && reload_completed"
cffb2a26 10173 [(set (match_dup 6) (match_dup 7))
f6c53574 10174 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10175 (set (match_dup 0) (match_dup 4)))
10176 (cond_exec (match_dup 8)
10177 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10178 "
215b30b3 10179 {
10180 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10181 operands[2], operands[3]);
f6c53574 10182 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10183
bd5b4116 10184 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10185 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10186 if (mode == CCFPmode || mode == CCFPEmode)
10187 rc = reverse_condition_maybe_unordered (rc);
10188 else
10189 rc = reverse_condition (rc);
10190
10191 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10192 }"
10193)
cffb2a26 10194
10195(define_insn "*cond_move_not"
10196 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10197 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10198 [(match_operand 3 "cc_register" "") (const_int 0)])
10199 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10200 (not:SI
10201 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10202 "TARGET_ARM"
10203 "@
10204 mvn%D4\\t%0, %2
10205 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10206 [(set_attr "conds" "use")
d2a518d1 10207 (set_attr "insn" "mvn")
0d66636f 10208 (set_attr "length" "4,8")]
10209)
cffb2a26 10210
9c08d1fa 10211;; The next two patterns occur when an AND operation is followed by a
10212;; scc insn sequence
10213
f7fbdd4a 10214(define_insn "*sign_extract_onebit"
9c08d1fa 10215 [(set (match_operand:SI 0 "s_register_operand" "=r")
10216 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10217 (const_int 1)
ed750274 10218 (match_operand:SI 2 "const_int_operand" "n")))
10219 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10220 "TARGET_ARM"
9c08d1fa 10221 "*
0d66636f 10222 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10223 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10224 return \"mvnne\\t%0, #0\";
10225 "
10226 [(set_attr "conds" "clob")
10227 (set_attr "length" "8")]
10228)
9c08d1fa 10229
f7fbdd4a 10230(define_insn "*not_signextract_onebit"
9c08d1fa 10231 [(set (match_operand:SI 0 "s_register_operand" "=r")
10232 (not:SI
10233 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10234 (const_int 1)
ed750274 10235 (match_operand:SI 2 "const_int_operand" "n"))))
10236 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10237 "TARGET_ARM"
9c08d1fa 10238 "*
0d66636f 10239 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10240 output_asm_insn (\"tst\\t%1, %2\", operands);
10241 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10242 return \"movne\\t%0, #0\";
10243 "
10244 [(set_attr "conds" "clob")
10245 (set_attr "length" "12")]
10246)
25f905c2 10247;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10248
0d66636f 10249;; Push multiple registers to the stack. Registers are in parallel (use ...)
10250;; expressions. For simplicity, the first register is also in the unspec
10251;; part.
08508cbf 10252;; To avoid the usage of GNU extension, the length attribute is computed
10253;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10254(define_insn "*push_multi"
87b22bf7 10255 [(match_parallel 2 "multi_register_push"
10256 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10257 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10258 UNSPEC_PUSH_MULT))])]
25f905c2 10259 "TARGET_32BIT"
87b22bf7 10260 "*
215b30b3 10261 {
10262 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10263
215b30b3 10264 /* For the StrongARM at least it is faster to
25f905c2 10265 use STR to store only a single register.
542d5028 10266 In Thumb mode always use push, and the assembler will pick
10267 something appropriate. */
25f905c2 10268 if (num_saves == 1 && TARGET_ARM)
215b30b3 10269 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10270 else
10271 {
10272 int i;
10273 char pattern[100];
ed593f11 10274
25f905c2 10275 if (TARGET_ARM)
10276 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10277 else
10278 strcpy (pattern, \"push\\t{%1\");
215b30b3 10279
6079f055 10280 for (i = 1; i < num_saves; i++)
215b30b3 10281 {
10282 strcat (pattern, \", %|\");
10283 strcat (pattern,
10284 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10285 }
10286
10287 strcat (pattern, \"}\");
10288 output_asm_insn (pattern, operands);
10289 }
10290
10291 return \"\";
10292 }"
a6864a24 10293 [(set_attr "type" "store4")
10294 (set (attr "length")
08508cbf 10295 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10296)
f7fbdd4a 10297
4c58c898 10298(define_insn "stack_tie"
10299 [(set (mem:BLK (scratch))
aaa37ad6 10300 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10301 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10302 UNSPEC_PRLG_STK))]
10303 ""
10304 ""
10305 [(set_attr "length" "0")]
10306)
10307
3398e91d 10308;; Similarly for the floating point registers
7b1d2fc4 10309(define_insn "*push_fp_multi"
10310 [(match_parallel 2 "multi_register_push"
10311 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10312 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10313 UNSPEC_PUSH_MULT))])]
25f905c2 10314 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10315 "*
215b30b3 10316 {
10317 char pattern[100];
7b1d2fc4 10318
215b30b3 10319 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10320 output_asm_insn (pattern, operands);
10321 return \"\";
10322 }"
013b9671 10323 [(set_attr "type" "f_fpa_store")]
215b30b3 10324)
7b1d2fc4 10325
f7fbdd4a 10326;; Special patterns for dealing with the constant pool
10327
cffb2a26 10328(define_insn "align_4"
e1159bbe 10329 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10330 "TARGET_EITHER"
f7fbdd4a 10331 "*
cffb2a26 10332 assemble_align (32);
f7fbdd4a 10333 return \"\";
cffb2a26 10334 "
10335)
f7fbdd4a 10336
755eb2b4 10337(define_insn "align_8"
10338 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10339 "TARGET_EITHER"
755eb2b4 10340 "*
10341 assemble_align (64);
10342 return \"\";
10343 "
10344)
10345
cffb2a26 10346(define_insn "consttable_end"
e1159bbe 10347 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10348 "TARGET_EITHER"
f7fbdd4a 10349 "*
cffb2a26 10350 making_const_table = FALSE;
f7fbdd4a 10351 return \"\";
cffb2a26 10352 "
10353)
f7fbdd4a 10354
cffb2a26 10355(define_insn "consttable_1"
e1159bbe 10356 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10357 "TARGET_THUMB1"
f7fbdd4a 10358 "*
cffb2a26 10359 making_const_table = TRUE;
09d688ff 10360 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10361 assemble_zeros (3);
f7fbdd4a 10362 return \"\";
cffb2a26 10363 "
10364 [(set_attr "length" "4")]
10365)
f7fbdd4a 10366
cffb2a26 10367(define_insn "consttable_2"
e1159bbe 10368 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10369 "TARGET_THUMB1"
f7fbdd4a 10370 "*
cffb2a26 10371 making_const_table = TRUE;
9b8516be 10372 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10373 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10374 assemble_zeros (2);
f7fbdd4a 10375 return \"\";
cffb2a26 10376 "
10377 [(set_attr "length" "4")]
10378)
10379
10380(define_insn "consttable_4"
e1159bbe 10381 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10382 "TARGET_EITHER"
10383 "*
10384 {
9b8516be 10385 rtx x = operands[0];
cffb2a26 10386 making_const_table = TRUE;
9b8516be 10387 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10388 {
10389 case MODE_FLOAT:
9b8516be 10390 if (GET_MODE (x) == HFmode)
10391 arm_emit_fp16_const (x);
10392 else
10393 {
10394 REAL_VALUE_TYPE r;
10395 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10396 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10397 }
10398 break;
cffb2a26 10399 default:
7b04c5d5 10400 /* XXX: Sometimes gcc does something really dumb and ends up with
10401 a HIGH in a constant pool entry, usually because it's trying to
10402 load into a VFP register. We know this will always be used in
10403 combination with a LO_SUM which ignores the high bits, so just
10404 strip off the HIGH. */
10405 if (GET_CODE (x) == HIGH)
10406 x = XEXP (x, 0);
9b8516be 10407 assemble_integer (x, 4, BITS_PER_WORD, 1);
10408 mark_symbol_refs_as_used (x);
cffb2a26 10409 break;
10410 }
10411 return \"\";
10412 }"
10413 [(set_attr "length" "4")]
10414)
10415
10416(define_insn "consttable_8"
e1159bbe 10417 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10418 "TARGET_EITHER"
10419 "*
10420 {
10421 making_const_table = TRUE;
10422 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10423 {
10424 case MODE_FLOAT:
10425 {
badfe841 10426 REAL_VALUE_TYPE r;
10427 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10428 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10429 break;
10430 }
10431 default:
09d688ff 10432 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10433 break;
10434 }
10435 return \"\";
10436 }"
10437 [(set_attr "length" "8")]
10438)
10439
d98a3884 10440(define_insn "consttable_16"
10441 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10442 "TARGET_EITHER"
10443 "*
10444 {
10445 making_const_table = TRUE;
10446 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10447 {
10448 case MODE_FLOAT:
10449 {
10450 REAL_VALUE_TYPE r;
10451 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10452 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10453 break;
10454 }
10455 default:
10456 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10457 break;
10458 }
10459 return \"\";
10460 }"
10461 [(set_attr "length" "16")]
10462)
10463
cffb2a26 10464;; Miscellaneous Thumb patterns
10465
fd957ef3 10466(define_expand "tablejump"
7db9af5d 10467 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10468 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10469 "TARGET_THUMB1"
fd957ef3 10470 "
10471 if (flag_pic)
10472 {
10473 /* Hopefully, CSE will eliminate this copy. */
10474 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10475 rtx reg2 = gen_reg_rtx (SImode);
10476
10477 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10478 operands[0] = reg2;
10479 }
10480 "
10481)
10482
f1039640 10483;; NB never uses BX.
25f905c2 10484(define_insn "*thumb1_tablejump"
cffb2a26 10485 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10486 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10487 "TARGET_THUMB1"
fd957ef3 10488 "mov\\t%|pc, %0"
cffb2a26 10489 [(set_attr "length" "2")]
10490)
0d66636f 10491
331beb1a 10492;; V5 Instructions,
10493
8f4be2be 10494(define_insn "clzsi2"
10495 [(set (match_operand:SI 0 "s_register_operand" "=r")
10496 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10497 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10498 "clz%?\\t%0, %1"
bcaec148 10499 [(set_attr "predicable" "yes")
10500 (set_attr "insn" "clz")])
331beb1a 10501
099ad98b 10502(define_insn "rbitsi2"
10503 [(set (match_operand:SI 0 "s_register_operand" "=r")
10504 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10505 "TARGET_32BIT && arm_arch_thumb2"
10506 "rbit%?\\t%0, %1"
10507 [(set_attr "predicable" "yes")
10508 (set_attr "insn" "clz")])
10509
10510(define_expand "ctzsi2"
10511 [(set (match_operand:SI 0 "s_register_operand" "")
10512 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10513 "TARGET_32BIT && arm_arch_thumb2"
10514 "
30191172 10515 {
10516 rtx tmp = gen_reg_rtx (SImode);
10517 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10518 emit_insn (gen_clzsi2 (operands[0], tmp));
10519 }
099ad98b 10520 DONE;
10521 "
10522)
10523
e1159bbe 10524;; V5E instructions.
331beb1a 10525
10526(define_insn "prefetch"
f4e79814 10527 [(prefetch (match_operand:SI 0 "address_operand" "p")
10528 (match_operand:SI 1 "" "")
10529 (match_operand:SI 2 "" ""))]
25f905c2 10530 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10531 "pld\\t%a0")
331beb1a 10532
0d66636f 10533;; General predication pattern
10534
10535(define_cond_exec
10536 [(match_operator 0 "arm_comparison_operator"
10537 [(match_operand 1 "cc_register" "")
10538 (const_int 0)])]
25f905c2 10539 "TARGET_32BIT"
0d66636f 10540 ""
10541)
10542
063a05c7 10543(define_insn "prologue_use"
10544 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10545 ""
10546 "%@ %0 needed for prologue"
02cfc9c9 10547 [(set_attr "length" "0")]
063a05c7 10548)
7db9af5d 10549
4c44712e 10550
10551;; Patterns for exception handling
10552
10553(define_expand "eh_return"
10554 [(use (match_operand 0 "general_operand" ""))]
10555 "TARGET_EITHER"
10556 "
10557 {
25f905c2 10558 if (TARGET_32BIT)
4c44712e 10559 emit_insn (gen_arm_eh_return (operands[0]));
10560 else
10561 emit_insn (gen_thumb_eh_return (operands[0]));
10562 DONE;
10563 }"
10564)
10565
10566;; We can't expand this before we know where the link register is stored.
10567(define_insn_and_split "arm_eh_return"
10568 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10569 VUNSPEC_EH_RETURN)
10570 (clobber (match_scratch:SI 1 "=&r"))]
10571 "TARGET_ARM"
10572 "#"
10573 "&& reload_completed"
10574 [(const_int 0)]
10575 "
10576 {
10577 arm_set_return_address (operands[0], operands[1]);
10578 DONE;
10579 }"
10580)
10581
10582(define_insn_and_split "thumb_eh_return"
10583 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10584 VUNSPEC_EH_RETURN)
10585 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10586 "TARGET_THUMB1"
4c44712e 10587 "#"
10588 "&& reload_completed"
10589 [(const_int 0)]
10590 "
10591 {
10592 thumb_set_return_address (operands[0], operands[1]);
10593 DONE;
10594 }"
10595)
10596
f655717d 10597\f
10598;; TLS support
10599
10600(define_insn "load_tp_hard"
10601 [(set (match_operand:SI 0 "register_operand" "=r")
10602 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10603 "TARGET_HARD_TP"
10604 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10605 [(set_attr "predicable" "yes")]
10606)
10607
10608;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10609(define_insn "load_tp_soft"
10610 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10611 (clobber (reg:SI LR_REGNUM))
10612 (clobber (reg:SI IP_REGNUM))
10613 (clobber (reg:CC CC_REGNUM))]
10614 "TARGET_SOFT_TP"
10615 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10616 [(set_attr "conds" "clob")]
10617)
10618
aabe09ac 10619;; We only care about the lower 16 bits of the constant
10620;; being inserted into the upper 16 bits of the register.
eca5c984 10621(define_insn "*arm_movtas_ze"
10622 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10623 (const_int 16)
10624 (const_int 16))
10625 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10626 "arm_arch_thumb2"
aabe09ac 10627 "movt%?\t%0, %L1"
eca5c984 10628 [(set_attr "predicable" "yes")
10629 (set_attr "length" "4")]
10630)
10631
c0fc3696 10632(define_insn "*arm_rev"
ff82f757 10633 [(set (match_operand:SI 0 "s_register_operand" "=r")
10634 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 10635 "TARGET_32BIT && arm_arch6"
10636 "rev%?\t%0, %1"
10637 [(set_attr "predicable" "yes")
10638 (set_attr "length" "4")]
10639)
10640
10641(define_insn "*thumb1_rev"
10642 [(set (match_operand:SI 0 "s_register_operand" "=l")
10643 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10644 "TARGET_THUMB1 && arm_arch6"
10645 "rev\t%0, %1"
10646 [(set_attr "length" "2")]
ff82f757 10647)
10648
10649(define_expand "arm_legacy_rev"
10650 [(set (match_operand:SI 2 "s_register_operand" "")
10651 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10652 (const_int 16))
10653 (match_dup 1)))
10654 (set (match_dup 2)
10655 (lshiftrt:SI (match_dup 2)
10656 (const_int 8)))
10657 (set (match_operand:SI 3 "s_register_operand" "")
10658 (rotatert:SI (match_dup 1)
10659 (const_int 8)))
10660 (set (match_dup 2)
10661 (and:SI (match_dup 2)
10662 (const_int -65281)))
10663 (set (match_operand:SI 0 "s_register_operand" "")
10664 (xor:SI (match_dup 3)
10665 (match_dup 2)))]
10666 "TARGET_32BIT"
10667 ""
10668)
10669
10670;; Reuse temporaries to keep register pressure down.
10671(define_expand "thumb_legacy_rev"
10672 [(set (match_operand:SI 2 "s_register_operand" "")
10673 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10674 (const_int 24)))
10675 (set (match_operand:SI 3 "s_register_operand" "")
10676 (lshiftrt:SI (match_dup 1)
10677 (const_int 24)))
10678 (set (match_dup 3)
10679 (ior:SI (match_dup 3)
10680 (match_dup 2)))
10681 (set (match_operand:SI 4 "s_register_operand" "")
10682 (const_int 16))
10683 (set (match_operand:SI 5 "s_register_operand" "")
10684 (rotatert:SI (match_dup 1)
10685 (match_dup 4)))
10686 (set (match_dup 2)
10687 (ashift:SI (match_dup 5)
10688 (const_int 24)))
10689 (set (match_dup 5)
10690 (lshiftrt:SI (match_dup 5)
10691 (const_int 24)))
10692 (set (match_dup 5)
10693 (ior:SI (match_dup 5)
10694 (match_dup 2)))
10695 (set (match_dup 5)
10696 (rotatert:SI (match_dup 5)
10697 (match_dup 4)))
10698 (set (match_operand:SI 0 "s_register_operand" "")
10699 (ior:SI (match_dup 5)
10700 (match_dup 3)))]
10701 "TARGET_THUMB"
10702 ""
10703)
10704
10705(define_expand "bswapsi2"
10706 [(set (match_operand:SI 0 "s_register_operand" "=r")
10707 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10708"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10709"
8d1af482 10710 if (!arm_arch6)
10711 {
10712 rtx op2 = gen_reg_rtx (SImode);
10713 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10714
8d1af482 10715 if (TARGET_THUMB)
10716 {
10717 rtx op4 = gen_reg_rtx (SImode);
10718 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10719
8d1af482 10720 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10721 op2, op3, op4, op5));
10722 }
10723 else
10724 {
10725 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10726 op2, op3));
10727 }
ff82f757 10728
8d1af482 10729 DONE;
10730 }
ff82f757 10731 "
10732)
10733
320ea44d 10734;; Load the load/store multiple patterns
10735(include "ldmstm.md")
7db9af5d 10736;; Load the FPA co-processor patterns
10737(include "fpa.md")
10738;; Load the Maverick co-processor patterns
10739(include "cirrus.md")
d98a3884 10740;; Vector bits common to IWMMXT and Neon
10741(include "vec-common.md")
755eb2b4 10742;; Load the Intel Wireless Multimedia Extension patterns
10743(include "iwmmxt.md")
a2cd141b 10744;; Load the VFP co-processor patterns
10745(include "vfp.md")
25f905c2 10746;; Thumb-2 patterns
10747(include "thumb2.md")
d98a3884 10748;; Neon patterns
10749(include "neon.md")
06df6b17 10750;; Synchronization Primitives
10751(include "sync.md")