]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
PR debug/42487
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
7cf0dbf3 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
934a1e72 4;; Free Software Foundation, Inc.
b11cae9e 5;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 6;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 7;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 8
acf6ed70 9;; This file is part of GCC.
b11cae9e 10
acf6ed70 11;; GCC is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published
038d1e19 13;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 14;; option) any later version.
b11cae9e 15
acf6ed70 16;; GCC is distributed in the hope that it will be useful, but WITHOUT
17;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19;; License for more details.
b11cae9e 20
21;; You should have received a copy of the GNU General Public License
038d1e19 22;; along with GCC; see the file COPYING3. If not see
23;; <http://www.gnu.org/licenses/>.
b11cae9e 24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
9c08d1fa 27\f
e1159bbe 28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
ccd90aaa 33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
e1159bbe 35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
ccd90aaa 39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
e1159bbe 51
9c08d1fa 52;; UNSPEC Usage:
8a18b90c 53;; Note: sin and cos are no-longer used.
d98a3884 54;; Unspec constants for Neon are defined in neon.md.
e1159bbe 55
56(define_constants
57 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
58 ; operand 0 is the result,
59 ; operand 1 the parameter.
60 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
61 ; operand 0 is the result,
62 ; operand 1 the parameter.
63 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
64 ; operand 0 is the first register,
65 ; subsequent registers are in parallel (use ...)
66 ; expressions.
67 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
68 ; usage, that is, we will add the pic_register
69 ; value to it before trying to dereference it.
c0c1fba5 70 (UNSPEC_PIC_BASE 4) ; Add PC and all but the last operand together,
71 ; The last operand is the number of a PIC_LABEL
72 ; that points at the containing instruction.
2c96dc5a 73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
e1159bbe 74 ; being scheduled before the stack adjustment insn.
063a05c7 75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
79 ; register to "use".
68121397 80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
8d232dc7 81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
f655717d 93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
6cdcb15c 94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95 ; instruction stream.
2c2d2f40 96 (UNSPEC_STACK_ALIGN 22) ; Doubleword aligned stack pointer. Used to
25f905c2 97 ; generate correct unwind information.
2c2d2f40 98 (UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
bac7fc85 99 ; correctly for PIC usage.
c0c1fba5 100 (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
101 ; a given symbolic address.
e6ac8414 102 (UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
099ad98b 103 (UNSPEC_RBIT 26) ; rbit operation.
825ae2ed 104 (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
105 ; another symbolic address.
e1159bbe 106 ]
107)
108
215b30b3 109;; UNSPEC_VOLATILE Usage:
e1159bbe 110
111(define_constants
112 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
113 ; insn in the code.
114 (VUNSPEC_EPILOGUE 1) ; `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 2) ; `align' insn. Used at the head of a minipool table
119 ; for inlined constants.
120 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
121 ; table.
122 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
123 ; an 8-bit object.
124 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
125 ; a 16-bit object.
126 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
127 ; a 32-bit object.
128 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
129 ; a 64-bit object.
d98a3884 130 (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
131 ; a 128-bit object.
132 (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
133 (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
134 (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
135 (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
136 (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
137 (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 138 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 139 ; handling.
e1159bbe 140 ]
141)
b11cae9e 142\f
e1159bbe 143;;---------------------------------------------------------------------------
9c08d1fa 144;; Attributes
145
215b30b3 146; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
147; generating ARM code. This is used to control the length of some insn
148; patterns that share the same RTL in both ARM and Thumb code.
1c494086 149(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 150
ef51b8e1 151; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
152(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
153
747b7458 154; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
155(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
156
331beb1a 157;; Operand number of an input operand that is shifted. Zero if the
158;; given instruction does not shift one of its input operands.
331beb1a 159(define_attr "shift" "" (const_int 0))
160
3d91c5d6 161; Floating Point Unit. If we only have floating point emulation, then there
162; is no point in scheduling the floating point insns. (Well, for best
163; performance we should try and group them together).
4fea7d65 164(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 165 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 166
094e994f 167; LENGTH of an instruction (in bytes)
168(define_attr "length" "" (const_int 4))
9c08d1fa 169
d5d4dc8d 170; The architecture which supports the instruction (or alternative).
171; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
172; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
173; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
174; arm_arch6. This attribute is used to compute attribute "enabled",
175; use type "any" to enable an alternative in all cases.
176(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6"
177 (const_string "any"))
178
179(define_attr "arch_enabled" "no,yes"
180 (cond [(eq_attr "arch" "any")
181 (const_string "yes")
182
183 (and (eq_attr "arch" "a")
184 (ne (symbol_ref "TARGET_ARM") (const_int 0)))
185 (const_string "yes")
186
187 (and (eq_attr "arch" "t")
188 (ne (symbol_ref "TARGET_THUMB") (const_int 0)))
189 (const_string "yes")
190
191 (and (eq_attr "arch" "t1")
192 (ne (symbol_ref "TARGET_THUMB1") (const_int 0)))
193 (const_string "yes")
194
195 (and (eq_attr "arch" "t2")
196 (ne (symbol_ref "TARGET_THUMB2") (const_int 0)))
197 (const_string "yes")
198
199 (and (eq_attr "arch" "32")
200 (ne (symbol_ref "TARGET_32BIT") (const_int 0)))
201 (const_string "yes")
202
203 (and (eq_attr "arch" "v6")
204 (ne (symbol_ref "(TARGET_32BIT && arm_arch6)") (const_int 0)))
205 (const_string "yes")
206
207 (and (eq_attr "arch" "nov6")
208 (ne (symbol_ref "(TARGET_32BIT && !arm_arch6)") (const_int 0)))
209 (const_string "yes")]
210 (const_string "no")))
211
212; Allows an insn to disable certain alternatives for reasons other than
213; arch support.
214(define_attr "insn_enabled" "no,yes"
215 (const_string "yes"))
216
217; Enable all alternatives that are both arch_enabled and insn_enabled.
218(define_attr "enabled" "no,yes"
219 (if_then_else (eq_attr "insn_enabled" "yes")
220 (attr "arch_enabled")
221 (const_string "no")))
222
56d27660 223; POOL_RANGE is how far away from a constant pool entry that this insn
224; can be placed. If the distance is zero, then this insn will never
225; reference the pool.
cffb2a26 226; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
227; before its address.
cde1623a 228(define_attr "arm_pool_range" "" (const_int 0))
229(define_attr "thumb2_pool_range" "" (const_int 0))
230(define_attr "arm_neg_pool_range" "" (const_int 0))
231(define_attr "thumb2_neg_pool_range" "" (const_int 0))
232
233(define_attr "pool_range" ""
234 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
235 (attr "arm_pool_range")))
236(define_attr "neg_pool_range" ""
237 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
238 (attr "arm_neg_pool_range")))
56d27660 239
215b30b3 240; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 241; If such an insn references the pool, then we have no way of knowing how,
242; so use the most conservative value for pool_range.
9c08d1fa 243(define_asm_attributes
4d7a8451 244 [(set_attr "conds" "clob")
245 (set_attr "length" "4")
246 (set_attr "pool_range" "250")])
9c08d1fa 247
a2cd141b 248;; The instruction used to implement a particular pattern. This
249;; information is used by pipeline descriptions to provide accurate
250;; scheduling information.
251
252(define_attr "insn"
934a1e72 253 "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 254 (const_string "other"))
255
9c08d1fa 256; TYPE attribute is used to detect floating point instructions which, if
257; running on a co-processor can run in parallel with other, basic instructions
258; If write-buffer scheduling is enabled then it can also be used in the
259; scheduling of writes.
260
261; Classification of each insn
607978a1 262; Note: vfp.md has different meanings for some of these, and some further
263; types as well. See that file for details.
a2cd141b 264; alu any alu instruction that doesn't hit memory or fp
265; regs or have a shifted source operand
266; alu_shift any data instruction that doesn't hit memory or fp
267; regs, but has a source operand shifted by a constant
268; alu_shift_reg any data instruction that doesn't hit memory or fp
269; regs, but has a source operand shifted by a register value
f7fbdd4a 270; mult a multiply instruction
9c08d1fa 271; block blockage insn, this blocks all functional units
272; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 273; fdivd DFmode floating point division
274; fdivs SFmode floating point division
275; fmul Floating point multiply
276; ffmul Fast floating point multiply
277; farith Floating point arithmetic (4 cycle)
278; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 279; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 280; even on a machine with an fpa.
9c08d1fa 281; f_load a floating point load from memory
282; f_store a floating point store to memory
9aff9709 283; f_load[sd] single/double load from memory
284; f_store[sd] single/double store to memory
c0e1af52 285; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 286; f_mem_r a transfer of a floating point register to a real reg via mem
287; r_mem_f the reverse of f_mem_r
288; f_2_r fast transfer float to arm (no memory needed)
289; r_2_f fast transfer arm to float
c0e1af52 290; f_cvt convert floating<->integral
a2cd141b 291; branch a branch
9c08d1fa 292; call a subroutine call
a2cd141b 293; load_byte load byte(s) from memory to arm registers
294; load1 load 1 word from memory to arm registers
295; load2 load 2 words from memory to arm registers
296; load3 load 3 words from memory to arm registers
297; load4 load 4 words from memory to arm registers
298; store store 1 word to memory from arm registers
9c08d1fa 299; store2 store 2 words
300; store3 store 3 words
a2cd141b 301; store4 store 4 (or more) words
2c6c7d8b 302; Additions for Cirrus Maverick co-processor:
303; mav_farith Floating point arithmetic (4 cycle)
304; mav_dmult Double multiplies (7 cycle)
9c08d1fa 305;
bcaec148 306
9c08d1fa 307(define_attr "type"
e3879fd0 308 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
a2cd141b 309 (if_then_else
310 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
311 (const_string "mult")
312 (const_string "alu")))
9c08d1fa 313
9888ad6d 314; Load scheduling, set from the arm_ld_sched variable
457275b6 315; initialized by arm_override_options()
9888ad6d 316(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 317
c52acdd2 318;; Classification of NEON instructions for scheduling purposes.
319;; Do not set this attribute and the "type" attribute together in
320;; any one instruction pattern.
321(define_attr "neon_type"
322 "neon_int_1,\
323 neon_int_2,\
324 neon_int_3,\
325 neon_int_4,\
326 neon_int_5,\
327 neon_vqneg_vqabs,\
328 neon_vmov,\
329 neon_vaba,\
330 neon_vsma,\
331 neon_vaba_qqq,\
332 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
333 neon_mul_qqq_8_16_32_ddd_32,\
334 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
335 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
336 neon_mla_qqq_8_16,\
337 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
338 neon_mla_qqq_32_qqd_32_scalar,\
339 neon_mul_ddd_16_scalar_32_16_long_scalar,\
340 neon_mul_qqd_32_scalar,\
341 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
342 neon_shift_1,\
343 neon_shift_2,\
344 neon_shift_3,\
345 neon_vshl_ddd,\
346 neon_vqshl_vrshl_vqrshl_qqq,\
347 neon_vsra_vrsra,\
348 neon_fp_vadd_ddd_vabs_dd,\
349 neon_fp_vadd_qqq_vabs_qq,\
350 neon_fp_vsum,\
351 neon_fp_vmul_ddd,\
352 neon_fp_vmul_qqd,\
353 neon_fp_vmla_ddd,\
354 neon_fp_vmla_qqq,\
355 neon_fp_vmla_ddd_scalar,\
356 neon_fp_vmla_qqq_scalar,\
357 neon_fp_vrecps_vrsqrts_ddd,\
358 neon_fp_vrecps_vrsqrts_qqq,\
359 neon_bp_simple,\
360 neon_bp_2cycle,\
361 neon_bp_3cycle,\
362 neon_ldr,\
363 neon_str,\
364 neon_vld1_1_2_regs,\
365 neon_vld1_3_4_regs,\
366 neon_vld2_2_regs_vld1_vld2_all_lanes,\
367 neon_vld2_4_regs,\
368 neon_vld3_vld4,\
369 neon_vst1_1_2_regs_vst2_2_regs,\
370 neon_vst1_3_4_regs,\
371 neon_vst2_4_regs_vst3_vst4,\
372 neon_vst3_vst4,\
373 neon_vld1_vld2_lane,\
374 neon_vld3_vld4_lane,\
375 neon_vst1_vst2_lane,\
376 neon_vst3_vst4_lane,\
377 neon_vld3_vld4_all_lanes,\
378 neon_mcr,\
379 neon_mcr_2_mcrr,\
380 neon_mrc,\
381 neon_mrrc,\
382 neon_ldm_2,\
383 neon_stm_2,\
384 none"
385 (const_string "none"))
386
f7fbdd4a 387; condition codes: this one is used by final_prescan_insn to speed up
388; conditionalizing instructions. It saves having to scan the rtl to see if
389; it uses or alters the condition codes.
215b30b3 390;
f7fbdd4a 391; USE means that the condition codes are used by the insn in the process of
215b30b3 392; outputting code, this means (at present) that we can't use the insn in
393; inlined branches
394;
f7fbdd4a 395; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 396; well defined manner.
397;
f7fbdd4a 398; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 399; they are altered at all
400;
c52acdd2 401; UNCONDITIONAL means the instions can not be conditionally executed.
402;
f7fbdd4a 403; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 404; output of this insn
f7fbdd4a 405
b0694be0 406(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 407 (if_then_else
408 (ior (eq_attr "is_thumb1" "yes")
409 (eq_attr "type" "call"))
c1a66faf 410 (const_string "clob")
c52acdd2 411 (if_then_else (eq_attr "neon_type" "none")
412 (const_string "nocond")
413 (const_string "unconditional"))))
f7fbdd4a 414
215b30b3 415; Predicable means that the insn can be conditionally executed based on
416; an automatically added predicate (additional patterns are generated by
417; gen...). We default to 'no' because no Thumb patterns match this rule
418; and not all ARM patterns do.
0d66636f 419(define_attr "predicable" "no,yes" (const_string "no"))
420
129a2fe4 421; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
422; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 423; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 424; affect the schedule).
74a71f7d 425(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 426
215b30b3 427; WRITE_CONFLICT implies that a read following an unrelated write is likely
428; to stall the processor. Used with model_wbuf above.
9c08d1fa 429(define_attr "write_conflict" "no,yes"
430 (if_then_else (eq_attr "type"
a2cd141b 431 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 432 (const_string "yes")
433 (const_string "no")))
434
215b30b3 435; Classify the insns into those that take one cycle and those that take more
436; than one on the main cpu execution unit.
f7fbdd4a 437(define_attr "core_cycles" "single,multi"
438 (if_then_else (eq_attr "type"
a2cd141b 439 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 440 (const_string "single")
441 (const_string "multi")))
442
cffb2a26 443;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 444;; distant label. Only applicable to Thumb code.
cffb2a26 445(define_attr "far_jump" "yes,no" (const_string "no"))
446
d51f92df 447
25f905c2 448;; The number of machine instructions this pattern expands to.
449;; Used for Thumb-2 conditional execution.
450(define_attr "ce_count" "" (const_int 1))
451
d51f92df 452;;---------------------------------------------------------------------------
fd781bb2 453;; Mode iterators
d51f92df 454
3de0dec6 455(include "iterators.md")
03770691 456
d51f92df 457;;---------------------------------------------------------------------------
458;; Predicates
459
9c9db025 460(include "predicates.md")
234f6557 461(include "constraints.md")
9c9db025 462
a2cd141b 463;;---------------------------------------------------------------------------
464;; Pipeline descriptions
215b30b3 465
06469f9e 466;; Processor type. This is created automatically from arm-cores.def.
467(include "arm-tune.md")
331beb1a 468
e3879fd0 469(define_attr "tune_cortexr4" "yes,no"
470 (const (if_then_else
471 (eq_attr "tune" "cortexr4,cortexr4f")
472 (const_string "yes")
473 (const_string "no"))))
474
a2cd141b 475;; True if the generic scheduling description should be used.
476
477(define_attr "generic_sched" "yes,no"
4d5cb40d 478 (const (if_then_else
036068af 479 (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
e3879fd0 480 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 481 (const_string "no")
482 (const_string "yes"))))
483
c0e1af52 484(define_attr "generic_vfp" "yes,no"
485 (const (if_then_else
486 (and (eq_attr "fpu" "vfp")
036068af 487 (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
e3879fd0 488 (eq_attr "tune_cortexr4" "no"))
c0e1af52 489 (const_string "yes")
490 (const_string "no"))))
491
a2cd141b 492(include "arm-generic.md")
493(include "arm926ejs.md")
c0e1af52 494(include "arm1020e.md")
a2cd141b 495(include "arm1026ejs.md")
496(include "arm1136jfs.md")
bcaec148 497(include "cortex-a8.md")
036068af 498(include "cortex-a9.md")
934a1e72 499(include "cortex-r4.md")
e3879fd0 500(include "cortex-r4f.md")
55e3ada8 501(include "vfp11.md")
3586df96 502
9c08d1fa 503\f
215b30b3 504;;---------------------------------------------------------------------------
e1159bbe 505;; Insn patterns
506;;
a0f94409 507;; Addition insns.
215b30b3 508
9c08d1fa 509;; Note: For DImode insns, there is normally no reason why operands should
510;; not be in the same register, what we don't want is for something being
511;; written to partially overlap something that is an input.
7d57ec45 512;; Cirrus 64bit additions should not be split because we have a native
513;; 64bit addition instructions.
9c08d1fa 514
cffb2a26 515(define_expand "adddi3"
516 [(parallel
215b30b3 517 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 518 (plus:DI (match_operand:DI 1 "s_register_operand" "")
519 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 520 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 521 "TARGET_EITHER"
522 "
a2cd141b 523 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 524 {
525 if (!cirrus_fp_register (operands[0], DImode))
526 operands[0] = force_reg (DImode, operands[0]);
527 if (!cirrus_fp_register (operands[1], DImode))
528 operands[1] = force_reg (DImode, operands[1]);
529 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
530 DONE;
531 }
532
25f905c2 533 if (TARGET_THUMB1)
cffb2a26 534 {
535 if (GET_CODE (operands[1]) != REG)
bc5a93af 536 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 537 if (GET_CODE (operands[2]) != REG)
bc5a93af 538 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 539 }
540 "
541)
542
25f905c2 543(define_insn "*thumb1_adddi3"
cffb2a26 544 [(set (match_operand:DI 0 "register_operand" "=l")
545 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 546 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 547 (clobber (reg:CC CC_REGNUM))
cffb2a26 548 ]
25f905c2 549 "TARGET_THUMB1"
cffb2a26 550 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
551 [(set_attr "length" "4")]
552)
553
a0f94409 554(define_insn_and_split "*arm_adddi3"
cffb2a26 555 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 556 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
557 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 558 (clobber (reg:CC CC_REGNUM))]
94829feb 559 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 560 "#"
94829feb 561 "TARGET_32BIT && reload_completed
562 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 563 [(parallel [(set (reg:CC_C CC_REGNUM)
564 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
565 (match_dup 1)))
566 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 567 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
568 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 569 "
570 {
571 operands[3] = gen_highpart (SImode, operands[0]);
572 operands[0] = gen_lowpart (SImode, operands[0]);
573 operands[4] = gen_highpart (SImode, operands[1]);
574 operands[1] = gen_lowpart (SImode, operands[1]);
575 operands[5] = gen_highpart (SImode, operands[2]);
576 operands[2] = gen_lowpart (SImode, operands[2]);
577 }"
cffb2a26 578 [(set_attr "conds" "clob")
579 (set_attr "length" "8")]
580)
9c08d1fa 581
a0f94409 582(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 583 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
584 (plus:DI (sign_extend:DI
97499065 585 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 586 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 587 (clobber (reg:CC CC_REGNUM))]
25f905c2 588 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 589 "#"
25f905c2 590 "TARGET_32BIT && reload_completed"
a0f94409 591 [(parallel [(set (reg:CC_C CC_REGNUM)
592 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
593 (match_dup 1)))
594 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 595 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 596 (const_int 31))
080c0b9a 597 (match_dup 4))
598 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 599 "
600 {
601 operands[3] = gen_highpart (SImode, operands[0]);
602 operands[0] = gen_lowpart (SImode, operands[0]);
603 operands[4] = gen_highpart (SImode, operands[1]);
604 operands[1] = gen_lowpart (SImode, operands[1]);
605 operands[2] = gen_lowpart (SImode, operands[2]);
606 }"
215b30b3 607 [(set_attr "conds" "clob")
608 (set_attr "length" "8")]
609)
9c08d1fa 610
a0f94409 611(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 612 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
613 (plus:DI (zero_extend:DI
97499065 614 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 615 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 616 (clobber (reg:CC CC_REGNUM))]
25f905c2 617 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 618 "#"
25f905c2 619 "TARGET_32BIT && reload_completed"
a0f94409 620 [(parallel [(set (reg:CC_C CC_REGNUM)
621 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
622 (match_dup 1)))
623 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 624 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
625 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 626 "
627 {
628 operands[3] = gen_highpart (SImode, operands[0]);
629 operands[0] = gen_lowpart (SImode, operands[0]);
630 operands[4] = gen_highpart (SImode, operands[1]);
631 operands[1] = gen_lowpart (SImode, operands[1]);
632 operands[2] = gen_lowpart (SImode, operands[2]);
633 }"
cffb2a26 634 [(set_attr "conds" "clob")
635 (set_attr "length" "8")]
636)
b11cae9e 637
87b22bf7 638(define_expand "addsi3"
cffb2a26 639 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 640 (plus:SI (match_operand:SI 1 "s_register_operand" "")
641 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 642 "TARGET_EITHER"
87b22bf7 643 "
25f905c2 644 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 645 {
96f57e36 646 arm_split_constant (PLUS, SImode, NULL_RTX,
647 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 648 optimize && can_create_pseudo_p ());
87b22bf7 649 DONE;
650 }
cffb2a26 651 "
652)
87b22bf7 653
5bd751ff 654; If there is a scratch available, this will be faster than synthesizing the
a0f94409 655; addition.
656(define_peephole2
657 [(match_scratch:SI 3 "r")
372575c7 658 (set (match_operand:SI 0 "arm_general_register_operand" "")
659 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 660 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 661 "TARGET_32BIT &&
a0f94409 662 !(const_ok_for_arm (INTVAL (operands[2]))
663 || const_ok_for_arm (-INTVAL (operands[2])))
664 && const_ok_for_arm (~INTVAL (operands[2]))"
665 [(set (match_dup 3) (match_dup 2))
666 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
667 ""
668)
87b22bf7 669
2f02c19f 670;; The r/r/k alternative is required when reloading the address
671;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
672;; put the duplicated register first, and not try the commutative version.
a0f94409 673(define_insn_and_split "*arm_addsi3"
bccb5444 674 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k,r")
675 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
676 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
25f905c2 677 "TARGET_32BIT"
5565501b 678 "@
679 add%?\\t%0, %1, %2
aaa37ad6 680 add%?\\t%0, %1, %2
2f02c19f 681 add%?\\t%0, %2, %1
aaa37ad6 682 sub%?\\t%0, %1, #%n2
87b22bf7 683 sub%?\\t%0, %1, #%n2
684 #"
a3ffc315 685 "TARGET_32BIT
686 && GET_CODE (operands[2]) == CONST_INT
a0f94409 687 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 688 || const_ok_for_arm (-INTVAL (operands[2])))
689 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 690 [(clobber (const_int 0))]
691 "
96f57e36 692 arm_split_constant (PLUS, SImode, curr_insn,
693 INTVAL (operands[2]), operands[0],
a0f94409 694 operands[1], 0);
695 DONE;
696 "
2f02c19f 697 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 698 (set_attr "predicable" "yes")]
cffb2a26 699)
700
0bdb6455 701(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 702 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
703 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
704 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 705 "TARGET_THUMB1"
cffb2a26 706 "*
0d66636f 707 static const char * const asms[] =
cffb2a26 708 {
709 \"add\\t%0, %0, %2\",
710 \"sub\\t%0, %0, #%n2\",
711 \"add\\t%0, %1, %2\",
712 \"add\\t%0, %0, %2\",
713 \"add\\t%0, %0, %2\",
714 \"add\\t%0, %1, %2\",
0bdb6455 715 \"add\\t%0, %1, %2\",
716 \"#\",
bf7bc2f6 717 \"#\",
0bdb6455 718 \"#\"
cffb2a26 719 };
720 if ((which_alternative == 2 || which_alternative == 6)
721 && GET_CODE (operands[2]) == CONST_INT
722 && INTVAL (operands[2]) < 0)
723 return \"sub\\t%0, %1, #%n2\";
724 return asms[which_alternative];
725 "
0bdb6455 726 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 727 && ((operands[1] != stack_pointer_rtx
728 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
729 || (operands[1] == stack_pointer_rtx
730 && INTVAL (operands[2]) > 1020))"
0bdb6455 731 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
732 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
733 {
734 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 735 if (operands[1] == stack_pointer_rtx)
736 offset -= 1020;
737 else
738 {
739 if (offset > 255)
740 offset = 255;
741 else if (offset < -255)
742 offset = -255;
743 }
0bdb6455 744 operands[3] = GEN_INT (offset);
745 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
746 }
bf7bc2f6 747 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 748)
749
750;; Reloading and elimination of the frame pointer can
751;; sometimes cause this optimization to be missed.
a0f94409 752(define_peephole2
372575c7 753 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 754 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 755 (set (match_dup 0)
372575c7 756 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 757 "TARGET_THUMB1
cffb2a26 758 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
759 && (INTVAL (operands[1]) & 3) == 0"
372575c7 760 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 761 ""
cffb2a26 762)
b11cae9e 763
f7fbdd4a 764(define_insn "*addsi3_compare0"
bd5b4116 765 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 766 (compare:CC_NOOV
215b30b3 767 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
768 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 769 (const_int 0)))
770 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 771 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 772 "TARGET_ARM"
5565501b 773 "@
25f905c2 774 add%.\\t%0, %1, %2
775 sub%.\\t%0, %1, #%n2"
cffb2a26 776 [(set_attr "conds" "set")]
777)
9c08d1fa 778
aea4c774 779(define_insn "*addsi3_compare0_scratch"
bd5b4116 780 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 781 (compare:CC_NOOV
215b30b3 782 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
783 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 784 (const_int 0)))]
ec792a7b 785 "TARGET_ARM"
cffb2a26 786 "@
787 cmn%?\\t%0, %1
788 cmp%?\\t%0, #%n1"
0d66636f 789 [(set_attr "conds" "set")]
790)
cffb2a26 791
aed179ae 792(define_insn "*compare_negsi_si"
793 [(set (reg:CC_Z CC_REGNUM)
794 (compare:CC_Z
795 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
796 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 797 "TARGET_32BIT"
aed179ae 798 "cmn%?\\t%1, %0"
0d66636f 799 [(set_attr "conds" "set")]
800)
aea4c774 801
203c488f 802;; This is the canonicalization of addsi3_compare0_for_combiner when the
803;; addend is a constant.
804(define_insn "*cmpsi2_addneg"
805 [(set (reg:CC CC_REGNUM)
806 (compare:CC
807 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 808 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 809 (set (match_operand:SI 0 "s_register_operand" "=r,r")
810 (plus:SI (match_dup 1)
2a977b78 811 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 812 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 813 "@
2a977b78 814 add%.\\t%0, %1, %3
815 sub%.\\t%0, %1, #%n3"
203c488f 816 [(set_attr "conds" "set")]
817)
818
819;; Convert the sequence
820;; sub rd, rn, #1
821;; cmn rd, #1 (equivalent to cmp rd, #-1)
822;; bne dest
823;; into
824;; subs rd, rn, #1
825;; bcs dest ((unsigned)rn >= 1)
826;; similarly for the beq variant using bcc.
827;; This is a common looping idiom (while (n--))
828(define_peephole2
372575c7 829 [(set (match_operand:SI 0 "arm_general_register_operand" "")
830 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 831 (const_int -1)))
832 (set (match_operand 2 "cc_register" "")
833 (compare (match_dup 0) (const_int -1)))
834 (set (pc)
835 (if_then_else (match_operator 3 "equality_operator"
836 [(match_dup 2) (const_int 0)])
837 (match_operand 4 "" "")
838 (match_operand 5 "" "")))]
25f905c2 839 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 840 [(parallel[
841 (set (match_dup 2)
842 (compare:CC
843 (match_dup 1) (const_int 1)))
844 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
845 (set (pc)
846 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
847 (match_dup 4)
848 (match_dup 5)))]
849 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
850 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
851 ? GEU : LTU),
852 VOIDmode,
853 operands[2], const0_rtx);"
854)
855
ebcc79bc 856;; The next four insns work because they compare the result with one of
857;; the operands, and we know that the use of the condition code is
858;; either GEU or LTU, so we can use the carry flag from the addition
859;; instead of doing the compare a second time.
860(define_insn "*addsi3_compare_op1"
bd5b4116 861 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 862 (compare:CC_C
863 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
864 (match_operand:SI 2 "arm_add_operand" "rI,L"))
865 (match_dup 1)))
866 (set (match_operand:SI 0 "s_register_operand" "=r,r")
867 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 868 "TARGET_32BIT"
ebcc79bc 869 "@
25f905c2 870 add%.\\t%0, %1, %2
871 sub%.\\t%0, %1, #%n2"
0d66636f 872 [(set_attr "conds" "set")]
873)
ebcc79bc 874
875(define_insn "*addsi3_compare_op2"
bd5b4116 876 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 877 (compare:CC_C
878 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
879 (match_operand:SI 2 "arm_add_operand" "rI,L"))
880 (match_dup 2)))
5565501b 881 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 882 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 883 "TARGET_32BIT"
5565501b 884 "@
25f905c2 885 add%.\\t%0, %1, %2
886 sub%.\\t%0, %1, #%n2"
0d66636f 887 [(set_attr "conds" "set")]
888)
9c08d1fa 889
ebcc79bc 890(define_insn "*compare_addsi2_op0"
bd5b4116 891 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 892 (compare:CC_C
893 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
894 (match_operand:SI 1 "arm_add_operand" "rI,L"))
895 (match_dup 0)))]
25f905c2 896 "TARGET_32BIT"
ebcc79bc 897 "@
898 cmn%?\\t%0, %1
899 cmp%?\\t%0, #%n1"
0d66636f 900 [(set_attr "conds" "set")]
901)
ebcc79bc 902
903(define_insn "*compare_addsi2_op1"
bd5b4116 904 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 905 (compare:CC_C
906 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
907 (match_operand:SI 1 "arm_add_operand" "rI,L"))
908 (match_dup 1)))]
25f905c2 909 "TARGET_32BIT"
ebcc79bc 910 "@
911 cmn%?\\t%0, %1
912 cmp%?\\t%0, #%n1"
0d66636f 913 [(set_attr "conds" "set")]
914)
ebcc79bc 915
080c0b9a 916(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 917 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 918 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 919 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 920 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 921 "TARGET_32BIT"
ebcc79bc 922 "adc%?\\t%0, %1, %2"
cffb2a26 923 [(set_attr "conds" "use")]
924)
ebcc79bc 925
080c0b9a 926(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 927 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 928 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
929 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 930 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 931 "TARGET_32BIT"
ebcc79bc 932 "adc%?\\t%0, %1, %2"
0d66636f 933 [(set_attr "conds" "use")]
934)
ebcc79bc 935
080c0b9a 936(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 937 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 938 (plus:SI (plus:SI
939 (match_operator:SI 2 "shift_operator"
940 [(match_operand:SI 3 "s_register_operand" "r")
941 (match_operand:SI 4 "reg_or_int_operand" "rM")])
942 (match_operand:SI 1 "s_register_operand" "r"))
943 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 944 "TARGET_32BIT"
080c0b9a 945 "adc%?\\t%0, %1, %3%S2"
946 [(set_attr "conds" "use")
947 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
948 (const_string "alu_shift")
949 (const_string "alu_shift_reg")))]
cffb2a26 950)
ebcc79bc 951
25f905c2 952(define_expand "incscc"
953 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
954 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
955 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
956 (match_operand:SI 1 "s_register_operand" "0,?r")))]
957 "TARGET_32BIT"
958 ""
959)
960
961(define_insn "*arm_incscc"
9c08d1fa 962 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 963 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 964 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 965 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 966 "TARGET_ARM"
5565501b 967 "@
968 add%d2\\t%0, %1, #1
969 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 970 [(set_attr "conds" "use")
215b30b3 971 (set_attr "length" "4,8")]
972)
9c08d1fa 973
d795fb69 974; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
975(define_split
976 [(set (match_operand:SI 0 "s_register_operand" "")
977 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
978 (match_operand:SI 2 "s_register_operand" ""))
979 (const_int -1)))
980 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 981 "TARGET_32BIT"
d795fb69 982 [(set (match_dup 3) (match_dup 1))
983 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
984 "
985 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
986")
987
604f3a0a 988(define_expand "addsf3"
989 [(set (match_operand:SF 0 "s_register_operand" "")
990 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 991 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 992 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 993 "
a2cd141b 994 if (TARGET_MAVERICK
604f3a0a 995 && !cirrus_fp_register (operands[2], SFmode))
996 operands[2] = force_reg (SFmode, operands[2]);
997")
998
604f3a0a 999(define_expand "adddf3"
1000 [(set (match_operand:DF 0 "s_register_operand" "")
1001 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1002 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1003 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1004 "
a2cd141b 1005 if (TARGET_MAVERICK
604f3a0a 1006 && !cirrus_fp_register (operands[2], DFmode))
1007 operands[2] = force_reg (DFmode, operands[2]);
1008")
1009
cffb2a26 1010(define_expand "subdi3"
1011 [(parallel
1012 [(set (match_operand:DI 0 "s_register_operand" "")
1013 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1014 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1015 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1016 "TARGET_EITHER"
1017 "
a2cd141b 1018 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1019 && TARGET_32BIT
7d57ec45 1020 && cirrus_fp_register (operands[0], DImode)
1021 && cirrus_fp_register (operands[1], DImode))
1022 {
1023 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1024 DONE;
1025 }
1026
25f905c2 1027 if (TARGET_THUMB1)
cffb2a26 1028 {
1029 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1030 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1031 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1032 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1033 }
1034 "
1035)
1036
1037(define_insn "*arm_subdi3"
1038 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1039 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1040 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1041 (clobber (reg:CC CC_REGNUM))]
94829feb 1042 "TARGET_32BIT && !TARGET_NEON"
97499065 1043 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1044 [(set_attr "conds" "clob")
1045 (set_attr "length" "8")]
1046)
1047
1048(define_insn "*thumb_subdi3"
1049 [(set (match_operand:DI 0 "register_operand" "=l")
1050 (minus:DI (match_operand:DI 1 "register_operand" "0")
1051 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1052 (clobber (reg:CC CC_REGNUM))]
25f905c2 1053 "TARGET_THUMB1"
cffb2a26 1054 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1055 [(set_attr "length" "4")]
1056)
9c08d1fa 1057
f7fbdd4a 1058(define_insn "*subdi_di_zesidi"
cffb2a26 1059 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1060 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1061 (zero_extend:DI
cffb2a26 1062 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1063 (clobber (reg:CC CC_REGNUM))]
25f905c2 1064 "TARGET_32BIT"
97499065 1065 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1066 [(set_attr "conds" "clob")
1067 (set_attr "length" "8")]
1068)
9c08d1fa 1069
f7fbdd4a 1070(define_insn "*subdi_di_sesidi"
cffb2a26 1071 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1072 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1073 (sign_extend:DI
cffb2a26 1074 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1075 (clobber (reg:CC CC_REGNUM))]
25f905c2 1076 "TARGET_32BIT"
97499065 1077 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1078 [(set_attr "conds" "clob")
1079 (set_attr "length" "8")]
1080)
9c08d1fa 1081
f7fbdd4a 1082(define_insn "*subdi_zesidi_di"
cffb2a26 1083 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1084 (minus:DI (zero_extend:DI
cffb2a26 1085 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1086 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1087 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1088 "TARGET_ARM"
97499065 1089 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1090 [(set_attr "conds" "clob")
1091 (set_attr "length" "8")]
1092)
9c08d1fa 1093
f7fbdd4a 1094(define_insn "*subdi_sesidi_di"
cffb2a26 1095 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1096 (minus:DI (sign_extend:DI
cffb2a26 1097 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1098 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1099 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1100 "TARGET_ARM"
97499065 1101 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1102 [(set_attr "conds" "clob")
1103 (set_attr "length" "8")]
1104)
9c08d1fa 1105
f7fbdd4a 1106(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1107 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1108 (minus:DI (zero_extend:DI
cffb2a26 1109 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1110 (zero_extend:DI
cffb2a26 1111 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1112 (clobber (reg:CC CC_REGNUM))]
25f905c2 1113 "TARGET_32BIT"
1114 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1115 [(set_attr "conds" "clob")
1116 (set_attr "length" "8")]
1117)
b11cae9e 1118
87b22bf7 1119(define_expand "subsi3"
cffb2a26 1120 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1121 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1122 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1123 "TARGET_EITHER"
87b22bf7 1124 "
1125 if (GET_CODE (operands[1]) == CONST_INT)
1126 {
25f905c2 1127 if (TARGET_32BIT)
cffb2a26 1128 {
96f57e36 1129 arm_split_constant (MINUS, SImode, NULL_RTX,
1130 INTVAL (operands[1]), operands[0],
e1ba4a27 1131 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1132 DONE;
1133 }
25f905c2 1134 else /* TARGET_THUMB1 */
cffb2a26 1135 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1136 }
cffb2a26 1137 "
1138)
87b22bf7 1139
747b7458 1140(define_insn "thumb1_subsi3_insn"
cffb2a26 1141 [(set (match_operand:SI 0 "register_operand" "=l")
1142 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1143 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1144 "TARGET_THUMB1"
cffb2a26 1145 "sub\\t%0, %1, %2"
747b7458 1146 [(set_attr "length" "2")
1147 (set_attr "conds" "set")])
cffb2a26 1148
25f905c2 1149; ??? Check Thumb-2 split length
a0f94409 1150(define_insn_and_split "*arm_subsi3_insn"
080c0b9a 1151 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
bccb5444 1152 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1153 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
25f905c2 1154 "TARGET_32BIT"
e2348bcb 1155 "@
87b22bf7 1156 rsb%?\\t%0, %2, %1
aaa37ad6 1157 sub%?\\t%0, %1, %2
080c0b9a 1158 sub%?\\t%0, %1, %2
1159 #
87b22bf7 1160 #"
080c0b9a 1161 "&& ((GET_CODE (operands[1]) == CONST_INT
1162 && !const_ok_for_arm (INTVAL (operands[1])))
1163 || (GET_CODE (operands[2]) == CONST_INT
1164 && !const_ok_for_arm (INTVAL (operands[2]))))"
87b22bf7 1165 [(clobber (const_int 0))]
1166 "
96f57e36 1167 arm_split_constant (MINUS, SImode, curr_insn,
1168 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1169 DONE;
cffb2a26 1170 "
080c0b9a 1171 [(set_attr "length" "4,4,4,16,16")
a0f94409 1172 (set_attr "predicable" "yes")]
1173)
1174
1175(define_peephole2
1176 [(match_scratch:SI 3 "r")
372575c7 1177 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1178 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1179 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1180 "TARGET_32BIT
a0f94409 1181 && !const_ok_for_arm (INTVAL (operands[1]))
1182 && const_ok_for_arm (~INTVAL (operands[1]))"
1183 [(set (match_dup 3) (match_dup 1))
1184 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1185 ""
cffb2a26 1186)
b11cae9e 1187
f7fbdd4a 1188(define_insn "*subsi3_compare0"
bd5b4116 1189 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1190 (compare:CC_NOOV
1191 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1192 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1193 (const_int 0)))
9c08d1fa 1194 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1195 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1196 "TARGET_32BIT"
e2348bcb 1197 "@
25f905c2 1198 sub%.\\t%0, %1, %2
1199 rsb%.\\t%0, %2, %1"
cffb2a26 1200 [(set_attr "conds" "set")]
1201)
9c08d1fa 1202
080c0b9a 1203(define_insn "*subsi3_compare"
1204 [(set (reg:CC CC_REGNUM)
1205 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1206 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1207 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1208 (minus:SI (match_dup 1) (match_dup 2)))]
1209 "TARGET_32BIT"
1210 "@
1211 sub%.\\t%0, %1, %2
1212 rsb%.\\t%0, %2, %1"
1213 [(set_attr "conds" "set")]
1214)
1215
25f905c2 1216(define_expand "decscc"
1217 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1218 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1219 (match_operator:SI 2 "arm_comparison_operator"
1220 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1221 "TARGET_32BIT"
1222 ""
1223)
1224
1225(define_insn "*arm_decscc"
cffb2a26 1226 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1227 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1228 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1229 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1230 "TARGET_ARM"
e2348bcb 1231 "@
215b30b3 1232 sub%d2\\t%0, %1, #1
1233 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1234 [(set_attr "conds" "use")
1235 (set_attr "length" "*,8")]
1236)
9c08d1fa 1237
604f3a0a 1238(define_expand "subsf3"
1239 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1240 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1241 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1242 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1243 "
a2cd141b 1244 if (TARGET_MAVERICK)
604f3a0a 1245 {
1246 if (!cirrus_fp_register (operands[1], SFmode))
1247 operands[1] = force_reg (SFmode, operands[1]);
1248 if (!cirrus_fp_register (operands[2], SFmode))
1249 operands[2] = force_reg (SFmode, operands[2]);
1250 }
1251")
1252
604f3a0a 1253(define_expand "subdf3"
1254 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1255 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1256 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1257 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1258 "
a2cd141b 1259 if (TARGET_MAVERICK)
604f3a0a 1260 {
1261 if (!cirrus_fp_register (operands[1], DFmode))
1262 operands[1] = force_reg (DFmode, operands[1]);
1263 if (!cirrus_fp_register (operands[2], DFmode))
1264 operands[2] = force_reg (DFmode, operands[2]);
1265 }
1266")
1267
b11cae9e 1268\f
1269;; Multiplication insns
1270
cffb2a26 1271(define_expand "mulsi3"
1272 [(set (match_operand:SI 0 "s_register_operand" "")
1273 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1274 (match_operand:SI 1 "s_register_operand" "")))]
1275 "TARGET_EITHER"
1276 ""
1277)
1278
9c08d1fa 1279;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1280(define_insn "*arm_mulsi3"
1281 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1282 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1283 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1284 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1285 "mul%?\\t%0, %2, %1"
a2cd141b 1286 [(set_attr "insn" "mul")
0d66636f 1287 (set_attr "predicable" "yes")]
cffb2a26 1288)
1289
58d7d654 1290(define_insn "*arm_mulsi3_v6"
1291 [(set (match_operand:SI 0 "s_register_operand" "=r")
1292 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1293 (match_operand:SI 2 "s_register_operand" "r")))]
1294 "TARGET_32BIT && arm_arch6"
1295 "mul%?\\t%0, %1, %2"
1296 [(set_attr "insn" "mul")
1297 (set_attr "predicable" "yes")]
1298)
1299
215b30b3 1300; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1301; 1 and 2; are the same, because reload will make operand 0 match
1302; operand 1 without realizing that this conflicts with operand 2. We fix
1303; this by adding another alternative to match this case, and then `reload'
1304; it ourselves. This alternative must come first.
cffb2a26 1305(define_insn "*thumb_mulsi3"
1306 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1307 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1308 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1309 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1310 "*
1311 if (which_alternative < 2)
20c4e896 1312 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1313 else
20c4e896 1314 return \"mul\\t%0, %2\";
cffb2a26 1315 "
1316 [(set_attr "length" "4,4,2")
a2cd141b 1317 (set_attr "insn" "mul")]
cffb2a26 1318)
b11cae9e 1319
58d7d654 1320(define_insn "*thumb_mulsi3_v6"
1321 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1322 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1323 (match_operand:SI 2 "register_operand" "l,0,0")))]
1324 "TARGET_THUMB1 && arm_arch6"
1325 "@
1490694c 1326 mul\\t%0, %2
1327 mul\\t%0, %1
58d7d654 1328 mul\\t%0, %1"
1329 [(set_attr "length" "2")
1330 (set_attr "insn" "mul")]
1331)
1332
f7fbdd4a 1333(define_insn "*mulsi3_compare0"
bd5b4116 1334 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1335 (compare:CC_NOOV (mult:SI
1336 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1337 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1338 (const_int 0)))
1339 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1340 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1341 "TARGET_ARM && !arm_arch6"
1342 "mul%.\\t%0, %2, %1"
1343 [(set_attr "conds" "set")
1344 (set_attr "insn" "muls")]
1345)
1346
1347(define_insn "*mulsi3_compare0_v6"
1348 [(set (reg:CC_NOOV CC_REGNUM)
1349 (compare:CC_NOOV (mult:SI
1350 (match_operand:SI 2 "s_register_operand" "r")
1351 (match_operand:SI 1 "s_register_operand" "r"))
1352 (const_int 0)))
1353 (set (match_operand:SI 0 "s_register_operand" "=r")
1354 (mult:SI (match_dup 2) (match_dup 1)))]
1355 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1356 "mul%.\\t%0, %2, %1"
cffb2a26 1357 [(set_attr "conds" "set")
a2cd141b 1358 (set_attr "insn" "muls")]
cffb2a26 1359)
9c08d1fa 1360
f7fbdd4a 1361(define_insn "*mulsi_compare0_scratch"
bd5b4116 1362 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1363 (compare:CC_NOOV (mult:SI
1364 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1365 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1366 (const_int 0)))
1367 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1368 "TARGET_ARM && !arm_arch6"
1369 "mul%.\\t%0, %2, %1"
1370 [(set_attr "conds" "set")
1371 (set_attr "insn" "muls")]
1372)
1373
1374(define_insn "*mulsi_compare0_scratch_v6"
1375 [(set (reg:CC_NOOV CC_REGNUM)
1376 (compare:CC_NOOV (mult:SI
1377 (match_operand:SI 2 "s_register_operand" "r")
1378 (match_operand:SI 1 "s_register_operand" "r"))
1379 (const_int 0)))
1380 (clobber (match_scratch:SI 0 "=r"))]
1381 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1382 "mul%.\\t%0, %2, %1"
cffb2a26 1383 [(set_attr "conds" "set")
a2cd141b 1384 (set_attr "insn" "muls")]
cffb2a26 1385)
9c08d1fa 1386
b11cae9e 1387;; Unnamed templates to match MLA instruction.
1388
f7fbdd4a 1389(define_insn "*mulsi3addsi"
9c08d1fa 1390 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1391 (plus:SI
9c08d1fa 1392 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1393 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1394 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1395 "TARGET_32BIT && !arm_arch6"
1396 "mla%?\\t%0, %2, %1, %3"
1397 [(set_attr "insn" "mla")
1398 (set_attr "predicable" "yes")]
1399)
1400
1401(define_insn "*mulsi3addsi_v6"
1402 [(set (match_operand:SI 0 "s_register_operand" "=r")
1403 (plus:SI
1404 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1405 (match_operand:SI 1 "s_register_operand" "r"))
1406 (match_operand:SI 3 "s_register_operand" "r")))]
1407 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1408 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1409 [(set_attr "insn" "mla")
0d66636f 1410 (set_attr "predicable" "yes")]
1411)
b11cae9e 1412
f7fbdd4a 1413(define_insn "*mulsi3addsi_compare0"
bd5b4116 1414 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1415 (compare:CC_NOOV
1416 (plus:SI (mult:SI
1417 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1418 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1419 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1420 (const_int 0)))
9c08d1fa 1421 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1422 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1423 (match_dup 3)))]
58d7d654 1424 "TARGET_ARM && arm_arch6"
1425 "mla%.\\t%0, %2, %1, %3"
1426 [(set_attr "conds" "set")
1427 (set_attr "insn" "mlas")]
1428)
1429
1430(define_insn "*mulsi3addsi_compare0_v6"
1431 [(set (reg:CC_NOOV CC_REGNUM)
1432 (compare:CC_NOOV
1433 (plus:SI (mult:SI
1434 (match_operand:SI 2 "s_register_operand" "r")
1435 (match_operand:SI 1 "s_register_operand" "r"))
1436 (match_operand:SI 3 "s_register_operand" "r"))
1437 (const_int 0)))
1438 (set (match_operand:SI 0 "s_register_operand" "=r")
1439 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1440 (match_dup 3)))]
1441 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1442 "mla%.\\t%0, %2, %1, %3"
0d66636f 1443 [(set_attr "conds" "set")
a2cd141b 1444 (set_attr "insn" "mlas")]
0d66636f 1445)
9c08d1fa 1446
f7fbdd4a 1447(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1448 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1449 (compare:CC_NOOV
1450 (plus:SI (mult:SI
1451 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1452 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1453 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1454 (const_int 0)))
9c08d1fa 1455 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1456 "TARGET_ARM && !arm_arch6"
1457 "mla%.\\t%0, %2, %1, %3"
1458 [(set_attr "conds" "set")
1459 (set_attr "insn" "mlas")]
1460)
1461
1462(define_insn "*mulsi3addsi_compare0_scratch_v6"
1463 [(set (reg:CC_NOOV CC_REGNUM)
1464 (compare:CC_NOOV
1465 (plus:SI (mult:SI
1466 (match_operand:SI 2 "s_register_operand" "r")
1467 (match_operand:SI 1 "s_register_operand" "r"))
1468 (match_operand:SI 3 "s_register_operand" "r"))
1469 (const_int 0)))
1470 (clobber (match_scratch:SI 0 "=r"))]
1471 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1472 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1473 [(set_attr "conds" "set")
a2cd141b 1474 (set_attr "insn" "mlas")]
cffb2a26 1475)
f7fbdd4a 1476
89545238 1477(define_insn "*mulsi3subsi"
1478 [(set (match_operand:SI 0 "s_register_operand" "=r")
1479 (minus:SI
1480 (match_operand:SI 3 "s_register_operand" "r")
1481 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1482 (match_operand:SI 1 "s_register_operand" "r"))))]
1483 "TARGET_32BIT && arm_arch_thumb2"
1484 "mls%?\\t%0, %2, %1, %3"
1485 [(set_attr "insn" "mla")
1486 (set_attr "predicable" "yes")]
1487)
1488
5cdca009 1489(define_expand "maddsidi4"
1490 [(set (match_operand:DI 0 "s_register_operand" "")
1491 (plus:DI
1492 (mult:DI
1493 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1494 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1495 (match_operand:DI 3 "s_register_operand" "")))]
1496 "TARGET_32BIT && arm_arch3m"
1497 "")
82b85d08 1498
1499(define_insn "*mulsidi3adddi"
fe8dbf85 1500 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1501 (plus:DI
215b30b3 1502 (mult:DI
fe8dbf85 1503 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1504 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1505 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1506 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1507 "smlal%?\\t%Q0, %R0, %3, %2"
1508 [(set_attr "insn" "smlal")
1509 (set_attr "predicable" "yes")]
1510)
1511
1512(define_insn "*mulsidi3adddi_v6"
1513 [(set (match_operand:DI 0 "s_register_operand" "=r")
1514 (plus:DI
1515 (mult:DI
1516 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1517 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1518 (match_operand:DI 1 "s_register_operand" "0")))]
1519 "TARGET_32BIT && arm_arch6"
fe8dbf85 1520 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1521 [(set_attr "insn" "smlal")
0d66636f 1522 (set_attr "predicable" "yes")]
1523)
82b85d08 1524
957788b0 1525;; 32x32->64 widening multiply.
1526;; As with mulsi3, the only difference between the v3-5 and v6+
1527;; versions of these patterns is the requirement that the output not
1528;; overlap the inputs, but that still means we have to have a named
1529;; expander and two different starred insns.
1530
1531(define_expand "mulsidi3"
1532 [(set (match_operand:DI 0 "s_register_operand" "")
1533 (mult:DI
1534 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1535 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1536 "TARGET_32BIT && arm_arch3m"
1537 ""
1538)
1539
1540(define_insn "*mulsidi3_nov6"
f7fbdd4a 1541 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1542 (mult:DI
1543 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1544 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1545 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1546 "smull%?\\t%Q0, %R0, %1, %2"
1547 [(set_attr "insn" "smull")
1548 (set_attr "predicable" "yes")]
1549)
1550
957788b0 1551(define_insn "*mulsidi3_v6"
58d7d654 1552 [(set (match_operand:DI 0 "s_register_operand" "=r")
1553 (mult:DI
1554 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1555 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1556 "TARGET_32BIT && arm_arch6"
97499065 1557 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1558 [(set_attr "insn" "smull")
0d66636f 1559 (set_attr "predicable" "yes")]
1560)
f7fbdd4a 1561
957788b0 1562(define_expand "umulsidi3"
1563 [(set (match_operand:DI 0 "s_register_operand" "")
1564 (mult:DI
1565 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1566 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1567 "TARGET_32BIT && arm_arch3m"
1568 ""
1569)
1570
1571(define_insn "*umulsidi3_nov6"
f7fbdd4a 1572 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1573 (mult:DI
1574 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1575 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1576 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1577 "umull%?\\t%Q0, %R0, %1, %2"
1578 [(set_attr "insn" "umull")
1579 (set_attr "predicable" "yes")]
1580)
1581
957788b0 1582(define_insn "*umulsidi3_v6"
58d7d654 1583 [(set (match_operand:DI 0 "s_register_operand" "=r")
1584 (mult:DI
1585 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1586 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1587 "TARGET_32BIT && arm_arch6"
97499065 1588 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1589 [(set_attr "insn" "umull")
0d66636f 1590 (set_attr "predicable" "yes")]
1591)
b11cae9e 1592
5cdca009 1593(define_expand "umaddsidi4"
1594 [(set (match_operand:DI 0 "s_register_operand" "")
1595 (plus:DI
1596 (mult:DI
1597 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1598 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1599 (match_operand:DI 3 "s_register_operand" "")))]
1600 "TARGET_32BIT && arm_arch3m"
1601 "")
82b85d08 1602
1603(define_insn "*umulsidi3adddi"
8ead09f9 1604 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1605 (plus:DI
215b30b3 1606 (mult:DI
fe8dbf85 1607 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1608 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1609 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1610 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1611 "umlal%?\\t%Q0, %R0, %3, %2"
1612 [(set_attr "insn" "umlal")
1613 (set_attr "predicable" "yes")]
1614)
1615
1616(define_insn "*umulsidi3adddi_v6"
1617 [(set (match_operand:DI 0 "s_register_operand" "=r")
1618 (plus:DI
1619 (mult:DI
1620 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1621 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1622 (match_operand:DI 1 "s_register_operand" "0")))]
1623 "TARGET_32BIT && arm_arch6"
fe8dbf85 1624 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1625 [(set_attr "insn" "umlal")
0d66636f 1626 (set_attr "predicable" "yes")]
1627)
82b85d08 1628
957788b0 1629(define_expand "smulsi3_highpart"
1630 [(parallel
1631 [(set (match_operand:SI 0 "s_register_operand" "")
1632 (truncate:SI
1633 (lshiftrt:DI
1634 (mult:DI
1635 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1636 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1637 (const_int 32))))
1638 (clobber (match_scratch:SI 3 ""))])]
1639 "TARGET_32BIT && arm_arch3m"
1640 ""
1641)
1642
1643(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1644 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1645 (truncate:SI
1646 (lshiftrt:DI
215b30b3 1647 (mult:DI
e5fea38e 1648 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1649 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1650 (const_int 32))))
1651 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1652 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1653 "smull%?\\t%3, %0, %2, %1"
1654 [(set_attr "insn" "smull")
1655 (set_attr "predicable" "yes")]
1656)
1657
957788b0 1658(define_insn "*smulsi3_highpart_v6"
58d7d654 1659 [(set (match_operand:SI 0 "s_register_operand" "=r")
1660 (truncate:SI
1661 (lshiftrt:DI
1662 (mult:DI
1663 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1664 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1665 (const_int 32))))
1666 (clobber (match_scratch:SI 3 "=r"))]
1667 "TARGET_32BIT && arm_arch6"
f082f1c4 1668 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1669 [(set_attr "insn" "smull")
0d66636f 1670 (set_attr "predicable" "yes")]
cffb2a26 1671)
f082f1c4 1672
957788b0 1673(define_expand "umulsi3_highpart"
1674 [(parallel
1675 [(set (match_operand:SI 0 "s_register_operand" "")
1676 (truncate:SI
1677 (lshiftrt:DI
1678 (mult:DI
1679 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1680 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1681 (const_int 32))))
1682 (clobber (match_scratch:SI 3 ""))])]
1683 "TARGET_32BIT && arm_arch3m"
1684 ""
1685)
1686
1687(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1688 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1689 (truncate:SI
1690 (lshiftrt:DI
215b30b3 1691 (mult:DI
e5fea38e 1692 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1693 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1694 (const_int 32))))
1695 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1696 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1697 "umull%?\\t%3, %0, %2, %1"
1698 [(set_attr "insn" "umull")
1699 (set_attr "predicable" "yes")]
1700)
1701
957788b0 1702(define_insn "*umulsi3_highpart_v6"
58d7d654 1703 [(set (match_operand:SI 0 "s_register_operand" "=r")
1704 (truncate:SI
1705 (lshiftrt:DI
1706 (mult:DI
1707 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1708 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1709 (const_int 32))))
1710 (clobber (match_scratch:SI 3 "=r"))]
1711 "TARGET_32BIT && arm_arch6"
f082f1c4 1712 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1713 [(set_attr "insn" "umull")
0d66636f 1714 (set_attr "predicable" "yes")]
cffb2a26 1715)
f082f1c4 1716
331beb1a 1717(define_insn "mulhisi3"
1718 [(set (match_operand:SI 0 "s_register_operand" "=r")
1719 (mult:SI (sign_extend:SI
1720 (match_operand:HI 1 "s_register_operand" "%r"))
1721 (sign_extend:SI
1722 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1723 "TARGET_DSP_MULTIPLY"
61a2d04c 1724 "smulbb%?\\t%0, %1, %2"
a2cd141b 1725 [(set_attr "insn" "smulxy")
fec538d9 1726 (set_attr "predicable" "yes")]
1727)
1728
1729(define_insn "*mulhisi3tb"
1730 [(set (match_operand:SI 0 "s_register_operand" "=r")
1731 (mult:SI (ashiftrt:SI
1732 (match_operand:SI 1 "s_register_operand" "r")
1733 (const_int 16))
1734 (sign_extend:SI
1735 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1736 "TARGET_DSP_MULTIPLY"
fec538d9 1737 "smultb%?\\t%0, %1, %2"
a2cd141b 1738 [(set_attr "insn" "smulxy")
fec538d9 1739 (set_attr "predicable" "yes")]
1740)
1741
1742(define_insn "*mulhisi3bt"
1743 [(set (match_operand:SI 0 "s_register_operand" "=r")
1744 (mult:SI (sign_extend:SI
1745 (match_operand:HI 1 "s_register_operand" "r"))
1746 (ashiftrt:SI
1747 (match_operand:SI 2 "s_register_operand" "r")
1748 (const_int 16))))]
25f905c2 1749 "TARGET_DSP_MULTIPLY"
fec538d9 1750 "smulbt%?\\t%0, %1, %2"
a2cd141b 1751 [(set_attr "insn" "smulxy")
fec538d9 1752 (set_attr "predicable" "yes")]
1753)
1754
1755(define_insn "*mulhisi3tt"
1756 [(set (match_operand:SI 0 "s_register_operand" "=r")
1757 (mult:SI (ashiftrt:SI
1758 (match_operand:SI 1 "s_register_operand" "r")
1759 (const_int 16))
1760 (ashiftrt:SI
1761 (match_operand:SI 2 "s_register_operand" "r")
1762 (const_int 16))))]
25f905c2 1763 "TARGET_DSP_MULTIPLY"
fec538d9 1764 "smultt%?\\t%0, %1, %2"
a2cd141b 1765 [(set_attr "insn" "smulxy")
fec538d9 1766 (set_attr "predicable" "yes")]
331beb1a 1767)
1768
5cdca009 1769(define_insn "maddhisi4"
331beb1a 1770 [(set (match_operand:SI 0 "s_register_operand" "=r")
5cdca009 1771 (plus:SI (match_operand:SI 3 "s_register_operand" "r")
331beb1a 1772 (mult:SI (sign_extend:SI
5cdca009 1773 (match_operand:HI 1 "s_register_operand" "%r"))
331beb1a 1774 (sign_extend:SI
5cdca009 1775 (match_operand:HI 2 "s_register_operand" "r")))))]
25f905c2 1776 "TARGET_DSP_MULTIPLY"
5cdca009 1777 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1778 [(set_attr "insn" "smlaxy")
fec538d9 1779 (set_attr "predicable" "yes")]
331beb1a 1780)
1781
5cdca009 1782(define_insn "*maddhidi4"
331beb1a 1783 [(set (match_operand:DI 0 "s_register_operand" "=r")
1784 (plus:DI
5cdca009 1785 (match_operand:DI 3 "s_register_operand" "0")
331beb1a 1786 (mult:DI (sign_extend:DI
5cdca009 1787 (match_operand:HI 1 "s_register_operand" "%r"))
331beb1a 1788 (sign_extend:DI
5cdca009 1789 (match_operand:HI 2 "s_register_operand" "r")))))]
25f905c2 1790 "TARGET_DSP_MULTIPLY"
5cdca009 1791 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1792 [(set_attr "insn" "smlalxy")
fec538d9 1793 (set_attr "predicable" "yes")])
331beb1a 1794
604f3a0a 1795(define_expand "mulsf3"
1796 [(set (match_operand:SF 0 "s_register_operand" "")
1797 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1798 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1799 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1800 "
a2cd141b 1801 if (TARGET_MAVERICK
604f3a0a 1802 && !cirrus_fp_register (operands[2], SFmode))
1803 operands[2] = force_reg (SFmode, operands[2]);
1804")
1805
604f3a0a 1806(define_expand "muldf3"
1807 [(set (match_operand:DF 0 "s_register_operand" "")
1808 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1809 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1810 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1811 "
a2cd141b 1812 if (TARGET_MAVERICK
604f3a0a 1813 && !cirrus_fp_register (operands[2], DFmode))
1814 operands[2] = force_reg (DFmode, operands[2]);
1815")
b11cae9e 1816\f
1817;; Division insns
1818
7db9af5d 1819(define_expand "divsf3"
1820 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1821 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1822 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1823 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1824 "")
9c08d1fa 1825
7db9af5d 1826(define_expand "divdf3"
1827 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1828 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1829 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1830 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1831 "")
b11cae9e 1832\f
1833;; Modulo insns
1834
7db9af5d 1835(define_expand "modsf3"
1836 [(set (match_operand:SF 0 "s_register_operand" "")
1837 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1838 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1839 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1840 "")
9c08d1fa 1841
7db9af5d 1842(define_expand "moddf3"
1843 [(set (match_operand:DF 0 "s_register_operand" "")
1844 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1845 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1846 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1847 "")
b11cae9e 1848\f
1849;; Boolean and,ior,xor insns
1850
f6ebffac 1851;; Split up double word logical operations
1852
1853;; Split up simple DImode logical operations. Simply perform the logical
1854;; operation on the upper and lower halves of the registers.
1855(define_split
1856 [(set (match_operand:DI 0 "s_register_operand" "")
1857 (match_operator:DI 6 "logical_binary_operator"
1858 [(match_operand:DI 1 "s_register_operand" "")
1859 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1860 "TARGET_32BIT && reload_completed
e2669ea7 1861 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1862 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1863 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1864 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1865 "
215b30b3 1866 {
1867 operands[3] = gen_highpart (SImode, operands[0]);
1868 operands[0] = gen_lowpart (SImode, operands[0]);
1869 operands[4] = gen_highpart (SImode, operands[1]);
1870 operands[1] = gen_lowpart (SImode, operands[1]);
1871 operands[5] = gen_highpart (SImode, operands[2]);
1872 operands[2] = gen_lowpart (SImode, operands[2]);
1873 }"
1874)
f6ebffac 1875
f6ebffac 1876(define_split
1877 [(set (match_operand:DI 0 "s_register_operand" "")
1878 (match_operator:DI 6 "logical_binary_operator"
1879 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1880 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1881 "TARGET_32BIT && reload_completed"
f6ebffac 1882 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1883 (set (match_dup 3) (match_op_dup:SI 6
1884 [(ashiftrt:SI (match_dup 2) (const_int 31))
1885 (match_dup 4)]))]
1886 "
215b30b3 1887 {
1888 operands[3] = gen_highpart (SImode, operands[0]);
1889 operands[0] = gen_lowpart (SImode, operands[0]);
1890 operands[4] = gen_highpart (SImode, operands[1]);
1891 operands[1] = gen_lowpart (SImode, operands[1]);
1892 operands[5] = gen_highpart (SImode, operands[2]);
1893 operands[2] = gen_lowpart (SImode, operands[2]);
1894 }"
1895)
f6ebffac 1896
f6ebffac 1897;; The zero extend of operand 2 means we can just copy the high part of
1898;; operand1 into operand0.
1899(define_split
1900 [(set (match_operand:DI 0 "s_register_operand" "")
1901 (ior:DI
1902 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1903 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1904 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1905 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1906 (set (match_dup 3) (match_dup 4))]
1907 "
215b30b3 1908 {
1909 operands[4] = gen_highpart (SImode, operands[1]);
1910 operands[3] = gen_highpart (SImode, operands[0]);
1911 operands[0] = gen_lowpart (SImode, operands[0]);
1912 operands[1] = gen_lowpart (SImode, operands[1]);
1913 }"
1914)
f6ebffac 1915
1916;; The zero extend of operand 2 means we can just copy the high part of
1917;; operand1 into operand0.
1918(define_split
1919 [(set (match_operand:DI 0 "s_register_operand" "")
1920 (xor:DI
1921 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1922 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1923 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1924 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1925 (set (match_dup 3) (match_dup 4))]
1926 "
215b30b3 1927 {
1928 operands[4] = gen_highpart (SImode, operands[1]);
1929 operands[3] = gen_highpart (SImode, operands[0]);
1930 operands[0] = gen_lowpart (SImode, operands[0]);
1931 operands[1] = gen_lowpart (SImode, operands[1]);
1932 }"
1933)
f6ebffac 1934
e2669ea7 1935(define_expand "anddi3"
1936 [(set (match_operand:DI 0 "s_register_operand" "")
1937 (and:DI (match_operand:DI 1 "s_register_operand" "")
1938 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1939 "TARGET_32BIT"
1940 ""
1941)
1942
1943(define_insn "*anddi3_insn"
cffb2a26 1944 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1945 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1946 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 1947 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 1948 "#"
215b30b3 1949 [(set_attr "length" "8")]
1950)
b11cae9e 1951
a0f94409 1952(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1953 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1954 (and:DI (zero_extend:DI
1955 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1956 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1957 "TARGET_32BIT"
f6ebffac 1958 "#"
25f905c2 1959 "TARGET_32BIT && reload_completed"
a0f94409 1960 ; The zero extend of operand 2 clears the high word of the output
1961 ; operand.
1962 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1963 (set (match_dup 3) (const_int 0))]
1964 "
1965 {
1966 operands[3] = gen_highpart (SImode, operands[0]);
1967 operands[0] = gen_lowpart (SImode, operands[0]);
1968 operands[1] = gen_lowpart (SImode, operands[1]);
1969 }"
215b30b3 1970 [(set_attr "length" "8")]
1971)
b11cae9e 1972
f7fbdd4a 1973(define_insn "*anddi_sesdi_di"
cffb2a26 1974 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1975 (and:DI (sign_extend:DI
1976 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1977 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1978 "TARGET_32BIT"
f6ebffac 1979 "#"
cffb2a26 1980 [(set_attr "length" "8")]
1981)
b11cae9e 1982
87b22bf7 1983(define_expand "andsi3"
cffb2a26 1984 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1985 (and:SI (match_operand:SI 1 "s_register_operand" "")
1986 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1987 "TARGET_EITHER"
87b22bf7 1988 "
25f905c2 1989 if (TARGET_32BIT)
87b22bf7 1990 {
cffb2a26 1991 if (GET_CODE (operands[2]) == CONST_INT)
1992 {
47b5b27b 1993 if (INTVAL (operands[2]) == 255 && arm_arch6)
1994 {
1995 operands[1] = convert_to_mode (QImode, operands[1], 1);
1996 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
1997 operands[1]));
1998 }
1999 else
2000 arm_split_constant (AND, SImode, NULL_RTX,
2001 INTVAL (operands[2]), operands[0],
2002 operands[1],
2003 optimize && can_create_pseudo_p ());
615caa51 2004
cffb2a26 2005 DONE;
2006 }
87b22bf7 2007 }
25f905c2 2008 else /* TARGET_THUMB1 */
cffb2a26 2009 {
2010 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2011 {
2012 rtx tmp = force_reg (SImode, operands[2]);
2013 if (rtx_equal_p (operands[0], operands[1]))
2014 operands[2] = tmp;
2015 else
2016 {
2017 operands[2] = operands[1];
2018 operands[1] = tmp;
2019 }
2020 }
cffb2a26 2021 else
2022 {
2023 int i;
2024
215b30b3 2025 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2026 {
215b30b3 2027 operands[2] = force_reg (SImode,
2028 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2029
747b7458 2030 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2031
2032 DONE;
2033 }
87b22bf7 2034
cffb2a26 2035 for (i = 9; i <= 31; i++)
2036 {
2037 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2038 {
2039 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2040 const0_rtx));
2041 DONE;
2042 }
215b30b3 2043 else if ((((HOST_WIDE_INT) 1) << i) - 1
2044 == ~INTVAL (operands[2]))
cffb2a26 2045 {
2046 rtx shift = GEN_INT (i);
2047 rtx reg = gen_reg_rtx (SImode);
2048
2049 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2050 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2051
2052 DONE;
2053 }
2054 }
2055
2056 operands[2] = force_reg (SImode, operands[2]);
2057 }
215b30b3 2058 }
2059 "
cffb2a26 2060)
2061
25f905c2 2062; ??? Check split length for Thumb-2
a0f94409 2063(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2064 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2065 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2066 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2067 "TARGET_32BIT"
5565501b 2068 "@
2069 and%?\\t%0, %1, %2
87b22bf7 2070 bic%?\\t%0, %1, #%B2
2071 #"
25f905c2 2072 "TARGET_32BIT
a0f94409 2073 && GET_CODE (operands[2]) == CONST_INT
2074 && !(const_ok_for_arm (INTVAL (operands[2]))
2075 || const_ok_for_arm (~INTVAL (operands[2])))"
2076 [(clobber (const_int 0))]
2077 "
96f57e36 2078 arm_split_constant (AND, SImode, curr_insn,
2079 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2080 DONE;
2081 "
0d66636f 2082 [(set_attr "length" "4,4,16")
2083 (set_attr "predicable" "yes")]
cffb2a26 2084)
2085
25f905c2 2086(define_insn "*thumb1_andsi3_insn"
cffb2a26 2087 [(set (match_operand:SI 0 "register_operand" "=l")
2088 (and:SI (match_operand:SI 1 "register_operand" "%0")
2089 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2090 "TARGET_THUMB1"
747b7458 2091 "and\\t%0, %2"
2092 [(set_attr "length" "2")
2093 (set_attr "conds" "set")])
87b22bf7 2094
f7fbdd4a 2095(define_insn "*andsi3_compare0"
bd5b4116 2096 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2097 (compare:CC_NOOV
2098 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2099 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2100 (const_int 0)))
cffb2a26 2101 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2102 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2103 "TARGET_32BIT"
5565501b 2104 "@
25f905c2 2105 and%.\\t%0, %1, %2
2106 bic%.\\t%0, %1, #%B2"
cffb2a26 2107 [(set_attr "conds" "set")]
2108)
9c08d1fa 2109
f7fbdd4a 2110(define_insn "*andsi3_compare0_scratch"
bd5b4116 2111 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2112 (compare:CC_NOOV
2113 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2114 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2115 (const_int 0)))
dd193d7c 2116 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2117 "TARGET_32BIT"
5565501b 2118 "@
2119 tst%?\\t%0, %1
25f905c2 2120 bic%.\\t%2, %0, #%B1"
0d66636f 2121 [(set_attr "conds" "set")]
2122)
9c08d1fa 2123
f7fbdd4a 2124(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2125 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2126 (compare:CC_NOOV (zero_extract:SI
2127 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2128 (match_operand 1 "const_int_operand" "n")
2129 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2130 (const_int 0)))]
25f905c2 2131 "TARGET_32BIT
cffb2a26 2132 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2133 && INTVAL (operands[1]) > 0
2134 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2135 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2136 "*
5c49a439 2137 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2138 << INTVAL (operands[2]));
40dbec34 2139 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2140 return \"\";
0d66636f 2141 "
2142 [(set_attr "conds" "set")]
2143)
9c08d1fa 2144
f4462328 2145(define_insn_and_split "*ne_zeroextractsi"
c4034607 2146 [(set (match_operand:SI 0 "s_register_operand" "=r")
2147 (ne:SI (zero_extract:SI
2148 (match_operand:SI 1 "s_register_operand" "r")
2149 (match_operand:SI 2 "const_int_operand" "n")
2150 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2151 (const_int 0)))
2152 (clobber (reg:CC CC_REGNUM))]
25f905c2 2153 "TARGET_32BIT
cffb2a26 2154 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2155 && INTVAL (operands[2]) > 0
2156 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2157 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2158 "#"
25f905c2 2159 "TARGET_32BIT
f4462328 2160 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2161 && INTVAL (operands[2]) > 0
2162 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2163 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2164 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2165 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2166 (const_int 0)))
2167 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2168 (set (match_dup 0)
2169 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2170 (match_dup 0) (const_int 1)))]
2171 "
2172 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2173 << INTVAL (operands[3]));
2174 "
2175 [(set_attr "conds" "clob")
25f905c2 2176 (set (attr "length")
2177 (if_then_else (eq_attr "is_thumb" "yes")
2178 (const_int 12)
2179 (const_int 8)))]
f4462328 2180)
2181
2182(define_insn_and_split "*ne_zeroextractsi_shifted"
2183 [(set (match_operand:SI 0 "s_register_operand" "=r")
2184 (ne:SI (zero_extract:SI
2185 (match_operand:SI 1 "s_register_operand" "r")
2186 (match_operand:SI 2 "const_int_operand" "n")
2187 (const_int 0))
2188 (const_int 0)))
2189 (clobber (reg:CC CC_REGNUM))]
2190 "TARGET_ARM"
2191 "#"
2192 "TARGET_ARM"
2193 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2194 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2195 (const_int 0)))
2196 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2197 (set (match_dup 0)
2198 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2199 (match_dup 0) (const_int 1)))]
2200 "
2201 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2202 "
2203 [(set_attr "conds" "clob")
2204 (set_attr "length" "8")]
2205)
2206
2207(define_insn_and_split "*ite_ne_zeroextractsi"
2208 [(set (match_operand:SI 0 "s_register_operand" "=r")
2209 (if_then_else:SI (ne (zero_extract:SI
2210 (match_operand:SI 1 "s_register_operand" "r")
2211 (match_operand:SI 2 "const_int_operand" "n")
2212 (match_operand:SI 3 "const_int_operand" "n"))
2213 (const_int 0))
2214 (match_operand:SI 4 "arm_not_operand" "rIK")
2215 (const_int 0)))
2216 (clobber (reg:CC CC_REGNUM))]
2217 "TARGET_ARM
2218 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2219 && INTVAL (operands[2]) > 0
2220 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2221 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2222 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2223 "#"
2224 "TARGET_ARM
2225 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2226 && INTVAL (operands[2]) > 0
2227 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2228 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2229 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2230 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2231 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2232 (const_int 0)))
2233 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2234 (set (match_dup 0)
2235 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2236 (match_dup 0) (match_dup 4)))]
2237 "
c4034607 2238 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2239 << INTVAL (operands[3]));
2240 "
2241 [(set_attr "conds" "clob")
2242 (set_attr "length" "8")]
2243)
2244
2245(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2246 [(set (match_operand:SI 0 "s_register_operand" "=r")
2247 (if_then_else:SI (ne (zero_extract:SI
2248 (match_operand:SI 1 "s_register_operand" "r")
2249 (match_operand:SI 2 "const_int_operand" "n")
2250 (const_int 0))
2251 (const_int 0))
2252 (match_operand:SI 3 "arm_not_operand" "rIK")
2253 (const_int 0)))
2254 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2255 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2256 "#"
f8d7bf2f 2257 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2258 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2259 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2260 (const_int 0)))
2261 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2262 (set (match_dup 0)
2263 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2264 (match_dup 0) (match_dup 3)))]
2265 "
2266 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2267 "
2268 [(set_attr "conds" "clob")
215b30b3 2269 (set_attr "length" "8")]
2270)
9c08d1fa 2271
58d6528b 2272(define_split
2273 [(set (match_operand:SI 0 "s_register_operand" "")
2274 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2275 (match_operand:SI 2 "const_int_operand" "")
2276 (match_operand:SI 3 "const_int_operand" "")))
2277 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2278 "TARGET_THUMB1"
58d6528b 2279 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2280 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2281 "{
2282 HOST_WIDE_INT temp = INTVAL (operands[2]);
2283
2284 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2285 operands[3] = GEN_INT (32 - temp);
2286 }"
2287)
2288
25f905c2 2289;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2290(define_split
2291 [(set (match_operand:SI 0 "s_register_operand" "")
2292 (match_operator:SI 1 "shiftable_operator"
2293 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2294 (match_operand:SI 3 "const_int_operand" "")
2295 (match_operand:SI 4 "const_int_operand" ""))
2296 (match_operand:SI 5 "s_register_operand" "")]))
2297 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2298 "TARGET_ARM"
2299 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2300 (set (match_dup 0)
2301 (match_op_dup 1
2302 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2303 (match_dup 5)]))]
2304 "{
2305 HOST_WIDE_INT temp = INTVAL (operands[3]);
2306
2307 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2308 operands[4] = GEN_INT (32 - temp);
2309 }"
2310)
2311
58d6528b 2312(define_split
2313 [(set (match_operand:SI 0 "s_register_operand" "")
2314 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2315 (match_operand:SI 2 "const_int_operand" "")
2316 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2317 "TARGET_THUMB1"
58d6528b 2318 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2319 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2320 "{
2321 HOST_WIDE_INT temp = INTVAL (operands[2]);
2322
2323 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2324 operands[3] = GEN_INT (32 - temp);
2325 }"
2326)
2327
d7863cfe 2328(define_split
2329 [(set (match_operand:SI 0 "s_register_operand" "")
2330 (match_operator:SI 1 "shiftable_operator"
2331 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2332 (match_operand:SI 3 "const_int_operand" "")
2333 (match_operand:SI 4 "const_int_operand" ""))
2334 (match_operand:SI 5 "s_register_operand" "")]))
2335 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2336 "TARGET_ARM"
2337 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2338 (set (match_dup 0)
2339 (match_op_dup 1
2340 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2341 (match_dup 5)]))]
2342 "{
2343 HOST_WIDE_INT temp = INTVAL (operands[3]);
2344
2345 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2346 operands[4] = GEN_INT (32 - temp);
2347 }"
2348)
2349
a42059fd 2350;;; ??? This pattern is bogus. If operand3 has bits outside the range
2351;;; represented by the bitfield, then this will produce incorrect results.
2352;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2353;;; which have a real bit-field insert instruction, the truncation happens
2354;;; in the bit-field insert instruction itself. Since arm does not have a
2355;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2356;;; the value before we insert. This loses some of the advantage of having
2357;;; this insv pattern, so this pattern needs to be reevalutated.
2358
8a18b90c 2359(define_expand "insv"
2360 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2361 (match_operand:SI 1 "general_operand" "")
2362 (match_operand:SI 2 "general_operand" ""))
19335226 2363 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2364 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2365 "
215b30b3 2366 {
2367 int start_bit = INTVAL (operands[2]);
2368 int width = INTVAL (operands[1]);
2369 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2370 rtx target, subtarget;
2371
8b054d5a 2372 if (arm_arch_thumb2)
2373 {
2374 bool use_bfi = TRUE;
2375
2376 if (GET_CODE (operands[3]) == CONST_INT)
2377 {
2378 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2379
2380 if (val == 0)
2381 {
2382 emit_insn (gen_insv_zero (operands[0], operands[1],
2383 operands[2]));
2384 DONE;
2385 }
2386
2387 /* See if the set can be done with a single orr instruction. */
2388 if (val == mask && const_ok_for_arm (val << start_bit))
2389 use_bfi = FALSE;
2390 }
2391
2392 if (use_bfi)
2393 {
2394 if (GET_CODE (operands[3]) != REG)
2395 operands[3] = force_reg (SImode, operands[3]);
2396
2397 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2398 operands[3]));
2399 DONE;
2400 }
2401 }
2402
3f8fde42 2403 target = copy_rtx (operands[0]);
215b30b3 2404 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2405 subreg as the final target. */
2406 if (GET_CODE (target) == SUBREG)
2407 {
2408 subtarget = gen_reg_rtx (SImode);
2409 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2410 < GET_MODE_SIZE (SImode))
2411 target = SUBREG_REG (target);
2412 }
2413 else
2414 subtarget = target;
8a18b90c 2415
215b30b3 2416 if (GET_CODE (operands[3]) == CONST_INT)
2417 {
2418 /* Since we are inserting a known constant, we may be able to
2419 reduce the number of bits that we have to clear so that
2420 the mask becomes simple. */
2421 /* ??? This code does not check to see if the new mask is actually
2422 simpler. It may not be. */
2423 rtx op1 = gen_reg_rtx (SImode);
2424 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2425 start of this pattern. */
2426 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2427 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2428
c5b3a71b 2429 emit_insn (gen_andsi3 (op1, operands[0],
2430 gen_int_mode (~mask2, SImode)));
215b30b3 2431 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2432 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2433 }
2434 else if (start_bit == 0
2435 && !(const_ok_for_arm (mask)
2436 || const_ok_for_arm (~mask)))
2437 {
2438 /* A Trick, since we are setting the bottom bits in the word,
2439 we can shift operand[3] up, operand[0] down, OR them together
2440 and rotate the result back again. This takes 3 insns, and
5910bb95 2441 the third might be mergeable into another op. */
215b30b3 2442 /* The shift up copes with the possibility that operand[3] is
2443 wider than the bitfield. */
2444 rtx op0 = gen_reg_rtx (SImode);
2445 rtx op1 = gen_reg_rtx (SImode);
2446
2447 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2448 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2449 emit_insn (gen_iorsi3 (op1, op1, op0));
2450 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2451 }
2452 else if ((width + start_bit == 32)
2453 && !(const_ok_for_arm (mask)
2454 || const_ok_for_arm (~mask)))
2455 {
2456 /* Similar trick, but slightly less efficient. */
8a18b90c 2457
215b30b3 2458 rtx op0 = gen_reg_rtx (SImode);
2459 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2460
215b30b3 2461 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2462 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2463 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2464 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2465 }
2466 else
2467 {
c5b3a71b 2468 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2469 rtx op1 = gen_reg_rtx (SImode);
2470 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2471
215b30b3 2472 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2473 {
2474 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2475
215b30b3 2476 emit_insn (gen_movsi (tmp, op0));
2477 op0 = tmp;
2478 }
8a18b90c 2479
215b30b3 2480 /* Mask out any bits in operand[3] that are not needed. */
2481 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2482
215b30b3 2483 if (GET_CODE (op0) == CONST_INT
2484 && (const_ok_for_arm (mask << start_bit)
2485 || const_ok_for_arm (~(mask << start_bit))))
2486 {
c5b3a71b 2487 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2488 emit_insn (gen_andsi3 (op2, operands[0], op0));
2489 }
2490 else
2491 {
2492 if (GET_CODE (op0) == CONST_INT)
2493 {
2494 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2495
215b30b3 2496 emit_insn (gen_movsi (tmp, op0));
2497 op0 = tmp;
2498 }
2499
2500 if (start_bit != 0)
2501 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2502
215b30b3 2503 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2504 }
8a18b90c 2505
215b30b3 2506 if (start_bit != 0)
2507 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2508
215b30b3 2509 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2510 }
f082f1c4 2511
215b30b3 2512 if (subtarget != target)
2513 {
2514 /* If TARGET is still a SUBREG, then it must be wider than a word,
2515 so we must be careful only to set the subword we were asked to. */
2516 if (GET_CODE (target) == SUBREG)
2517 emit_move_insn (target, subtarget);
2518 else
2519 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2520 }
8a18b90c 2521
215b30b3 2522 DONE;
2523 }"
2524)
8a18b90c 2525
8b054d5a 2526(define_insn "insv_zero"
2527 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2528 (match_operand:SI 1 "const_int_operand" "M")
2529 (match_operand:SI 2 "const_int_operand" "M"))
2530 (const_int 0))]
2531 "arm_arch_thumb2"
2532 "bfc%?\t%0, %2, %1"
2533 [(set_attr "length" "4")
2534 (set_attr "predicable" "yes")]
2535)
2536
2537(define_insn "insv_t2"
2538 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2539 (match_operand:SI 1 "const_int_operand" "M")
2540 (match_operand:SI 2 "const_int_operand" "M"))
2541 (match_operand:SI 3 "s_register_operand" "r"))]
2542 "arm_arch_thumb2"
2543 "bfi%?\t%0, %3, %2, %1"
2544 [(set_attr "length" "4")
2545 (set_attr "predicable" "yes")]
2546)
2547
215b30b3 2548; constants for op 2 will never be given to these patterns.
a0f94409 2549(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2550 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2551 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2552 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2553 "TARGET_32BIT"
f6ebffac 2554 "#"
e2669ea7 2555 "TARGET_32BIT && reload_completed
2556 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2557 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2558 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2559 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2560 "
2561 {
2562 operands[3] = gen_highpart (SImode, operands[0]);
2563 operands[0] = gen_lowpart (SImode, operands[0]);
2564 operands[4] = gen_highpart (SImode, operands[1]);
2565 operands[1] = gen_lowpart (SImode, operands[1]);
2566 operands[5] = gen_highpart (SImode, operands[2]);
2567 operands[2] = gen_lowpart (SImode, operands[2]);
2568 }"
0d66636f 2569 [(set_attr "length" "8")
2570 (set_attr "predicable" "yes")]
2571)
9c08d1fa 2572
a0f94409 2573(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2574 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2575 (and:DI (not:DI (zero_extend:DI
2576 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2577 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2578 "TARGET_32BIT"
e2348bcb 2579 "@
97499065 2580 bic%?\\t%Q0, %Q1, %2
f6ebffac 2581 #"
a0f94409 2582 ; (not (zero_extend ...)) allows us to just copy the high word from
2583 ; operand1 to operand0.
25f905c2 2584 "TARGET_32BIT
a0f94409 2585 && reload_completed
2586 && operands[0] != operands[1]"
5a097f7d 2587 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2588 (set (match_dup 3) (match_dup 4))]
2589 "
2590 {
2591 operands[3] = gen_highpart (SImode, operands[0]);
2592 operands[0] = gen_lowpart (SImode, operands[0]);
2593 operands[4] = gen_highpart (SImode, operands[1]);
2594 operands[1] = gen_lowpart (SImode, operands[1]);
2595 }"
0d66636f 2596 [(set_attr "length" "4,8")
2597 (set_attr "predicable" "yes")]
2598)
9c08d1fa 2599
a0f94409 2600(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2601 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2602 (and:DI (not:DI (sign_extend:DI
2603 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2604 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2605 "TARGET_32BIT"
f6ebffac 2606 "#"
25f905c2 2607 "TARGET_32BIT && reload_completed"
5a097f7d 2608 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2609 (set (match_dup 3) (and:SI (not:SI
2610 (ashiftrt:SI (match_dup 2) (const_int 31)))
2611 (match_dup 4)))]
2612 "
2613 {
2614 operands[3] = gen_highpart (SImode, operands[0]);
2615 operands[0] = gen_lowpart (SImode, operands[0]);
2616 operands[4] = gen_highpart (SImode, operands[1]);
2617 operands[1] = gen_lowpart (SImode, operands[1]);
2618 }"
0d66636f 2619 [(set_attr "length" "8")
2620 (set_attr "predicable" "yes")]
2621)
9c08d1fa 2622
8a18b90c 2623(define_insn "andsi_notsi_si"
9c08d1fa 2624 [(set (match_operand:SI 0 "s_register_operand" "=r")
2625 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2626 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2627 "TARGET_32BIT"
0d66636f 2628 "bic%?\\t%0, %1, %2"
2629 [(set_attr "predicable" "yes")]
2630)
b11cae9e 2631
747b7458 2632(define_insn "thumb1_bicsi3"
cffb2a26 2633 [(set (match_operand:SI 0 "register_operand" "=l")
2634 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2635 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2636 "TARGET_THUMB1"
747b7458 2637 "bic\\t%0, %1"
2638 [(set_attr "length" "2")
2639 (set_attr "conds" "set")])
cffb2a26 2640
8a18b90c 2641(define_insn "andsi_not_shiftsi_si"
a2cd141b 2642 [(set (match_operand:SI 0 "s_register_operand" "=r")
2643 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2644 [(match_operand:SI 2 "s_register_operand" "r")
2645 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2646 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2647 "TARGET_ARM"
6c4c2133 2648 "bic%?\\t%0, %1, %2%S4"
344495ea 2649 [(set_attr "predicable" "yes")
331beb1a 2650 (set_attr "shift" "2")
a2cd141b 2651 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2652 (const_string "alu_shift")
2653 (const_string "alu_shift_reg")))]
6c4c2133 2654)
8a18b90c 2655
f7fbdd4a 2656(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2657 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2658 (compare:CC_NOOV
2659 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2660 (match_operand:SI 1 "s_register_operand" "r"))
2661 (const_int 0)))
9c08d1fa 2662 (set (match_operand:SI 0 "s_register_operand" "=r")
2663 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2664 "TARGET_32BIT"
2665 "bic%.\\t%0, %1, %2"
0d66636f 2666 [(set_attr "conds" "set")]
2667)
9c08d1fa 2668
f7fbdd4a 2669(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2670 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2671 (compare:CC_NOOV
2672 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2673 (match_operand:SI 1 "s_register_operand" "r"))
2674 (const_int 0)))
9c08d1fa 2675 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2676 "TARGET_32BIT"
2677 "bic%.\\t%0, %1, %2"
0d66636f 2678 [(set_attr "conds" "set")]
2679)
9c08d1fa 2680
e2669ea7 2681(define_expand "iordi3"
2682 [(set (match_operand:DI 0 "s_register_operand" "")
2683 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2684 (match_operand:DI 2 "neon_logic_op2" "")))]
2685 "TARGET_32BIT"
2686 ""
2687)
2688
2689(define_insn "*iordi3_insn"
cffb2a26 2690 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2691 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2692 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2693 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2694 "#"
0d66636f 2695 [(set_attr "length" "8")
2696 (set_attr "predicable" "yes")]
cffb2a26 2697)
9c08d1fa 2698
f7fbdd4a 2699(define_insn "*iordi_zesidi_di"
9c08d1fa 2700 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2701 (ior:DI (zero_extend:DI
2702 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2703 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2704 "TARGET_32BIT"
e2348bcb 2705 "@
97499065 2706 orr%?\\t%Q0, %Q1, %2
f6ebffac 2707 #"
0d66636f 2708 [(set_attr "length" "4,8")
2709 (set_attr "predicable" "yes")]
cffb2a26 2710)
9c08d1fa 2711
f7fbdd4a 2712(define_insn "*iordi_sesidi_di"
9c08d1fa 2713 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2714 (ior:DI (sign_extend:DI
2715 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2716 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2717 "TARGET_32BIT"
f6ebffac 2718 "#"
0d66636f 2719 [(set_attr "length" "8")
2720 (set_attr "predicable" "yes")]
cffb2a26 2721)
9c08d1fa 2722
87b22bf7 2723(define_expand "iorsi3"
cffb2a26 2724 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2725 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2726 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2727 "TARGET_EITHER"
87b22bf7 2728 "
2729 if (GET_CODE (operands[2]) == CONST_INT)
2730 {
25f905c2 2731 if (TARGET_32BIT)
cffb2a26 2732 {
96f57e36 2733 arm_split_constant (IOR, SImode, NULL_RTX,
2734 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2735 optimize && can_create_pseudo_p ());
cffb2a26 2736 DONE;
2737 }
25f905c2 2738 else /* TARGET_THUMB1 */
923ffadb 2739 {
2740 rtx tmp = force_reg (SImode, operands[2]);
2741 if (rtx_equal_p (operands[0], operands[1]))
2742 operands[2] = tmp;
2743 else
2744 {
2745 operands[2] = operands[1];
2746 operands[1] = tmp;
2747 }
2748 }
87b22bf7 2749 }
cffb2a26 2750 "
2751)
87b22bf7 2752
d5d4dc8d 2753(define_insn_and_split "*iorsi3_insn"
2754 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2755 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2756 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2757 "TARGET_32BIT"
87b22bf7 2758 "@
2759 orr%?\\t%0, %1, %2
d5d4dc8d 2760 orn%?\\t%0, %1, #%B2
87b22bf7 2761 #"
d5d4dc8d 2762 "TARGET_32BIT
a0f94409 2763 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2764 && !(const_ok_for_arm (INTVAL (operands[2]))
2765 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2766 [(clobber (const_int 0))]
d5d4dc8d 2767{
96f57e36 2768 arm_split_constant (IOR, SImode, curr_insn,
2769 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2770 DONE;
d5d4dc8d 2771}
2772 [(set_attr "length" "4,4,16")
2773 (set_attr "arch" "32,t2,32")
2774 (set_attr "predicable" "yes")])
cffb2a26 2775
747b7458 2776(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2777 [(set (match_operand:SI 0 "register_operand" "=l")
2778 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2779 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2780 "TARGET_THUMB1"
747b7458 2781 "orr\\t%0, %2"
2782 [(set_attr "length" "2")
2783 (set_attr "conds" "set")])
9c08d1fa 2784
a0f94409 2785(define_peephole2
2786 [(match_scratch:SI 3 "r")
372575c7 2787 (set (match_operand:SI 0 "arm_general_register_operand" "")
2788 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2789 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2790 "TARGET_ARM
a0f94409 2791 && !const_ok_for_arm (INTVAL (operands[2]))
2792 && const_ok_for_arm (~INTVAL (operands[2]))"
2793 [(set (match_dup 3) (match_dup 2))
2794 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2795 ""
215b30b3 2796)
a0f94409 2797
f7fbdd4a 2798(define_insn "*iorsi3_compare0"
bd5b4116 2799 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2800 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2801 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2802 (const_int 0)))
2803 (set (match_operand:SI 0 "s_register_operand" "=r")
2804 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2805 "TARGET_32BIT"
2806 "orr%.\\t%0, %1, %2"
cffb2a26 2807 [(set_attr "conds" "set")]
2808)
9c08d1fa 2809
f7fbdd4a 2810(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2811 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2812 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2813 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2814 (const_int 0)))
2815 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2816 "TARGET_32BIT"
2817 "orr%.\\t%0, %1, %2"
0d66636f 2818 [(set_attr "conds" "set")]
2819)
9c08d1fa 2820
e2669ea7 2821(define_expand "xordi3"
2822 [(set (match_operand:DI 0 "s_register_operand" "")
2823 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2824 (match_operand:DI 2 "s_register_operand" "")))]
2825 "TARGET_32BIT"
2826 ""
2827)
2828
2829(define_insn "*xordi3_insn"
cffb2a26 2830 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2831 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2832 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2833 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2834 "#"
0d66636f 2835 [(set_attr "length" "8")
2836 (set_attr "predicable" "yes")]
cffb2a26 2837)
9c08d1fa 2838
f7fbdd4a 2839(define_insn "*xordi_zesidi_di"
9c08d1fa 2840 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2841 (xor:DI (zero_extend:DI
2842 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2843 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2844 "TARGET_32BIT"
e2348bcb 2845 "@
97499065 2846 eor%?\\t%Q0, %Q1, %2
f6ebffac 2847 #"
0d66636f 2848 [(set_attr "length" "4,8")
2849 (set_attr "predicable" "yes")]
cffb2a26 2850)
9c08d1fa 2851
f7fbdd4a 2852(define_insn "*xordi_sesidi_di"
9c08d1fa 2853 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2854 (xor:DI (sign_extend:DI
2855 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2856 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2857 "TARGET_32BIT"
f6ebffac 2858 "#"
0d66636f 2859 [(set_attr "length" "8")
2860 (set_attr "predicable" "yes")]
cffb2a26 2861)
9c08d1fa 2862
cffb2a26 2863(define_expand "xorsi3"
2864 [(set (match_operand:SI 0 "s_register_operand" "")
2865 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2866 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2867 "TARGET_EITHER"
923ffadb 2868 "if (GET_CODE (operands[2]) == CONST_INT)
2869 {
2870 if (TARGET_32BIT)
2871 {
2872 arm_split_constant (XOR, SImode, NULL_RTX,
2873 INTVAL (operands[2]), operands[0], operands[1],
2874 optimize && can_create_pseudo_p ());
2875 DONE;
2876 }
2877 else /* TARGET_THUMB1 */
2878 {
2879 rtx tmp = force_reg (SImode, operands[2]);
2880 if (rtx_equal_p (operands[0], operands[1]))
2881 operands[2] = tmp;
2882 else
2883 {
2884 operands[2] = operands[1];
2885 operands[1] = tmp;
2886 }
2887 }
2888 }"
cffb2a26 2889)
2890
2891(define_insn "*arm_xorsi3"
2892 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2893 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2894 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2895 "TARGET_32BIT"
cffb2a26 2896 "eor%?\\t%0, %1, %2"
0d66636f 2897 [(set_attr "predicable" "yes")]
cffb2a26 2898)
2899
747b7458 2900(define_insn "*thumb1_xorsi3_insn"
cffb2a26 2901 [(set (match_operand:SI 0 "register_operand" "=l")
2902 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2903 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2904 "TARGET_THUMB1"
747b7458 2905 "eor\\t%0, %2"
2906 [(set_attr "length" "2")
2907 (set_attr "conds" "set")])
9c08d1fa 2908
f7fbdd4a 2909(define_insn "*xorsi3_compare0"
bd5b4116 2910 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2911 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2912 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2913 (const_int 0)))
2914 (set (match_operand:SI 0 "s_register_operand" "=r")
2915 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2916 "TARGET_32BIT"
2917 "eor%.\\t%0, %1, %2"
0d66636f 2918 [(set_attr "conds" "set")]
2919)
9c08d1fa 2920
f7fbdd4a 2921(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2922 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2923 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2924 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2925 (const_int 0)))]
25f905c2 2926 "TARGET_32BIT"
40dbec34 2927 "teq%?\\t%0, %1"
cffb2a26 2928 [(set_attr "conds" "set")]
2929)
9c08d1fa 2930
215b30b3 2931; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2932; (NOT D) we can sometimes merge the final NOT into one of the following
2933; insns.
9c08d1fa 2934
2935(define_split
a058e94a 2936 [(set (match_operand:SI 0 "s_register_operand" "")
2937 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2938 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2939 (match_operand:SI 3 "arm_rhs_operand" "")))
2940 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2941 "TARGET_32BIT"
9c08d1fa 2942 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2943 (not:SI (match_dup 3))))
2944 (set (match_dup 0) (not:SI (match_dup 4)))]
2945 ""
2946)
2947
f7fbdd4a 2948(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2949 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 2950 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 2951 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2952 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2953 "TARGET_32BIT"
40dbec34 2954 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2955 [(set_attr "length" "8")
25f905c2 2956 (set_attr "ce_count" "2")
0d66636f 2957 (set_attr "predicable" "yes")]
cffb2a26 2958)
9c08d1fa 2959
25f905c2 2960; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2961; insns are available?
d7863cfe 2962(define_split
2963 [(set (match_operand:SI 0 "s_register_operand" "")
2964 (match_operator:SI 1 "logical_binary_operator"
2965 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2966 (match_operand:SI 3 "const_int_operand" "")
2967 (match_operand:SI 4 "const_int_operand" ""))
2968 (match_operator:SI 9 "logical_binary_operator"
2969 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2970 (match_operand:SI 6 "const_int_operand" ""))
2971 (match_operand:SI 7 "s_register_operand" "")])]))
2972 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2973 "TARGET_32BIT
d7863cfe 2974 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2975 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2976 [(set (match_dup 8)
2977 (match_op_dup 1
2978 [(ashift:SI (match_dup 2) (match_dup 4))
2979 (match_dup 5)]))
2980 (set (match_dup 0)
2981 (match_op_dup 1
2982 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2983 (match_dup 7)]))]
2984 "
2985 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2986")
2987
2988(define_split
2989 [(set (match_operand:SI 0 "s_register_operand" "")
2990 (match_operator:SI 1 "logical_binary_operator"
2991 [(match_operator:SI 9 "logical_binary_operator"
2992 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2993 (match_operand:SI 6 "const_int_operand" ""))
2994 (match_operand:SI 7 "s_register_operand" "")])
2995 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2996 (match_operand:SI 3 "const_int_operand" "")
2997 (match_operand:SI 4 "const_int_operand" ""))]))
2998 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2999 "TARGET_32BIT
d7863cfe 3000 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3001 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3002 [(set (match_dup 8)
3003 (match_op_dup 1
3004 [(ashift:SI (match_dup 2) (match_dup 4))
3005 (match_dup 5)]))
3006 (set (match_dup 0)
3007 (match_op_dup 1
3008 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3009 (match_dup 7)]))]
3010 "
3011 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3012")
3013
3014(define_split
3015 [(set (match_operand:SI 0 "s_register_operand" "")
3016 (match_operator:SI 1 "logical_binary_operator"
3017 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3018 (match_operand:SI 3 "const_int_operand" "")
3019 (match_operand:SI 4 "const_int_operand" ""))
3020 (match_operator:SI 9 "logical_binary_operator"
3021 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3022 (match_operand:SI 6 "const_int_operand" ""))
3023 (match_operand:SI 7 "s_register_operand" "")])]))
3024 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3025 "TARGET_32BIT
d7863cfe 3026 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3027 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3028 [(set (match_dup 8)
3029 (match_op_dup 1
3030 [(ashift:SI (match_dup 2) (match_dup 4))
3031 (match_dup 5)]))
3032 (set (match_dup 0)
3033 (match_op_dup 1
3034 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3035 (match_dup 7)]))]
3036 "
3037 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3038")
3039
3040(define_split
3041 [(set (match_operand:SI 0 "s_register_operand" "")
3042 (match_operator:SI 1 "logical_binary_operator"
3043 [(match_operator:SI 9 "logical_binary_operator"
3044 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3045 (match_operand:SI 6 "const_int_operand" ""))
3046 (match_operand:SI 7 "s_register_operand" "")])
3047 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3048 (match_operand:SI 3 "const_int_operand" "")
3049 (match_operand:SI 4 "const_int_operand" ""))]))
3050 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3051 "TARGET_32BIT
d7863cfe 3052 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3053 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3054 [(set (match_dup 8)
3055 (match_op_dup 1
3056 [(ashift:SI (match_dup 2) (match_dup 4))
3057 (match_dup 5)]))
3058 (set (match_dup 0)
3059 (match_op_dup 1
3060 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3061 (match_dup 7)]))]
3062 "
3063 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3064")
9c08d1fa 3065\f
3066
3067;; Minimum and maximum insns
3068
8b9dc177 3069(define_expand "smaxsi3"
3070 [(parallel [
3071 (set (match_operand:SI 0 "s_register_operand" "")
3072 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3073 (match_operand:SI 2 "arm_rhs_operand" "")))
3074 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3075 "TARGET_32BIT"
8b9dc177 3076 "
8774928b 3077 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3078 {
3079 /* No need for a clobber of the condition code register here. */
3080 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3081 gen_rtx_SMAX (SImode, operands[1],
3082 operands[2])));
3083 DONE;
3084 }
3085")
3086
3087(define_insn "*smax_0"
3088 [(set (match_operand:SI 0 "s_register_operand" "=r")
3089 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3090 (const_int 0)))]
25f905c2 3091 "TARGET_32BIT"
8b9dc177 3092 "bic%?\\t%0, %1, %1, asr #31"
3093 [(set_attr "predicable" "yes")]
3094)
3095
8774928b 3096(define_insn "*smax_m1"
3097 [(set (match_operand:SI 0 "s_register_operand" "=r")
3098 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3099 (const_int -1)))]
25f905c2 3100 "TARGET_32BIT"
8774928b 3101 "orr%?\\t%0, %1, %1, asr #31"
3102 [(set_attr "predicable" "yes")]
3103)
3104
25f905c2 3105(define_insn "*arm_smax_insn"
8b9dc177 3106 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3107 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3108 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3109 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3110 "TARGET_ARM"
e2348bcb 3111 "@
3112 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3113 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3114 [(set_attr "conds" "clob")
8b9dc177 3115 (set_attr "length" "8,12")]
cffb2a26 3116)
9c08d1fa 3117
8b9dc177 3118(define_expand "sminsi3"
3119 [(parallel [
3120 (set (match_operand:SI 0 "s_register_operand" "")
3121 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3122 (match_operand:SI 2 "arm_rhs_operand" "")))
3123 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3124 "TARGET_32BIT"
8b9dc177 3125 "
3126 if (operands[2] == const0_rtx)
3127 {
3128 /* No need for a clobber of the condition code register here. */
3129 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3130 gen_rtx_SMIN (SImode, operands[1],
3131 operands[2])));
3132 DONE;
3133 }
3134")
3135
3136(define_insn "*smin_0"
3137 [(set (match_operand:SI 0 "s_register_operand" "=r")
3138 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3139 (const_int 0)))]
25f905c2 3140 "TARGET_32BIT"
8b9dc177 3141 "and%?\\t%0, %1, %1, asr #31"
3142 [(set_attr "predicable" "yes")]
3143)
3144
25f905c2 3145(define_insn "*arm_smin_insn"
8b9dc177 3146 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3147 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3148 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3149 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3150 "TARGET_ARM"
e2348bcb 3151 "@
3152 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3153 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3154 [(set_attr "conds" "clob")
8b9dc177 3155 (set_attr "length" "8,12")]
0d66636f 3156)
9c08d1fa 3157
25f905c2 3158(define_expand "umaxsi3"
3159 [(parallel [
3160 (set (match_operand:SI 0 "s_register_operand" "")
3161 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3162 (match_operand:SI 2 "arm_rhs_operand" "")))
3163 (clobber (reg:CC CC_REGNUM))])]
3164 "TARGET_32BIT"
3165 ""
3166)
3167
3168(define_insn "*arm_umaxsi3"
9c08d1fa 3169 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3170 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3171 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3172 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3173 "TARGET_ARM"
e2348bcb 3174 "@
3175 cmp\\t%1, %2\;movcc\\t%0, %2
3176 cmp\\t%1, %2\;movcs\\t%0, %1
3177 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3178 [(set_attr "conds" "clob")
3179 (set_attr "length" "8,8,12")]
3180)
9c08d1fa 3181
25f905c2 3182(define_expand "uminsi3"
3183 [(parallel [
3184 (set (match_operand:SI 0 "s_register_operand" "")
3185 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3186 (match_operand:SI 2 "arm_rhs_operand" "")))
3187 (clobber (reg:CC CC_REGNUM))])]
3188 "TARGET_32BIT"
3189 ""
3190)
3191
3192(define_insn "*arm_uminsi3"
9c08d1fa 3193 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3194 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3195 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3196 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3197 "TARGET_ARM"
e2348bcb 3198 "@
3199 cmp\\t%1, %2\;movcs\\t%0, %2
3200 cmp\\t%1, %2\;movcc\\t%0, %1
3201 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3202 [(set_attr "conds" "clob")
3203 (set_attr "length" "8,8,12")]
3204)
9c08d1fa 3205
8a18b90c 3206(define_insn "*store_minmaxsi"
9c08d1fa 3207 [(set (match_operand:SI 0 "memory_operand" "=m")
3208 (match_operator:SI 3 "minmax_operator"
3209 [(match_operand:SI 1 "s_register_operand" "r")
3210 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3211 (clobber (reg:CC CC_REGNUM))]
25f905c2 3212 "TARGET_32BIT"
9c08d1fa 3213 "*
dc55b8a9 3214 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3215 operands[1], operands[2]);
e2348bcb 3216 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3217 if (TARGET_THUMB2)
3218 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3219 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3220 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3221 return \"\";
0d66636f 3222 "
3223 [(set_attr "conds" "clob")
25f905c2 3224 (set (attr "length")
3225 (if_then_else (eq_attr "is_thumb" "yes")
3226 (const_int 14)
3227 (const_int 12)))
0d66636f 3228 (set_attr "type" "store1")]
3229)
9c08d1fa 3230
8a18b90c 3231; Reject the frame pointer in operand[1], since reloading this after
3232; it has been eliminated can cause carnage.
f7fbdd4a 3233(define_insn "*minmax_arithsi"
9c08d1fa 3234 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3235 (match_operator:SI 4 "shiftable_operator"
3236 [(match_operator:SI 5 "minmax_operator"
3237 [(match_operand:SI 2 "s_register_operand" "r,r")
3238 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3239 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3240 (clobber (reg:CC CC_REGNUM))]
25f905c2 3241 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3242 "*
0d66636f 3243 {
3244 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3245 bool need_else;
3246
3247 if (which_alternative != 0 || operands[3] != const0_rtx
3248 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3249 need_else = true;
3250 else
3251 need_else = false;
0d66636f 3252
dc55b8a9 3253 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3254 operands[2], operands[3]);
0d66636f 3255 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3256 if (TARGET_THUMB2)
3257 {
3258 if (need_else)
3259 output_asm_insn (\"ite\\t%d5\", operands);
3260 else
3261 output_asm_insn (\"it\\t%d5\", operands);
3262 }
0d66636f 3263 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3264 if (need_else)
0d66636f 3265 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3266 return \"\";
215b30b3 3267 }"
0d66636f 3268 [(set_attr "conds" "clob")
25f905c2 3269 (set (attr "length")
3270 (if_then_else (eq_attr "is_thumb" "yes")
3271 (const_int 14)
3272 (const_int 12)))]
0d66636f 3273)
9c08d1fa 3274
b11cae9e 3275\f
3276;; Shift and rotation insns
3277
a2cd141b 3278(define_expand "ashldi3"
3279 [(set (match_operand:DI 0 "s_register_operand" "")
3280 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3281 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3282 "TARGET_32BIT"
a2cd141b 3283 "
3284 if (GET_CODE (operands[2]) == CONST_INT)
3285 {
3286 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3287 {
3288 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3289 DONE;
3290 }
3291 /* Ideally we shouldn't fail here if we could know that operands[1]
3292 ends up already living in an iwmmxt register. Otherwise it's
3293 cheaper to have the alternate code being generated than moving
1d60d981 3294 values to iwmmxt regs and back. */
a2cd141b 3295 FAIL;
3296 }
3297 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3298 FAIL;
3299 "
3300)
3301
3302(define_insn "arm_ashldi3_1bit"
3303 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3304 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3305 (const_int 1)))
3306 (clobber (reg:CC CC_REGNUM))]
25f905c2 3307 "TARGET_32BIT"
a2cd141b 3308 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3309 [(set_attr "conds" "clob")
3310 (set_attr "length" "8")]
3311)
3312
87b22bf7 3313(define_expand "ashlsi3"
cffb2a26 3314 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3315 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3316 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3317 "TARGET_EITHER"
87b22bf7 3318 "
3319 if (GET_CODE (operands[2]) == CONST_INT
3320 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3321 {
3322 emit_insn (gen_movsi (operands[0], const0_rtx));
3323 DONE;
3324 }
cffb2a26 3325 "
3326)
3327
25f905c2 3328(define_insn "*thumb1_ashlsi3"
cffb2a26 3329 [(set (match_operand:SI 0 "register_operand" "=l,l")
3330 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3331 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3332 "TARGET_THUMB1"
cffb2a26 3333 "lsl\\t%0, %1, %2"
747b7458 3334 [(set_attr "length" "2")
3335 (set_attr "conds" "set")])
b11cae9e 3336
a2cd141b 3337(define_expand "ashrdi3"
3338 [(set (match_operand:DI 0 "s_register_operand" "")
3339 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3340 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3341 "TARGET_32BIT"
a2cd141b 3342 "
3343 if (GET_CODE (operands[2]) == CONST_INT)
3344 {
3345 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3346 {
3347 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3348 DONE;
3349 }
3350 /* Ideally we shouldn't fail here if we could know that operands[1]
3351 ends up already living in an iwmmxt register. Otherwise it's
3352 cheaper to have the alternate code being generated than moving
1d60d981 3353 values to iwmmxt regs and back. */
a2cd141b 3354 FAIL;
3355 }
3356 else if (!TARGET_REALLY_IWMMXT)
3357 FAIL;
3358 "
3359)
3360
3361(define_insn "arm_ashrdi3_1bit"
3362 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3363 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3364 (const_int 1)))
3365 (clobber (reg:CC CC_REGNUM))]
25f905c2 3366 "TARGET_32BIT"
a2cd141b 3367 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3368 [(set_attr "conds" "clob")
3369 (set_attr "length" "8")]
3370)
3371
87b22bf7 3372(define_expand "ashrsi3"
cffb2a26 3373 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3374 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3375 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3376 "TARGET_EITHER"
87b22bf7 3377 "
3378 if (GET_CODE (operands[2]) == CONST_INT
3379 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3380 operands[2] = GEN_INT (31);
cffb2a26 3381 "
3382)
3383
25f905c2 3384(define_insn "*thumb1_ashrsi3"
cffb2a26 3385 [(set (match_operand:SI 0 "register_operand" "=l,l")
3386 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3387 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3388 "TARGET_THUMB1"
cffb2a26 3389 "asr\\t%0, %1, %2"
747b7458 3390 [(set_attr "length" "2")
3391 (set_attr "conds" "set")])
b11cae9e 3392
a2cd141b 3393(define_expand "lshrdi3"
3394 [(set (match_operand:DI 0 "s_register_operand" "")
3395 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3396 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3397 "TARGET_32BIT"
a2cd141b 3398 "
3399 if (GET_CODE (operands[2]) == CONST_INT)
3400 {
3401 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3402 {
3403 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3404 DONE;
3405 }
3406 /* Ideally we shouldn't fail here if we could know that operands[1]
3407 ends up already living in an iwmmxt register. Otherwise it's
3408 cheaper to have the alternate code being generated than moving
1d60d981 3409 values to iwmmxt regs and back. */
a2cd141b 3410 FAIL;
3411 }
3412 else if (!TARGET_REALLY_IWMMXT)
3413 FAIL;
3414 "
3415)
3416
3417(define_insn "arm_lshrdi3_1bit"
3418 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3419 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3420 (const_int 1)))
3421 (clobber (reg:CC CC_REGNUM))]
25f905c2 3422 "TARGET_32BIT"
a2cd141b 3423 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3424 [(set_attr "conds" "clob")
3425 (set_attr "length" "8")]
3426)
3427
87b22bf7 3428(define_expand "lshrsi3"
cffb2a26 3429 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3430 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3431 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3432 "TARGET_EITHER"
87b22bf7 3433 "
3434 if (GET_CODE (operands[2]) == CONST_INT
3435 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3436 {
3437 emit_insn (gen_movsi (operands[0], const0_rtx));
3438 DONE;
3439 }
cffb2a26 3440 "
3441)
3442
25f905c2 3443(define_insn "*thumb1_lshrsi3"
cffb2a26 3444 [(set (match_operand:SI 0 "register_operand" "=l,l")
3445 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3446 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3447 "TARGET_THUMB1"
cffb2a26 3448 "lsr\\t%0, %1, %2"
747b7458 3449 [(set_attr "length" "2")
3450 (set_attr "conds" "set")])
b11cae9e 3451
87b22bf7 3452(define_expand "rotlsi3"
cffb2a26 3453 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3454 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3455 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3456 "TARGET_32BIT"
87b22bf7 3457 "
3458 if (GET_CODE (operands[2]) == CONST_INT)
3459 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3460 else
b11cae9e 3461 {
87b22bf7 3462 rtx reg = gen_reg_rtx (SImode);
3463 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3464 operands[2] = reg;
b11cae9e 3465 }
cffb2a26 3466 "
3467)
9c08d1fa 3468
87b22bf7 3469(define_expand "rotrsi3"
cffb2a26 3470 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3471 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3472 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3473 "TARGET_EITHER"
87b22bf7 3474 "
25f905c2 3475 if (TARGET_32BIT)
cffb2a26 3476 {
3477 if (GET_CODE (operands[2]) == CONST_INT
3478 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3479 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3480 }
25f905c2 3481 else /* TARGET_THUMB1 */
cffb2a26 3482 {
3483 if (GET_CODE (operands [2]) == CONST_INT)
3484 operands [2] = force_reg (SImode, operands[2]);
3485 }
3486 "
3487)
87b22bf7 3488
25f905c2 3489(define_insn "*thumb1_rotrsi3"
cffb2a26 3490 [(set (match_operand:SI 0 "register_operand" "=l")
3491 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3492 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3493 "TARGET_THUMB1"
cffb2a26 3494 "ror\\t%0, %0, %2"
3495 [(set_attr "length" "2")]
3496)
3497
3498(define_insn "*arm_shiftsi3"
3499 [(set (match_operand:SI 0 "s_register_operand" "=r")
3500 (match_operator:SI 3 "shift_operator"
3501 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3502 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3503 "TARGET_32BIT"
3504 "* return arm_output_shift(operands, 0);"
344495ea 3505 [(set_attr "predicable" "yes")
331beb1a 3506 (set_attr "shift" "1")
a2cd141b 3507 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3508 (const_string "alu_shift")
3509 (const_string "alu_shift_reg")))]
6c4c2133 3510)
87b22bf7 3511
f7fbdd4a 3512(define_insn "*shiftsi3_compare0"
bd5b4116 3513 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3514 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3515 [(match_operand:SI 1 "s_register_operand" "r")
3516 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3517 (const_int 0)))
3518 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3519 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3520 "TARGET_32BIT"
3521 "* return arm_output_shift(operands, 1);"
344495ea 3522 [(set_attr "conds" "set")
331beb1a 3523 (set_attr "shift" "1")
a2cd141b 3524 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3525 (const_string "alu_shift")
3526 (const_string "alu_shift_reg")))]
0d66636f 3527)
9c08d1fa 3528
f7fbdd4a 3529(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3530 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3531 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3532 [(match_operand:SI 1 "s_register_operand" "r")
3533 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3534 (const_int 0)))
3535 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3536 "TARGET_32BIT"
3537 "* return arm_output_shift(operands, 1);"
344495ea 3538 [(set_attr "conds" "set")
a2cd141b 3539 (set_attr "shift" "1")]
0d66636f 3540)
9c08d1fa 3541
d5d4dc8d 3542(define_insn "*not_shiftsi"
3543 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3544 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3545 [(match_operand:SI 1 "s_register_operand" "r,r")
3546 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3547 "TARGET_32BIT"
6c4c2133 3548 "mvn%?\\t%0, %1%S3"
344495ea 3549 [(set_attr "predicable" "yes")
331beb1a 3550 (set_attr "shift" "1")
d5d4dc8d 3551 (set_attr "arch" "32,a")
3552 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3553
d5d4dc8d 3554(define_insn "*not_shiftsi_compare0"
bd5b4116 3555 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3556 (compare:CC_NOOV
3557 (not:SI (match_operator:SI 3 "shift_operator"
3558 [(match_operand:SI 1 "s_register_operand" "r,r")
3559 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3560 (const_int 0)))
3561 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3562 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3563 "TARGET_32BIT"
25f905c2 3564 "mvn%.\\t%0, %1%S3"
344495ea 3565 [(set_attr "conds" "set")
331beb1a 3566 (set_attr "shift" "1")
d5d4dc8d 3567 (set_attr "arch" "32,a")
3568 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3569
d5d4dc8d 3570(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3571 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3572 (compare:CC_NOOV
3573 (not:SI (match_operator:SI 3 "shift_operator"
3574 [(match_operand:SI 1 "s_register_operand" "r,r")
3575 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3576 (const_int 0)))
3577 (clobber (match_scratch:SI 0 "=r,r"))]
3578 "TARGET_32BIT"
25f905c2 3579 "mvn%.\\t%0, %1%S3"
344495ea 3580 [(set_attr "conds" "set")
331beb1a 3581 (set_attr "shift" "1")
d5d4dc8d 3582 (set_attr "arch" "32,a")
3583 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3584
cffb2a26 3585;; We don't really have extzv, but defining this using shifts helps
3586;; to reduce register pressure later on.
3587
3588(define_expand "extzv"
3589 [(set (match_dup 4)
3590 (ashift:SI (match_operand:SI 1 "register_operand" "")
3591 (match_operand:SI 2 "const_int_operand" "")))
3592 (set (match_operand:SI 0 "register_operand" "")
3593 (lshiftrt:SI (match_dup 4)
215b30b3 3594 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3595 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3596 "
3597 {
3598 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3599 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3600
8b054d5a 3601 if (arm_arch_thumb2)
3602 {
3603 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3604 operands[3]));
3605 DONE;
3606 }
3607
cffb2a26 3608 operands[3] = GEN_INT (rshift);
3609
3610 if (lshift == 0)
3611 {
3612 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3613 DONE;
3614 }
3615
3616 operands[2] = GEN_INT (lshift);
3617 operands[4] = gen_reg_rtx (SImode);
215b30b3 3618 }"
cffb2a26 3619)
3620
8b054d5a 3621(define_insn "extv"
3622 [(set (match_operand:SI 0 "s_register_operand" "=r")
3623 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3624 (match_operand:SI 2 "const_int_operand" "M")
3625 (match_operand:SI 3 "const_int_operand" "M")))]
3626 "arm_arch_thumb2"
3627 "sbfx%?\t%0, %1, %3, %2"
3628 [(set_attr "length" "4")
3629 (set_attr "predicable" "yes")]
3630)
3631
3632(define_insn "extzv_t2"
3633 [(set (match_operand:SI 0 "s_register_operand" "=r")
3634 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3635 (match_operand:SI 2 "const_int_operand" "M")
3636 (match_operand:SI 3 "const_int_operand" "M")))]
3637 "arm_arch_thumb2"
3638 "ubfx%?\t%0, %1, %3, %2"
3639 [(set_attr "length" "4")
3640 (set_attr "predicable" "yes")]
3641)
3642
b11cae9e 3643\f
3644;; Unary arithmetic insns
3645
cffb2a26 3646(define_expand "negdi2"
3647 [(parallel
8135a42b 3648 [(set (match_operand:DI 0 "s_register_operand" "")
3649 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3650 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3651 "TARGET_EITHER"
8135a42b 3652 ""
cffb2a26 3653)
3654
3655;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 3656;; The first alternative allows the common case of a *full* overlap.
cffb2a26 3657(define_insn "*arm_negdi2"
3658 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3659 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 3660 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3661 "TARGET_ARM"
97499065 3662 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3663 [(set_attr "conds" "clob")
3664 (set_attr "length" "8")]
3665)
b11cae9e 3666
25f905c2 3667(define_insn "*thumb1_negdi2"
8135a42b 3668 [(set (match_operand:DI 0 "register_operand" "=&l")
3669 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3670 (clobber (reg:CC CC_REGNUM))]
25f905c2 3671 "TARGET_THUMB1"
cffb2a26 3672 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3673 [(set_attr "length" "6")]
3674)
3675
3676(define_expand "negsi2"
3677 [(set (match_operand:SI 0 "s_register_operand" "")
3678 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3679 "TARGET_EITHER"
b11cae9e 3680 ""
cffb2a26 3681)
3682
3683(define_insn "*arm_negsi2"
3684 [(set (match_operand:SI 0 "s_register_operand" "=r")
3685 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3686 "TARGET_32BIT"
cffb2a26 3687 "rsb%?\\t%0, %1, #0"
0d66636f 3688 [(set_attr "predicable" "yes")]
cffb2a26 3689)
3690
25f905c2 3691(define_insn "*thumb1_negsi2"
cffb2a26 3692 [(set (match_operand:SI 0 "register_operand" "=l")
3693 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3694 "TARGET_THUMB1"
cffb2a26 3695 "neg\\t%0, %1"
3696 [(set_attr "length" "2")]
3697)
b11cae9e 3698
604f3a0a 3699(define_expand "negsf2"
3700 [(set (match_operand:SF 0 "s_register_operand" "")
3701 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3702 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3703 ""
3704)
3705
3706(define_expand "negdf2"
3707 [(set (match_operand:DF 0 "s_register_operand" "")
3708 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3709 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3710 "")
3711
9c08d1fa 3712;; abssi2 doesn't really clobber the condition codes if a different register
3713;; is being set. To keep things simple, assume during rtl manipulations that
3714;; it does, but tell the final scan operator the truth. Similarly for
3715;; (neg (abs...))
3716
604f3a0a 3717(define_expand "abssi2"
3718 [(parallel
3719 [(set (match_operand:SI 0 "s_register_operand" "")
3720 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3721 (clobber (match_dup 2))])]
3722 "TARGET_EITHER"
3723 "
25f905c2 3724 if (TARGET_THUMB1)
ba156559 3725 operands[2] = gen_rtx_SCRATCH (SImode);
3726 else
3727 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3728")
604f3a0a 3729
7d57ec45 3730(define_insn "*arm_abssi2"
ba156559 3731 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3732 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3733 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3734 "TARGET_ARM"
e2348bcb 3735 "@
3736 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3737 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3738 [(set_attr "conds" "clob,*")
331beb1a 3739 (set_attr "shift" "1")
0d66636f 3740 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3741 (set_attr "length" "8")]
3742)
9c08d1fa 3743
25f905c2 3744(define_insn_and_split "*thumb1_abssi2"
ba156559 3745 [(set (match_operand:SI 0 "s_register_operand" "=l")
3746 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3747 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3748 "TARGET_THUMB1"
ba156559 3749 "#"
25f905c2 3750 "TARGET_THUMB1 && reload_completed"
ba156559 3751 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3752 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3753 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3754 ""
3755 [(set_attr "length" "6")]
3756)
3757
3758(define_insn "*arm_neg_abssi2"
9c08d1fa 3759 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3760 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3761 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3762 "TARGET_ARM"
e2348bcb 3763 "@
3764 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3765 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3766 [(set_attr "conds" "clob,*")
331beb1a 3767 (set_attr "shift" "1")
0d66636f 3768 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3769 (set_attr "length" "8")]
3770)
b11cae9e 3771
25f905c2 3772(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3773 [(set (match_operand:SI 0 "s_register_operand" "=l")
3774 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3775 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3776 "TARGET_THUMB1"
ba156559 3777 "#"
25f905c2 3778 "TARGET_THUMB1 && reload_completed"
ba156559 3779 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3780 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3781 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3782 ""
3783 [(set_attr "length" "6")]
3784)
3785
604f3a0a 3786(define_expand "abssf2"
3787 [(set (match_operand:SF 0 "s_register_operand" "")
3788 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3789 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3790 "")
3791
604f3a0a 3792(define_expand "absdf2"
3793 [(set (match_operand:DF 0 "s_register_operand" "")
3794 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3795 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3796 "")
3797
7db9af5d 3798(define_expand "sqrtsf2"
3799 [(set (match_operand:SF 0 "s_register_operand" "")
3800 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3801 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3802 "")
9c08d1fa 3803
7db9af5d 3804(define_expand "sqrtdf2"
3805 [(set (match_operand:DF 0 "s_register_operand" "")
3806 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3807 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3808 "")
9c08d1fa 3809
a0f94409 3810(define_insn_and_split "one_cmpldi2"
9c08d1fa 3811 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3812 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3813 "TARGET_32BIT"
f6ebffac 3814 "#"
25f905c2 3815 "TARGET_32BIT && reload_completed"
a0f94409 3816 [(set (match_dup 0) (not:SI (match_dup 1)))
3817 (set (match_dup 2) (not:SI (match_dup 3)))]
3818 "
3819 {
3820 operands[2] = gen_highpart (SImode, operands[0]);
3821 operands[0] = gen_lowpart (SImode, operands[0]);
3822 operands[3] = gen_highpart (SImode, operands[1]);
3823 operands[1] = gen_lowpart (SImode, operands[1]);
3824 }"
0d66636f 3825 [(set_attr "length" "8")
3826 (set_attr "predicable" "yes")]
cffb2a26 3827)
b11cae9e 3828
cffb2a26 3829(define_expand "one_cmplsi2"
3830 [(set (match_operand:SI 0 "s_register_operand" "")
3831 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3832 "TARGET_EITHER"
b11cae9e 3833 ""
cffb2a26 3834)
3835
3836(define_insn "*arm_one_cmplsi2"
3837 [(set (match_operand:SI 0 "s_register_operand" "=r")
3838 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3839 "TARGET_32BIT"
cffb2a26 3840 "mvn%?\\t%0, %1"
0d66636f 3841 [(set_attr "predicable" "yes")]
cffb2a26 3842)
3843
25f905c2 3844(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3845 [(set (match_operand:SI 0 "register_operand" "=l")
3846 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3847 "TARGET_THUMB1"
cffb2a26 3848 "mvn\\t%0, %1"
3849 [(set_attr "length" "2")]
3850)
9c08d1fa 3851
f7fbdd4a 3852(define_insn "*notsi_compare0"
bd5b4116 3853 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3854 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3855 (const_int 0)))
3856 (set (match_operand:SI 0 "s_register_operand" "=r")
3857 (not:SI (match_dup 1)))]
25f905c2 3858 "TARGET_32BIT"
3859 "mvn%.\\t%0, %1"
cffb2a26 3860 [(set_attr "conds" "set")]
3861)
9c08d1fa 3862
f7fbdd4a 3863(define_insn "*notsi_compare0_scratch"
bd5b4116 3864 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3865 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3866 (const_int 0)))
3867 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3868 "TARGET_32BIT"
3869 "mvn%.\\t%0, %1"
cffb2a26 3870 [(set_attr "conds" "set")]
3871)
b11cae9e 3872\f
3873;; Fixed <--> Floating conversion insns
3874
9b8516be 3875(define_expand "floatsihf2"
3876 [(set (match_operand:HF 0 "general_operand" "")
3877 (float:HF (match_operand:SI 1 "general_operand" "")))]
3878 "TARGET_EITHER"
3879 "
3880 {
3881 rtx op1 = gen_reg_rtx (SFmode);
3882 expand_float (op1, operands[1], 0);
3883 op1 = convert_to_mode (HFmode, op1, 0);
3884 emit_move_insn (operands[0], op1);
3885 DONE;
3886 }"
3887)
3888
3889(define_expand "floatdihf2"
3890 [(set (match_operand:HF 0 "general_operand" "")
3891 (float:HF (match_operand:DI 1 "general_operand" "")))]
3892 "TARGET_EITHER"
3893 "
3894 {
3895 rtx op1 = gen_reg_rtx (SFmode);
3896 expand_float (op1, operands[1], 0);
3897 op1 = convert_to_mode (HFmode, op1, 0);
3898 emit_move_insn (operands[0], op1);
3899 DONE;
3900 }"
3901)
3902
604f3a0a 3903(define_expand "floatsisf2"
3904 [(set (match_operand:SF 0 "s_register_operand" "")
3905 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3906 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3907 "
a2cd141b 3908 if (TARGET_MAVERICK)
604f3a0a 3909 {
3910 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3911 DONE;
3912 }
3913")
3914
604f3a0a 3915(define_expand "floatsidf2"
3916 [(set (match_operand:DF 0 "s_register_operand" "")
3917 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 3918 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3919 "
a2cd141b 3920 if (TARGET_MAVERICK)
604f3a0a 3921 {
3922 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3923 DONE;
3924 }
3925")
3926
9b8516be 3927(define_expand "fix_trunchfsi2"
3928 [(set (match_operand:SI 0 "general_operand" "")
3929 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3930 "TARGET_EITHER"
3931 "
3932 {
3933 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3934 expand_fix (operands[0], op1, 0);
3935 DONE;
3936 }"
3937)
3938
3939(define_expand "fix_trunchfdi2"
3940 [(set (match_operand:DI 0 "general_operand" "")
3941 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3942 "TARGET_EITHER"
3943 "
3944 {
3945 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3946 expand_fix (operands[0], op1, 0);
3947 DONE;
3948 }"
3949)
3950
604f3a0a 3951(define_expand "fix_truncsfsi2"
3952 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3953 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3954 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3955 "
a2cd141b 3956 if (TARGET_MAVERICK)
604f3a0a 3957 {
3958 if (!cirrus_fp_register (operands[0], SImode))
3959 operands[0] = force_reg (SImode, operands[0]);
3960 if (!cirrus_fp_register (operands[1], SFmode))
3961 operands[1] = force_reg (SFmode, operands[0]);
3962 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3963 DONE;
3964 }
3965")
3966
604f3a0a 3967(define_expand "fix_truncdfsi2"
3968 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3969 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 3970 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3971 "
a2cd141b 3972 if (TARGET_MAVERICK)
604f3a0a 3973 {
3974 if (!cirrus_fp_register (operands[1], DFmode))
3975 operands[1] = force_reg (DFmode, operands[0]);
3976 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3977 DONE;
3978 }
3979")
3980
f544c6d2 3981;; Truncation insns
b11cae9e 3982
604f3a0a 3983(define_expand "truncdfsf2"
3984 [(set (match_operand:SF 0 "s_register_operand" "")
3985 (float_truncate:SF
3986 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3987 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3988 ""
3989)
9b8516be 3990
3991/* DFmode -> HFmode conversions have to go through SFmode. */
3992(define_expand "truncdfhf2"
3993 [(set (match_operand:HF 0 "general_operand" "")
3994 (float_truncate:HF
3995 (match_operand:DF 1 "general_operand" "")))]
3996 "TARGET_EITHER"
3997 "
3998 {
3999 rtx op1;
4000 op1 = convert_to_mode (SFmode, operands[1], 0);
4001 op1 = convert_to_mode (HFmode, op1, 0);
4002 emit_move_insn (operands[0], op1);
4003 DONE;
4004 }"
4005)
b11cae9e 4006\f
9c08d1fa 4007;; Zero and sign extension instructions.
b11cae9e 4008
25f905c2 4009(define_expand "zero_extendsidi2"
4010 [(set (match_operand:DI 0 "s_register_operand" "")
4011 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
4012 "TARGET_32BIT"
4013 ""
4014)
4015
4016(define_insn "*arm_zero_extendsidi2"
9c08d1fa 4017 [(set (match_operand:DI 0 "s_register_operand" "=r")
4018 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 4019 "TARGET_ARM"
9c08d1fa 4020 "*
0d66636f 4021 if (REGNO (operands[1])
4022 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
4023 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
4024 return \"mov%?\\t%R0, #0\";
4025 "
4026 [(set_attr "length" "8")
4027 (set_attr "predicable" "yes")]
4028)
9c08d1fa 4029
25f905c2 4030(define_expand "zero_extendqidi2"
4031 [(set (match_operand:DI 0 "s_register_operand" "")
4032 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
4033 "TARGET_32BIT"
4034 ""
4035)
4036
4037(define_insn "*arm_zero_extendqidi2"
cffb2a26 4038 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 4039 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 4040 "TARGET_ARM"
e2348bcb 4041 "@
97499065 4042 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
25f905c2 4043 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 4044 [(set_attr "length" "8")
0d66636f 4045 (set_attr "predicable" "yes")
a2cd141b 4046 (set_attr "type" "*,load_byte")
cffb2a26 4047 (set_attr "pool_range" "*,4092")
4048 (set_attr "neg_pool_range" "*,4084")]
4049)
9c08d1fa 4050
25f905c2 4051(define_expand "extendsidi2"
4052 [(set (match_operand:DI 0 "s_register_operand" "")
4053 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
4054 "TARGET_32BIT"
4055 ""
4056)
4057
4058(define_insn "*arm_extendsidi2"
9c08d1fa 4059 [(set (match_operand:DI 0 "s_register_operand" "=r")
4060 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 4061 "TARGET_ARM"
9c08d1fa 4062 "*
0d66636f 4063 if (REGNO (operands[1])
4064 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
4065 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
4066 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 4067 "
4068 [(set_attr "length" "8")
331beb1a 4069 (set_attr "shift" "1")
0d66636f 4070 (set_attr "predicable" "yes")]
4071)
9c08d1fa 4072
4073(define_expand "zero_extendhisi2"
ef51b8e1 4074 [(set (match_operand:SI 0 "s_register_operand" "")
4075 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4076 "TARGET_EITHER"
ef51b8e1 4077{
4078 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4079 {
ef51b8e1 4080 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4081 DONE;
25f7a26e 4082 }
ef51b8e1 4083 if (!arm_arch6 && !MEM_P (operands[1]))
4084 {
4085 rtx t = gen_lowpart (SImode, operands[1]);
4086 rtx tmp = gen_reg_rtx (SImode);
4087 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4088 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4089 DONE;
4090 }
4091})
9c08d1fa 4092
ef51b8e1 4093(define_split
4094 [(set (match_operand:SI 0 "register_operand" "")
747b7458 4095 (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
ef51b8e1 4096 "!TARGET_THUMB2 && !arm_arch6"
4097 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4098 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4099{
4100 operands[2] = gen_lowpart (SImode, operands[1]);
4101})
4102
4103(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4104 [(set (match_operand:SI 0 "register_operand" "=l,l")
4105 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4106 "TARGET_THUMB1"
a2cd141b 4107 "*
4108 rtx mem;
4109
ef51b8e1 4110 if (which_alternative == 0 && arm_arch6)
a2cd141b 4111 return \"uxth\\t%0, %1\";
ef51b8e1 4112 if (which_alternative == 0)
4113 return \"#\";
a2cd141b 4114
4115 mem = XEXP (operands[1], 0);
4116
4117 if (GET_CODE (mem) == CONST)
4118 mem = XEXP (mem, 0);
4119
4120 if (GET_CODE (mem) == LABEL_REF)
4121 return \"ldr\\t%0, %1\";
4122
4123 if (GET_CODE (mem) == PLUS)
4124 {
4125 rtx a = XEXP (mem, 0);
4126 rtx b = XEXP (mem, 1);
4127
4128 /* This can happen due to bugs in reload. */
4129 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4130 {
4131 rtx ops[2];
4132 ops[0] = operands[0];
4133 ops[1] = a;
4134
4135 output_asm_insn (\"mov %0, %1\", ops);
4136
4137 XEXP (mem, 0) = operands[0];
4138 }
4139
4140 else if ( GET_CODE (a) == LABEL_REF
4141 && GET_CODE (b) == CONST_INT)
4142 return \"ldr\\t%0, %1\";
4143 }
4144
4145 return \"ldrh\\t%0, %1\";
4146 "
ef51b8e1 4147 [(set_attr_alternative "length"
4148 [(if_then_else (eq_attr "is_arch6" "yes")
4149 (const_int 2) (const_int 4))
4150 (const_int 4)])
a2cd141b 4151 (set_attr "type" "alu_shift,load_byte")
4152 (set_attr "pool_range" "*,60")]
4153)
4154
cffb2a26 4155(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4156 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4157 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4158 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4159 "@
4160 #
4161 ldr%(h%)\\t%0, %1"
4162 [(set_attr "type" "alu_shift,load_byte")
0d66636f 4163 (set_attr "predicable" "yes")
ef51b8e1 4164 (set_attr "pool_range" "*,256")
4165 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4166)
f7fbdd4a 4167
a2cd141b 4168(define_insn "*arm_zero_extendhisi2_v6"
4169 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4170 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4171 "TARGET_ARM && arm_arch6"
4172 "@
4173 uxth%?\\t%0, %1
25f905c2 4174 ldr%(h%)\\t%0, %1"
a2cd141b 4175 [(set_attr "type" "alu_shift,load_byte")
4176 (set_attr "predicable" "yes")
4177 (set_attr "pool_range" "*,256")
4178 (set_attr "neg_pool_range" "*,244")]
4179)
4180
4181(define_insn "*arm_zero_extendhisi2addsi"
4182 [(set (match_operand:SI 0 "s_register_operand" "=r")
4183 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4184 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4185 "TARGET_INT_SIMD"
a2cd141b 4186 "uxtah%?\\t%0, %2, %1"
4187 [(set_attr "type" "alu_shift")
4188 (set_attr "predicable" "yes")]
4189)
4190
87b22bf7 4191(define_expand "zero_extendqisi2"
cffb2a26 4192 [(set (match_operand:SI 0 "s_register_operand" "")
4193 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4194 "TARGET_EITHER"
ef51b8e1 4195{
4196 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4197 {
ef51b8e1 4198 emit_insn (gen_andsi3 (operands[0],
4199 gen_lowpart (SImode, operands[1]),
4200 GEN_INT (255)));
4201 DONE;
4202 }
4203 if (!arm_arch6 && !MEM_P (operands[1]))
4204 {
4205 rtx t = gen_lowpart (SImode, operands[1]);
4206 rtx tmp = gen_reg_rtx (SImode);
4207 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4208 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4209 DONE;
4210 }
4211})
cffb2a26 4212
ef51b8e1 4213(define_split
4214 [(set (match_operand:SI 0 "register_operand" "")
4215 (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4216 "!arm_arch6"
4217 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4218 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4219{
4220 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4221 if (TARGET_ARM)
4222 {
4223 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4224 DONE;
4225 }
ef51b8e1 4226})
9c08d1fa 4227
25f905c2 4228(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4229 [(set (match_operand:SI 0 "register_operand" "=l,l")
4230 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4231 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4232 "@
4233 #
4234 ldrb\\t%0, %1"
4235 [(set_attr "length" "4,2")
4236 (set_attr "type" "alu_shift,load_byte")
4237 (set_attr "pool_range" "*,32")]
cffb2a26 4238)
4239
25f905c2 4240(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4241 [(set (match_operand:SI 0 "register_operand" "=l,l")
4242 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4243 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4244 "@
4245 uxtb\\t%0, %1
4246 ldrb\\t%0, %1"
4247 [(set_attr "length" "2,2")
4248 (set_attr "type" "alu_shift,load_byte")
4249 (set_attr "pool_range" "*,32")]
4250)
4251
cffb2a26 4252(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4253 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4254 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4255 "TARGET_ARM && !arm_arch6"
ef51b8e1 4256 "@
4257 #
4258 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4259 [(set_attr "length" "8,4")
4260 (set_attr "type" "alu_shift,load_byte")
0d66636f 4261 (set_attr "predicable" "yes")
ef51b8e1 4262 (set_attr "pool_range" "*,4096")
4263 (set_attr "neg_pool_range" "*,4084")]
cffb2a26 4264)
87b22bf7 4265
a2cd141b 4266(define_insn "*arm_zero_extendqisi2_v6"
4267 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4268 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4269 "TARGET_ARM && arm_arch6"
4270 "@
25f905c2 4271 uxtb%(%)\\t%0, %1
4272 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4273 [(set_attr "type" "alu_shift,load_byte")
4274 (set_attr "predicable" "yes")
4275 (set_attr "pool_range" "*,4096")
4276 (set_attr "neg_pool_range" "*,4084")]
4277)
4278
4279(define_insn "*arm_zero_extendqisi2addsi"
4280 [(set (match_operand:SI 0 "s_register_operand" "=r")
4281 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4282 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4283 "TARGET_INT_SIMD"
a2cd141b 4284 "uxtab%?\\t%0, %2, %1"
4285 [(set_attr "predicable" "yes")
bcaec148 4286 (set_attr "insn" "xtab")
a2cd141b 4287 (set_attr "type" "alu_shift")]
4288)
4289
87b22bf7 4290(define_split
4291 [(set (match_operand:SI 0 "s_register_operand" "")
4292 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4293 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4294 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4295 [(set (match_dup 2) (match_dup 1))
4296 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4297 ""
4298)
9c08d1fa 4299
8a4d25d6 4300(define_split
4301 [(set (match_operand:SI 0 "s_register_operand" "")
4302 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4303 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4304 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4305 [(set (match_dup 2) (match_dup 1))
4306 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4307 ""
4308)
4309
1c274529 4310
4311(define_split
4312 [(set (match_operand:SI 0 "s_register_operand" "")
4313 (ior_xor:SI (and:SI (ashift:SI
4314 (match_operand:SI 1 "s_register_operand" "")
4315 (match_operand:SI 2 "const_int_operand" ""))
4316 (match_operand:SI 3 "const_int_operand" ""))
4317 (zero_extend:SI
4318 (match_operator 5 "subreg_lowpart_operator"
4319 [(match_operand:SI 4 "s_register_operand" "")]))))]
4320 "TARGET_32BIT
63787642 4321 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4322 == (GET_MODE_MASK (GET_MODE (operands[5]))
4323 & (GET_MODE_MASK (GET_MODE (operands[5]))
4324 << (INTVAL (operands[2])))))"
4325 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4326 (match_dup 4)))
4327 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4328 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4329)
4330
f7fbdd4a 4331(define_insn "*compareqi_eq0"
bd5b4116 4332 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4333 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4334 (const_int 0)))]
25f905c2 4335 "TARGET_32BIT"
87b22bf7 4336 "tst\\t%0, #255"
cffb2a26 4337 [(set_attr "conds" "set")]
4338)
b11cae9e 4339
b11cae9e 4340(define_expand "extendhisi2"
ef51b8e1 4341 [(set (match_operand:SI 0 "s_register_operand" "")
4342 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4343 "TARGET_EITHER"
ef51b8e1 4344{
4345 if (TARGET_THUMB1)
4346 {
4347 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4348 DONE;
4349 }
4350 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4351 {
4352 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4353 DONE;
4354 }
ed29c566 4355
ef51b8e1 4356 if (!arm_arch6 && !MEM_P (operands[1]))
4357 {
4358 rtx t = gen_lowpart (SImode, operands[1]);
4359 rtx tmp = gen_reg_rtx (SImode);
4360 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4361 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4362 DONE;
4363 }
4364})
cffb2a26 4365
ef51b8e1 4366(define_split
4367 [(parallel
4368 [(set (match_operand:SI 0 "register_operand" "")
4369 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4370 (clobber (match_scratch:SI 2 ""))])]
4371 "!arm_arch6"
4372 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4373 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4374{
4375 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4376})
25f7a26e 4377
a2cd141b 4378;; We used to have an early-clobber on the scratch register here.
4379;; However, there's a bug somewhere in reload which means that this
4380;; can be partially ignored during spill allocation if the memory
ed29c566 4381;; address also needs reloading; this causes us to die later on when
a2cd141b 4382;; we try to verify the operands. Fortunately, we don't really need
4383;; the early-clobber: we can always use operand 0 if operand 2
4384;; overlaps the address.
ef51b8e1 4385(define_insn "thumb1_extendhisi2"
a2cd141b 4386 [(set (match_operand:SI 0 "register_operand" "=l,l")
4387 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4388 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4389 "TARGET_THUMB1"
a2cd141b 4390 "*
4391 {
4392 rtx ops[4];
4393 rtx mem;
4394
ef51b8e1 4395 if (which_alternative == 0 && !arm_arch6)
4396 return \"#\";
a2cd141b 4397 if (which_alternative == 0)
4398 return \"sxth\\t%0, %1\";
4399
4400 mem = XEXP (operands[1], 0);
4401
4402 /* This code used to try to use 'V', and fix the address only if it was
4403 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4404 range of QImode offsets, and offsettable_address_p does a QImode
4405 address check. */
4406
4407 if (GET_CODE (mem) == CONST)
4408 mem = XEXP (mem, 0);
4409
4410 if (GET_CODE (mem) == LABEL_REF)
4411 return \"ldr\\t%0, %1\";
4412
4413 if (GET_CODE (mem) == PLUS)
4414 {
4415 rtx a = XEXP (mem, 0);
4416 rtx b = XEXP (mem, 1);
4417
4418 if (GET_CODE (a) == LABEL_REF
4419 && GET_CODE (b) == CONST_INT)
4420 return \"ldr\\t%0, %1\";
4421
4422 if (GET_CODE (b) == REG)
4423 return \"ldrsh\\t%0, %1\";
4424
4425 ops[1] = a;
4426 ops[2] = b;
4427 }
4428 else
4429 {
4430 ops[1] = mem;
4431 ops[2] = const0_rtx;
4432 }
4433
ed29c566 4434 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4435
4436 ops[0] = operands[0];
4437 if (reg_mentioned_p (operands[2], ops[1]))
4438 ops[3] = ops[0];
4439 else
4440 ops[3] = operands[2];
4441 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4442 return \"\";
4443 }"
ef51b8e1 4444 [(set_attr_alternative "length"
4445 [(if_then_else (eq_attr "is_arch6" "yes")
4446 (const_int 2) (const_int 4))
4447 (const_int 4)])
a2cd141b 4448 (set_attr "type" "alu_shift,load_byte")
4449 (set_attr "pool_range" "*,1020")]
4450)
4451
25f905c2 4452;; This pattern will only be used when ldsh is not available
25f7a26e 4453(define_expand "extendhisi2_mem"
eab14235 4454 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4455 (set (match_dup 3)
eab14235 4456 (zero_extend:SI (match_dup 7)))
25f7a26e 4457 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4458 (set (match_operand:SI 0 "" "")
4459 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4460 "TARGET_ARM"
25f7a26e 4461 "
215b30b3 4462 {
4463 rtx mem1, mem2;
4464 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4465
788fcce0 4466 mem1 = change_address (operands[1], QImode, addr);
4467 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4468 operands[0] = gen_lowpart (SImode, operands[0]);
4469 operands[1] = mem1;
4470 operands[2] = gen_reg_rtx (SImode);
4471 operands[3] = gen_reg_rtx (SImode);
4472 operands[6] = gen_reg_rtx (SImode);
4473 operands[7] = mem2;
25f7a26e 4474
215b30b3 4475 if (BYTES_BIG_ENDIAN)
4476 {
4477 operands[4] = operands[2];
4478 operands[5] = operands[3];
4479 }
4480 else
4481 {
4482 operands[4] = operands[3];
4483 operands[5] = operands[2];
4484 }
4485 }"
4486)
b11cae9e 4487
ef51b8e1 4488(define_split
4489 [(set (match_operand:SI 0 "register_operand" "")
4490 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4491 "!arm_arch6"
4492 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4493 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4494{
4495 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4496})
4497
a2cd141b 4498(define_insn "*arm_extendhisi2"
ef51b8e1 4499 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4500 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4501 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4502 "@
4503 #
4504 ldr%(sh%)\\t%0, %1"
4505 [(set_attr "length" "8,4")
4506 (set_attr "type" "alu_shift,load_byte")
0d66636f 4507 (set_attr "predicable" "yes")
ef51b8e1 4508 (set_attr "pool_range" "*,256")
4509 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4510)
f7fbdd4a 4511
25f905c2 4512;; ??? Check Thumb-2 pool range
a2cd141b 4513(define_insn "*arm_extendhisi2_v6"
4514 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4515 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4516 "TARGET_32BIT && arm_arch6"
a2cd141b 4517 "@
4518 sxth%?\\t%0, %1
25f905c2 4519 ldr%(sh%)\\t%0, %1"
a2cd141b 4520 [(set_attr "type" "alu_shift,load_byte")
4521 (set_attr "predicable" "yes")
4522 (set_attr "pool_range" "*,256")
4523 (set_attr "neg_pool_range" "*,244")]
4524)
4525
4526(define_insn "*arm_extendhisi2addsi"
4527 [(set (match_operand:SI 0 "s_register_operand" "=r")
4528 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4529 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4530 "TARGET_INT_SIMD"
a2cd141b 4531 "sxtah%?\\t%0, %2, %1"
4532)
4533
c8f69309 4534(define_expand "extendqihi2"
4535 [(set (match_dup 2)
bed7d9a5 4536 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4537 (const_int 24)))
9c08d1fa 4538 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4539 (ashiftrt:SI (match_dup 2)
4540 (const_int 24)))]
cffb2a26 4541 "TARGET_ARM"
c8f69309 4542 "
215b30b3 4543 {
4544 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4545 {
4546 emit_insn (gen_rtx_SET (VOIDmode,
4547 operands[0],
4548 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4549 DONE;
4550 }
4551 if (!s_register_operand (operands[1], QImode))
4552 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4553 operands[0] = gen_lowpart (SImode, operands[0]);
4554 operands[1] = gen_lowpart (SImode, operands[1]);
4555 operands[2] = gen_reg_rtx (SImode);
4556 }"
4557)
f7fbdd4a 4558
25f905c2 4559(define_insn "*arm_extendqihi_insn"
b4e8a300 4560 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4561 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4562 "TARGET_ARM && arm_arch4"
25f905c2 4563 "ldr%(sb%)\\t%0, %1"
a2cd141b 4564 [(set_attr "type" "load_byte")
0d66636f 4565 (set_attr "predicable" "yes")
cffb2a26 4566 (set_attr "pool_range" "256")
4567 (set_attr "neg_pool_range" "244")]
4568)
3fc2009e 4569
b11cae9e 4570(define_expand "extendqisi2"
ef51b8e1 4571 [(set (match_operand:SI 0 "s_register_operand" "")
4572 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 4573 "TARGET_EITHER"
ef51b8e1 4574{
4575 if (!arm_arch4 && MEM_P (operands[1]))
4576 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4577
ef51b8e1 4578 if (!arm_arch6 && !MEM_P (operands[1]))
4579 {
4580 rtx t = gen_lowpart (SImode, operands[1]);
4581 rtx tmp = gen_reg_rtx (SImode);
4582 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4583 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4584 DONE;
4585 }
4586})
a2cd141b 4587
ef51b8e1 4588(define_split
4589 [(set (match_operand:SI 0 "register_operand" "")
4590 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4591 "!arm_arch6"
4592 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4593 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4594{
4595 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4596})
f7fbdd4a 4597
a2cd141b 4598(define_insn "*arm_extendqisi"
ef51b8e1 4599 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4600 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4601 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4602 "@
4603 #
4604 ldr%(sb%)\\t%0, %1"
4605 [(set_attr "length" "8,4")
4606 (set_attr "type" "alu_shift,load_byte")
0d66636f 4607 (set_attr "predicable" "yes")
ef51b8e1 4608 (set_attr "pool_range" "*,256")
4609 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4610)
3fc2009e 4611
a2cd141b 4612(define_insn "*arm_extendqisi_v6"
4613 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4614 (sign_extend:SI
4615 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4616 "TARGET_ARM && arm_arch6"
b4e8a300 4617 "@
4618 sxtb%?\\t%0, %1
25f905c2 4619 ldr%(sb%)\\t%0, %1"
a2cd141b 4620 [(set_attr "type" "alu_shift,load_byte")
4621 (set_attr "predicable" "yes")
a2cd141b 4622 (set_attr "pool_range" "*,256")
4623 (set_attr "neg_pool_range" "*,244")]
4624)
4625
4626(define_insn "*arm_extendqisi2addsi"
4627 [(set (match_operand:SI 0 "s_register_operand" "=r")
4628 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4629 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4630 "TARGET_INT_SIMD"
a2cd141b 4631 "sxtab%?\\t%0, %2, %1"
4632 [(set_attr "type" "alu_shift")
bcaec148 4633 (set_attr "insn" "xtab")
a2cd141b 4634 (set_attr "predicable" "yes")]
4635)
4636
ef51b8e1 4637(define_split
4638 [(set (match_operand:SI 0 "register_operand" "")
4639 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4640 "TARGET_THUMB1 && reload_completed"
4641 [(set (match_dup 0) (match_dup 2))
4642 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4643{
4644 rtx addr = XEXP (operands[1], 0);
cffb2a26 4645
ef51b8e1 4646 if (GET_CODE (addr) == CONST)
4647 addr = XEXP (addr, 0);
cffb2a26 4648
ef51b8e1 4649 if (GET_CODE (addr) == PLUS
4650 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4651 /* No split necessary. */
4652 FAIL;
4653
4654 if (GET_CODE (addr) == PLUS
4655 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4656 FAIL;
4657
4658 if (reg_overlap_mentioned_p (operands[0], addr))
4659 {
4660 rtx t = gen_lowpart (QImode, operands[0]);
4661 emit_move_insn (t, operands[1]);
4662 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4663 DONE;
4664 }
4665
4666 if (REG_P (addr))
4667 {
4668 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4669 operands[2] = const0_rtx;
4670 }
4671 else if (GET_CODE (addr) != PLUS)
4672 FAIL;
4673 else if (REG_P (XEXP (addr, 0)))
4674 {
4675 operands[2] = XEXP (addr, 1);
4676 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4677 }
4678 else
4679 {
4680 operands[2] = XEXP (addr, 0);
4681 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4682 }
cffb2a26 4683
ef51b8e1 4684 operands[3] = change_address (operands[1], QImode, addr);
4685})
4686
8a3b73a1 4687(define_peephole2
4688 [(set (match_operand:SI 0 "register_operand" "")
4689 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4690 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4691 (set (match_operand:SI 3 "register_operand" "")
4692 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4693 "TARGET_THUMB1
4694 && GET_CODE (XEXP (operands[4], 0)) == PLUS
4695 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4696 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4697 && (peep2_reg_dead_p (3, operands[0])
4698 || rtx_equal_p (operands[0], operands[3]))
4699 && (peep2_reg_dead_p (3, operands[2])
4700 || rtx_equal_p (operands[2], operands[3]))"
4701 [(set (match_dup 2) (match_dup 1))
4702 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4703{
4704 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4705 operands[4] = change_address (operands[4], QImode, addr);
4706})
4707
ef51b8e1 4708(define_insn "thumb1_extendqisi2"
a2cd141b 4709 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4710 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 4711 "TARGET_THUMB1"
4712{
4713 rtx addr;
a2cd141b 4714
ef51b8e1 4715 if (which_alternative == 0 && arm_arch6)
4716 return "sxtb\\t%0, %1";
4717 if (which_alternative == 0)
4718 return "#";
a2cd141b 4719
ef51b8e1 4720 addr = XEXP (operands[1], 0);
4721 if (GET_CODE (addr) == PLUS
4722 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4723 return "ldrsb\\t%0, %1";
a2cd141b 4724
ef51b8e1 4725 return "#";
4726}
4727 [(set_attr_alternative "length"
4728 [(if_then_else (eq_attr "is_arch6" "yes")
4729 (const_int 2) (const_int 4))
4730 (const_int 2)
4731 (if_then_else (eq_attr "is_arch6" "yes")
4732 (const_int 4) (const_int 6))])
4733 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 4734)
4735
caedf871 4736(define_expand "extendsfdf2"
4737 [(set (match_operand:DF 0 "s_register_operand" "")
4738 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4739 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4740 ""
4741)
9b8516be 4742
4743/* HFmode -> DFmode conversions have to go through SFmode. */
4744(define_expand "extendhfdf2"
4745 [(set (match_operand:DF 0 "general_operand" "")
4746 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4747 "TARGET_EITHER"
4748 "
4749 {
4750 rtx op1;
4751 op1 = convert_to_mode (SFmode, operands[1], 0);
4752 op1 = convert_to_mode (DFmode, op1, 0);
4753 emit_insn (gen_movdf (operands[0], op1));
4754 DONE;
4755 }"
4756)
b11cae9e 4757\f
4758;; Move insns (including loads and stores)
4759
4760;; XXX Just some ideas about movti.
9c08d1fa 4761;; I don't think these are a good idea on the arm, there just aren't enough
4762;; registers
b11cae9e 4763;;(define_expand "loadti"
9c08d1fa 4764;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4765;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4766;; "" "")
4767
4768;;(define_expand "storeti"
4769;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4770;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4771;; "" "")
4772
4773;;(define_expand "movti"
4774;; [(set (match_operand:TI 0 "general_operand" "")
4775;; (match_operand:TI 1 "general_operand" ""))]
4776;; ""
4777;; "
4778;;{
4779;; rtx insn;
4780;;
4781;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4782;; operands[1] = copy_to_reg (operands[1]);
4783;; if (GET_CODE (operands[0]) == MEM)
4784;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4785;; else if (GET_CODE (operands[1]) == MEM)
4786;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4787;; else
4788;; FAIL;
4789;;
4790;; emit_insn (insn);
4791;; DONE;
4792;;}")
4793
a2f10574 4794;; Recognize garbage generated above.
b11cae9e 4795
4796;;(define_insn ""
4797;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4798;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4799;; ""
4800;; "*
4801;; {
4802;; register mem = (which_alternative < 3);
0d66636f 4803;; register const char *template;
b11cae9e 4804;;
4805;; operands[mem] = XEXP (operands[mem], 0);
4806;; switch (which_alternative)
4807;; {
4808;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4809;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4810;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4811;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4812;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4813;; case 5: template = \"stmia\\t%0, %M1\"; break;
4814;; }
e2348bcb 4815;; output_asm_insn (template, operands);
4816;; return \"\";
b11cae9e 4817;; }")
4818
cffb2a26 4819(define_expand "movdi"
4820 [(set (match_operand:DI 0 "general_operand" "")
4821 (match_operand:DI 1 "general_operand" ""))]
4822 "TARGET_EITHER"
4823 "
e1ba4a27 4824 if (can_create_pseudo_p ())
cffb2a26 4825 {
b2778788 4826 if (GET_CODE (operands[0]) != REG)
4827 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4828 }
4829 "
4830)
b11cae9e 4831
cffb2a26 4832(define_insn "*arm_movdi"
d51f92df 4833 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4834 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 4835 "TARGET_32BIT
b2778788 4836 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4837 && !TARGET_IWMMXT
4838 && ( register_operand (operands[0], DImode)
4839 || register_operand (operands[1], DImode))"
b11cae9e 4840 "*
d51f92df 4841 switch (which_alternative)
4842 {
4843 case 0:
4844 case 1:
4845 case 2:
4846 return \"#\";
4847 default:
4848 return output_move_double (operands);
4849 }
cffb2a26 4850 "
359a6e9f 4851 [(set_attr "length" "8,12,16,8,8")
4852 (set_attr "type" "*,*,*,load2,store2")
cde1623a 4853 (set_attr "arm_pool_range" "*,*,*,1020,*")
4854 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
4855 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
4856 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 4857)
4858
d51f92df 4859(define_split
4860 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4861 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4862 "TARGET_32BIT
d51f92df 4863 && reload_completed
4864 && (arm_const_double_inline_cost (operands[1])
4865 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4866 [(const_int 0)]
4867 "
4868 arm_split_constant (SET, SImode, curr_insn,
4869 INTVAL (gen_lowpart (SImode, operands[1])),
4870 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4871 arm_split_constant (SET, SImode, curr_insn,
4872 INTVAL (gen_highpart_mode (SImode,
4873 GET_MODE (operands[0]),
4874 operands[1])),
4875 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4876 DONE;
4877 "
4878)
4879
e5ba9289 4880; If optimizing for size, or if we have load delay slots, then
4881; we want to split the constant into two separate operations.
4882; In both cases this may split a trivial part into a single data op
4883; leaving a single complex constant to load. We can also get longer
4884; offsets in a LDR which means we get better chances of sharing the pool
4885; entries. Finally, we can normally do a better job of scheduling
4886; LDR instructions than we can with LDM.
4887; This pattern will only match if the one above did not.
4888(define_split
4889 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4890 (match_operand:ANY64 1 "const_double_operand" ""))]
4891 "TARGET_ARM && reload_completed
4892 && arm_const_double_by_parts (operands[1])"
4893 [(set (match_dup 0) (match_dup 1))
4894 (set (match_dup 2) (match_dup 3))]
4895 "
4896 operands[2] = gen_highpart (SImode, operands[0]);
4897 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4898 operands[1]);
4899 operands[0] = gen_lowpart (SImode, operands[0]);
4900 operands[1] = gen_lowpart (SImode, operands[1]);
4901 "
4902)
4903
d51f92df 4904(define_split
4905 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4906 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4907 "TARGET_EITHER && reload_completed"
4908 [(set (match_dup 0) (match_dup 1))
4909 (set (match_dup 2) (match_dup 3))]
4910 "
4911 operands[2] = gen_highpart (SImode, operands[0]);
4912 operands[3] = gen_highpart (SImode, operands[1]);
4913 operands[0] = gen_lowpart (SImode, operands[0]);
4914 operands[1] = gen_lowpart (SImode, operands[1]);
4915
4916 /* Handle a partial overlap. */
4917 if (rtx_equal_p (operands[0], operands[3]))
4918 {
4919 rtx tmp0 = operands[0];
4920 rtx tmp1 = operands[1];
4921
4922 operands[0] = operands[2];
4923 operands[1] = operands[3];
4924 operands[2] = tmp0;
4925 operands[3] = tmp1;
4926 }
4927 "
4928)
4929
a8a3b539 4930;; We can't actually do base+index doubleword loads if the index and
4931;; destination overlap. Split here so that we at least have chance to
4932;; schedule.
4933(define_split
4934 [(set (match_operand:DI 0 "s_register_operand" "")
4935 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4936 (match_operand:SI 2 "s_register_operand" ""))))]
4937 "TARGET_LDRD
4938 && reg_overlap_mentioned_p (operands[0], operands[1])
4939 && reg_overlap_mentioned_p (operands[0], operands[2])"
4940 [(set (match_dup 4)
4941 (plus:SI (match_dup 1)
4942 (match_dup 2)))
4943 (set (match_dup 0)
4944 (mem:DI (match_dup 4)))]
4945 "
4946 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4947 "
4948)
4949
cffb2a26 4950;;; ??? This should have alternatives for constants.
4951;;; ??? This was originally identical to the movdf_insn pattern.
4952;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4953;;; thumb_reorg with a memory reference.
25f905c2 4954(define_insn "*thumb1_movdi_insn"
215b30b3 4955 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4956 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4957 "TARGET_THUMB1
a2cd141b 4958 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4959 && ( register_operand (operands[0], DImode)
4960 || register_operand (operands[1], DImode))"
4961 "*
4962 {
4963 switch (which_alternative)
4964 {
4965 default:
4966 case 0:
4967 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4968 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4969 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4970 case 1:
4971 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4972 case 2:
4973 operands[1] = GEN_INT (- INTVAL (operands[1]));
4974 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4975 case 3:
4976 return \"ldmia\\t%1, {%0, %H0}\";
4977 case 4:
4978 return \"stmia\\t%0, {%1, %H1}\";
4979 case 5:
4980 return thumb_load_double_from_address (operands);
4981 case 6:
1a83b3ff 4982 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4983 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4984 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4985 return \"\";
4986 case 7:
4987 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4988 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4989 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4990 }
4991 }"
4992 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4993 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4994 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4995)
b11cae9e 4996
9c08d1fa 4997(define_expand "movsi"
4998 [(set (match_operand:SI 0 "general_operand" "")
4999 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5000 "TARGET_EITHER"
9c08d1fa 5001 "
befb0bac 5002 {
e348ff3e 5003 rtx base, offset, tmp;
5004
25f905c2 5005 if (TARGET_32BIT)
9c08d1fa 5006 {
674a8f0b 5007 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5008 if (GET_CODE (operands[0]) == MEM)
5009 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5010 if (arm_general_register_operand (operands[0], SImode)
5011 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5012 && !(const_ok_for_arm (INTVAL (operands[1]))
5013 || const_ok_for_arm (~INTVAL (operands[1]))))
5014 {
96f57e36 5015 arm_split_constant (SET, SImode, NULL_RTX,
5016 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5017 optimize && can_create_pseudo_p ());
cffb2a26 5018 DONE;
5019 }
d0e6a121 5020
5021 if (TARGET_USE_MOVT && !target_word_relocations
5022 && GET_CODE (operands[1]) == SYMBOL_REF
5023 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5024 {
5025 arm_emit_movpair (operands[0], operands[1]);
5026 DONE;
5027 }
cffb2a26 5028 }
25f905c2 5029 else /* TARGET_THUMB1... */
cffb2a26 5030 {
e1ba4a27 5031 if (can_create_pseudo_p ())
cffb2a26 5032 {
5033 if (GET_CODE (operands[0]) != REG)
5034 operands[1] = force_reg (SImode, operands[1]);
5035 }
9c08d1fa 5036 }
f655717d 5037
e348ff3e 5038 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5039 {
5040 split_const (operands[1], &base, &offset);
5041 if (GET_CODE (base) == SYMBOL_REF
5042 && !offset_within_block_p (base, INTVAL (offset)))
5043 {
b308ddcf 5044 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5045 emit_move_insn (tmp, base);
5046 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5047 DONE;
5048 }
5049 }
5050
f655717d 5051 /* Recognize the case where operand[1] is a reference to thread-local
5052 data and load its address to a register. */
5053 if (arm_tls_referenced_p (operands[1]))
5054 {
5055 rtx tmp = operands[1];
5056 rtx addend = NULL;
5057
5058 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5059 {
5060 addend = XEXP (XEXP (tmp, 0), 1);
5061 tmp = XEXP (XEXP (tmp, 0), 0);
5062 }
5063
5064 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5065 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5066
e1ba4a27 5067 tmp = legitimize_tls_address (tmp,
5068 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5069 if (addend)
5070 {
5071 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5072 tmp = force_operand (tmp, operands[0]);
5073 }
5074 operands[1] = tmp;
5075 }
5076 else if (flag_pic
5077 && (CONSTANT_P (operands[1])
5078 || symbol_mentioned_p (operands[1])
5079 || label_mentioned_p (operands[1])))
5080 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5081 (!can_create_pseudo_p ()
5082 ? operands[0]
5083 : 0));
befb0bac 5084 }
215b30b3 5085 "
5086)
9c08d1fa 5087
d0e6a121 5088;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5089;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5090;; so this does not matter.
5091(define_insn "*arm_movt"
5092 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5093 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5094 (match_operand:SI 2 "general_operand" "i")))]
5095 "TARGET_32BIT"
5096 "movt%?\t%0, #:upper16:%c2"
5097 [(set_attr "predicable" "yes")
5098 (set_attr "length" "4")]
5099)
5100
cffb2a26 5101(define_insn "*arm_movsi_insn"
aaa37ad6 5102 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5103 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5104 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5105 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5106 && ( register_operand (operands[0], SImode)
5107 || register_operand (operands[1], SImode))"
f7fbdd4a 5108 "@
aaa37ad6 5109 mov%?\\t%0, %1
f7fbdd4a 5110 mov%?\\t%0, %1
5111 mvn%?\\t%0, #%B1
25f905c2 5112 movw%?\\t%0, %1
f7fbdd4a 5113 ldr%?\\t%0, %1
5114 str%?\\t%1, %0"
aaa37ad6 5115 [(set_attr "type" "*,*,*,*,load1,store1")
0d66636f 5116 (set_attr "predicable" "yes")
aaa37ad6 5117 (set_attr "pool_range" "*,*,*,*,4096,*")
5118 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5119)
87b22bf7 5120
5121(define_split
a2cd141b 5122 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5123 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5124 "TARGET_32BIT
215b30b3 5125 && (!(const_ok_for_arm (INTVAL (operands[1]))
5126 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5127 [(clobber (const_int 0))]
5128 "
96f57e36 5129 arm_split_constant (SET, SImode, NULL_RTX,
5130 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5131 DONE;
215b30b3 5132 "
5133)
9c08d1fa 5134
25f905c2 5135(define_insn "*thumb1_movsi_insn"
aaa37ad6 5136 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5137 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
25f905c2 5138 "TARGET_THUMB1
cffb2a26 5139 && ( register_operand (operands[0], SImode)
5140 || register_operand (operands[1], SImode))"
5141 "@
5142 mov %0, %1
5143 mov %0, %1
5144 #
5145 #
5146 ldmia\\t%1, {%0}
5147 stmia\\t%0, {%1}
5148 ldr\\t%0, %1
5149 str\\t%1, %0
5150 mov\\t%0, %1"
5151 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5152 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5153 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5154 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5155
5156(define_split
5157 [(set (match_operand:SI 0 "register_operand" "")
5158 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5159 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5160 [(set (match_dup 2) (match_dup 1))
5161 (set (match_dup 0) (neg:SI (match_dup 2)))]
5162 "
5163 {
5164 operands[1] = GEN_INT (- INTVAL (operands[1]));
5165 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5166 }"
cffb2a26 5167)
5168
5169(define_split
5170 [(set (match_operand:SI 0 "register_operand" "")
5171 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5172 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5173 [(set (match_dup 2) (match_dup 1))
5174 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5175 "
5176 {
e4aeee53 5177 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5178 unsigned HOST_WIDE_INT mask = 0xff;
5179 int i;
5180
5181 for (i = 0; i < 25; i++)
5182 if ((val & (mask << i)) == val)
5183 break;
5184
1276f1b8 5185 /* Don't split if the shift is zero. */
cffb2a26 5186 if (i == 0)
5187 FAIL;
5188
5189 operands[1] = GEN_INT (val >> i);
1276f1b8 5190 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5191 operands[3] = GEN_INT (i);
cffb2a26 5192 }"
5193)
5194
67336bcf 5195;; When generating pic, we need to load the symbol offset into a register.
5196;; So that the optimizer does not confuse this with a normal symbol load
5197;; we use an unspec. The offset will be loaded from a constant pool entry,
5198;; since that is the only type of relocation we can use.
5199
94f8caca 5200;; Wrap calculation of the whole PIC address in a single pattern for the
5201;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5202;; a PIC address involves two loads from memory, so we want to CSE it
5203;; as often as possible.
5204;; This pattern will be split into one of the pic_load_addr_* patterns
5205;; and a move after GCSE optimizations.
5206;;
5207;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5208(define_expand "calculate_pic_address"
5209 [(set (match_operand:SI 0 "register_operand" "")
5210 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5211 (unspec:SI [(match_operand:SI 2 "" "")]
5212 UNSPEC_PIC_SYM))))]
5213 "flag_pic"
5214)
5215
5216;; Split calculate_pic_address into pic_load_addr_* and a move.
5217(define_split
5218 [(set (match_operand:SI 0 "register_operand" "")
5219 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5220 (unspec:SI [(match_operand:SI 2 "" "")]
5221 UNSPEC_PIC_SYM))))]
5222 "flag_pic"
5223 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5224 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5225 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5226)
5227
67336bcf 5228;; The rather odd constraints on the following are to force reload to leave
5229;; the insn alone, and to force the minipool generation pass to then move
5230;; the GOT symbol to memory.
849170fd 5231
b3cd5f55 5232(define_insn "pic_load_addr_32bit"
849170fd 5233 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5234 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5235 "TARGET_32BIT && flag_pic"
67336bcf 5236 "ldr%?\\t%0, %1"
a2cd141b 5237 [(set_attr "type" "load1")
b3cd5f55 5238 (set_attr "pool_range" "4096")
5239 (set (attr "neg_pool_range")
5240 (if_then_else (eq_attr "is_thumb" "no")
5241 (const_int 4084)
5242 (const_int 0)))]
8c4d8060 5243)
5244
25f905c2 5245(define_insn "pic_load_addr_thumb1"
8c4d8060 5246 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5247 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5248 "TARGET_THUMB1 && flag_pic"
8c4d8060 5249 "ldr\\t%0, %1"
a2cd141b 5250 [(set_attr "type" "load1")
8c4d8060 5251 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5252)
849170fd 5253
cffb2a26 5254(define_insn "pic_add_dot_plus_four"
15d5d060 5255 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5256 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5257 (const_int 4)
beef0fb5 5258 (match_operand 2 "" "")]
5259 UNSPEC_PIC_BASE))]
b3cd5f55 5260 "TARGET_THUMB"
cffb2a26 5261 "*
6cdcb15c 5262 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5263 INTVAL (operands[2]));
cffb2a26 5264 return \"add\\t%0, %|pc\";
5265 "
5266 [(set_attr "length" "2")]
5267)
849170fd 5268
5269(define_insn "pic_add_dot_plus_eight"
15d5d060 5270 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5271 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5272 (const_int 8)
beef0fb5 5273 (match_operand 2 "" "")]
5274 UNSPEC_PIC_BASE))]
f655717d 5275 "TARGET_ARM"
c4034607 5276 "*
6cdcb15c 5277 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5278 INTVAL (operands[2]));
15d5d060 5279 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5280 "
0d66636f 5281 [(set_attr "predicable" "yes")]
cffb2a26 5282)
849170fd 5283
f655717d 5284(define_insn "tls_load_dot_plus_eight"
cc071db6 5285 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5286 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5287 (const_int 8)
beef0fb5 5288 (match_operand 2 "" "")]
5289 UNSPEC_PIC_BASE)))]
f655717d 5290 "TARGET_ARM"
5291 "*
6cdcb15c 5292 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5293 INTVAL (operands[2]));
f655717d 5294 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5295 "
5296 [(set_attr "predicable" "yes")]
5297)
5298
5299;; PIC references to local variables can generate pic_add_dot_plus_eight
5300;; followed by a load. These sequences can be crunched down to
5301;; tls_load_dot_plus_eight by a peephole.
5302
5303(define_peephole2
c0c1fba5 5304 [(set (match_operand:SI 0 "register_operand" "")
5305 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5306 (const_int 8)
5307 (match_operand 1 "" "")]
5308 UNSPEC_PIC_BASE))
f655717d 5309 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5310 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5311 [(set (match_dup 2)
5312 (mem:SI (unspec:SI [(match_dup 3)
5313 (const_int 8)
5314 (match_dup 1)]
5315 UNSPEC_PIC_BASE)))]
f655717d 5316 ""
5317)
5318
bac7fc85 5319(define_insn "pic_offset_arm"
5320 [(set (match_operand:SI 0 "register_operand" "=r")
5321 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5322 (unspec:SI [(match_operand:SI 2 "" "X")]
5323 UNSPEC_PIC_OFFSET))))]
5324 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5325 "ldr%?\\t%0, [%1,%2]"
5326 [(set_attr "type" "load1")]
5327)
5328
95373f08 5329(define_expand "builtin_setjmp_receiver"
5330 [(label_ref (match_operand 0 "" ""))]
5331 "flag_pic"
5332 "
5333{
b935b306 5334 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5335 register. */
2cb7d577 5336 if (arm_pic_register != INVALID_REGNUM)
5337 arm_load_pic_register (1UL << 3);
95373f08 5338 DONE;
5339}")
5340
9c08d1fa 5341;; If copying one reg to another we can set the condition codes according to
5342;; its value. Such a move is common after a return from subroutine and the
5343;; result is being tested against zero.
5344
f7fbdd4a 5345(define_insn "*movsi_compare0"
bd5b4116 5346 [(set (reg:CC CC_REGNUM)
cffb2a26 5347 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5348 (const_int 0)))
5349 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5350 (match_dup 1))]
25f905c2 5351 "TARGET_32BIT"
e2348bcb 5352 "@
40dbec34 5353 cmp%?\\t%0, #0
25f905c2 5354 sub%.\\t%0, %1, #0"
cffb2a26 5355 [(set_attr "conds" "set")]
5356)
b11cae9e 5357
b11cae9e 5358;; Subroutine to store a half word from a register into memory.
5359;; Operand 0 is the source register (HImode)
c8f69309 5360;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5361
9c08d1fa 5362;; In both this routine and the next, we must be careful not to spill
01cc3b75 5363;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5364;; can generate unrecognizable rtl.
5365
b11cae9e 5366(define_expand "storehi"
c8f69309 5367 [;; store the low byte
f082f1c4 5368 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5369 ;; extract the high byte
c8f69309 5370 (set (match_dup 2)
5371 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5372 ;; store the high byte
787f8210 5373 (set (match_dup 4) (match_dup 5))]
cffb2a26 5374 "TARGET_ARM"
b11cae9e 5375 "
215b30b3 5376 {
537ffcfc 5377 rtx op1 = operands[1];
5378 rtx addr = XEXP (op1, 0);
215b30b3 5379 enum rtx_code code = GET_CODE (addr);
5380
5381 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5382 || code == MINUS)
537ffcfc 5383 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5384
537ffcfc 5385 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5386 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5387 operands[3] = gen_lowpart (QImode, operands[0]);
5388 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5389 operands[2] = gen_reg_rtx (SImode);
5390 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5391 }"
5392)
b11cae9e 5393
c7597b5d 5394(define_expand "storehi_bigend"
f082f1c4 5395 [(set (match_dup 4) (match_dup 3))
c7597b5d 5396 (set (match_dup 2)
5397 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5398 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5399 "TARGET_ARM"
b11cae9e 5400 "
215b30b3 5401 {
537ffcfc 5402 rtx op1 = operands[1];
5403 rtx addr = XEXP (op1, 0);
215b30b3 5404 enum rtx_code code = GET_CODE (addr);
5405
5406 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5407 || code == MINUS)
537ffcfc 5408 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5409
537ffcfc 5410 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5411 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5412 operands[3] = gen_lowpart (QImode, operands[0]);
5413 operands[0] = gen_lowpart (SImode, operands[0]);
5414 operands[2] = gen_reg_rtx (SImode);
787f8210 5415 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5416 }"
5417)
c7597b5d 5418
5419;; Subroutine to store a half word integer constant into memory.
5420(define_expand "storeinthi"
f082f1c4 5421 [(set (match_operand 0 "" "")
787f8210 5422 (match_operand 1 "" ""))
9e8503e6 5423 (set (match_dup 3) (match_dup 2))]
cffb2a26 5424 "TARGET_ARM"
c7597b5d 5425 "
215b30b3 5426 {
5427 HOST_WIDE_INT value = INTVAL (operands[1]);
5428 rtx addr = XEXP (operands[0], 0);
537ffcfc 5429 rtx op0 = operands[0];
215b30b3 5430 enum rtx_code code = GET_CODE (addr);
c7597b5d 5431
215b30b3 5432 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5433 || code == MINUS)
537ffcfc 5434 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5435
215b30b3 5436 operands[1] = gen_reg_rtx (SImode);
5437 if (BYTES_BIG_ENDIAN)
5438 {
5439 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5440 if ((value & 255) == ((value >> 8) & 255))
5441 operands[2] = operands[1];
5442 else
5443 {
5444 operands[2] = gen_reg_rtx (SImode);
5445 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5446 }
5447 }
5448 else
5449 {
5450 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5451 if ((value & 255) == ((value >> 8) & 255))
5452 operands[2] = operands[1];
5453 else
5454 {
5455 operands[2] = gen_reg_rtx (SImode);
5456 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5457 }
5458 }
c7597b5d 5459
537ffcfc 5460 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5461 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5462 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5463 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5464 }"
5465)
b11cae9e 5466
f7fbdd4a 5467(define_expand "storehi_single_op"
5468 [(set (match_operand:HI 0 "memory_operand" "")
5469 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5470 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5471 "
215b30b3 5472 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5473 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5474 "
5475)
f7fbdd4a 5476
b11cae9e 5477(define_expand "movhi"
5478 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5479 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5480 "TARGET_EITHER"
b11cae9e 5481 "
cffb2a26 5482 if (TARGET_ARM)
b11cae9e 5483 {
e1ba4a27 5484 if (can_create_pseudo_p ())
cffb2a26 5485 {
5486 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5487 {
cffb2a26 5488 if (arm_arch4)
5489 {
5490 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5491 DONE;
5492 }
5493 if (GET_CODE (operands[1]) == CONST_INT)
5494 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5495 else
cffb2a26 5496 {
5497 if (GET_CODE (operands[1]) == MEM)
5498 operands[1] = force_reg (HImode, operands[1]);
5499 if (BYTES_BIG_ENDIAN)
5500 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5501 else
5502 emit_insn (gen_storehi (operands[1], operands[0]));
5503 }
5504 DONE;
b11cae9e 5505 }
cffb2a26 5506 /* Sign extend a constant, and keep it in an SImode reg. */
5507 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5508 {
cffb2a26 5509 rtx reg = gen_reg_rtx (SImode);
5510 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5511
5512 /* If the constant is already valid, leave it alone. */
215b30b3 5513 if (!const_ok_for_arm (val))
cffb2a26 5514 {
5515 /* If setting all the top bits will make the constant
5516 loadable in a single instruction, then set them.
5517 Otherwise, sign extend the number. */
5518
215b30b3 5519 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5520 val |= ~0xffff;
5521 else if (val & 0x8000)
5522 val |= ~0xffff;
5523 }
5524
5525 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5526 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5527 }
e1ba4a27 5528 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5529 && GET_CODE (operands[1]) == MEM)
5530 {
5531 rtx reg = gen_reg_rtx (SImode);
5532
5533 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5534 operands[1] = gen_lowpart (HImode, reg);
5535 }
215b30b3 5536 else if (!arm_arch4)
f7fbdd4a 5537 {
cffb2a26 5538 if (GET_CODE (operands[1]) == MEM)
5539 {
c1a66faf 5540 rtx base;
5541 rtx offset = const0_rtx;
5542 rtx reg = gen_reg_rtx (SImode);
5543
5544 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5545 || (GET_CODE (base) == PLUS
5546 && (GET_CODE (offset = XEXP (base, 1))
5547 == CONST_INT)
5548 && ((INTVAL(offset) & 1) != 1)
5549 && GET_CODE (base = XEXP (base, 0)) == REG))
5550 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5551 {
8deb3959 5552 rtx new_rtx;
c1a66faf 5553
8deb3959 5554 new_rtx = widen_memory_access (operands[1], SImode,
5555 ((INTVAL (offset) & ~3)
5556 - INTVAL (offset)));
5557 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5558 if (((INTVAL (offset) & 2) != 0)
5559 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5560 {
5561 rtx reg2 = gen_reg_rtx (SImode);
5562
5563 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5564 reg = reg2;
5565 }
206ee9a2 5566 }
c1a66faf 5567 else
5568 emit_insn (gen_movhi_bytes (reg, operands[1]));
5569
5570 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5571 }
5572 }
5573 }
674a8f0b 5574 /* Handle loading a large integer during reload. */
cffb2a26 5575 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5576 && !const_ok_for_arm (INTVAL (operands[1]))
5577 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5578 {
5579 /* Writing a constant to memory needs a scratch, which should
5580 be handled with SECONDARY_RELOADs. */
ed29c566 5581 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5582
5583 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5584 emit_insn (gen_movsi (operands[0], operands[1]));
5585 DONE;
5586 }
5587 }
25f905c2 5588 else if (TARGET_THUMB2)
5589 {
5590 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5591 if (can_create_pseudo_p ())
25f905c2 5592 {
5593 if (GET_CODE (operands[0]) != REG)
5594 operands[1] = force_reg (HImode, operands[1]);
5595 /* Zero extend a constant, and keep it in an SImode reg. */
5596 else if (GET_CODE (operands[1]) == CONST_INT)
5597 {
5598 rtx reg = gen_reg_rtx (SImode);
5599 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5600
5601 emit_insn (gen_movsi (reg, GEN_INT (val)));
5602 operands[1] = gen_lowpart (HImode, reg);
5603 }
5604 }
5605 }
5606 else /* TARGET_THUMB1 */
cffb2a26 5607 {
e1ba4a27 5608 if (can_create_pseudo_p ())
cffb2a26 5609 {
6cffc037 5610 if (GET_CODE (operands[1]) == CONST_INT)
5611 {
5612 rtx reg = gen_reg_rtx (SImode);
5613
5614 emit_insn (gen_movsi (reg, operands[1]));
5615 operands[1] = gen_lowpart (HImode, reg);
5616 }
cffb2a26 5617
5618 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5619 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5620 virtual register (also rejected as illegitimate for HImode/QImode)
5621 relative address. */
cffb2a26 5622 /* ??? This should perhaps be fixed elsewhere, for instance, in
5623 fixup_stack_1, by checking for other kinds of invalid addresses,
5624 e.g. a bare reference to a virtual register. This may confuse the
5625 alpha though, which must handle this case differently. */
5626 if (GET_CODE (operands[0]) == MEM
215b30b3 5627 && !memory_address_p (GET_MODE (operands[0]),
5628 XEXP (operands[0], 0)))
537ffcfc 5629 operands[0]
5630 = replace_equiv_address (operands[0],
5631 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5632
5633 if (GET_CODE (operands[1]) == MEM
215b30b3 5634 && !memory_address_p (GET_MODE (operands[1]),
5635 XEXP (operands[1], 0)))
537ffcfc 5636 operands[1]
5637 = replace_equiv_address (operands[1],
5638 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5639
5640 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5641 {
5642 rtx reg = gen_reg_rtx (SImode);
5643
5644 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5645 operands[1] = gen_lowpart (HImode, reg);
5646 }
5647
5648 if (GET_CODE (operands[0]) == MEM)
5649 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5650 }
cffb2a26 5651 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5652 && !satisfies_constraint_I (operands[1]))
cffb2a26 5653 {
6cffc037 5654 /* Handle loading a large integer during reload. */
5655
cffb2a26 5656 /* Writing a constant to memory needs a scratch, which should
5657 be handled with SECONDARY_RELOADs. */
ed29c566 5658 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5659
1a83b3ff 5660 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5661 emit_insn (gen_movsi (operands[0], operands[1]));
5662 DONE;
5663 }
b11cae9e 5664 }
cffb2a26 5665 "
5666)
5667
25f905c2 5668(define_insn "*thumb1_movhi_insn"
a941568e 5669 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5670 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5671 "TARGET_THUMB1
cffb2a26 5672 && ( register_operand (operands[0], HImode)
5673 || register_operand (operands[1], HImode))"
5674 "*
5675 switch (which_alternative)
d79300ac 5676 {
cffb2a26 5677 case 0: return \"add %0, %1, #0\";
5678 case 2: return \"strh %1, %0\";
5679 case 3: return \"mov %0, %1\";
5680 case 4: return \"mov %0, %1\";
5681 case 5: return \"mov %0, %1\";
ed29c566 5682 default: gcc_unreachable ();
cffb2a26 5683 case 1:
5684 /* The stack pointer can end up being taken as an index register.
5685 Catch this case here and deal with it. */
5686 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5687 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5688 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5689 {
5690 rtx ops[2];
5691 ops[0] = operands[0];
5692 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5693
5694 output_asm_insn (\"mov %0, %1\", ops);
5695
5696 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5697
5698 }
5699 return \"ldrh %0, %1\";
5700 }"
5701 [(set_attr "length" "2,4,2,2,2,2")
747b7458 5702 (set_attr "type" "*,load1,store1,*,*,*")
5703 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 5704
b11cae9e 5705
25f7a26e 5706(define_expand "movhi_bytes"
eab14235 5707 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5708 (set (match_dup 3)
eab14235 5709 (zero_extend:SI (match_dup 6)))
25f7a26e 5710 (set (match_operand:SI 0 "" "")
5711 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5712 "TARGET_ARM"
25f7a26e 5713 "
215b30b3 5714 {
5715 rtx mem1, mem2;
5716 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5717
788fcce0 5718 mem1 = change_address (operands[1], QImode, addr);
5719 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5720 operands[0] = gen_lowpart (SImode, operands[0]);
5721 operands[1] = mem1;
5722 operands[2] = gen_reg_rtx (SImode);
5723 operands[3] = gen_reg_rtx (SImode);
5724 operands[6] = mem2;
25f7a26e 5725
215b30b3 5726 if (BYTES_BIG_ENDIAN)
5727 {
5728 operands[4] = operands[2];
5729 operands[5] = operands[3];
5730 }
5731 else
5732 {
5733 operands[4] = operands[3];
5734 operands[5] = operands[2];
5735 }
5736 }"
5737)
25f7a26e 5738
c7597b5d 5739(define_expand "movhi_bigend"
5740 [(set (match_dup 2)
5741 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5742 (const_int 16)))
5743 (set (match_dup 3)
5744 (ashiftrt:SI (match_dup 2) (const_int 16)))
5745 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5746 (match_dup 4))]
cffb2a26 5747 "TARGET_ARM"
c7597b5d 5748 "
5749 operands[2] = gen_reg_rtx (SImode);
5750 operands[3] = gen_reg_rtx (SImode);
787f8210 5751 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5752 "
5753)
b11cae9e 5754
a2f10574 5755;; Pattern to recognize insn generated default case above
f7fbdd4a 5756(define_insn "*movhi_insn_arch4"
cde1623a 5757 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5758 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5759 "TARGET_ARM
5760 && arm_arch4
f7fbdd4a 5761 && (GET_CODE (operands[1]) != CONST_INT
5762 || const_ok_for_arm (INTVAL (operands[1]))
5763 || const_ok_for_arm (~INTVAL (operands[1])))"
5764 "@
5765 mov%?\\t%0, %1\\t%@ movhi
5766 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5767 str%(h%)\\t%1, %0\\t%@ movhi
5768 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5769 [(set_attr "type" "*,*,store1,load1")
0d66636f 5770 (set_attr "predicable" "yes")
cffb2a26 5771 (set_attr "pool_range" "*,*,*,256")
5772 (set_attr "neg_pool_range" "*,*,*,244")]
5773)
f7fbdd4a 5774
f7fbdd4a 5775(define_insn "*movhi_bytes"
25f7a26e 5776 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5777 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5778 "TARGET_ARM"
25f7a26e 5779 "@
5780 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5781 mvn%?\\t%0, #%B1\\t%@ movhi"
5782 [(set_attr "predicable" "yes")]
5783)
25f7a26e 5784
f90b51f1 5785(define_expand "thumb_movhi_clobber"
5786 [(set (match_operand:HI 0 "memory_operand" "")
5787 (match_operand:HI 1 "register_operand" ""))
5788 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5789 "TARGET_THUMB1"
f90b51f1 5790 "
5791 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5792 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5793 {
5794 emit_insn (gen_movhi (operands[0], operands[1]));
5795 DONE;
5796 }
5797 /* XXX Fixme, need to handle other cases here as well. */
5798 gcc_unreachable ();
5799 "
cffb2a26 5800)
5801
bc5c7e08 5802;; We use a DImode scratch because we may occasionally need an additional
5803;; temporary if the address isn't offsettable -- push_reload doesn't seem
5804;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5805(define_expand "reload_outhi"
cffb2a26 5806 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5807 (match_operand:HI 1 "s_register_operand" "r")
5808 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5809 "TARGET_EITHER"
5810 "if (TARGET_ARM)
5811 arm_reload_out_hi (operands);
5812 else
5813 thumb_reload_out_hi (operands);
d3373b54 5814 DONE;
cffb2a26 5815 "
5816)
d3373b54 5817
25f7a26e 5818(define_expand "reload_inhi"
5819 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5820 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5821 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5822 "TARGET_EITHER"
25f7a26e 5823 "
cffb2a26 5824 if (TARGET_ARM)
5825 arm_reload_in_hi (operands);
5826 else
5827 thumb_reload_out_hi (operands);
25f7a26e 5828 DONE;
5829")
5830
9c08d1fa 5831(define_expand "movqi"
5832 [(set (match_operand:QI 0 "general_operand" "")
5833 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5834 "TARGET_EITHER"
9c08d1fa 5835 "
6cffc037 5836 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5837
e1ba4a27 5838 if (can_create_pseudo_p ())
cffb2a26 5839 {
6cffc037 5840 if (GET_CODE (operands[1]) == CONST_INT)
5841 {
5842 rtx reg = gen_reg_rtx (SImode);
5843
03770691 5844 /* For thumb we want an unsigned immediate, then we are more likely
5845 to be able to use a movs insn. */
5846 if (TARGET_THUMB)
5847 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5848
6cffc037 5849 emit_insn (gen_movsi (reg, operands[1]));
5850 operands[1] = gen_lowpart (QImode, reg);
5851 }
cffb2a26 5852
6cffc037 5853 if (TARGET_THUMB)
5854 {
cffb2a26 5855 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5856 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5857 virtual register (also rejected as illegitimate for HImode/QImode)
5858 relative address. */
cffb2a26 5859 /* ??? This should perhaps be fixed elsewhere, for instance, in
5860 fixup_stack_1, by checking for other kinds of invalid addresses,
5861 e.g. a bare reference to a virtual register. This may confuse the
5862 alpha though, which must handle this case differently. */
5863 if (GET_CODE (operands[0]) == MEM
215b30b3 5864 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5865 XEXP (operands[0], 0)))
537ffcfc 5866 operands[0]
5867 = replace_equiv_address (operands[0],
5868 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5869 if (GET_CODE (operands[1]) == MEM
5870 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5871 XEXP (operands[1], 0)))
537ffcfc 5872 operands[1]
5873 = replace_equiv_address (operands[1],
5874 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5875 }
5876
5877 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5878 {
5879 rtx reg = gen_reg_rtx (SImode);
5880
5881 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5882 operands[1] = gen_lowpart (QImode, reg);
5883 }
5884
5885 if (GET_CODE (operands[0]) == MEM)
5886 operands[1] = force_reg (QImode, operands[1]);
5887 }
5888 else if (TARGET_THUMB
5889 && GET_CODE (operands[1]) == CONST_INT
234f6557 5890 && !satisfies_constraint_I (operands[1]))
6cffc037 5891 {
674a8f0b 5892 /* Handle loading a large integer during reload. */
cffb2a26 5893
6cffc037 5894 /* Writing a constant to memory needs a scratch, which should
5895 be handled with SECONDARY_RELOADs. */
5896 gcc_assert (GET_CODE (operands[0]) == REG);
5897
5898 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5899 emit_insn (gen_movsi (operands[0], operands[1]));
5900 DONE;
cffb2a26 5901 }
5902 "
5903)
b11cae9e 5904
9c08d1fa 5905
cffb2a26 5906(define_insn "*arm_movqi_insn"
5907 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5908 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5909 "TARGET_32BIT
cffb2a26 5910 && ( register_operand (operands[0], QImode)
5911 || register_operand (operands[1], QImode))"
5565501b 5912 "@
5913 mov%?\\t%0, %1
5914 mvn%?\\t%0, #%B1
25f905c2 5915 ldr%(b%)\\t%0, %1
5916 str%(b%)\\t%1, %0"
a2cd141b 5917 [(set_attr "type" "*,*,load1,store1")
0d66636f 5918 (set_attr "predicable" "yes")]
cffb2a26 5919)
5920
25f905c2 5921(define_insn "*thumb1_movqi_insn"
cffb2a26 5922 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5923 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5924 "TARGET_THUMB1
cffb2a26 5925 && ( register_operand (operands[0], QImode)
5926 || register_operand (operands[1], QImode))"
5927 "@
5928 add\\t%0, %1, #0
5929 ldrb\\t%0, %1
5930 strb\\t%1, %0
5931 mov\\t%0, %1
5932 mov\\t%0, %1
5933 mov\\t%0, %1"
5934 [(set_attr "length" "2")
a2cd141b 5935 (set_attr "type" "*,load1,store1,*,*,*")
747b7458 5936 (set_attr "pool_range" "*,32,*,*,*,*")
5937 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 5938
9b8516be 5939;; HFmode moves
5940(define_expand "movhf"
5941 [(set (match_operand:HF 0 "general_operand" "")
5942 (match_operand:HF 1 "general_operand" ""))]
5943 "TARGET_EITHER"
5944 "
5945 if (TARGET_32BIT)
5946 {
5947 if (GET_CODE (operands[0]) == MEM)
5948 operands[1] = force_reg (HFmode, operands[1]);
5949 }
5950 else /* TARGET_THUMB1 */
5951 {
5952 if (can_create_pseudo_p ())
5953 {
5954 if (GET_CODE (operands[0]) != REG)
5955 operands[1] = force_reg (HFmode, operands[1]);
5956 }
5957 }
5958 "
5959)
5960
5961(define_insn "*arm32_movhf"
5962 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5963 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 5964 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 5965 && ( s_register_operand (operands[0], HFmode)
5966 || s_register_operand (operands[1], HFmode))"
5967 "*
5968 switch (which_alternative)
5969 {
5970 case 0: /* ARM register from memory */
5971 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5972 case 1: /* memory from ARM register */
5973 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5974 case 2: /* ARM register from ARM register */
5975 return \"mov%?\\t%0, %1\\t%@ __fp16\";
5976 case 3: /* ARM register from constant */
5977 {
5978 REAL_VALUE_TYPE r;
5979 long bits;
5980 rtx ops[4];
5981
5982 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
5983 bits = real_to_target (NULL, &r, HFmode);
5984 ops[0] = operands[0];
5985 ops[1] = GEN_INT (bits);
5986 ops[2] = GEN_INT (bits & 0xff00);
5987 ops[3] = GEN_INT (bits & 0x00ff);
5988
5989 if (arm_arch_thumb2)
5990 output_asm_insn (\"movw%?\\t%0, %1\", ops);
5991 else
5992 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
5993 return \"\";
5994 }
5995 default:
5996 gcc_unreachable ();
5997 }
5998 "
5999 [(set_attr "conds" "unconditional")
6000 (set_attr "type" "load1,store1,*,*")
6001 (set_attr "length" "4,4,4,8")
6002 (set_attr "predicable" "yes")
6003 ]
6004)
6005
6006(define_insn "*thumb1_movhf"
6007 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6008 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6009 "TARGET_THUMB1
6010 && ( s_register_operand (operands[0], HFmode)
6011 || s_register_operand (operands[1], HFmode))"
6012 "*
6013 switch (which_alternative)
6014 {
6015 case 1:
6016 {
6017 rtx addr;
6018 gcc_assert (GET_CODE(operands[1]) == MEM);
6019 addr = XEXP (operands[1], 0);
6020 if (GET_CODE (addr) == LABEL_REF
6021 || (GET_CODE (addr) == CONST
6022 && GET_CODE (XEXP (addr, 0)) == PLUS
6023 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6024 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6025 {
6026 /* Constant pool entry. */
6027 return \"ldr\\t%0, %1\";
6028 }
6029 return \"ldrh\\t%0, %1\";
6030 }
6031 case 2: return \"strh\\t%1, %0\";
6032 default: return \"mov\\t%0, %1\";
6033 }
6034 "
6035 [(set_attr "length" "2")
6036 (set_attr "type" "*,load1,store1,*,*")
747b7458 6037 (set_attr "pool_range" "*,1020,*,*,*")
6038 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6039
87b22bf7 6040(define_expand "movsf"
6041 [(set (match_operand:SF 0 "general_operand" "")
6042 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6043 "TARGET_EITHER"
87b22bf7 6044 "
25f905c2 6045 if (TARGET_32BIT)
cffb2a26 6046 {
6047 if (GET_CODE (operands[0]) == MEM)
6048 operands[1] = force_reg (SFmode, operands[1]);
6049 }
25f905c2 6050 else /* TARGET_THUMB1 */
cffb2a26 6051 {
e1ba4a27 6052 if (can_create_pseudo_p ())
cffb2a26 6053 {
6054 if (GET_CODE (operands[0]) != REG)
6055 operands[1] = force_reg (SFmode, operands[1]);
6056 }
6057 }
6058 "
6059)
6060
03d440a6 6061;; Transform a floating-point move of a constant into a core register into
6062;; an SImode operation.
cffb2a26 6063(define_split
03d440a6 6064 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6065 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6066 "TARGET_EITHER
cffb2a26 6067 && reload_completed
6068 && GET_CODE (operands[1]) == CONST_DOUBLE"
6069 [(set (match_dup 2) (match_dup 3))]
6070 "
6071 operands[2] = gen_lowpart (SImode, operands[0]);
6072 operands[3] = gen_lowpart (SImode, operands[1]);
6073 if (operands[2] == 0 || operands[3] == 0)
6074 FAIL;
215b30b3 6075 "
6076)
87b22bf7 6077
cffb2a26 6078(define_insn "*arm_movsf_soft_insn"
6079 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6080 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6081 "TARGET_32BIT
cffb2a26 6082 && TARGET_SOFT_FLOAT
215b30b3 6083 && (GET_CODE (operands[0]) != MEM
6084 || register_operand (operands[1], SFmode))"
9a1112d7 6085 "@
6086 mov%?\\t%0, %1
6087 ldr%?\\t%0, %1\\t%@ float
6088 str%?\\t%1, %0\\t%@ float"
cde1623a 6089 [(set_attr "predicable" "yes")
a2cd141b 6090 (set_attr "type" "*,load1,store1")
cffb2a26 6091 (set_attr "pool_range" "*,4096,*")
cde1623a 6092 (set_attr "arm_neg_pool_range" "*,4084,*")
6093 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6094)
6095
6096;;; ??? This should have alternatives for constants.
25f905c2 6097(define_insn "*thumb1_movsf_insn"
215b30b3 6098 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6099 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6100 "TARGET_THUMB1
cffb2a26 6101 && ( register_operand (operands[0], SFmode)
6102 || register_operand (operands[1], SFmode))"
6103 "@
6104 add\\t%0, %1, #0
6105 ldmia\\t%1, {%0}
6106 stmia\\t%0, {%1}
6107 ldr\\t%0, %1
6108 str\\t%1, %0
6109 mov\\t%0, %1
6110 mov\\t%0, %1"
6111 [(set_attr "length" "2")
a2cd141b 6112 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6113 (set_attr "pool_range" "*,*,*,1020,*,*,*")
6114 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6115)
9a1112d7 6116
9c08d1fa 6117(define_expand "movdf"
87b22bf7 6118 [(set (match_operand:DF 0 "general_operand" "")
6119 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6120 "TARGET_EITHER"
9c08d1fa 6121 "
25f905c2 6122 if (TARGET_32BIT)
cffb2a26 6123 {
6124 if (GET_CODE (operands[0]) == MEM)
6125 operands[1] = force_reg (DFmode, operands[1]);
6126 }
6127 else /* TARGET_THUMB */
6128 {
e1ba4a27 6129 if (can_create_pseudo_p ())
cffb2a26 6130 {
6131 if (GET_CODE (operands[0]) != REG)
6132 operands[1] = force_reg (DFmode, operands[1]);
6133 }
6134 }
6135 "
6136)
b11cae9e 6137
9c08d1fa 6138;; Reloading a df mode value stored in integer regs to memory can require a
6139;; scratch reg.
6140(define_expand "reload_outdf"
cffb2a26 6141 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6142 (match_operand:DF 1 "s_register_operand" "r")
6143 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6144 "TARGET_32BIT"
87b22bf7 6145 "
215b30b3 6146 {
6147 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6148
215b30b3 6149 if (code == REG)
6150 operands[2] = XEXP (operands[0], 0);
6151 else if (code == POST_INC || code == PRE_DEC)
6152 {
6153 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6154 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6155 emit_insn (gen_movdi (operands[0], operands[1]));
6156 DONE;
6157 }
6158 else if (code == PRE_INC)
6159 {
6160 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6161
215b30b3 6162 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6163 operands[2] = reg;
6164 }
6165 else if (code == POST_DEC)
6166 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6167 else
6168 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6169 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6170
788fcce0 6171 emit_insn (gen_rtx_SET (VOIDmode,
6172 replace_equiv_address (operands[0], operands[2]),
215b30b3 6173 operands[1]));
f7fbdd4a 6174
215b30b3 6175 if (code == POST_DEC)
6176 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6177
6178 DONE;
6179 }"
6180)
9c08d1fa 6181
9a1112d7 6182(define_insn "*movdf_soft_insn"
359a6e9f 6183 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6184 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6185 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6186 && ( register_operand (operands[0], DFmode)
6187 || register_operand (operands[1], DFmode))"
d51f92df 6188 "*
6189 switch (which_alternative)
6190 {
6191 case 0:
6192 case 1:
6193 case 2:
6194 return \"#\";
6195 default:
6196 return output_move_double (operands);
6197 }
6198 "
359a6e9f 6199 [(set_attr "length" "8,12,16,8,8")
6200 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6201 (set_attr "pool_range" "*,*,*,1020,*")
6202 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6203 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6204)
6205
6206;;; ??? This should have alternatives for constants.
6207;;; ??? This was originally identical to the movdi_insn pattern.
6208;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6209;;; thumb_reorg with a memory reference.
6210(define_insn "*thumb_movdf_insn"
215b30b3 6211 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6212 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6213 "TARGET_THUMB1
cffb2a26 6214 && ( register_operand (operands[0], DFmode)
6215 || register_operand (operands[1], DFmode))"
6216 "*
6217 switch (which_alternative)
6218 {
6219 default:
6220 case 0:
6221 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6222 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6223 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6224 case 1:
6225 return \"ldmia\\t%1, {%0, %H0}\";
6226 case 2:
6227 return \"stmia\\t%0, {%1, %H1}\";
6228 case 3:
6229 return thumb_load_double_from_address (operands);
6230 case 4:
1a83b3ff 6231 operands[2] = gen_rtx_MEM (SImode,
6232 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6233 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6234 return \"\";
6235 case 5:
6236 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6237 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6238 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6239 }
6240 "
6241 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6242 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 6243 (set_attr "pool_range" "*,*,*,1020,*,*")]
6244)
755eb2b4 6245
ccd90aaa 6246(define_expand "movxf"
6247 [(set (match_operand:XF 0 "general_operand" "")
6248 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6249 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6250 "
6251 if (GET_CODE (operands[0]) == MEM)
6252 operands[1] = force_reg (XFmode, operands[1]);
6253 "
6254)
6255
b11cae9e 6256\f
b11cae9e 6257
9c08d1fa 6258;; load- and store-multiple insns
6259;; The arm can load/store any set of registers, provided that they are in
320ea44d 6260;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6261
9c08d1fa 6262(define_expand "load_multiple"
6263 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6264 (match_operand:SI 1 "" ""))
6265 (use (match_operand:SI 2 "" ""))])]
25f905c2 6266 "TARGET_32BIT"
9580c25f 6267{
6268 HOST_WIDE_INT offset = 0;
6269
bd5b4116 6270 /* Support only fixed point registers. */
9c08d1fa 6271 if (GET_CODE (operands[2]) != CONST_INT
6272 || INTVAL (operands[2]) > 14
6273 || INTVAL (operands[2]) < 2
6274 || GET_CODE (operands[1]) != MEM
6275 || GET_CODE (operands[0]) != REG
bd5b4116 6276 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6277 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6278 FAIL;
6279
6280 operands[3]
320ea44d 6281 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6282 INTVAL (operands[2]),
f082f1c4 6283 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6284 FALSE, operands[1], &offset);
9580c25f 6285})
b11cae9e 6286
9c08d1fa 6287(define_expand "store_multiple"
6288 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6289 (match_operand:SI 1 "" ""))
6290 (use (match_operand:SI 2 "" ""))])]
25f905c2 6291 "TARGET_32BIT"
9580c25f 6292{
6293 HOST_WIDE_INT offset = 0;
6294
674a8f0b 6295 /* Support only fixed point registers. */
9c08d1fa 6296 if (GET_CODE (operands[2]) != CONST_INT
6297 || INTVAL (operands[2]) > 14
6298 || INTVAL (operands[2]) < 2
6299 || GET_CODE (operands[1]) != REG
6300 || GET_CODE (operands[0]) != MEM
bd5b4116 6301 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6302 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6303 FAIL;
6304
6305 operands[3]
320ea44d 6306 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6307 INTVAL (operands[2]),
f082f1c4 6308 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6309 FALSE, operands[0], &offset);
9580c25f 6310})
b11cae9e 6311
9c08d1fa 6312
6313;; Move a block of memory if it is word aligned and MORE than 2 words long.
6314;; We could let this apply for blocks of less than this, but it clobbers so
6315;; many registers that there is then probably a better way.
6316
008c057d 6317(define_expand "movmemqi"
34191dd1 6318 [(match_operand:BLK 0 "general_operand" "")
6319 (match_operand:BLK 1 "general_operand" "")
6320 (match_operand:SI 2 "const_int_operand" "")
6321 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6322 "TARGET_EITHER"
9c08d1fa 6323 "
25f905c2 6324 if (TARGET_32BIT)
cffb2a26 6325 {
008c057d 6326 if (arm_gen_movmemqi (operands))
cffb2a26 6327 DONE;
6328 FAIL;
6329 }
25f905c2 6330 else /* TARGET_THUMB1 */
cffb2a26 6331 {
6332 if ( INTVAL (operands[3]) != 4
6333 || INTVAL (operands[2]) > 48)
6334 FAIL;
6335
008c057d 6336 thumb_expand_movmemqi (operands);
cffb2a26 6337 DONE;
6338 }
6339 "
6340)
6341
2162064c 6342;; Thumb block-move insns
cffb2a26 6343
6344(define_insn "movmem12b"
960f3acf 6345 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6346 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6347 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6348 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6349 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6350 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6351 (set (match_operand:SI 0 "register_operand" "=l")
6352 (plus:SI (match_dup 2) (const_int 12)))
6353 (set (match_operand:SI 1 "register_operand" "=l")
6354 (plus:SI (match_dup 3) (const_int 12)))
6355 (clobber (match_scratch:SI 4 "=&l"))
6356 (clobber (match_scratch:SI 5 "=&l"))
6357 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6358 "TARGET_THUMB1"
cffb2a26 6359 "* return thumb_output_move_mem_multiple (3, operands);"
6360 [(set_attr "length" "4")
215b30b3 6361 ; This isn't entirely accurate... It loads as well, but in terms of
6362 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6363 (set_attr "type" "store3")]
6364)
6365
6366(define_insn "movmem8b"
960f3acf 6367 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6368 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6369 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6370 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6371 (set (match_operand:SI 0 "register_operand" "=l")
6372 (plus:SI (match_dup 2) (const_int 8)))
6373 (set (match_operand:SI 1 "register_operand" "=l")
6374 (plus:SI (match_dup 3) (const_int 8)))
6375 (clobber (match_scratch:SI 4 "=&l"))
6376 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6377 "TARGET_THUMB1"
cffb2a26 6378 "* return thumb_output_move_mem_multiple (2, operands);"
6379 [(set_attr "length" "4")
215b30b3 6380 ; This isn't entirely accurate... It loads as well, but in terms of
6381 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6382 (set_attr "type" "store2")]
6383)
6384
9c08d1fa 6385\f
b11cae9e 6386
341940e8 6387;; Compare & branch insns
8d232dc7 6388;; The range calculations are based as follows:
341940e8 6389;; For forward branches, the address calculation returns the address of
6390;; the next instruction. This is 2 beyond the branch instruction.
6391;; For backward branches, the address calculation returns the address of
6392;; the first instruction in this pattern (cmp). This is 2 before the branch
6393;; instruction for the shortest sequence, and 4 before the branch instruction
6394;; if we have to jump around an unconditional branch.
6395;; To the basic branch range the PC offset must be added (this is +4).
6396;; So for forward branches we have
6397;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6398;; And for backward branches we have
6399;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6400;;
6401;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6402;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6403
aeac46d4 6404(define_expand "cbranchsi4"
6405 [(set (pc) (if_then_else
6406 (match_operator 0 "arm_comparison_operator"
6407 [(match_operand:SI 1 "s_register_operand" "")
6408 (match_operand:SI 2 "nonmemory_operand" "")])
6409 (label_ref (match_operand 3 "" ""))
6410 (pc)))]
74f4459c 6411 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6412 "
74f4459c 6413 if (!TARGET_THUMB1)
6414 {
6415 if (!arm_add_operand (operands[2], SImode))
6416 operands[2] = force_reg (SImode, operands[2]);
6417 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6418 operands[3]));
6419 DONE;
6420 }
25f905c2 6421 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6422 {
6423 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6424 operands[3], operands[0]));
6425 DONE;
6426 }
25f905c2 6427 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6428 operands[2] = force_reg (SImode, operands[2]);
6429 ")
6430
a8e6c15d 6431;; A pattern to recognize a special situation and optimize for it.
6432;; On the thumb, zero-extension from memory is preferrable to sign-extension
6433;; due to the available addressing modes. Hence, convert a signed comparison
6434;; with zero into an unsigned comparison with 127 if possible.
6435(define_expand "cbranchqi4"
6436 [(set (pc) (if_then_else
6437 (match_operator 0 "lt_ge_comparison_operator"
6438 [(match_operand:QI 1 "memory_operand" "")
6439 (match_operand:QI 2 "const0_operand" "")])
6440 (label_ref (match_operand 3 "" ""))
6441 (pc)))]
6442 "TARGET_THUMB1"
6443{
d0f6c30d 6444 rtx xops[4];
a8e6c15d 6445 xops[1] = gen_reg_rtx (SImode);
6446 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6447 xops[2] = GEN_INT (127);
6448 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6449 VOIDmode, xops[1], xops[2]);
6450 xops[3] = operands[3];
6451 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6452 DONE;
6453})
6454
74f4459c 6455(define_expand "cbranchsf4"
6456 [(set (pc) (if_then_else
6457 (match_operator 0 "arm_comparison_operator"
6458 [(match_operand:SF 1 "s_register_operand" "")
6459 (match_operand:SF 2 "arm_float_compare_operand" "")])
6460 (label_ref (match_operand 3 "" ""))
6461 (pc)))]
6462 "TARGET_32BIT && TARGET_HARD_FLOAT"
6463 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6464 operands[3])); DONE;"
6465)
6466
6467(define_expand "cbranchdf4"
6468 [(set (pc) (if_then_else
6469 (match_operator 0 "arm_comparison_operator"
6470 [(match_operand:DF 1 "s_register_operand" "")
6471 (match_operand:DF 2 "arm_float_compare_operand" "")])
6472 (label_ref (match_operand 3 "" ""))
6473 (pc)))]
a50d7267 6474 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6475 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6476 operands[3])); DONE;"
6477)
6478
74f4459c 6479(define_expand "cbranchdi4"
6480 [(set (pc) (if_then_else
6481 (match_operator 0 "arm_comparison_operator"
a8045a4f 6482 [(match_operand:DI 1 "cmpdi_operand" "")
6483 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6484 (label_ref (match_operand 3 "" ""))
6485 (pc)))]
a8045a4f 6486 "TARGET_32BIT"
6487 "{
6488 rtx swap = NULL_RTX;
6489 enum rtx_code code = GET_CODE (operands[0]);
6490
6491 /* We should not have two constants. */
6492 gcc_assert (GET_MODE (operands[1]) == DImode
6493 || GET_MODE (operands[2]) == DImode);
6494
6495 /* Flip unimplemented DImode comparisons to a form that
6496 arm_gen_compare_reg can handle. */
6497 switch (code)
6498 {
6499 case GT:
6500 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6501 case LE:
6502 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6503 case GTU:
6504 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6505 case LEU:
6506 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6507 default:
6508 break;
6509 }
6510 if (swap)
6511 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6512 operands[3]));
6513 else
6514 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6515 operands[3]));
6516 DONE;
6517 }"
74f4459c 6518)
6519
d60047aa 6520(define_insn "cbranchsi4_insn"
aeac46d4 6521 [(set (pc) (if_then_else
6522 (match_operator 0 "arm_comparison_operator"
747b7458 6523 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 6524 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6525 (label_ref (match_operand 3 "" ""))
6526 (pc)))]
25f905c2 6527 "TARGET_THUMB1"
747b7458 6528{
6529 rtx t = cfun->machine->thumb1_cc_insn;
6530 if (t != NULL_RTX)
d60047aa 6531 {
747b7458 6532 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6533 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6534 t = NULL_RTX;
6535 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6536 {
6537 if (!noov_comparison_operator (operands[0], VOIDmode))
6538 t = NULL_RTX;
6539 }
6540 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 6541 t = NULL_RTX;
6542 }
d60047aa 6543 if (t == NULL_RTX)
747b7458 6544 {
6545 output_asm_insn ("cmp\t%1, %2", operands);
6546 cfun->machine->thumb1_cc_insn = insn;
6547 cfun->machine->thumb1_cc_op0 = operands[1];
6548 cfun->machine->thumb1_cc_op1 = operands[2];
6549 cfun->machine->thumb1_cc_mode = CCmode;
6550 }
6551 else
6552 /* Ensure we emit the right type of condition code on the jump. */
6553 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6554 CC_REGNUM);
aeac46d4 6555
cffb2a26 6556 switch (get_attr_length (insn))
6557 {
6558 case 4: return \"b%d0\\t%l3\";
6559 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6560 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6561 }
747b7458 6562}
cffb2a26 6563 [(set (attr "far_jump")
6564 (if_then_else
6565 (eq_attr "length" "8")
6566 (const_string "yes")
6567 (const_string "no")))
6568 (set (attr "length")
6569 (if_then_else
6570 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6571 (le (minus (match_dup 3) (pc)) (const_int 256)))
6572 (const_int 4)
6573 (if_then_else
6574 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6575 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6576 (const_int 6)
6577 (const_int 8))))]
6578)
6579
aeac46d4 6580(define_insn "cbranchsi4_scratch"
6581 [(set (pc) (if_then_else
6582 (match_operator 4 "arm_comparison_operator"
6583 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6584 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6585 (label_ref (match_operand 3 "" ""))
6586 (pc)))
6587 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6588 "TARGET_THUMB1"
aeac46d4 6589 "*
6590 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6591
6592 switch (get_attr_length (insn))
6593 {
6594 case 4: return \"b%d4\\t%l3\";
6595 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6596 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6597 }
6598 "
6599 [(set (attr "far_jump")
6600 (if_then_else
6601 (eq_attr "length" "8")
6602 (const_string "yes")
6603 (const_string "no")))
6604 (set (attr "length")
6605 (if_then_else
6606 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6607 (le (minus (match_dup 3) (pc)) (const_int 256)))
6608 (const_int 4)
6609 (if_then_else
6610 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6611 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6612 (const_int 6)
6613 (const_int 8))))]
6614)
446a1e96 6615
747b7458 6616;; Two peepholes to generate subtract of 0 instead of a move if the
6617;; condition codes will be useful.
446a1e96 6618(define_peephole2
6619 [(set (match_operand:SI 0 "low_register_operand" "")
6620 (match_operand:SI 1 "low_register_operand" ""))
6621 (set (pc)
6622 (if_then_else (match_operator 2 "arm_comparison_operator"
6623 [(match_dup 1) (const_int 0)])
6624 (label_ref (match_operand 3 "" ""))
6625 (pc)))]
6626 "TARGET_THUMB1"
747b7458 6627 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6628 (set (pc)
6629 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6630 (label_ref (match_dup 3))
747b7458 6631 (pc)))]
6632 "")
446a1e96 6633
6634;; Sigh! This variant shouldn't be needed, but combine often fails to
6635;; merge cases like this because the op1 is a hard register in
6636;; CLASS_LIKELY_SPILLED_P.
6637(define_peephole2
6638 [(set (match_operand:SI 0 "low_register_operand" "")
6639 (match_operand:SI 1 "low_register_operand" ""))
6640 (set (pc)
6641 (if_then_else (match_operator 2 "arm_comparison_operator"
6642 [(match_dup 0) (const_int 0)])
6643 (label_ref (match_operand 3 "" ""))
6644 (pc)))]
6645 "TARGET_THUMB1"
747b7458 6646 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6647 (set (pc)
6648 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 6649 (label_ref (match_dup 3))
747b7458 6650 (pc)))]
6651 "")
446a1e96 6652
cffb2a26 6653(define_insn "*negated_cbranchsi4"
6654 [(set (pc)
6655 (if_then_else
aed179ae 6656 (match_operator 0 "equality_operator"
aeac46d4 6657 [(match_operand:SI 1 "s_register_operand" "l")
6658 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6659 (label_ref (match_operand 3 "" ""))
215b30b3 6660 (pc)))]
25f905c2 6661 "TARGET_THUMB1"
cffb2a26 6662 "*
6663 output_asm_insn (\"cmn\\t%1, %2\", operands);
6664 switch (get_attr_length (insn))
6665 {
6666 case 4: return \"b%d0\\t%l3\";
6667 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6668 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6669 }
6670 "
6671 [(set (attr "far_jump")
6672 (if_then_else
6673 (eq_attr "length" "8")
6674 (const_string "yes")
6675 (const_string "no")))
6676 (set (attr "length")
6677 (if_then_else
6678 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6679 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6680 (const_int 4)
6681 (if_then_else
341940e8 6682 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6683 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6684 (const_int 6)
6685 (const_int 8))))]
6686)
6687
58d6528b 6688(define_insn "*tbit_cbranch"
6689 [(set (pc)
6690 (if_then_else
6691 (match_operator 0 "equality_operator"
6692 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6693 (const_int 1)
6694 (match_operand:SI 2 "const_int_operand" "i"))
6695 (const_int 0)])
6696 (label_ref (match_operand 3 "" ""))
6697 (pc)))
6698 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6699 "TARGET_THUMB1"
58d6528b 6700 "*
6701 {
6702 rtx op[3];
6703 op[0] = operands[4];
6704 op[1] = operands[1];
6705 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6706
86efa74d 6707 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6708 switch (get_attr_length (insn))
6709 {
6710 case 4: return \"b%d0\\t%l3\";
6711 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6712 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6713 }
6714 }"
6715 [(set (attr "far_jump")
6716 (if_then_else
6717 (eq_attr "length" "8")
6718 (const_string "yes")
6719 (const_string "no")))
6720 (set (attr "length")
6721 (if_then_else
6722 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6723 (le (minus (match_dup 3) (pc)) (const_int 256)))
6724 (const_int 4)
6725 (if_then_else
6726 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6727 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6728 (const_int 6)
6729 (const_int 8))))]
6730)
6731
6732(define_insn "*tlobits_cbranch"
6733 [(set (pc)
6734 (if_then_else
6735 (match_operator 0 "equality_operator"
6736 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6737 (match_operand:SI 2 "const_int_operand" "i")
6738 (const_int 0))
6739 (const_int 0)])
6740 (label_ref (match_operand 3 "" ""))
6741 (pc)))
6742 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6743 "TARGET_THUMB1"
86efa74d 6744 "*
6745 {
6746 rtx op[3];
6747 op[0] = operands[4];
6748 op[1] = operands[1];
6749 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6750
58d6528b 6751 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6752 switch (get_attr_length (insn))
6753 {
6754 case 4: return \"b%d0\\t%l3\";
6755 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6756 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6757 }
6758 }"
6759 [(set (attr "far_jump")
6760 (if_then_else
6761 (eq_attr "length" "8")
6762 (const_string "yes")
6763 (const_string "no")))
6764 (set (attr "length")
6765 (if_then_else
6766 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6767 (le (minus (match_dup 3) (pc)) (const_int 256)))
6768 (const_int 4)
6769 (if_then_else
6770 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6771 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6772 (const_int 6)
6773 (const_int 8))))]
6774)
747b7458 6775
aeac46d4 6776(define_insn "*tstsi3_cbranch"
58d6528b 6777 [(set (pc)
6778 (if_then_else
aeac46d4 6779 (match_operator 3 "equality_operator"
6780 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6781 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6782 (const_int 0)])
aeac46d4 6783 (label_ref (match_operand 2 "" ""))
6784 (pc)))]
25f905c2 6785 "TARGET_THUMB1"
58d6528b 6786 "*
6787 {
aeac46d4 6788 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6789 switch (get_attr_length (insn))
6790 {
aeac46d4 6791 case 4: return \"b%d3\\t%l2\";
6792 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6793 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6794 }
6795 }"
6796 [(set (attr "far_jump")
6797 (if_then_else
6798 (eq_attr "length" "8")
6799 (const_string "yes")
6800 (const_string "no")))
6801 (set (attr "length")
6802 (if_then_else
aeac46d4 6803 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6804 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6805 (const_int 4)
6806 (if_then_else
aeac46d4 6807 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6808 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6809 (const_int 6)
6810 (const_int 8))))]
6811)
6812
203c488f 6813(define_insn "*cbranchne_decr1"
6814 [(set (pc)
6815 (if_then_else (match_operator 3 "equality_operator"
6816 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6817 (const_int 0)])
6818 (label_ref (match_operand 4 "" ""))
6819 (pc)))
aeac46d4 6820 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6821 (plus:SI (match_dup 2) (const_int -1)))
6822 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6823 "TARGET_THUMB1"
203c488f 6824 "*
6825 {
6826 rtx cond[2];
6827 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6828 ? GEU : LTU),
58d6528b 6829 VOIDmode, operands[2], const1_rtx);
203c488f 6830 cond[1] = operands[4];
6831
6832 if (which_alternative == 0)
6833 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6834 else if (which_alternative == 1)
6835 {
6836 /* We must provide an alternative for a hi reg because reload
6837 cannot handle output reloads on a jump instruction, but we
6838 can't subtract into that. Fortunately a mov from lo to hi
6839 does not clobber the condition codes. */
6840 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6841 output_asm_insn (\"mov\\t%0, %1\", operands);
6842 }
6843 else
6844 {
6845 /* Similarly, but the target is memory. */
6846 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6847 output_asm_insn (\"str\\t%1, %0\", operands);
6848 }
6849
6850 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6851 {
6852 case 4:
8aea555f 6853 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6854 return \"\";
6855 case 6:
8aea555f 6856 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6857 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6858 default:
8aea555f 6859 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6860 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6861 }
6862 }
6863 "
6864 [(set (attr "far_jump")
6865 (if_then_else
6866 (ior (and (eq (symbol_ref ("which_alternative"))
6867 (const_int 0))
6868 (eq_attr "length" "8"))
6869 (eq_attr "length" "10"))
6870 (const_string "yes")
6871 (const_string "no")))
6872 (set_attr_alternative "length"
6873 [
6874 ;; Alternative 0
6875 (if_then_else
6876 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6877 (le (minus (match_dup 4) (pc)) (const_int 256)))
6878 (const_int 4)
6879 (if_then_else
6880 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6881 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6882 (const_int 6)
6883 (const_int 8)))
6884 ;; Alternative 1
6885 (if_then_else
6886 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6887 (le (minus (match_dup 4) (pc)) (const_int 256)))
6888 (const_int 6)
6889 (if_then_else
6890 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6891 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6892 (const_int 8)
6893 (const_int 10)))
6894 ;; Alternative 2
6895 (if_then_else
6896 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6897 (le (minus (match_dup 4) (pc)) (const_int 256)))
6898 (const_int 6)
6899 (if_then_else
6900 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6901 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6902 (const_int 8)
6903 (const_int 10)))
6904 ;; Alternative 3
6905 (if_then_else
6906 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6907 (le (minus (match_dup 4) (pc)) (const_int 256)))
6908 (const_int 6)
6909 (if_then_else
6910 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6911 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6912 (const_int 8)
6913 (const_int 10)))])]
6914)
cffb2a26 6915
58d6528b 6916(define_insn "*addsi3_cbranch"
6917 [(set (pc)
6918 (if_then_else
b0694be0 6919 (match_operator 4 "arm_comparison_operator"
58d6528b 6920 [(plus:SI
e54011cb 6921 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
6922 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 6923 (const_int 0)])
6924 (label_ref (match_operand 5 "" ""))
6925 (pc)))
aeac46d4 6926 (set
6927 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6928 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 6929 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 6930 "TARGET_THUMB1
58d6528b 6931 && (GET_CODE (operands[4]) == EQ
6932 || GET_CODE (operands[4]) == NE
6933 || GET_CODE (operands[4]) == GE
6934 || GET_CODE (operands[4]) == LT)"
6935 "*
6936 {
6937 rtx cond[3];
6938
956a6170 6939 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 6940 cond[1] = operands[2];
6941 cond[2] = operands[3];
6942
6943 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6944 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6945 else
6946 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6947
956a6170 6948 if (which_alternative >= 2
58d6528b 6949 && which_alternative < 4)
6950 output_asm_insn (\"mov\\t%0, %1\", operands);
6951 else if (which_alternative >= 4)
6952 output_asm_insn (\"str\\t%1, %0\", operands);
6953
d0f6c30d 6954 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 6955 {
6956 case 4:
6957 return \"b%d4\\t%l5\";
6958 case 6:
6959 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6960 default:
6961 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6962 }
6963 }
6964 "
6965 [(set (attr "far_jump")
6966 (if_then_else
6967 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 6968 (const_int 2))
58d6528b 6969 (eq_attr "length" "8"))
6970 (eq_attr "length" "10"))
6971 (const_string "yes")
6972 (const_string "no")))
6973 (set (attr "length")
6974 (if_then_else
6975 (lt (symbol_ref ("which_alternative"))
d0f6c30d 6976 (const_int 2))
58d6528b 6977 (if_then_else
6978 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6979 (le (minus (match_dup 5) (pc)) (const_int 256)))
6980 (const_int 4)
6981 (if_then_else
6982 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6983 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6984 (const_int 6)
6985 (const_int 8)))
6986 (if_then_else
6987 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6988 (le (minus (match_dup 5) (pc)) (const_int 256)))
6989 (const_int 6)
6990 (if_then_else
6991 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6992 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6993 (const_int 8)
6994 (const_int 10)))))]
6995)
6996
6997(define_insn "*addsi3_cbranch_scratch"
6998 [(set (pc)
6999 (if_then_else
b0694be0 7000 (match_operator 3 "arm_comparison_operator"
58d6528b 7001 [(plus:SI
7002 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7003 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7004 (const_int 0)])
7005 (label_ref (match_operand 4 "" ""))
7006 (pc)))
7007 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7008 "TARGET_THUMB1
58d6528b 7009 && (GET_CODE (operands[3]) == EQ
7010 || GET_CODE (operands[3]) == NE
7011 || GET_CODE (operands[3]) == GE
7012 || GET_CODE (operands[3]) == LT)"
7013 "*
7014 {
7015 switch (which_alternative)
7016 {
7017 case 0:
7018 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7019 break;
7020 case 1:
7021 output_asm_insn (\"cmn\t%1, %2\", operands);
7022 break;
0f5e9701 7023 case 2:
3a445a04 7024 if (INTVAL (operands[2]) < 0)
7025 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7026 else
7027 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7028 break;
0f5e9701 7029 case 3:
3a445a04 7030 if (INTVAL (operands[2]) < 0)
7031 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7032 else
7033 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7034 break;
7035 }
7036
7037 switch (get_attr_length (insn))
7038 {
7039 case 4:
7040 return \"b%d3\\t%l4\";
7041 case 6:
7042 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7043 default:
7044 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7045 }
7046 }
7047 "
7048 [(set (attr "far_jump")
7049 (if_then_else
7050 (eq_attr "length" "8")
7051 (const_string "yes")
7052 (const_string "no")))
7053 (set (attr "length")
7054 (if_then_else
7055 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7056 (le (minus (match_dup 4) (pc)) (const_int 256)))
7057 (const_int 4)
7058 (if_then_else
7059 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7060 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7061 (const_int 6)
7062 (const_int 8))))]
7063)
7064
58d6528b 7065
9c08d1fa 7066;; Comparison and test insns
7067
cffb2a26 7068(define_insn "*arm_cmpsi_insn"
bd5b4116 7069 [(set (reg:CC CC_REGNUM)
aea4c774 7070 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7071 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7072 "TARGET_32BIT"
5565501b 7073 "@
aea4c774 7074 cmp%?\\t%0, %1
7075 cmn%?\\t%0, #%n1"
cffb2a26 7076 [(set_attr "conds" "set")]
7077)
b11cae9e 7078
d5d4dc8d 7079(define_insn "*cmpsi_shiftsi"
bd5b4116 7080 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7081 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7082 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7083 [(match_operand:SI 1 "s_register_operand" "r,r")
7084 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7085 "TARGET_32BIT"
aea4c774 7086 "cmp%?\\t%0, %1%S3"
344495ea 7087 [(set_attr "conds" "set")
331beb1a 7088 (set_attr "shift" "1")
d5d4dc8d 7089 (set_attr "arch" "32,a")
7090 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7091
d5d4dc8d 7092(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7093 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7094 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7095 [(match_operand:SI 1 "s_register_operand" "r,r")
7096 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7097 (match_operand:SI 0 "s_register_operand" "r,r")))]
7098 "TARGET_32BIT"
aea4c774 7099 "cmp%?\\t%0, %1%S3"
344495ea 7100 [(set_attr "conds" "set")
331beb1a 7101 (set_attr "shift" "1")
d5d4dc8d 7102 (set_attr "arch" "32,a")
7103 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7104
25f905c2 7105(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7106 [(set (reg:CC_Z CC_REGNUM)
7107 (compare:CC_Z
7108 (neg:SI (match_operator:SI 1 "shift_operator"
7109 [(match_operand:SI 2 "s_register_operand" "r")
7110 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7111 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7112 "TARGET_ARM"
aed179ae 7113 "cmn%?\\t%0, %2%S1"
344495ea 7114 [(set_attr "conds" "set")
aed179ae 7115 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7116 (const_string "alu_shift")
7117 (const_string "alu_shift_reg")))]
0d66636f 7118)
b11cae9e 7119
a8045a4f 7120;; DImode comparisons. The generic code generates branches that
7121;; if-conversion can not reduce to a conditional compare, so we do
7122;; that directly.
7123
7124(define_insn "*arm_cmpdi_insn"
7125 [(set (reg:CC_NCV CC_REGNUM)
7126 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7127 (match_operand:DI 1 "arm_di_operand" "rDi")))
7128 (clobber (match_scratch:SI 2 "=r"))]
7129 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7130 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7131 [(set_attr "conds" "set")
7132 (set_attr "length" "8")]
7133)
7134
7135(define_insn "*arm_cmpdi_unsigned"
7136 [(set (reg:CC_CZ CC_REGNUM)
7137 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7138 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7139 "TARGET_ARM"
7140 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7141 [(set_attr "conds" "set")
7142 (set_attr "length" "8")]
7143)
7144
7145(define_insn "*arm_cmpdi_zero"
7146 [(set (reg:CC_Z CC_REGNUM)
7147 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7148 (const_int 0)))
7149 (clobber (match_scratch:SI 1 "=r"))]
7150 "TARGET_32BIT"
7151 "orr%.\\t%1, %Q0, %R0"
7152 [(set_attr "conds" "set")]
7153)
7154
7155(define_insn "*thumb_cmpdi_zero"
7156 [(set (reg:CC_Z CC_REGNUM)
7157 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7158 (const_int 0)))
7159 (clobber (match_scratch:SI 1 "=l"))]
7160 "TARGET_THUMB1"
7161 "orr\\t%1, %Q0, %R0"
7162 [(set_attr "conds" "set")
7163 (set_attr "length" "2")]
7164)
7165
7d57ec45 7166;; Cirrus SF compare instruction
7167(define_insn "*cirrus_cmpsf"
7168 [(set (reg:CCFP CC_REGNUM)
7169 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7170 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7171 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7172 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7173 [(set_attr "type" "mav_farith")
7d57ec45 7174 (set_attr "cirrus" "compare")]
7175)
7176
7177;; Cirrus DF compare instruction
7178(define_insn "*cirrus_cmpdf"
7179 [(set (reg:CCFP CC_REGNUM)
7180 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7181 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7182 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7183 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7184 [(set_attr "type" "mav_farith")
7d57ec45 7185 (set_attr "cirrus" "compare")]
7186)
7187
7d57ec45 7188(define_insn "*cirrus_cmpdi"
7189 [(set (reg:CC CC_REGNUM)
7190 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7191 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7192 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7193 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7194 [(set_attr "type" "mav_farith")
7d57ec45 7195 (set_attr "cirrus" "compare")]
7196)
7197
9c08d1fa 7198; This insn allows redundant compares to be removed by cse, nothing should
7199; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7200; is deleted later on. The match_dup will match the mode here, so that
7201; mode changes of the condition codes aren't lost by this even though we don't
7202; specify what they are.
7203
8a18b90c 7204(define_insn "*deleted_compare"
9c08d1fa 7205 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7206 "TARGET_32BIT"
40dbec34 7207 "\\t%@ deleted compare"
cffb2a26 7208 [(set_attr "conds" "set")
7209 (set_attr "length" "0")]
7210)
9c08d1fa 7211
7212\f
7213;; Conditional branch insns
7214
74f4459c 7215(define_expand "cbranch_cc"
9c08d1fa 7216 [(set (pc)
74f4459c 7217 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7218 (match_operand 2 "" "")])
7219 (label_ref (match_operand 3 "" ""))
9c08d1fa 7220 (pc)))]
25f905c2 7221 "TARGET_32BIT"
74f4459c 7222 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7223 operands[1], operands[2]);
7224 operands[2] = const0_rtx;"
8fa3ba89 7225)
7226
7227;;
7228;; Patterns to match conditional branch insns.
7229;;
7230
cffb2a26 7231(define_insn "*arm_cond_branch"
9c08d1fa 7232 [(set (pc)
8fa3ba89 7233 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7234 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7235 (label_ref (match_operand 0 "" ""))
7236 (pc)))]
25f905c2 7237 "TARGET_32BIT"
d75350ce 7238 "*
9c08d1fa 7239 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7240 {
7241 arm_ccfsm_state += 2;
7242 return \"\";
7243 }
e2348bcb 7244 return \"b%d1\\t%l0\";
cffb2a26 7245 "
a2cd141b 7246 [(set_attr "conds" "use")
7247 (set_attr "type" "branch")]
cffb2a26 7248)
d75350ce 7249
cffb2a26 7250(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7251 [(set (pc)
8fa3ba89 7252 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7253 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7254 (pc)
7255 (label_ref (match_operand 0 "" ""))))]
25f905c2 7256 "TARGET_32BIT"
d75350ce 7257 "*
9c08d1fa 7258 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7259 {
7260 arm_ccfsm_state += 2;
7261 return \"\";
7262 }
e2348bcb 7263 return \"b%D1\\t%l0\";
cffb2a26 7264 "
a2cd141b 7265 [(set_attr "conds" "use")
7266 (set_attr "type" "branch")]
cffb2a26 7267)
7268
b11cae9e 7269\f
9c08d1fa 7270
7271; scc insns
7272
74f4459c 7273(define_expand "cstore_cc"
7db9af5d 7274 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7275 (match_operator:SI 1 "" [(match_operand 2 "" "")
7276 (match_operand 3 "" "")]))]
25f905c2 7277 "TARGET_32BIT"
74f4459c 7278 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7279 operands[2], operands[3]);
7280 operands[3] = const0_rtx;"
8fa3ba89 7281)
7282
f7fbdd4a 7283(define_insn "*mov_scc"
9c08d1fa 7284 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7285 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7286 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7287 "TARGET_ARM"
4d61e570 7288 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7289 [(set_attr "conds" "use")
7290 (set_attr "length" "8")]
7291)
9c08d1fa 7292
f7fbdd4a 7293(define_insn "*mov_negscc"
9c08d1fa 7294 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7295 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7296 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7297 "TARGET_ARM"
4d61e570 7298 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7299 [(set_attr "conds" "use")
7300 (set_attr "length" "8")]
7301)
9c08d1fa 7302
f7fbdd4a 7303(define_insn "*mov_notscc"
9c08d1fa 7304 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7305 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7306 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7307 "TARGET_ARM"
4d61e570 7308 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7309 [(set_attr "conds" "use")
7310 (set_attr "length" "8")]
7311)
9c08d1fa 7312
595d88b5 7313(define_expand "cstoresi4"
7314 [(set (match_operand:SI 0 "s_register_operand" "")
7315 (match_operator:SI 1 "arm_comparison_operator"
7316 [(match_operand:SI 2 "s_register_operand" "")
7317 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7318 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7319 "{
7320 rtx op3, scratch, scratch2;
7321
74f4459c 7322 if (!TARGET_THUMB1)
7323 {
7324 if (!arm_add_operand (operands[3], SImode))
7325 operands[3] = force_reg (SImode, operands[3]);
7326 emit_insn (gen_cstore_cc (operands[0], operands[1],
7327 operands[2], operands[3]));
7328 DONE;
7329 }
7330
595d88b5 7331 if (operands[3] == const0_rtx)
7332 {
7333 switch (GET_CODE (operands[1]))
7334 {
7335 case EQ:
25f905c2 7336 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7337 break;
7338
7339 case NE:
25f905c2 7340 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7341 break;
7342
7343 case LE:
7344 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7345 NULL_RTX, 0, OPTAB_WIDEN);
7346 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7347 NULL_RTX, 0, OPTAB_WIDEN);
7348 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7349 operands[0], 1, OPTAB_WIDEN);
7350 break;
7351
7352 case GE:
7353 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7354 NULL_RTX, 1);
7355 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7356 NULL_RTX, 1, OPTAB_WIDEN);
7357 break;
7358
7359 case GT:
7360 scratch = expand_binop (SImode, ashr_optab, operands[2],
7361 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7362 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7363 NULL_RTX, 0, OPTAB_WIDEN);
7364 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7365 0, OPTAB_WIDEN);
7366 break;
7367
7368 /* LT is handled by generic code. No need for unsigned with 0. */
7369 default:
7370 FAIL;
7371 }
7372 DONE;
7373 }
7374
7375 switch (GET_CODE (operands[1]))
7376 {
7377 case EQ:
7378 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7379 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7380 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7381 break;
7382
7383 case NE:
7384 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7385 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7386 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7387 break;
7388
7389 case LE:
7390 op3 = force_reg (SImode, operands[3]);
7391
7392 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7393 NULL_RTX, 1, OPTAB_WIDEN);
7394 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7395 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7396 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7397 op3, operands[2]));
7398 break;
7399
7400 case GE:
7401 op3 = operands[3];
25f905c2 7402 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7403 op3 = force_reg (SImode, op3);
7404 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7405 NULL_RTX, 0, OPTAB_WIDEN);
7406 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7407 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7408 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7409 operands[2], op3));
7410 break;
7411
7412 case LEU:
7413 op3 = force_reg (SImode, operands[3]);
7414 scratch = force_reg (SImode, const0_rtx);
25f905c2 7415 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7416 op3, operands[2]));
7417 break;
7418
7419 case GEU:
7420 op3 = operands[3];
25f905c2 7421 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7422 op3 = force_reg (SImode, op3);
7423 scratch = force_reg (SImode, const0_rtx);
25f905c2 7424 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7425 operands[2], op3));
7426 break;
7427
7428 case LTU:
7429 op3 = operands[3];
25f905c2 7430 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7431 op3 = force_reg (SImode, op3);
7432 scratch = gen_reg_rtx (SImode);
408b7ae5 7433 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7434 break;
7435
7436 case GTU:
7437 op3 = force_reg (SImode, operands[3]);
7438 scratch = gen_reg_rtx (SImode);
408b7ae5 7439 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7440 break;
7441
7442 /* No good sequences for GT, LT. */
7443 default:
7444 FAIL;
7445 }
7446 DONE;
7447}")
7448
74f4459c 7449(define_expand "cstoresf4"
7450 [(set (match_operand:SI 0 "s_register_operand" "")
7451 (match_operator:SI 1 "arm_comparison_operator"
7452 [(match_operand:SF 2 "s_register_operand" "")
7453 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7454 "TARGET_32BIT && TARGET_HARD_FLOAT"
7455 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7456 operands[2], operands[3])); DONE;"
7457)
7458
7459(define_expand "cstoredf4"
7460 [(set (match_operand:SI 0 "s_register_operand" "")
7461 (match_operator:SI 1 "arm_comparison_operator"
7462 [(match_operand:DF 2 "s_register_operand" "")
7463 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7464 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7465 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7466 operands[2], operands[3])); DONE;"
7467)
7468
74f4459c 7469(define_expand "cstoredi4"
7470 [(set (match_operand:SI 0 "s_register_operand" "")
7471 (match_operator:SI 1 "arm_comparison_operator"
a8045a4f 7472 [(match_operand:DI 2 "cmpdi_operand" "")
7473 (match_operand:DI 3 "cmpdi_operand" "")]))]
7474 "TARGET_32BIT"
7475 "{
7476 rtx swap = NULL_RTX;
7477 enum rtx_code code = GET_CODE (operands[1]);
7478
7479 /* We should not have two constants. */
7480 gcc_assert (GET_MODE (operands[2]) == DImode
7481 || GET_MODE (operands[3]) == DImode);
7482
7483 /* Flip unimplemented DImode comparisons to a form that
7484 arm_gen_compare_reg can handle. */
7485 switch (code)
7486 {
7487 case GT:
7488 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7489 case LE:
7490 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7491 case GTU:
7492 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7493 case LEU:
7494 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7495 default:
7496 break;
7497 }
7498 if (swap)
7499 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7500 operands[2]));
7501 else
7502 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7503 operands[3]));
7504 DONE;
7505 }"
74f4459c 7506)
7507
25f905c2 7508(define_expand "cstoresi_eq0_thumb1"
595d88b5 7509 [(parallel
7510 [(set (match_operand:SI 0 "s_register_operand" "")
7511 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7512 (const_int 0)))
7513 (clobber (match_dup:SI 2))])]
25f905c2 7514 "TARGET_THUMB1"
595d88b5 7515 "operands[2] = gen_reg_rtx (SImode);"
7516)
7517
25f905c2 7518(define_expand "cstoresi_ne0_thumb1"
595d88b5 7519 [(parallel
7520 [(set (match_operand:SI 0 "s_register_operand" "")
7521 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7522 (const_int 0)))
7523 (clobber (match_dup:SI 2))])]
25f905c2 7524 "TARGET_THUMB1"
595d88b5 7525 "operands[2] = gen_reg_rtx (SImode);"
7526)
7527
25f905c2 7528(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7529 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7530 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7531 (const_int 0)))
7532 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7533 "TARGET_THUMB1"
595d88b5 7534 "@
7535 neg\\t%0, %1\;adc\\t%0, %0, %1
7536 neg\\t%2, %1\;adc\\t%0, %1, %2"
7537 [(set_attr "length" "4")]
7538)
7539
25f905c2 7540(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7541 [(set (match_operand:SI 0 "s_register_operand" "=l")
7542 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7543 (const_int 0)))
7544 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7545 "TARGET_THUMB1"
595d88b5 7546 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7547 [(set_attr "length" "4")]
7548)
7549
408b7ae5 7550;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 7551(define_insn "cstoresi_nltu_thumb1"
595d88b5 7552 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7553 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7554 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7555 "TARGET_THUMB1"
595d88b5 7556 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7557 [(set_attr "length" "4")]
7558)
7559
408b7ae5 7560(define_insn_and_split "cstoresi_ltu_thumb1"
7561 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7562 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7563 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7564 "TARGET_THUMB1"
7565 "#"
7566 "TARGET_THUMB1"
7567 [(set (match_dup 3)
7568 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7569 (set (match_dup 0) (neg:SI (match_dup 3)))]
7570 "operands[3] = gen_reg_rtx (SImode);"
7571 [(set_attr "length" "4")]
7572)
7573
595d88b5 7574;; Used as part of the expansion of thumb les sequence.
25f905c2 7575(define_insn "thumb1_addsi3_addgeu"
595d88b5 7576 [(set (match_operand:SI 0 "s_register_operand" "=l")
7577 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7578 (match_operand:SI 2 "s_register_operand" "l"))
7579 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 7580 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7581 "TARGET_THUMB1"
595d88b5 7582 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7583 [(set_attr "length" "4")]
7584)
7585
9c08d1fa 7586\f
39b5e676 7587;; Conditional move insns
7588
7589(define_expand "movsicc"
8a18b90c 7590 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7591 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7592 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7593 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7594 "TARGET_32BIT"
39b5e676 7595 "
215b30b3 7596 {
7597 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7598 rtx ccreg;
7599
7600 if (code == UNEQ || code == LTGT)
7601 FAIL;
39b5e676 7602
74f4459c 7603 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7604 XEXP (operands[1], 1));
29bb088d 7605 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7606 }"
7607)
39b5e676 7608
7609(define_expand "movsfcc"
8a18b90c 7610 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7611 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7612 (match_operand:SF 2 "s_register_operand" "")
7613 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 7614 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7615 "
215b30b3 7616 {
7617 enum rtx_code code = GET_CODE (operands[1]);
7618 rtx ccreg;
f082f1c4 7619
278b301d 7620 if (code == UNEQ || code == LTGT)
7621 FAIL;
7622
215b30b3 7623 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7624 Otherwise, ensure it is a valid FP add operand */
7625 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7626 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7627 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7628
74f4459c 7629 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7630 XEXP (operands[1], 1));
29bb088d 7631 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7632 }"
7633)
39b5e676 7634
7635(define_expand "movdfcc"
8a18b90c 7636 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7637 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7638 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7639 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 7640 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 7641 "
215b30b3 7642 {
7643 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7644 rtx ccreg;
39b5e676 7645
278b301d 7646 if (code == UNEQ || code == LTGT)
7647 FAIL;
7648
74f4459c 7649 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7650 XEXP (operands[1], 1));
29bb088d 7651 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7652 }"
7653)
39b5e676 7654
7655(define_insn "*movsicc_insn"
f082f1c4 7656 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7657 (if_then_else:SI
8fa3ba89 7658 (match_operator 3 "arm_comparison_operator"
8a18b90c 7659 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7660 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7661 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7662 "TARGET_ARM"
39b5e676 7663 "@
8a18b90c 7664 mov%D3\\t%0, %2
7665 mvn%D3\\t%0, #%B2
f082f1c4 7666 mov%d3\\t%0, %1
7667 mvn%d3\\t%0, #%B1
8a18b90c 7668 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7669 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7670 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7671 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7672 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 7673 (set_attr "conds" "use")]
7674)
39b5e676 7675
39b5e676 7676(define_insn "*movsfcc_soft_insn"
f082f1c4 7677 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7678 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7679 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7680 (match_operand:SF 1 "s_register_operand" "0,r")
7681 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7682 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7683 "@
7684 mov%D3\\t%0, %2
7685 mov%d3\\t%0, %1"
8fa3ba89 7686 [(set_attr "conds" "use")]
7687)
39b5e676 7688
39b5e676 7689\f
9c08d1fa 7690;; Jump and linkage insns
7691
cffb2a26 7692(define_expand "jump"
9c08d1fa 7693 [(set (pc)
7694 (label_ref (match_operand 0 "" "")))]
cffb2a26 7695 "TARGET_EITHER"
9c08d1fa 7696 ""
cffb2a26 7697)
7698
7699(define_insn "*arm_jump"
7700 [(set (pc)
7701 (label_ref (match_operand 0 "" "")))]
25f905c2 7702 "TARGET_32BIT"
9c08d1fa 7703 "*
0d66636f 7704 {
7705 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7706 {
7707 arm_ccfsm_state += 2;
7708 return \"\";
7709 }
7710 return \"b%?\\t%l0\";
7711 }
7712 "
7713 [(set_attr "predicable" "yes")]
7714)
9c08d1fa 7715
cffb2a26 7716(define_insn "*thumb_jump"
7717 [(set (pc)
7718 (label_ref (match_operand 0 "" "")))]
25f905c2 7719 "TARGET_THUMB1"
cffb2a26 7720 "*
7721 if (get_attr_length (insn) == 2)
7722 return \"b\\t%l0\";
7723 return \"bl\\t%l0\\t%@ far jump\";
7724 "
7725 [(set (attr "far_jump")
7726 (if_then_else
7727 (eq_attr "length" "4")
7728 (const_string "yes")
7729 (const_string "no")))
7730 (set (attr "length")
7731 (if_then_else
911ed8af 7732 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7733 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7734 (const_int 2)
7735 (const_int 4)))]
7736)
7737
d3373b54 7738(define_expand "call"
7739 [(parallel [(call (match_operand 0 "memory_operand" "")
7740 (match_operand 1 "general_operand" ""))
cffb2a26 7741 (use (match_operand 2 "" ""))
bd5b4116 7742 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7743 "TARGET_EITHER"
6c4c2133 7744 "
7745 {
bac7fc85 7746 rtx callee, pat;
bbe777ea 7747
bbe777ea 7748 /* In an untyped call, we can get NULL for operand 2. */
7749 if (operands[2] == NULL_RTX)
7750 operands[2] = const0_rtx;
7751
de55252a 7752 /* Decide if we should generate indirect calls by loading the
85c36fd1 7753 32-bit address of the callee into a register before performing the
de55252a 7754 branch and link. */
7755 callee = XEXP (operands[0], 0);
7756 if (GET_CODE (callee) == SYMBOL_REF
7757 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7758 : !REG_P (callee))
bbe777ea 7759 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7760
7761 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7762 arm_emit_call_insn (pat, XEXP (operands[0], 0));
7763 DONE;
6c4c2133 7764 }"
7765)
d3373b54 7766
bac7fc85 7767(define_expand "call_internal"
7768 [(parallel [(call (match_operand 0 "memory_operand" "")
7769 (match_operand 1 "general_operand" ""))
7770 (use (match_operand 2 "" ""))
7771 (clobber (reg:SI LR_REGNUM))])])
7772
f1039640 7773(define_insn "*call_reg_armv5"
d3373b54 7774 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7775 (match_operand 1 "" ""))
7776 (use (match_operand 2 "" ""))
bd5b4116 7777 (clobber (reg:SI LR_REGNUM))]
f1039640 7778 "TARGET_ARM && arm_arch5"
7779 "blx%?\\t%0"
7780 [(set_attr "type" "call")]
7781)
7782
7783(define_insn "*call_reg_arm"
7784 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7785 (match_operand 1 "" ""))
7786 (use (match_operand 2 "" ""))
7787 (clobber (reg:SI LR_REGNUM))]
7788 "TARGET_ARM && !arm_arch5"
9c08d1fa 7789 "*
5565501b 7790 return output_call (operands);
cffb2a26 7791 "
7792 ;; length is worst case, normally it is only two
7793 [(set_attr "length" "12")
7794 (set_attr "type" "call")]
7795)
9c08d1fa 7796
89504fc1 7797
7798;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7799;; considered a function call by the branch predictor of some cores (PR40887).
7800;; Falls back to blx rN (*call_reg_armv5).
7801
f7fbdd4a 7802(define_insn "*call_mem"
a3c63a9d 7803 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7804 (match_operand 1 "" ""))
7805 (use (match_operand 2 "" ""))
bd5b4116 7806 (clobber (reg:SI LR_REGNUM))]
89504fc1 7807 "TARGET_ARM && !arm_arch5"
9c08d1fa 7808 "*
5565501b 7809 return output_call_mem (operands);
cffb2a26 7810 "
7811 [(set_attr "length" "12")
7812 (set_attr "type" "call")]
7813)
7814
25f905c2 7815(define_insn "*call_reg_thumb1_v5"
cffb2a26 7816 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7817 (match_operand 1 "" ""))
7818 (use (match_operand 2 "" ""))
bd5b4116 7819 (clobber (reg:SI LR_REGNUM))]
25f905c2 7820 "TARGET_THUMB1 && arm_arch5"
f1039640 7821 "blx\\t%0"
7822 [(set_attr "length" "2")
7823 (set_attr "type" "call")]
cffb2a26 7824)
7825
25f905c2 7826(define_insn "*call_reg_thumb1"
f1039640 7827 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7828 (match_operand 1 "" ""))
7829 (use (match_operand 2 "" ""))
bd5b4116 7830 (clobber (reg:SI LR_REGNUM))]
25f905c2 7831 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 7832 "*
7833 {
150502c9 7834 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7835 return thumb_call_via_reg (operands[0]);
150502c9 7836 else if (operands[1] == const0_rtx)
f1039640 7837 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7838 else if (frame_pointer_needed)
7839 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7840 else
150502c9 7841 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7842 }"
7843 [(set_attr "type" "call")]
7844)
9c08d1fa 7845
d3373b54 7846(define_expand "call_value"
e0698af7 7847 [(parallel [(set (match_operand 0 "" "")
7848 (call (match_operand 1 "memory_operand" "")
7849 (match_operand 2 "general_operand" "")))
cffb2a26 7850 (use (match_operand 3 "" ""))
bd5b4116 7851 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7852 "TARGET_EITHER"
6c4c2133 7853 "
7854 {
bac7fc85 7855 rtx pat, callee;
bbe777ea 7856
7857 /* In an untyped call, we can get NULL for operand 2. */
7858 if (operands[3] == 0)
7859 operands[3] = const0_rtx;
7860
de55252a 7861 /* Decide if we should generate indirect calls by loading the
7862 32-bit address of the callee into a register before performing the
7863 branch and link. */
7864 callee = XEXP (operands[1], 0);
7865 if (GET_CODE (callee) == SYMBOL_REF
7866 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7867 : !REG_P (callee))
78fe751b 7868 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7869
7870 pat = gen_call_value_internal (operands[0], operands[1],
7871 operands[2], operands[3]);
7872 arm_emit_call_insn (pat, XEXP (operands[1], 0));
7873 DONE;
6c4c2133 7874 }"
7875)
d3373b54 7876
bac7fc85 7877(define_expand "call_value_internal"
7878 [(parallel [(set (match_operand 0 "" "")
7879 (call (match_operand 1 "memory_operand" "")
7880 (match_operand 2 "general_operand" "")))
7881 (use (match_operand 3 "" ""))
7882 (clobber (reg:SI LR_REGNUM))])])
7883
f1039640 7884(define_insn "*call_value_reg_armv5"
27ed6835 7885 [(set (match_operand 0 "" "")
755eb2b4 7886 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7887 (match_operand 2 "" "")))
bbe777ea 7888 (use (match_operand 3 "" ""))
bd5b4116 7889 (clobber (reg:SI LR_REGNUM))]
f1039640 7890 "TARGET_ARM && arm_arch5"
7891 "blx%?\\t%1"
7892 [(set_attr "type" "call")]
7893)
7894
7895(define_insn "*call_value_reg_arm"
7896 [(set (match_operand 0 "" "")
7897 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7898 (match_operand 2 "" "")))
7899 (use (match_operand 3 "" ""))
7900 (clobber (reg:SI LR_REGNUM))]
7901 "TARGET_ARM && !arm_arch5"
9c08d1fa 7902 "*
215b30b3 7903 return output_call (&operands[1]);
cffb2a26 7904 "
7905 [(set_attr "length" "12")
7906 (set_attr "type" "call")]
7907)
9c08d1fa 7908
89504fc1 7909;; Note: see *call_mem
7910
f7fbdd4a 7911(define_insn "*call_value_mem"
27ed6835 7912 [(set (match_operand 0 "" "")
a3c63a9d 7913 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7914 (match_operand 2 "" "")))
bbe777ea 7915 (use (match_operand 3 "" ""))
bd5b4116 7916 (clobber (reg:SI LR_REGNUM))]
89504fc1 7917 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7918 "*
215b30b3 7919 return output_call_mem (&operands[1]);
cffb2a26 7920 "
7921 [(set_attr "length" "12")
7922 (set_attr "type" "call")]
7923)
9c08d1fa 7924
25f905c2 7925(define_insn "*call_value_reg_thumb1_v5"
f1039640 7926 [(set (match_operand 0 "" "")
7927 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7928 (match_operand 2 "" "")))
7929 (use (match_operand 3 "" ""))
7930 (clobber (reg:SI LR_REGNUM))]
25f905c2 7931 "TARGET_THUMB1 && arm_arch5"
f1039640 7932 "blx\\t%1"
7933 [(set_attr "length" "2")
7934 (set_attr "type" "call")]
7935)
7936
25f905c2 7937(define_insn "*call_value_reg_thumb1"
f1039640 7938 [(set (match_operand 0 "" "")
7939 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7940 (match_operand 2 "" "")))
7941 (use (match_operand 3 "" ""))
7942 (clobber (reg:SI LR_REGNUM))]
25f905c2 7943 "TARGET_THUMB1 && !arm_arch5"
f1039640 7944 "*
7945 {
150502c9 7946 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7947 return thumb_call_via_reg (operands[1]);
150502c9 7948 else if (operands[2] == const0_rtx)
f1039640 7949 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7950 else if (frame_pointer_needed)
7951 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7952 else
150502c9 7953 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 7954 }"
7955 [(set_attr "type" "call")]
7956)
7957
9c08d1fa 7958;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7959;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7960
f7fbdd4a 7961(define_insn "*call_symbol"
27ed6835 7962 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7963 (match_operand 1 "" ""))
bbe777ea 7964 (use (match_operand 2 "" ""))
bd5b4116 7965 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7966 "TARGET_32BIT
cffb2a26 7967 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7968 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7969 "*
7970 {
55c1e470 7971 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7972 }"
cffb2a26 7973 [(set_attr "type" "call")]
7974)
9c08d1fa 7975
f7fbdd4a 7976(define_insn "*call_value_symbol"
ccd90aaa 7977 [(set (match_operand 0 "" "")
27ed6835 7978 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7979 (match_operand:SI 2 "" "")))
bbe777ea 7980 (use (match_operand 3 "" ""))
bd5b4116 7981 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7982 "TARGET_32BIT
cffb2a26 7983 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7984 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7985 "*
7986 {
55c1e470 7987 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7988 }"
cffb2a26 7989 [(set_attr "type" "call")]
7990)
7991
7992(define_insn "*call_insn"
27ed6835 7993 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7994 (match_operand:SI 1 "" ""))
7995 (use (match_operand 2 "" ""))
bd5b4116 7996 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7997 "TARGET_THUMB1
1675c6e9 7998 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 7999 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8000 "bl\\t%a0"
8001 [(set_attr "length" "4")
8002 (set_attr "type" "call")]
8003)
8004
8005(define_insn "*call_value_insn"
ccd90aaa 8006 [(set (match_operand 0 "" "")
27ed6835 8007 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8008 (match_operand 2 "" "")))
8009 (use (match_operand 3 "" ""))
bd5b4116 8010 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8011 "TARGET_THUMB1
1675c6e9 8012 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8013 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8014 "bl\\t%a1"
8015 [(set_attr "length" "4")
8016 (set_attr "type" "call")]
8017)
9c08d1fa 8018
1c494086 8019;; We may also be able to do sibcalls for Thumb, but it's much harder...
8020(define_expand "sibcall"
8021 [(parallel [(call (match_operand 0 "memory_operand" "")
8022 (match_operand 1 "general_operand" ""))
2ba80634 8023 (return)
8024 (use (match_operand 2 "" ""))])]
d68c2c10 8025 "TARGET_32BIT"
1c494086 8026 "
8027 {
8028 if (operands[2] == NULL_RTX)
8029 operands[2] = const0_rtx;
1c494086 8030 }"
8031)
8032
8033(define_expand "sibcall_value"
ccd90aaa 8034 [(parallel [(set (match_operand 0 "" "")
1c494086 8035 (call (match_operand 1 "memory_operand" "")
8036 (match_operand 2 "general_operand" "")))
2ba80634 8037 (return)
8038 (use (match_operand 3 "" ""))])]
d68c2c10 8039 "TARGET_32BIT"
1c494086 8040 "
8041 {
8042 if (operands[3] == NULL_RTX)
8043 operands[3] = const0_rtx;
1c494086 8044 }"
8045)
8046
8047(define_insn "*sibcall_insn"
8048 [(call (mem:SI (match_operand:SI 0 "" "X"))
8049 (match_operand 1 "" ""))
2ba80634 8050 (return)
8051 (use (match_operand 2 "" ""))]
d68c2c10 8052 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8053 "*
8054 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8055 "
8056 [(set_attr "type" "call")]
8057)
8058
8059(define_insn "*sibcall_value_insn"
ccd90aaa 8060 [(set (match_operand 0 "" "")
755eb2b4 8061 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8062 (match_operand 2 "" "")))
2ba80634 8063 (return)
8064 (use (match_operand 3 "" ""))]
d68c2c10 8065 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8066 "*
8067 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8068 "
8069 [(set_attr "type" "call")]
8070)
8071
d68c2c10 8072(define_expand "return"
8073 [(return)]
8074 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8075 "")
8076
9c08d1fa 8077;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8078(define_insn "*arm_return"
9c08d1fa 8079 [(return)]
cffb2a26 8080 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8081 "*
9c08d1fa 8082 {
cffb2a26 8083 if (arm_ccfsm_state == 2)
8084 {
8085 arm_ccfsm_state += 2;
8086 return \"\";
8087 }
5db468b7 8088 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8089 }"
a2cd141b 8090 [(set_attr "type" "load1")
755eb2b4 8091 (set_attr "length" "12")
0d66636f 8092 (set_attr "predicable" "yes")]
cffb2a26 8093)
9c08d1fa 8094
f7fbdd4a 8095(define_insn "*cond_return"
9c08d1fa 8096 [(set (pc)
8fa3ba89 8097 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8098 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8099 (return)
8100 (pc)))]
cffb2a26 8101 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8102 "*
8fa3ba89 8103 {
8104 if (arm_ccfsm_state == 2)
8105 {
8106 arm_ccfsm_state += 2;
8107 return \"\";
8108 }
8109 return output_return_instruction (operands[0], TRUE, FALSE);
8110 }"
8111 [(set_attr "conds" "use")
755eb2b4 8112 (set_attr "length" "12")
a2cd141b 8113 (set_attr "type" "load1")]
8fa3ba89 8114)
9c08d1fa 8115
f7fbdd4a 8116(define_insn "*cond_return_inverted"
9c08d1fa 8117 [(set (pc)
8fa3ba89 8118 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8119 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8120 (pc)
8121 (return)))]
cffb2a26 8122 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8123 "*
8fa3ba89 8124 {
8125 if (arm_ccfsm_state == 2)
8126 {
8127 arm_ccfsm_state += 2;
8128 return \"\";
8129 }
8130 return output_return_instruction (operands[0], TRUE, TRUE);
8131 }"
8132 [(set_attr "conds" "use")
37a1317b 8133 (set_attr "length" "12")
a2cd141b 8134 (set_attr "type" "load1")]
8fa3ba89 8135)
9c08d1fa 8136
68121397 8137;; Generate a sequence of instructions to determine if the processor is
8138;; in 26-bit or 32-bit mode, and return the appropriate return address
8139;; mask.
8140
8141(define_expand "return_addr_mask"
8142 [(set (match_dup 1)
8143 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8144 (const_int 0)))
8145 (set (match_operand:SI 0 "s_register_operand" "")
8146 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8147 (const_int -1)
8148 (const_int 67108860)))] ; 0x03fffffc
8149 "TARGET_ARM"
8150 "
62eddbd4 8151 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8152 ")
8153
8154(define_insn "*check_arch2"
8155 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8156 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8157 (const_int 0)))]
8158 "TARGET_ARM"
8159 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8160 [(set_attr "length" "8")
8161 (set_attr "conds" "set")]
8162)
8163
9c08d1fa 8164;; Call subroutine returning any type.
8165
8166(define_expand "untyped_call"
8167 [(parallel [(call (match_operand 0 "" "")
8168 (const_int 0))
8169 (match_operand 1 "" "")
8170 (match_operand 2 "" "")])]
ccd90aaa 8171 "TARGET_EITHER"
9c08d1fa 8172 "
215b30b3 8173 {
8174 int i;
ccd90aaa 8175 rtx par = gen_rtx_PARALLEL (VOIDmode,
8176 rtvec_alloc (XVECLEN (operands[2], 0)));
8177 rtx addr = gen_reg_rtx (Pmode);
8178 rtx mem;
8179 int size = 0;
9c08d1fa 8180
ccd90aaa 8181 emit_move_insn (addr, XEXP (operands[1], 0));
8182 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8183
215b30b3 8184 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8185 {
ccd90aaa 8186 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8187
ccd90aaa 8188 /* Default code only uses r0 as a return value, but we could
8189 be using anything up to 4 registers. */
8190 if (REGNO (src) == R0_REGNUM)
8191 src = gen_rtx_REG (TImode, R0_REGNUM);
8192
8193 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8194 GEN_INT (size));
8195 size += GET_MODE_SIZE (GET_MODE (src));
8196 }
8197
8198 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8199 const0_rtx));
8200
8201 size = 0;
8202
8203 for (i = 0; i < XVECLEN (par, 0); i++)
8204 {
8205 HOST_WIDE_INT offset = 0;
8206 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8207
8208 if (size != 0)
8209 emit_move_insn (addr, plus_constant (addr, size));
8210
8211 mem = change_address (mem, GET_MODE (reg), NULL);
8212 if (REGNO (reg) == R0_REGNUM)
8213 {
8214 /* On thumb we have to use a write-back instruction. */
320ea44d 8215 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8216 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8217 size = TARGET_ARM ? 16 : 0;
8218 }
8219 else
8220 {
8221 emit_move_insn (mem, reg);
8222 size = GET_MODE_SIZE (GET_MODE (reg));
8223 }
215b30b3 8224 }
9c08d1fa 8225
215b30b3 8226 /* The optimizer does not know that the call sets the function value
8227 registers we stored in the result block. We avoid problems by
8228 claiming that all hard registers are used and clobbered at this
8229 point. */
8230 emit_insn (gen_blockage ());
8231
8232 DONE;
8233 }"
8234)
9c08d1fa 8235
ccd90aaa 8236(define_expand "untyped_return"
8237 [(match_operand:BLK 0 "memory_operand" "")
8238 (match_operand 1 "" "")]
8239 "TARGET_EITHER"
8240 "
8241 {
8242 int i;
8243 rtx addr = gen_reg_rtx (Pmode);
8244 rtx mem;
8245 int size = 0;
8246
8247 emit_move_insn (addr, XEXP (operands[0], 0));
8248 mem = change_address (operands[0], BLKmode, addr);
8249
8250 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8251 {
8252 HOST_WIDE_INT offset = 0;
8253 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8254
8255 if (size != 0)
8256 emit_move_insn (addr, plus_constant (addr, size));
8257
8258 mem = change_address (mem, GET_MODE (reg), NULL);
8259 if (REGNO (reg) == R0_REGNUM)
8260 {
8261 /* On thumb we have to use a write-back instruction. */
320ea44d 8262 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8263 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8264 size = TARGET_ARM ? 16 : 0;
8265 }
8266 else
8267 {
8268 emit_move_insn (reg, mem);
8269 size = GET_MODE_SIZE (GET_MODE (reg));
8270 }
8271 }
8272
8273 /* Emit USE insns before the return. */
8274 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8275 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8276
8277 /* Construct the return. */
8278 expand_naked_return ();
8279
8280 DONE;
8281 }"
8282)
8283
9c08d1fa 8284;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8285;; all of memory. This blocks insns from being moved across this point.
8286
8287(define_insn "blockage"
e1159bbe 8288 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8289 "TARGET_EITHER"
9c08d1fa 8290 ""
cffb2a26 8291 [(set_attr "length" "0")
8292 (set_attr "type" "block")]
8293)
9c08d1fa 8294
f7fbdd4a 8295(define_expand "casesi"
8296 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8297 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8298 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8299 (match_operand:SI 3 "" "") ; table label
8300 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8301 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8302 "
215b30b3 8303 {
e6ac8414 8304 enum insn_code code;
215b30b3 8305 if (operands[1] != const0_rtx)
8306 {
e6ac8414 8307 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8308
215b30b3 8309 emit_insn (gen_addsi3 (reg, operands[0],
8310 GEN_INT (-INTVAL (operands[1]))));
8311 operands[0] = reg;
8312 }
9c08d1fa 8313
25f905c2 8314 if (TARGET_ARM)
e6ac8414 8315 code = CODE_FOR_arm_casesi_internal;
3db2019b 8316 else if (TARGET_THUMB1)
e6ac8414 8317 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8318 else if (flag_pic)
e6ac8414 8319 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8320 else
e6ac8414 8321 code = CODE_FOR_thumb2_casesi_internal;
8322
8323 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8324 operands[2] = force_reg (SImode, operands[2]);
8325
8326 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8327 operands[3], operands[4]));
215b30b3 8328 DONE;
8329 }"
8330)
f7fbdd4a 8331
f082f1c4 8332;; The USE in this pattern is needed to tell flow analysis that this is
8333;; a CASESI insn. It has no other purpose.
25f905c2 8334(define_insn "arm_casesi_internal"
f082f1c4 8335 [(parallel [(set (pc)
8336 (if_then_else
8337 (leu (match_operand:SI 0 "s_register_operand" "r")
8338 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8339 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8340 (label_ref (match_operand 2 "" ""))))
8341 (label_ref (match_operand 3 "" ""))))
bd5b4116 8342 (clobber (reg:CC CC_REGNUM))
f082f1c4 8343 (use (label_ref (match_dup 2)))])]
cffb2a26 8344 "TARGET_ARM"
f7fbdd4a 8345 "*
0d66636f 8346 if (flag_pic)
8347 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8348 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8349 "
8350 [(set_attr "conds" "clob")
8351 (set_attr "length" "12")]
8352)
9c08d1fa 8353
e6ac8414 8354(define_expand "thumb1_casesi_internal_pic"
8355 [(match_operand:SI 0 "s_register_operand" "")
8356 (match_operand:SI 1 "thumb1_cmp_operand" "")
8357 (match_operand 2 "" "")
8358 (match_operand 3 "" "")]
3db2019b 8359 "TARGET_THUMB1"
e6ac8414 8360 {
8361 rtx reg0;
8362 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8363 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8364 operands[3]));
8365 reg0 = gen_rtx_REG (SImode, 0);
8366 emit_move_insn (reg0, operands[0]);
8367 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8368 DONE;
8369 }
8370)
8371
8372(define_insn "thumb1_casesi_dispatch"
8373 [(parallel [(set (pc) (unspec [(reg:SI 0)
8374 (label_ref (match_operand 0 "" ""))
8375;; (label_ref (match_operand 1 "" ""))
8376]
8377 UNSPEC_THUMB1_CASESI))
8378 (clobber (reg:SI IP_REGNUM))
8379 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8380 "TARGET_THUMB1"
e6ac8414 8381 "* return thumb1_output_casesi(operands);"
8382 [(set_attr "length" "4")]
8383)
8384
cffb2a26 8385(define_expand "indirect_jump"
9c08d1fa 8386 [(set (pc)
cffb2a26 8387 (match_operand:SI 0 "s_register_operand" ""))]
8388 "TARGET_EITHER"
25f905c2 8389 "
8390 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8391 address and use bx. */
8392 if (TARGET_THUMB2)
8393 {
8394 rtx tmp;
8395 tmp = gen_reg_rtx (SImode);
8396 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8397 operands[0] = tmp;
8398 }
8399 "
cffb2a26 8400)
8401
f1039640 8402;; NB Never uses BX.
cffb2a26 8403(define_insn "*arm_indirect_jump"
8404 [(set (pc)
8405 (match_operand:SI 0 "s_register_operand" "r"))]
8406 "TARGET_ARM"
8407 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8408 [(set_attr "predicable" "yes")]
cffb2a26 8409)
9c08d1fa 8410
f7fbdd4a 8411(define_insn "*load_indirect_jump"
9c08d1fa 8412 [(set (pc)
8413 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8414 "TARGET_ARM"
8415 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8416 [(set_attr "type" "load1")
61a2d04c 8417 (set_attr "pool_range" "4096")
8418 (set_attr "neg_pool_range" "4084")
0d66636f 8419 (set_attr "predicable" "yes")]
cffb2a26 8420)
8421
f1039640 8422;; NB Never uses BX.
25f905c2 8423(define_insn "*thumb1_indirect_jump"
cffb2a26 8424 [(set (pc)
8425 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8426 "TARGET_THUMB1"
cffb2a26 8427 "mov\\tpc, %0"
8428 [(set_attr "conds" "clob")
8429 (set_attr "length" "2")]
8430)
8431
9c08d1fa 8432\f
8433;; Misc insns
8434
8435(define_insn "nop"
8436 [(const_int 0)]
cffb2a26 8437 "TARGET_EITHER"
8438 "*
25f905c2 8439 if (TARGET_UNIFIED_ASM)
8440 return \"nop\";
cffb2a26 8441 if (TARGET_ARM)
8442 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8443 return \"mov\\tr8, r8\";
8444 "
8445 [(set (attr "length")
8446 (if_then_else (eq_attr "is_thumb" "yes")
8447 (const_int 2)
8448 (const_int 4)))]
8449)
8450
9c08d1fa 8451\f
8452;; Patterns to allow combination of arithmetic, cond code and shifts
8453
f7fbdd4a 8454(define_insn "*arith_shiftsi"
d5d4dc8d 8455 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8456 (match_operator:SI 1 "shiftable_operator"
8457 [(match_operator:SI 3 "shift_operator"
d5d4dc8d 8458 [(match_operand:SI 4 "s_register_operand" "r,r")
8459 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8460 (match_operand:SI 2 "s_register_operand" "rk,rk")]))]
8461 "TARGET_32BIT"
6c4c2133 8462 "%i1%?\\t%0, %2, %4%S3"
344495ea 8463 [(set_attr "predicable" "yes")
331beb1a 8464 (set_attr "shift" "4")
d5d4dc8d 8465 (set_attr "arch" "32,a")
8466 ;; We have to make sure to disable the second alternative if
8467 ;; the shift_operator is MULT, since otherwise the insn will
8468 ;; also match a multiply_accumulate pattern and validate_change
8469 ;; will allow a replacement of the constant with a register
8470 ;; despite the checks done in shift_operator.
8471 (set_attr_alternative "insn_enabled"
8472 [(const_string "yes")
8473 (if_then_else
8474 (match_operand:SI 3 "mult_operator" "")
8475 (const_string "no") (const_string "yes"))])
8476 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8477
d7863cfe 8478(define_split
8479 [(set (match_operand:SI 0 "s_register_operand" "")
8480 (match_operator:SI 1 "shiftable_operator"
8481 [(match_operator:SI 2 "shiftable_operator"
8482 [(match_operator:SI 3 "shift_operator"
8483 [(match_operand:SI 4 "s_register_operand" "")
8484 (match_operand:SI 5 "reg_or_int_operand" "")])
8485 (match_operand:SI 6 "s_register_operand" "")])
8486 (match_operand:SI 7 "arm_rhs_operand" "")]))
8487 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8488 "TARGET_32BIT"
d7863cfe 8489 [(set (match_dup 8)
8490 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8491 (match_dup 6)]))
8492 (set (match_dup 0)
8493 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8494 "")
8495
f7fbdd4a 8496(define_insn "*arith_shiftsi_compare0"
bd5b4116 8497 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8498 (compare:CC_NOOV
8499 (match_operator:SI 1 "shiftable_operator"
8500 [(match_operator:SI 3 "shift_operator"
8501 [(match_operand:SI 4 "s_register_operand" "r,r")
8502 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8503 (match_operand:SI 2 "s_register_operand" "r,r")])
8504 (const_int 0)))
8505 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8506 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8507 (match_dup 2)]))]
d5d4dc8d 8508 "TARGET_32BIT"
25f905c2 8509 "%i1%.\\t%0, %2, %4%S3"
344495ea 8510 [(set_attr "conds" "set")
331beb1a 8511 (set_attr "shift" "4")
d5d4dc8d 8512 (set_attr "arch" "32,a")
8513 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8514
f7fbdd4a 8515(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8516 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8517 (compare:CC_NOOV
8518 (match_operator:SI 1 "shiftable_operator"
8519 [(match_operator:SI 3 "shift_operator"
8520 [(match_operand:SI 4 "s_register_operand" "r,r")
8521 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8522 (match_operand:SI 2 "s_register_operand" "r,r")])
8523 (const_int 0)))
8524 (clobber (match_scratch:SI 0 "=r,r"))]
8525 "TARGET_32BIT"
25f905c2 8526 "%i1%.\\t%0, %2, %4%S3"
344495ea 8527 [(set_attr "conds" "set")
331beb1a 8528 (set_attr "shift" "4")
d5d4dc8d 8529 (set_attr "arch" "32,a")
8530 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8531
f7fbdd4a 8532(define_insn "*sub_shiftsi"
d5d4dc8d 8533 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8534 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8535 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8536 [(match_operand:SI 3 "s_register_operand" "r,r")
8537 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8538 "TARGET_32BIT"
6c4c2133 8539 "sub%?\\t%0, %1, %3%S2"
344495ea 8540 [(set_attr "predicable" "yes")
331beb1a 8541 (set_attr "shift" "3")
d5d4dc8d 8542 (set_attr "arch" "32,a")
8543 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8544
f7fbdd4a 8545(define_insn "*sub_shiftsi_compare0"
bd5b4116 8546 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8547 (compare:CC_NOOV
d5d4dc8d 8548 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8549 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8550 [(match_operand:SI 3 "s_register_operand" "r,r")
8551 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8552 (const_int 0)))
d5d4dc8d 8553 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8554 (minus:SI (match_dup 1)
8555 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8556 "TARGET_32BIT"
25f905c2 8557 "sub%.\\t%0, %1, %3%S2"
344495ea 8558 [(set_attr "conds" "set")
a2cd141b 8559 (set_attr "shift" "3")
d5d4dc8d 8560 (set_attr "arch" "32,a")
8561 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8562
f7fbdd4a 8563(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8564 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8565 (compare:CC_NOOV
d5d4dc8d 8566 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8567 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8568 [(match_operand:SI 3 "s_register_operand" "r,r")
8569 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8570 (const_int 0)))
d5d4dc8d 8571 (clobber (match_scratch:SI 0 "=r,r"))]
8572 "TARGET_32BIT"
25f905c2 8573 "sub%.\\t%0, %1, %3%S2"
344495ea 8574 [(set_attr "conds" "set")
a2cd141b 8575 (set_attr "shift" "3")
d5d4dc8d 8576 (set_attr "arch" "32,a")
8577 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8578\f
8579
f7fbdd4a 8580(define_insn "*and_scc"
9c08d1fa 8581 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8582 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8583 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8584 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8585 "TARGET_ARM"
e2348bcb 8586 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8587 [(set_attr "conds" "use")
8588 (set_attr "length" "8")]
8589)
9c08d1fa 8590
f7fbdd4a 8591(define_insn "*ior_scc"
9c08d1fa 8592 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8593 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8594 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8595 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8596 "TARGET_ARM"
e2348bcb 8597 "@
899850b0 8598 orr%d2\\t%0, %1, #1
8599 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8600 [(set_attr "conds" "use")
8601 (set_attr "length" "4,8")]
8602)
9c08d1fa 8603
2df9477b 8604; A series of splitters for the compare_scc pattern below. Note that
8605; order is important.
8606(define_split
8607 [(set (match_operand:SI 0 "s_register_operand" "")
8608 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8609 (const_int 0)))
8610 (clobber (reg:CC CC_REGNUM))]
8611 "TARGET_32BIT && reload_completed"
8612 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8613
8614(define_split
8615 [(set (match_operand:SI 0 "s_register_operand" "")
8616 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8617 (const_int 0)))
8618 (clobber (reg:CC CC_REGNUM))]
8619 "TARGET_32BIT && reload_completed"
8620 [(set (match_dup 0) (not:SI (match_dup 1)))
8621 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8622
8623(define_split
8624 [(set (match_operand:SI 0 "s_register_operand" "")
8625 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8626 (const_int 0)))
8627 (clobber (reg:CC CC_REGNUM))]
8628 "TARGET_32BIT && reload_completed"
8629 [(parallel
080c0b9a 8630 [(set (reg:CC CC_REGNUM)
8631 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8632 (set (match_dup 0)
8633 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8634 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8635 (set (match_dup 0) (const_int 0)))])
8636
8637(define_split
8638 [(set (match_operand:SI 0 "s_register_operand" "")
8639 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8640 (match_operand:SI 2 "const_int_operand" "")))
8641 (clobber (reg:CC CC_REGNUM))]
8642 "TARGET_32BIT && reload_completed"
8643 [(parallel
8644 [(set (reg:CC CC_REGNUM)
8645 (compare:CC (match_dup 1) (match_dup 2)))
8646 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8647 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8648 (set (match_dup 0) (const_int 1)))]
8649{
8650 operands[3] = GEN_INT (-INTVAL (operands[2]));
8651})
8652
8653(define_split
8654 [(set (match_operand:SI 0 "s_register_operand" "")
8655 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8656 (match_operand:SI 2 "arm_add_operand" "")))
8657 (clobber (reg:CC CC_REGNUM))]
8658 "TARGET_32BIT && reload_completed"
8659 [(parallel
8660 [(set (reg:CC_NOOV CC_REGNUM)
8661 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8662 (const_int 0)))
8663 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8664 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8665 (set (match_dup 0) (const_int 1)))])
8666
8667(define_insn_and_split "*compare_scc"
5565501b 8668 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8669 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8670 [(match_operand:SI 2 "s_register_operand" "r,r")
8671 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8672 (clobber (reg:CC CC_REGNUM))]
2df9477b 8673 "TARGET_32BIT"
8674 "#"
8675 "&& reload_completed"
8676 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8677 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8678 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8679{
8680 rtx tmp1;
8681 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8682 operands[2], operands[3]);
8683 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8684
2df9477b 8685 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8686
2df9477b 8687 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8688 if (mode == CCFPmode || mode == CCFPEmode)
8689 rc = reverse_condition_maybe_unordered (rc);
8690 else
8691 rc = reverse_condition (rc);
8692 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8693})
9c08d1fa 8694
080c0b9a 8695;; Attempt to improve the sequence generated by the compare_scc splitters
8696;; not to use conditional execution.
8697(define_peephole2
8698 [(set (reg:CC CC_REGNUM)
8699 (compare:CC (match_operand:SI 1 "register_operand" "")
8700 (match_operand:SI 2 "arm_rhs_operand" "")))
8701 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8702 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8703 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8704 (set (match_dup 0) (const_int 1)))
8705 (match_scratch:SI 3 "r")]
8706 "TARGET_32BIT"
8707 [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
8708 (parallel
8709 [(set (reg:CC CC_REGNUM)
8710 (compare:CC (const_int 0) (match_dup 3)))
8711 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8712 (set (match_dup 0)
8713 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8714 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
8715
f7fbdd4a 8716(define_insn "*cond_move"
9c08d1fa 8717 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8718 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8719 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8720 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8721 (const_int 0)])
8722 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8723 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8724 "TARGET_ARM"
9c08d1fa 8725 "*
8fa3ba89 8726 if (GET_CODE (operands[3]) == NE)
8727 {
8728 if (which_alternative != 1)
8729 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8730 if (which_alternative != 0)
8731 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8732 return \"\";
8733 }
8734 if (which_alternative != 0)
8735 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8736 if (which_alternative != 1)
8737 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8738 return \"\";
8739 "
8740 [(set_attr "conds" "use")
8741 (set_attr "length" "4,4,8")]
8742)
9c08d1fa 8743
f7fbdd4a 8744(define_insn "*cond_arith"
9c08d1fa 8745 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8746 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8747 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8748 [(match_operand:SI 2 "s_register_operand" "r,r")
8749 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8750 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8751 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8752 "TARGET_ARM"
9c08d1fa 8753 "*
8fa3ba89 8754 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8755 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8756
8fa3ba89 8757 output_asm_insn (\"cmp\\t%2, %3\", operands);
8758 if (GET_CODE (operands[5]) == AND)
8759 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8760 else if (GET_CODE (operands[5]) == MINUS)
8761 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8762 else if (which_alternative != 0)
8763 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8764 return \"%i5%d4\\t%0, %1, #1\";
8765 "
8766 [(set_attr "conds" "clob")
8767 (set_attr "length" "12")]
8768)
9c08d1fa 8769
f7fbdd4a 8770(define_insn "*cond_sub"
9c08d1fa 8771 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8772 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8773 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8774 [(match_operand:SI 2 "s_register_operand" "r,r")
8775 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8776 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8777 "TARGET_ARM"
9c08d1fa 8778 "*
8fa3ba89 8779 output_asm_insn (\"cmp\\t%2, %3\", operands);
8780 if (which_alternative != 0)
8781 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8782 return \"sub%d4\\t%0, %1, #1\";
8783 "
8784 [(set_attr "conds" "clob")
8785 (set_attr "length" "8,12")]
8786)
9c08d1fa 8787
25f905c2 8788;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 8789(define_insn "*cmp_ite0"
cffb2a26 8790 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8791 (compare
8792 (if_then_else:SI
8fa3ba89 8793 (match_operator 4 "arm_comparison_operator"
aea4c774 8794 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8795 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8796 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8797 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8798 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8799 (const_int 0))
8800 (const_int 0)))]
cffb2a26 8801 "TARGET_ARM"
9c08d1fa 8802 "*
aea4c774 8803 {
8fa3ba89 8804 static const char * const opcodes[4][2] =
8805 {
8806 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8807 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8808 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8809 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8810 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8811 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8812 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8813 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8814 };
8815 int swap =
8816 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8817
8818 return opcodes[which_alternative][swap];
8819 }"
8820 [(set_attr "conds" "set")
8821 (set_attr "length" "8")]
8822)
9c08d1fa 8823
aea4c774 8824(define_insn "*cmp_ite1"
cffb2a26 8825 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8826 (compare
8827 (if_then_else:SI
8fa3ba89 8828 (match_operator 4 "arm_comparison_operator"
aea4c774 8829 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8830 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8831 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8832 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8833 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8834 (const_int 1))
8835 (const_int 0)))]
cffb2a26 8836 "TARGET_ARM"
9c08d1fa 8837 "*
9c08d1fa 8838 {
215b30b3 8839 static const char * const opcodes[4][2] =
8840 {
8841 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8842 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8843 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8844 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8845 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8846 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8847 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8848 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8849 };
8850 int swap =
8851 comparison_dominates_p (GET_CODE (operands[5]),
8852 reverse_condition (GET_CODE (operands[4])));
8853
8854 return opcodes[which_alternative][swap];
8855 }"
8fa3ba89 8856 [(set_attr "conds" "set")
8857 (set_attr "length" "8")]
8858)
9c08d1fa 8859
f6c53574 8860(define_insn "*cmp_and"
8861 [(set (match_operand 6 "dominant_cc_register" "")
8862 (compare
8863 (and:SI
8864 (match_operator 4 "arm_comparison_operator"
8865 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8866 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8867 (match_operator:SI 5 "arm_comparison_operator"
8868 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8869 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8870 (const_int 0)))]
8871 "TARGET_ARM"
8872 "*
8873 {
35823b64 8874 static const char *const opcodes[4][2] =
f6c53574 8875 {
8876 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8877 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8878 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8879 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8880 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8881 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8882 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8883 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8884 };
8885 int swap =
8886 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8887
8888 return opcodes[which_alternative][swap];
8889 }"
8890 [(set_attr "conds" "set")
8891 (set_attr "predicable" "no")
8892 (set_attr "length" "8")]
8893)
8894
8895(define_insn "*cmp_ior"
8896 [(set (match_operand 6 "dominant_cc_register" "")
8897 (compare
8898 (ior:SI
8899 (match_operator 4 "arm_comparison_operator"
8900 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8901 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8902 (match_operator:SI 5 "arm_comparison_operator"
8903 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8904 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8905 (const_int 0)))]
8906 "TARGET_ARM"
8907 "*
8908{
35823b64 8909 static const char *const opcodes[4][2] =
f6c53574 8910 {
8911 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8912 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8913 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8914 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8915 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8916 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8917 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8918 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8919 };
8920 int swap =
8921 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8922
8923 return opcodes[which_alternative][swap];
8924}
8925"
8926 [(set_attr "conds" "set")
8927 (set_attr "length" "8")]
8928)
8929
3c5afce6 8930(define_insn_and_split "*ior_scc_scc"
8931 [(set (match_operand:SI 0 "s_register_operand" "=r")
8932 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8933 [(match_operand:SI 1 "s_register_operand" "r")
8934 (match_operand:SI 2 "arm_add_operand" "rIL")])
8935 (match_operator:SI 6 "arm_comparison_operator"
8936 [(match_operand:SI 4 "s_register_operand" "r")
8937 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8938 (clobber (reg:CC CC_REGNUM))]
8939 "TARGET_ARM
8940 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8941 != CCmode)"
8942 "#"
8943 "TARGET_ARM && reload_completed"
8944 [(set (match_dup 7)
8945 (compare
8946 (ior:SI
8947 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8948 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8949 (const_int 0)))
8950 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8951 "operands[7]
8952 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8953 DOM_CC_X_OR_Y),
601f584c 8954 CC_REGNUM);"
8955 [(set_attr "conds" "clob")
8956 (set_attr "length" "16")])
8957
8958; If the above pattern is followed by a CMP insn, then the compare is
8959; redundant, since we can rework the conditional instruction that follows.
8960(define_insn_and_split "*ior_scc_scc_cmp"
8961 [(set (match_operand 0 "dominant_cc_register" "")
8962 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8963 [(match_operand:SI 1 "s_register_operand" "r")
8964 (match_operand:SI 2 "arm_add_operand" "rIL")])
8965 (match_operator:SI 6 "arm_comparison_operator"
8966 [(match_operand:SI 4 "s_register_operand" "r")
8967 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8968 (const_int 0)))
8969 (set (match_operand:SI 7 "s_register_operand" "=r")
8970 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8971 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8972 "TARGET_ARM"
8973 "#"
8974 "TARGET_ARM && reload_completed"
8975 [(set (match_dup 0)
8976 (compare
8977 (ior:SI
8978 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8979 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8980 (const_int 0)))
8981 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8982 ""
8983 [(set_attr "conds" "set")
8984 (set_attr "length" "16")])
3c5afce6 8985
8986(define_insn_and_split "*and_scc_scc"
8987 [(set (match_operand:SI 0 "s_register_operand" "=r")
8988 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8989 [(match_operand:SI 1 "s_register_operand" "r")
8990 (match_operand:SI 2 "arm_add_operand" "rIL")])
8991 (match_operator:SI 6 "arm_comparison_operator"
8992 [(match_operand:SI 4 "s_register_operand" "r")
8993 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8994 (clobber (reg:CC CC_REGNUM))]
8995 "TARGET_ARM
8996 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8997 != CCmode)"
8998 "#"
601f584c 8999 "TARGET_ARM && reload_completed
9000 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9001 != CCmode)"
3c5afce6 9002 [(set (match_dup 7)
9003 (compare
9004 (and:SI
9005 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9006 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9007 (const_int 0)))
9008 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9009 "operands[7]
9010 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9011 DOM_CC_X_AND_Y),
601f584c 9012 CC_REGNUM);"
9013 [(set_attr "conds" "clob")
9014 (set_attr "length" "16")])
9015
9016; If the above pattern is followed by a CMP insn, then the compare is
9017; redundant, since we can rework the conditional instruction that follows.
9018(define_insn_and_split "*and_scc_scc_cmp"
9019 [(set (match_operand 0 "dominant_cc_register" "")
9020 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9021 [(match_operand:SI 1 "s_register_operand" "r")
9022 (match_operand:SI 2 "arm_add_operand" "rIL")])
9023 (match_operator:SI 6 "arm_comparison_operator"
9024 [(match_operand:SI 4 "s_register_operand" "r")
9025 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9026 (const_int 0)))
9027 (set (match_operand:SI 7 "s_register_operand" "=r")
9028 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9029 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9030 "TARGET_ARM"
9031 "#"
9032 "TARGET_ARM && reload_completed"
9033 [(set (match_dup 0)
9034 (compare
9035 (and:SI
9036 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9037 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9038 (const_int 0)))
9039 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9040 ""
9041 [(set_attr "conds" "set")
9042 (set_attr "length" "16")])
9043
9044;; If there is no dominance in the comparison, then we can still save an
9045;; instruction in the AND case, since we can know that the second compare
9046;; need only zero the value if false (if true, then the value is already
9047;; correct).
9048(define_insn_and_split "*and_scc_scc_nodom"
9049 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9050 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9051 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9052 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9053 (match_operator:SI 6 "arm_comparison_operator"
9054 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9055 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9056 (clobber (reg:CC CC_REGNUM))]
9057 "TARGET_ARM
9058 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9059 == CCmode)"
9060 "#"
9061 "TARGET_ARM && reload_completed"
9062 [(parallel [(set (match_dup 0)
9063 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9064 (clobber (reg:CC CC_REGNUM))])
9065 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9066 (set (match_dup 0)
9067 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9068 (match_dup 0)
9069 (const_int 0)))]
9070 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9071 operands[4], operands[5]),
9072 CC_REGNUM);
9073 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9074 operands[5]);"
9075 [(set_attr "conds" "clob")
9076 (set_attr "length" "20")])
3c5afce6 9077
3a0bdee0 9078(define_split
9079 [(set (reg:CC_NOOV CC_REGNUM)
9080 (compare:CC_NOOV (ior:SI
9081 (and:SI (match_operand:SI 0 "s_register_operand" "")
9082 (const_int 1))
b0694be0 9083 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9084 [(match_operand:SI 2 "s_register_operand" "")
9085 (match_operand:SI 3 "arm_add_operand" "")]))
9086 (const_int 0)))
9087 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9088 "TARGET_ARM"
9089 [(set (match_dup 4)
9090 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9091 (match_dup 0)))
9092 (set (reg:CC_NOOV CC_REGNUM)
9093 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9094 (const_int 0)))]
9095 "")
9096
9097(define_split
9098 [(set (reg:CC_NOOV CC_REGNUM)
9099 (compare:CC_NOOV (ior:SI
b0694be0 9100 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9101 [(match_operand:SI 2 "s_register_operand" "")
9102 (match_operand:SI 3 "arm_add_operand" "")])
9103 (and:SI (match_operand:SI 0 "s_register_operand" "")
9104 (const_int 1)))
9105 (const_int 0)))
9106 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9107 "TARGET_ARM"
9108 [(set (match_dup 4)
9109 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9110 (match_dup 0)))
9111 (set (reg:CC_NOOV CC_REGNUM)
9112 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9113 (const_int 0)))]
9114 "")
25f905c2 9115;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9116
f7fbdd4a 9117(define_insn "*negscc"
9c08d1fa 9118 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9119 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9120 [(match_operand:SI 1 "s_register_operand" "r")
9121 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9122 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9123 "TARGET_ARM"
9c08d1fa 9124 "*
2ca2ec2e 9125 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9126 return \"mov\\t%0, %1, asr #31\";
9127
9c08d1fa 9128 if (GET_CODE (operands[3]) == NE)
e2348bcb 9129 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9130
e2348bcb 9131 output_asm_insn (\"cmp\\t%1, %2\", operands);
9132 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9133 return \"mvn%d3\\t%0, #0\";
215b30b3 9134 "
8fa3ba89 9135 [(set_attr "conds" "clob")
9136 (set_attr "length" "12")]
9137)
9c08d1fa 9138
9139(define_insn "movcond"
9140 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9141 (if_then_else:SI
8fa3ba89 9142 (match_operator 5 "arm_comparison_operator"
5565501b 9143 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9144 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9145 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9146 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9147 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9148 "TARGET_ARM"
9c08d1fa 9149 "*
9150 if (GET_CODE (operands[5]) == LT
9151 && (operands[4] == const0_rtx))
9152 {
5565501b 9153 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9154 {
9c08d1fa 9155 if (operands[2] == const0_rtx)
e2348bcb 9156 return \"and\\t%0, %1, %3, asr #31\";
9157 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9158 }
9159 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9160 {
9c08d1fa 9161 if (operands[1] == const0_rtx)
e2348bcb 9162 return \"bic\\t%0, %2, %3, asr #31\";
9163 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9164 }
9165 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9166 are constants. */
9c08d1fa 9167 }
e2348bcb 9168
9c08d1fa 9169 if (GET_CODE (operands[5]) == GE
9170 && (operands[4] == const0_rtx))
9171 {
9172 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9173 {
9c08d1fa 9174 if (operands[2] == const0_rtx)
e2348bcb 9175 return \"bic\\t%0, %1, %3, asr #31\";
9176 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9177 }
9178 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9179 {
9c08d1fa 9180 if (operands[1] == const0_rtx)
e2348bcb 9181 return \"and\\t%0, %2, %3, asr #31\";
9182 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9183 }
9184 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9185 are constants. */
9c08d1fa 9186 }
9187 if (GET_CODE (operands[4]) == CONST_INT
9188 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9189 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9190 else
e2348bcb 9191 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9192 if (which_alternative != 0)
e2348bcb 9193 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9194 if (which_alternative != 1)
e2348bcb 9195 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9196 return \"\";
215b30b3 9197 "
8fa3ba89 9198 [(set_attr "conds" "clob")
9199 (set_attr "length" "8,8,12")]
9200)
9c08d1fa 9201
25f905c2 9202;; ??? The patterns below need checking for Thumb-2 usefulness.
9203
8a18b90c 9204(define_insn "*ifcompare_plus_move"
9205 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9206 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9207 [(match_operand:SI 4 "s_register_operand" "r,r")
9208 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9209 (plus:SI
9210 (match_operand:SI 2 "s_register_operand" "r,r")
9211 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9212 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9213 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9214 "TARGET_ARM"
8a18b90c 9215 "#"
8fa3ba89 9216 [(set_attr "conds" "clob")
9217 (set_attr "length" "8,12")]
9218)
8a18b90c 9219
9220(define_insn "*if_plus_move"
129a2fe4 9221 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9222 (if_then_else:SI
8fa3ba89 9223 (match_operator 4 "arm_comparison_operator"
8a18b90c 9224 [(match_operand 5 "cc_register" "") (const_int 0)])
9225 (plus:SI
129a2fe4 9226 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9227 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9228 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9229 "TARGET_ARM"
8a18b90c 9230 "@
9231 add%d4\\t%0, %2, %3
9232 sub%d4\\t%0, %2, #%n3
9233 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9234 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9235 [(set_attr "conds" "use")
9236 (set_attr "length" "4,4,8,8")
9237 (set_attr "type" "*,*,*,*")]
9238)
8a18b90c 9239
9240(define_insn "*ifcompare_move_plus"
5565501b 9241 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9242 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9243 [(match_operand:SI 4 "s_register_operand" "r,r")
9244 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9245 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9246 (plus:SI
9247 (match_operand:SI 2 "s_register_operand" "r,r")
9248 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9249 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9250 "TARGET_ARM"
8a18b90c 9251 "#"
8fa3ba89 9252 [(set_attr "conds" "clob")
9253 (set_attr "length" "8,12")]
9254)
8a18b90c 9255
9256(define_insn "*if_move_plus"
129a2fe4 9257 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9258 (if_then_else:SI
8fa3ba89 9259 (match_operator 4 "arm_comparison_operator"
8a18b90c 9260 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9261 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9262 (plus:SI
129a2fe4 9263 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9264 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9265 "TARGET_ARM"
8a18b90c 9266 "@
9267 add%D4\\t%0, %2, %3
9268 sub%D4\\t%0, %2, #%n3
9269 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9270 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9271 [(set_attr "conds" "use")
9272 (set_attr "length" "4,4,8,8")
9273 (set_attr "type" "*,*,*,*")]
9274)
8a18b90c 9275
9276(define_insn "*ifcompare_arith_arith"
9277 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9278 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9279 [(match_operand:SI 5 "s_register_operand" "r")
9280 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9281 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9282 [(match_operand:SI 1 "s_register_operand" "r")
9283 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9284 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9285 [(match_operand:SI 3 "s_register_operand" "r")
9286 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9287 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9288 "TARGET_ARM"
8a18b90c 9289 "#"
8fa3ba89 9290 [(set_attr "conds" "clob")
9291 (set_attr "length" "12")]
9292)
9c08d1fa 9293
8a18b90c 9294(define_insn "*if_arith_arith"
9295 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9296 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9297 [(match_operand 8 "cc_register" "") (const_int 0)])
9298 (match_operator:SI 6 "shiftable_operator"
9299 [(match_operand:SI 1 "s_register_operand" "r")
9300 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9301 (match_operator:SI 7 "shiftable_operator"
9302 [(match_operand:SI 3 "s_register_operand" "r")
9303 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9304 "TARGET_ARM"
8a18b90c 9305 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9306 [(set_attr "conds" "use")
9307 (set_attr "length" "8")]
9308)
8a18b90c 9309
f7fbdd4a 9310(define_insn "*ifcompare_arith_move"
9c08d1fa 9311 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9312 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9313 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9314 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9315 (match_operator:SI 7 "shiftable_operator"
9316 [(match_operand:SI 4 "s_register_operand" "r,r")
9317 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9318 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9319 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9320 "TARGET_ARM"
9c08d1fa 9321 "*
9c08d1fa 9322 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9323 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9324 everything is in registers then we can do this in two instructions. */
9c08d1fa 9325 if (operands[3] == const0_rtx
9326 && GET_CODE (operands[7]) != AND
9327 && GET_CODE (operands[5]) == REG
9328 && GET_CODE (operands[1]) == REG
9329 && REGNO (operands[1]) == REGNO (operands[4])
9330 && REGNO (operands[4]) != REGNO (operands[0]))
9331 {
9332 if (GET_CODE (operands[6]) == LT)
40dbec34 9333 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9334 else if (GET_CODE (operands[6]) == GE)
40dbec34 9335 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9336 }
9337 if (GET_CODE (operands[3]) == CONST_INT
9338 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9339 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9340 else
e2348bcb 9341 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9342 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9343 if (which_alternative != 0)
129a2fe4 9344 return \"mov%D6\\t%0, %1\";
9c08d1fa 9345 return \"\";
215b30b3 9346 "
8fa3ba89 9347 [(set_attr "conds" "clob")
9348 (set_attr "length" "8,12")]
9349)
9c08d1fa 9350
8a18b90c 9351(define_insn "*if_arith_move"
129a2fe4 9352 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9353 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9354 [(match_operand 6 "cc_register" "") (const_int 0)])
9355 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9356 [(match_operand:SI 2 "s_register_operand" "r,r")
9357 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9358 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9359 "TARGET_ARM"
8a18b90c 9360 "@
9361 %I5%d4\\t%0, %2, %3
129a2fe4 9362 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9363 [(set_attr "conds" "use")
9364 (set_attr "length" "4,8")
9365 (set_attr "type" "*,*")]
9366)
8a18b90c 9367
f7fbdd4a 9368(define_insn "*ifcompare_move_arith"
9c08d1fa 9369 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9370 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9371 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9372 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9373 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9374 (match_operator:SI 7 "shiftable_operator"
9375 [(match_operand:SI 2 "s_register_operand" "r,r")
9376 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9377 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9378 "TARGET_ARM"
9c08d1fa 9379 "*
9c08d1fa 9380 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9381 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9382 everything is in registers then we can do this in two instructions */
9383 if (operands[5] == const0_rtx
9384 && GET_CODE (operands[7]) != AND
9385 && GET_CODE (operands[3]) == REG
9386 && GET_CODE (operands[1]) == REG
9387 && REGNO (operands[1]) == REGNO (operands[2])
9388 && REGNO (operands[2]) != REGNO (operands[0]))
9389 {
9390 if (GET_CODE (operands[6]) == GE)
40dbec34 9391 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9392 else if (GET_CODE (operands[6]) == LT)
40dbec34 9393 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9394 }
40dbec34 9395
9c08d1fa 9396 if (GET_CODE (operands[5]) == CONST_INT
9397 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9398 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9399 else
e2348bcb 9400 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9401
9c08d1fa 9402 if (which_alternative != 0)
129a2fe4 9403 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9404 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9405 "
8fa3ba89 9406 [(set_attr "conds" "clob")
9407 (set_attr "length" "8,12")]
9408)
9c08d1fa 9409
8a18b90c 9410(define_insn "*if_move_arith"
129a2fe4 9411 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9412 (if_then_else:SI
8fa3ba89 9413 (match_operator 4 "arm_comparison_operator"
8a18b90c 9414 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9415 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9416 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9417 [(match_operand:SI 2 "s_register_operand" "r,r")
9418 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9419 "TARGET_ARM"
8a18b90c 9420 "@
9421 %I5%D4\\t%0, %2, %3
129a2fe4 9422 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9423 [(set_attr "conds" "use")
9424 (set_attr "length" "4,8")
9425 (set_attr "type" "*,*")]
9426)
8a18b90c 9427
9428(define_insn "*ifcompare_move_not"
9c08d1fa 9429 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9430 (if_then_else:SI
8fa3ba89 9431 (match_operator 5 "arm_comparison_operator"
8a18b90c 9432 [(match_operand:SI 3 "s_register_operand" "r,r")
9433 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9434 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9435 (not:SI
9436 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9437 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9438 "TARGET_ARM"
8a18b90c 9439 "#"
8fa3ba89 9440 [(set_attr "conds" "clob")
9441 (set_attr "length" "8,12")]
9442)
9c08d1fa 9443
8a18b90c 9444(define_insn "*if_move_not"
9445 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9446 (if_then_else:SI
8fa3ba89 9447 (match_operator 4 "arm_comparison_operator"
8a18b90c 9448 [(match_operand 3 "cc_register" "") (const_int 0)])
9449 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9450 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9451 "TARGET_ARM"
8a18b90c 9452 "@
9453 mvn%D4\\t%0, %2
9454 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9455 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9456 [(set_attr "conds" "use")
9457 (set_attr "length" "4,8,8")]
9458)
8a18b90c 9459
9460(define_insn "*ifcompare_not_move"
9c08d1fa 9461 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9462 (if_then_else:SI
8fa3ba89 9463 (match_operator 5 "arm_comparison_operator"
8a18b90c 9464 [(match_operand:SI 3 "s_register_operand" "r,r")
9465 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9466 (not:SI
9467 (match_operand:SI 2 "s_register_operand" "r,r"))
9468 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9469 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9470 "TARGET_ARM"
8a18b90c 9471 "#"
8fa3ba89 9472 [(set_attr "conds" "clob")
9473 (set_attr "length" "8,12")]
9474)
9c08d1fa 9475
8a18b90c 9476(define_insn "*if_not_move"
9477 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9478 (if_then_else:SI
8fa3ba89 9479 (match_operator 4 "arm_comparison_operator"
8a18b90c 9480 [(match_operand 3 "cc_register" "") (const_int 0)])
9481 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9482 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9483 "TARGET_ARM"
8a18b90c 9484 "@
9485 mvn%d4\\t%0, %2
9486 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9487 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9488 [(set_attr "conds" "use")
9489 (set_attr "length" "4,8,8")]
9490)
8a18b90c 9491
9492(define_insn "*ifcompare_shift_move"
9c08d1fa 9493 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9494 (if_then_else:SI
8fa3ba89 9495 (match_operator 6 "arm_comparison_operator"
8a18b90c 9496 [(match_operand:SI 4 "s_register_operand" "r,r")
9497 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9498 (match_operator:SI 7 "shift_operator"
9499 [(match_operand:SI 2 "s_register_operand" "r,r")
9500 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9501 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9502 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9503 "TARGET_ARM"
9c08d1fa 9504 "#"
8fa3ba89 9505 [(set_attr "conds" "clob")
9506 (set_attr "length" "8,12")]
9507)
9c08d1fa 9508
8a18b90c 9509(define_insn "*if_shift_move"
9510 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9511 (if_then_else:SI
8fa3ba89 9512 (match_operator 5 "arm_comparison_operator"
8a18b90c 9513 [(match_operand 6 "cc_register" "") (const_int 0)])
9514 (match_operator:SI 4 "shift_operator"
9515 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9516 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9517 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9518 "TARGET_ARM"
5565501b 9519 "@
8a18b90c 9520 mov%d5\\t%0, %2%S4
9521 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9522 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9523 [(set_attr "conds" "use")
331beb1a 9524 (set_attr "shift" "2")
a2cd141b 9525 (set_attr "length" "4,8,8")
9526 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9527 (const_string "alu_shift")
9528 (const_string "alu_shift_reg")))]
8fa3ba89 9529)
5565501b 9530
8a18b90c 9531(define_insn "*ifcompare_move_shift"
9532 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9533 (if_then_else:SI
8fa3ba89 9534 (match_operator 6 "arm_comparison_operator"
8a18b90c 9535 [(match_operand:SI 4 "s_register_operand" "r,r")
9536 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9537 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9538 (match_operator:SI 7 "shift_operator"
8a18b90c 9539 [(match_operand:SI 2 "s_register_operand" "r,r")
9540 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9541 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9542 "TARGET_ARM"
8a18b90c 9543 "#"
8fa3ba89 9544 [(set_attr "conds" "clob")
9545 (set_attr "length" "8,12")]
9546)
5565501b 9547
8a18b90c 9548(define_insn "*if_move_shift"
9549 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9550 (if_then_else:SI
8fa3ba89 9551 (match_operator 5 "arm_comparison_operator"
8a18b90c 9552 [(match_operand 6 "cc_register" "") (const_int 0)])
9553 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9554 (match_operator:SI 4 "shift_operator"
9555 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9556 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9557 "TARGET_ARM"
5565501b 9558 "@
8a18b90c 9559 mov%D5\\t%0, %2%S4
9560 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9561 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9562 [(set_attr "conds" "use")
331beb1a 9563 (set_attr "shift" "2")
a2cd141b 9564 (set_attr "length" "4,8,8")
9565 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9566 (const_string "alu_shift")
9567 (const_string "alu_shift_reg")))]
8fa3ba89 9568)
9c08d1fa 9569
f7fbdd4a 9570(define_insn "*ifcompare_shift_shift"
8a18b90c 9571 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9572 (if_then_else:SI
8fa3ba89 9573 (match_operator 7 "arm_comparison_operator"
8a18b90c 9574 [(match_operand:SI 5 "s_register_operand" "r")
9575 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9576 (match_operator:SI 8 "shift_operator"
8a18b90c 9577 [(match_operand:SI 1 "s_register_operand" "r")
9578 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9579 (match_operator:SI 9 "shift_operator"
8a18b90c 9580 [(match_operand:SI 3 "s_register_operand" "r")
9581 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9582 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9583 "TARGET_ARM"
8a18b90c 9584 "#"
8fa3ba89 9585 [(set_attr "conds" "clob")
9586 (set_attr "length" "12")]
9587)
9c08d1fa 9588
8a18b90c 9589(define_insn "*if_shift_shift"
9590 [(set (match_operand:SI 0 "s_register_operand" "=r")
9591 (if_then_else:SI
8fa3ba89 9592 (match_operator 5 "arm_comparison_operator"
8a18b90c 9593 [(match_operand 8 "cc_register" "") (const_int 0)])
9594 (match_operator:SI 6 "shift_operator"
9595 [(match_operand:SI 1 "s_register_operand" "r")
9596 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9597 (match_operator:SI 7 "shift_operator"
9598 [(match_operand:SI 3 "s_register_operand" "r")
9599 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9600 "TARGET_ARM"
8a18b90c 9601 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9602 [(set_attr "conds" "use")
331beb1a 9603 (set_attr "shift" "1")
a2cd141b 9604 (set_attr "length" "8")
9605 (set (attr "type") (if_then_else
9606 (and (match_operand 2 "const_int_operand" "")
9607 (match_operand 4 "const_int_operand" ""))
9608 (const_string "alu_shift")
9609 (const_string "alu_shift_reg")))]
8fa3ba89 9610)
8a18b90c 9611
f7fbdd4a 9612(define_insn "*ifcompare_not_arith"
8a18b90c 9613 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9614 (if_then_else:SI
8fa3ba89 9615 (match_operator 6 "arm_comparison_operator"
8a18b90c 9616 [(match_operand:SI 4 "s_register_operand" "r")
9617 (match_operand:SI 5 "arm_add_operand" "rIL")])
9618 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9619 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9620 [(match_operand:SI 2 "s_register_operand" "r")
9621 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9622 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9623 "TARGET_ARM"
8a18b90c 9624 "#"
8fa3ba89 9625 [(set_attr "conds" "clob")
9626 (set_attr "length" "12")]
9627)
9c08d1fa 9628
8a18b90c 9629(define_insn "*if_not_arith"
9630 [(set (match_operand:SI 0 "s_register_operand" "=r")
9631 (if_then_else:SI
8fa3ba89 9632 (match_operator 5 "arm_comparison_operator"
8a18b90c 9633 [(match_operand 4 "cc_register" "") (const_int 0)])
9634 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9635 (match_operator:SI 6 "shiftable_operator"
9636 [(match_operand:SI 2 "s_register_operand" "r")
9637 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9638 "TARGET_ARM"
8a18b90c 9639 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9640 [(set_attr "conds" "use")
9641 (set_attr "length" "8")]
9642)
8a18b90c 9643
9644(define_insn "*ifcompare_arith_not"
9645 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9646 (if_then_else:SI
8fa3ba89 9647 (match_operator 6 "arm_comparison_operator"
8a18b90c 9648 [(match_operand:SI 4 "s_register_operand" "r")
9649 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9650 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9651 [(match_operand:SI 2 "s_register_operand" "r")
9652 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9653 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9654 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9655 "TARGET_ARM"
8a18b90c 9656 "#"
8fa3ba89 9657 [(set_attr "conds" "clob")
9658 (set_attr "length" "12")]
9659)
9c08d1fa 9660
8a18b90c 9661(define_insn "*if_arith_not"
9662 [(set (match_operand:SI 0 "s_register_operand" "=r")
9663 (if_then_else:SI
8fa3ba89 9664 (match_operator 5 "arm_comparison_operator"
8a18b90c 9665 [(match_operand 4 "cc_register" "") (const_int 0)])
9666 (match_operator:SI 6 "shiftable_operator"
9667 [(match_operand:SI 2 "s_register_operand" "r")
9668 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9669 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9670 "TARGET_ARM"
8a18b90c 9671 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9672 [(set_attr "conds" "use")
9673 (set_attr "length" "8")]
9674)
8a18b90c 9675
f7fbdd4a 9676(define_insn "*ifcompare_neg_move"
8a18b90c 9677 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9678 (if_then_else:SI
8fa3ba89 9679 (match_operator 5 "arm_comparison_operator"
8a18b90c 9680 [(match_operand:SI 3 "s_register_operand" "r,r")
9681 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9682 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9683 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9684 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9685 "TARGET_ARM"
8a18b90c 9686 "#"
8fa3ba89 9687 [(set_attr "conds" "clob")
9688 (set_attr "length" "8,12")]
9689)
8a18b90c 9690
9691(define_insn "*if_neg_move"
9692 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9693 (if_then_else:SI
8fa3ba89 9694 (match_operator 4 "arm_comparison_operator"
8a18b90c 9695 [(match_operand 3 "cc_register" "") (const_int 0)])
9696 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9697 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9698 "TARGET_ARM"
8a18b90c 9699 "@
9700 rsb%d4\\t%0, %2, #0
9701 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9702 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9703 [(set_attr "conds" "use")
9704 (set_attr "length" "4,8,8")]
9705)
9c08d1fa 9706
f7fbdd4a 9707(define_insn "*ifcompare_move_neg"
8a18b90c 9708 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9709 (if_then_else:SI
8fa3ba89 9710 (match_operator 5 "arm_comparison_operator"
8a18b90c 9711 [(match_operand:SI 3 "s_register_operand" "r,r")
9712 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9713 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9714 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9715 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9716 "TARGET_ARM"
8a18b90c 9717 "#"
8fa3ba89 9718 [(set_attr "conds" "clob")
9719 (set_attr "length" "8,12")]
9720)
8a18b90c 9721
9722(define_insn "*if_move_neg"
9723 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9724 (if_then_else:SI
8fa3ba89 9725 (match_operator 4 "arm_comparison_operator"
8a18b90c 9726 [(match_operand 3 "cc_register" "") (const_int 0)])
9727 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9728 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9729 "TARGET_ARM"
8a18b90c 9730 "@
9731 rsb%D4\\t%0, %2, #0
9732 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9733 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9734 [(set_attr "conds" "use")
9735 (set_attr "length" "4,8,8")]
9736)
9c08d1fa 9737
f7fbdd4a 9738(define_insn "*arith_adjacentmem"
9c08d1fa 9739 [(set (match_operand:SI 0 "s_register_operand" "=r")
9740 (match_operator:SI 1 "shiftable_operator"
9741 [(match_operand:SI 2 "memory_operand" "m")
9742 (match_operand:SI 3 "memory_operand" "m")]))
9743 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9744 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9745 "*
215b30b3 9746 {
9747 rtx ldm[3];
9748 rtx arith[4];
94dee231 9749 rtx base_reg;
9750 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9751
215b30b3 9752 if (REGNO (operands[0]) > REGNO (operands[4]))
9753 {
9754 ldm[1] = operands[4];
9755 ldm[2] = operands[0];
9756 }
9757 else
9758 {
9759 ldm[1] = operands[0];
9760 ldm[2] = operands[4];
9761 }
94dee231 9762
9763 base_reg = XEXP (operands[2], 0);
9764
9765 if (!REG_P (base_reg))
9766 {
9767 val1 = INTVAL (XEXP (base_reg, 1));
9768 base_reg = XEXP (base_reg, 0);
9769 }
9770
9771 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9772 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9773
215b30b3 9774 arith[0] = operands[0];
9775 arith[3] = operands[1];
94dee231 9776
215b30b3 9777 if (val1 < val2)
9778 {
9779 arith[1] = ldm[1];
9780 arith[2] = ldm[2];
9781 }
9782 else
9783 {
9784 arith[1] = ldm[2];
9785 arith[2] = ldm[1];
9786 }
94dee231 9787
9788 ldm[0] = base_reg;
9789 if (val1 !=0 && val2 != 0)
215b30b3 9790 {
cdb1295a 9791 rtx ops[3];
9792
94dee231 9793 if (val1 == 4 || val2 == 4)
9794 /* Other val must be 8, since we know they are adjacent and neither
9795 is zero. */
25f905c2 9796 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 9797 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 9798 {
94dee231 9799 ldm[0] = ops[0] = operands[4];
9800 ops[1] = base_reg;
9801 ops[2] = GEN_INT (val1);
9802 output_add_immediate (ops);
9803 if (val1 < val2)
25f905c2 9804 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 9805 else
25f905c2 9806 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 9807 }
cdb1295a 9808 else
9809 {
9810 /* Offset is out of range for a single add, so use two ldr. */
9811 ops[0] = ldm[1];
9812 ops[1] = base_reg;
9813 ops[2] = GEN_INT (val1);
9814 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9815 ops[0] = ldm[2];
9816 ops[2] = GEN_INT (val2);
9817 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9818 }
215b30b3 9819 }
94dee231 9820 else if (val1 != 0)
215b30b3 9821 {
215b30b3 9822 if (val1 < val2)
25f905c2 9823 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9824 else
25f905c2 9825 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9826 }
9827 else
9828 {
215b30b3 9829 if (val1 < val2)
25f905c2 9830 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 9831 else
25f905c2 9832 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 9833 }
9834 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9835 return \"\";
9836 }"
9837 [(set_attr "length" "12")
9838 (set_attr "predicable" "yes")
a2cd141b 9839 (set_attr "type" "load1")]
215b30b3 9840)
9c08d1fa 9841
9c08d1fa 9842; This pattern is never tried by combine, so do it as a peephole
9843
a0f94409 9844(define_peephole2
372575c7 9845 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9846 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9847 (set (reg:CC CC_REGNUM)
aea4c774 9848 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9849 "TARGET_ARM"
a0f94409 9850 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9851 (set (match_dup 0) (match_dup 1))])]
9852 ""
0d66636f 9853)
9c08d1fa 9854
9c08d1fa 9855(define_split
9856 [(set (match_operand:SI 0 "s_register_operand" "")
9857 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9858 (const_int 0))
8fa3ba89 9859 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9860 [(match_operand:SI 3 "s_register_operand" "")
9861 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9862 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9863 "TARGET_ARM"
9c08d1fa 9864 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9865 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9866 (match_dup 5)))]
215b30b3 9867 ""
9868)
9c08d1fa 9869
aea4c774 9870;; This split can be used because CC_Z mode implies that the following
9871;; branch will be an equality, or an unsigned inequality, so the sign
9872;; extension is not needed.
9c08d1fa 9873
aea4c774 9874(define_split
bd5b4116 9875 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9876 (compare:CC_Z
9877 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9878 (const_int 24))
aea4c774 9879 (match_operand 1 "const_int_operand" "")))
9880 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9881 "TARGET_ARM
9882 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9883 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9884 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9885 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9886 "
9c08d1fa 9887 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9888 "
9889)
25f905c2 9890;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 9891
87b22bf7 9892(define_expand "prologue"
9893 [(clobber (const_int 0))]
cffb2a26 9894 "TARGET_EITHER"
25f905c2 9895 "if (TARGET_32BIT)
cffb2a26 9896 arm_expand_prologue ();
9897 else
25f905c2 9898 thumb1_expand_prologue ();
87b22bf7 9899 DONE;
cffb2a26 9900 "
9901)
87b22bf7 9902
56d27660 9903(define_expand "epilogue"
4c44712e 9904 [(clobber (const_int 0))]
cffb2a26 9905 "TARGET_EITHER"
56d27660 9906 "
18d50ae6 9907 if (crtl->calls_eh_return)
4c44712e 9908 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 9909 if (TARGET_THUMB1)
9910 thumb1_expand_epilogue ();
cffb2a26 9911 else if (USE_RETURN_INSN (FALSE))
56d27660 9912 {
9913 emit_jump_insn (gen_return ());
9914 DONE;
9915 }
cffb2a26 9916 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9917 gen_rtvec (1,
9918 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9919 VUNSPEC_EPILOGUE));
cffb2a26 9920 DONE;
9921 "
9922)
56d27660 9923
ef5651d0 9924;; Note - although unspec_volatile's USE all hard registers,
9925;; USEs are ignored after relaod has completed. Thus we need
9926;; to add an unspec of the link register to ensure that flow
9927;; does not think that it is unused by the sibcall branch that
9928;; will replace the standard function epilogue.
1c494086 9929(define_insn "sibcall_epilogue"
ef5651d0 9930 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9931 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 9932 "TARGET_32BIT"
1c494086 9933 "*
ffc9d00c 9934 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9935 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9936 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9937 "
9938;; Length is absolute worst case
9939 [(set_attr "length" "44")
defc47cf 9940 (set_attr "type" "block")
9941 ;; We don't clobber the conditions, but the potential length of this
9942 ;; operation is sufficient to make conditionalizing the sequence
9943 ;; unlikely to be profitable.
9944 (set_attr "conds" "clob")]
1c494086 9945)
9946
cffb2a26 9947(define_insn "*epilogue_insns"
e1159bbe 9948 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9949 "TARGET_EITHER"
56d27660 9950 "*
25f905c2 9951 if (TARGET_32BIT)
ffc9d00c 9952 return arm_output_epilogue (NULL);
25f905c2 9953 else /* TARGET_THUMB1 */
cffb2a26 9954 return thumb_unexpanded_epilogue ();
9955 "
215b30b3 9956 ; Length is absolute worst case
cffb2a26 9957 [(set_attr "length" "44")
defc47cf 9958 (set_attr "type" "block")
9959 ;; We don't clobber the conditions, but the potential length of this
9960 ;; operation is sufficient to make conditionalizing the sequence
9961 ;; unlikely to be profitable.
9962 (set_attr "conds" "clob")]
cffb2a26 9963)
9964
9965(define_expand "eh_epilogue"
7db9af5d 9966 [(use (match_operand:SI 0 "register_operand" ""))
9967 (use (match_operand:SI 1 "register_operand" ""))
9968 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 9969 "TARGET_EITHER"
9970 "
215b30b3 9971 {
9972 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9973 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9974 {
9975 rtx ra = gen_rtx_REG (Pmode, 2);
9976
9977 emit_move_insn (ra, operands[2]);
9978 operands[2] = ra;
9979 }
5cf3595a 9980 /* This is a hack -- we may have crystalized the function type too
9981 early. */
9982 cfun->machine->func_type = 0;
215b30b3 9983 }"
9984)
56d27660 9985
9c08d1fa 9986;; This split is only used during output to reduce the number of patterns
9987;; that need assembler instructions adding to them. We allowed the setting
9988;; of the conditions to be implicit during rtl generation so that
9989;; the conditional compare patterns would work. However this conflicts to
8a18b90c 9990;; some extent with the conditional data operations, so we have to split them
9c08d1fa 9991;; up again here.
9992
25f905c2 9993;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
9994;; conditional execution sufficient?
9995
9c08d1fa 9996(define_split
9997 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 9998 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9999 [(match_operand 2 "" "") (match_operand 3 "" "")])
10000 (match_dup 0)
10001 (match_operand 4 "" "")))
bd5b4116 10002 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10003 "TARGET_ARM && reload_completed"
8fa3ba89 10004 [(set (match_dup 5) (match_dup 6))
10005 (cond_exec (match_dup 7)
10006 (set (match_dup 0) (match_dup 4)))]
10007 "
10008 {
10009 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10010 operands[2], operands[3]);
10011 enum rtx_code rc = GET_CODE (operands[1]);
10012
bd5b4116 10013 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10014 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10015 if (mode == CCFPmode || mode == CCFPEmode)
10016 rc = reverse_condition_maybe_unordered (rc);
10017 else
10018 rc = reverse_condition (rc);
10019
10020 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10021 }"
10022)
10023
10024(define_split
10025 [(set (match_operand:SI 0 "s_register_operand" "")
10026 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10027 [(match_operand 2 "" "") (match_operand 3 "" "")])
10028 (match_operand 4 "" "")
10029 (match_dup 0)))
bd5b4116 10030 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10031 "TARGET_ARM && reload_completed"
8fa3ba89 10032 [(set (match_dup 5) (match_dup 6))
10033 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10034 (set (match_dup 0) (match_dup 4)))]
10035 "
10036 {
10037 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10038 operands[2], operands[3]);
10039
bd5b4116 10040 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10041 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10042 }"
10043)
10044
10045(define_split
10046 [(set (match_operand:SI 0 "s_register_operand" "")
10047 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10048 [(match_operand 2 "" "") (match_operand 3 "" "")])
10049 (match_operand 4 "" "")
10050 (match_operand 5 "" "")))
bd5b4116 10051 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10052 "TARGET_ARM && reload_completed"
8fa3ba89 10053 [(set (match_dup 6) (match_dup 7))
10054 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10055 (set (match_dup 0) (match_dup 4)))
10056 (cond_exec (match_dup 8)
10057 (set (match_dup 0) (match_dup 5)))]
10058 "
10059 {
10060 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10061 operands[2], operands[3]);
10062 enum rtx_code rc = GET_CODE (operands[1]);
10063
bd5b4116 10064 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10065 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10066 if (mode == CCFPmode || mode == CCFPEmode)
10067 rc = reverse_condition_maybe_unordered (rc);
10068 else
10069 rc = reverse_condition (rc);
10070
10071 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10072 }"
10073)
10074
cffb2a26 10075(define_split
10076 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10077 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10078 [(match_operand:SI 2 "s_register_operand" "")
10079 (match_operand:SI 3 "arm_add_operand" "")])
10080 (match_operand:SI 4 "arm_rhs_operand" "")
10081 (not:SI
10082 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10083 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10084 "TARGET_ARM && reload_completed"
cffb2a26 10085 [(set (match_dup 6) (match_dup 7))
f6c53574 10086 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10087 (set (match_dup 0) (match_dup 4)))
10088 (cond_exec (match_dup 8)
10089 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10090 "
215b30b3 10091 {
10092 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10093 operands[2], operands[3]);
f6c53574 10094 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10095
bd5b4116 10096 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10097 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10098 if (mode == CCFPmode || mode == CCFPEmode)
10099 rc = reverse_condition_maybe_unordered (rc);
10100 else
10101 rc = reverse_condition (rc);
10102
10103 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10104 }"
10105)
cffb2a26 10106
10107(define_insn "*cond_move_not"
10108 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10109 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10110 [(match_operand 3 "cc_register" "") (const_int 0)])
10111 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10112 (not:SI
10113 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10114 "TARGET_ARM"
10115 "@
10116 mvn%D4\\t%0, %2
10117 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10118 [(set_attr "conds" "use")
10119 (set_attr "length" "4,8")]
10120)
cffb2a26 10121
9c08d1fa 10122;; The next two patterns occur when an AND operation is followed by a
10123;; scc insn sequence
10124
f7fbdd4a 10125(define_insn "*sign_extract_onebit"
9c08d1fa 10126 [(set (match_operand:SI 0 "s_register_operand" "=r")
10127 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10128 (const_int 1)
ed750274 10129 (match_operand:SI 2 "const_int_operand" "n")))
10130 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10131 "TARGET_ARM"
9c08d1fa 10132 "*
0d66636f 10133 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10134 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10135 return \"mvnne\\t%0, #0\";
10136 "
10137 [(set_attr "conds" "clob")
10138 (set_attr "length" "8")]
10139)
9c08d1fa 10140
f7fbdd4a 10141(define_insn "*not_signextract_onebit"
9c08d1fa 10142 [(set (match_operand:SI 0 "s_register_operand" "=r")
10143 (not:SI
10144 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10145 (const_int 1)
ed750274 10146 (match_operand:SI 2 "const_int_operand" "n"))))
10147 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10148 "TARGET_ARM"
9c08d1fa 10149 "*
0d66636f 10150 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10151 output_asm_insn (\"tst\\t%1, %2\", operands);
10152 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10153 return \"movne\\t%0, #0\";
10154 "
10155 [(set_attr "conds" "clob")
10156 (set_attr "length" "12")]
10157)
25f905c2 10158;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10159
0d66636f 10160;; Push multiple registers to the stack. Registers are in parallel (use ...)
10161;; expressions. For simplicity, the first register is also in the unspec
10162;; part.
f7fbdd4a 10163(define_insn "*push_multi"
87b22bf7 10164 [(match_parallel 2 "multi_register_push"
10165 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10166 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10167 UNSPEC_PUSH_MULT))])]
25f905c2 10168 "TARGET_32BIT"
87b22bf7 10169 "*
215b30b3 10170 {
10171 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10172
215b30b3 10173 /* For the StrongARM at least it is faster to
25f905c2 10174 use STR to store only a single register.
542d5028 10175 In Thumb mode always use push, and the assembler will pick
10176 something appropriate. */
25f905c2 10177 if (num_saves == 1 && TARGET_ARM)
215b30b3 10178 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10179 else
10180 {
10181 int i;
10182 char pattern[100];
ed593f11 10183
25f905c2 10184 if (TARGET_ARM)
10185 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10186 else
10187 strcpy (pattern, \"push\\t{%1\");
215b30b3 10188
6079f055 10189 for (i = 1; i < num_saves; i++)
215b30b3 10190 {
10191 strcat (pattern, \", %|\");
10192 strcat (pattern,
10193 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10194 }
10195
10196 strcat (pattern, \"}\");
10197 output_asm_insn (pattern, operands);
10198 }
10199
10200 return \"\";
10201 }"
10202 [(set_attr "type" "store4")]
10203)
f7fbdd4a 10204
4c58c898 10205(define_insn "stack_tie"
10206 [(set (mem:BLK (scratch))
aaa37ad6 10207 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10208 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10209 UNSPEC_PRLG_STK))]
10210 ""
10211 ""
10212 [(set_attr "length" "0")]
10213)
10214
3398e91d 10215;; Similarly for the floating point registers
7b1d2fc4 10216(define_insn "*push_fp_multi"
10217 [(match_parallel 2 "multi_register_push"
10218 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10219 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10220 UNSPEC_PUSH_MULT))])]
25f905c2 10221 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10222 "*
215b30b3 10223 {
10224 char pattern[100];
7b1d2fc4 10225
215b30b3 10226 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10227 output_asm_insn (pattern, operands);
10228 return \"\";
10229 }"
10230 [(set_attr "type" "f_store")]
10231)
7b1d2fc4 10232
f7fbdd4a 10233;; Special patterns for dealing with the constant pool
10234
cffb2a26 10235(define_insn "align_4"
e1159bbe 10236 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10237 "TARGET_EITHER"
f7fbdd4a 10238 "*
cffb2a26 10239 assemble_align (32);
f7fbdd4a 10240 return \"\";
cffb2a26 10241 "
10242)
f7fbdd4a 10243
755eb2b4 10244(define_insn "align_8"
10245 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10246 "TARGET_EITHER"
755eb2b4 10247 "*
10248 assemble_align (64);
10249 return \"\";
10250 "
10251)
10252
cffb2a26 10253(define_insn "consttable_end"
e1159bbe 10254 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10255 "TARGET_EITHER"
f7fbdd4a 10256 "*
cffb2a26 10257 making_const_table = FALSE;
f7fbdd4a 10258 return \"\";
cffb2a26 10259 "
10260)
f7fbdd4a 10261
cffb2a26 10262(define_insn "consttable_1"
e1159bbe 10263 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10264 "TARGET_THUMB1"
f7fbdd4a 10265 "*
cffb2a26 10266 making_const_table = TRUE;
09d688ff 10267 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10268 assemble_zeros (3);
f7fbdd4a 10269 return \"\";
cffb2a26 10270 "
10271 [(set_attr "length" "4")]
10272)
f7fbdd4a 10273
cffb2a26 10274(define_insn "consttable_2"
e1159bbe 10275 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10276 "TARGET_THUMB1"
f7fbdd4a 10277 "*
cffb2a26 10278 making_const_table = TRUE;
9b8516be 10279 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10280 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10281 assemble_zeros (2);
f7fbdd4a 10282 return \"\";
cffb2a26 10283 "
10284 [(set_attr "length" "4")]
10285)
10286
10287(define_insn "consttable_4"
e1159bbe 10288 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10289 "TARGET_EITHER"
10290 "*
10291 {
9b8516be 10292 rtx x = operands[0];
cffb2a26 10293 making_const_table = TRUE;
9b8516be 10294 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10295 {
10296 case MODE_FLOAT:
9b8516be 10297 if (GET_MODE (x) == HFmode)
10298 arm_emit_fp16_const (x);
10299 else
10300 {
10301 REAL_VALUE_TYPE r;
10302 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10303 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10304 }
10305 break;
cffb2a26 10306 default:
7b04c5d5 10307 /* XXX: Sometimes gcc does something really dumb and ends up with
10308 a HIGH in a constant pool entry, usually because it's trying to
10309 load into a VFP register. We know this will always be used in
10310 combination with a LO_SUM which ignores the high bits, so just
10311 strip off the HIGH. */
10312 if (GET_CODE (x) == HIGH)
10313 x = XEXP (x, 0);
9b8516be 10314 assemble_integer (x, 4, BITS_PER_WORD, 1);
10315 mark_symbol_refs_as_used (x);
cffb2a26 10316 break;
10317 }
10318 return \"\";
10319 }"
10320 [(set_attr "length" "4")]
10321)
10322
10323(define_insn "consttable_8"
e1159bbe 10324 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10325 "TARGET_EITHER"
10326 "*
10327 {
10328 making_const_table = TRUE;
10329 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10330 {
10331 case MODE_FLOAT:
10332 {
badfe841 10333 REAL_VALUE_TYPE r;
10334 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10335 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10336 break;
10337 }
10338 default:
09d688ff 10339 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10340 break;
10341 }
10342 return \"\";
10343 }"
10344 [(set_attr "length" "8")]
10345)
10346
d98a3884 10347(define_insn "consttable_16"
10348 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10349 "TARGET_EITHER"
10350 "*
10351 {
10352 making_const_table = TRUE;
10353 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10354 {
10355 case MODE_FLOAT:
10356 {
10357 REAL_VALUE_TYPE r;
10358 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10359 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10360 break;
10361 }
10362 default:
10363 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10364 break;
10365 }
10366 return \"\";
10367 }"
10368 [(set_attr "length" "16")]
10369)
10370
cffb2a26 10371;; Miscellaneous Thumb patterns
10372
fd957ef3 10373(define_expand "tablejump"
7db9af5d 10374 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10375 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10376 "TARGET_THUMB1"
fd957ef3 10377 "
10378 if (flag_pic)
10379 {
10380 /* Hopefully, CSE will eliminate this copy. */
10381 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10382 rtx reg2 = gen_reg_rtx (SImode);
10383
10384 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10385 operands[0] = reg2;
10386 }
10387 "
10388)
10389
f1039640 10390;; NB never uses BX.
25f905c2 10391(define_insn "*thumb1_tablejump"
cffb2a26 10392 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10393 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10394 "TARGET_THUMB1"
fd957ef3 10395 "mov\\t%|pc, %0"
cffb2a26 10396 [(set_attr "length" "2")]
10397)
0d66636f 10398
331beb1a 10399;; V5 Instructions,
10400
8f4be2be 10401(define_insn "clzsi2"
10402 [(set (match_operand:SI 0 "s_register_operand" "=r")
10403 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10404 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10405 "clz%?\\t%0, %1"
bcaec148 10406 [(set_attr "predicable" "yes")
10407 (set_attr "insn" "clz")])
331beb1a 10408
099ad98b 10409(define_insn "rbitsi2"
10410 [(set (match_operand:SI 0 "s_register_operand" "=r")
10411 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10412 "TARGET_32BIT && arm_arch_thumb2"
10413 "rbit%?\\t%0, %1"
10414 [(set_attr "predicable" "yes")
10415 (set_attr "insn" "clz")])
10416
10417(define_expand "ctzsi2"
10418 [(set (match_operand:SI 0 "s_register_operand" "")
10419 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10420 "TARGET_32BIT && arm_arch_thumb2"
10421 "
30191172 10422 {
10423 rtx tmp = gen_reg_rtx (SImode);
10424 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10425 emit_insn (gen_clzsi2 (operands[0], tmp));
10426 }
099ad98b 10427 DONE;
10428 "
10429)
10430
e1159bbe 10431;; V5E instructions.
331beb1a 10432
10433(define_insn "prefetch"
f4e79814 10434 [(prefetch (match_operand:SI 0 "address_operand" "p")
10435 (match_operand:SI 1 "" "")
10436 (match_operand:SI 2 "" ""))]
25f905c2 10437 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10438 "pld\\t%a0")
331beb1a 10439
0d66636f 10440;; General predication pattern
10441
10442(define_cond_exec
10443 [(match_operator 0 "arm_comparison_operator"
10444 [(match_operand 1 "cc_register" "")
10445 (const_int 0)])]
25f905c2 10446 "TARGET_32BIT"
0d66636f 10447 ""
10448)
10449
063a05c7 10450(define_insn "prologue_use"
10451 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10452 ""
10453 "%@ %0 needed for prologue"
02cfc9c9 10454 [(set_attr "length" "0")]
063a05c7 10455)
7db9af5d 10456
4c44712e 10457
10458;; Patterns for exception handling
10459
10460(define_expand "eh_return"
10461 [(use (match_operand 0 "general_operand" ""))]
10462 "TARGET_EITHER"
10463 "
10464 {
25f905c2 10465 if (TARGET_32BIT)
4c44712e 10466 emit_insn (gen_arm_eh_return (operands[0]));
10467 else
10468 emit_insn (gen_thumb_eh_return (operands[0]));
10469 DONE;
10470 }"
10471)
10472
10473;; We can't expand this before we know where the link register is stored.
10474(define_insn_and_split "arm_eh_return"
10475 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10476 VUNSPEC_EH_RETURN)
10477 (clobber (match_scratch:SI 1 "=&r"))]
10478 "TARGET_ARM"
10479 "#"
10480 "&& reload_completed"
10481 [(const_int 0)]
10482 "
10483 {
10484 arm_set_return_address (operands[0], operands[1]);
10485 DONE;
10486 }"
10487)
10488
10489(define_insn_and_split "thumb_eh_return"
10490 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10491 VUNSPEC_EH_RETURN)
10492 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10493 "TARGET_THUMB1"
4c44712e 10494 "#"
10495 "&& reload_completed"
10496 [(const_int 0)]
10497 "
10498 {
10499 thumb_set_return_address (operands[0], operands[1]);
10500 DONE;
10501 }"
10502)
10503
f655717d 10504\f
10505;; TLS support
10506
10507(define_insn "load_tp_hard"
10508 [(set (match_operand:SI 0 "register_operand" "=r")
10509 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10510 "TARGET_HARD_TP"
10511 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10512 [(set_attr "predicable" "yes")]
10513)
10514
10515;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10516(define_insn "load_tp_soft"
10517 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10518 (clobber (reg:SI LR_REGNUM))
10519 (clobber (reg:SI IP_REGNUM))
10520 (clobber (reg:CC CC_REGNUM))]
10521 "TARGET_SOFT_TP"
10522 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10523 [(set_attr "conds" "clob")]
10524)
10525
eca5c984 10526(define_insn "*arm_movtas_ze"
10527 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10528 (const_int 16)
10529 (const_int 16))
10530 (match_operand:SI 1 "const_int_operand" ""))]
10531 "TARGET_32BIT"
10532 "movt%?\t%0, %c1"
10533 [(set_attr "predicable" "yes")
10534 (set_attr "length" "4")]
10535)
10536
c0fc3696 10537(define_insn "*arm_rev"
ff82f757 10538 [(set (match_operand:SI 0 "s_register_operand" "=r")
10539 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 10540 "TARGET_32BIT && arm_arch6"
10541 "rev%?\t%0, %1"
10542 [(set_attr "predicable" "yes")
10543 (set_attr "length" "4")]
10544)
10545
10546(define_insn "*thumb1_rev"
10547 [(set (match_operand:SI 0 "s_register_operand" "=l")
10548 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10549 "TARGET_THUMB1 && arm_arch6"
10550 "rev\t%0, %1"
10551 [(set_attr "length" "2")]
ff82f757 10552)
10553
10554(define_expand "arm_legacy_rev"
10555 [(set (match_operand:SI 2 "s_register_operand" "")
10556 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10557 (const_int 16))
10558 (match_dup 1)))
10559 (set (match_dup 2)
10560 (lshiftrt:SI (match_dup 2)
10561 (const_int 8)))
10562 (set (match_operand:SI 3 "s_register_operand" "")
10563 (rotatert:SI (match_dup 1)
10564 (const_int 8)))
10565 (set (match_dup 2)
10566 (and:SI (match_dup 2)
10567 (const_int -65281)))
10568 (set (match_operand:SI 0 "s_register_operand" "")
10569 (xor:SI (match_dup 3)
10570 (match_dup 2)))]
10571 "TARGET_32BIT"
10572 ""
10573)
10574
10575;; Reuse temporaries to keep register pressure down.
10576(define_expand "thumb_legacy_rev"
10577 [(set (match_operand:SI 2 "s_register_operand" "")
10578 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10579 (const_int 24)))
10580 (set (match_operand:SI 3 "s_register_operand" "")
10581 (lshiftrt:SI (match_dup 1)
10582 (const_int 24)))
10583 (set (match_dup 3)
10584 (ior:SI (match_dup 3)
10585 (match_dup 2)))
10586 (set (match_operand:SI 4 "s_register_operand" "")
10587 (const_int 16))
10588 (set (match_operand:SI 5 "s_register_operand" "")
10589 (rotatert:SI (match_dup 1)
10590 (match_dup 4)))
10591 (set (match_dup 2)
10592 (ashift:SI (match_dup 5)
10593 (const_int 24)))
10594 (set (match_dup 5)
10595 (lshiftrt:SI (match_dup 5)
10596 (const_int 24)))
10597 (set (match_dup 5)
10598 (ior:SI (match_dup 5)
10599 (match_dup 2)))
10600 (set (match_dup 5)
10601 (rotatert:SI (match_dup 5)
10602 (match_dup 4)))
10603 (set (match_operand:SI 0 "s_register_operand" "")
10604 (ior:SI (match_dup 5)
10605 (match_dup 3)))]
10606 "TARGET_THUMB"
10607 ""
10608)
10609
10610(define_expand "bswapsi2"
10611 [(set (match_operand:SI 0 "s_register_operand" "=r")
10612 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
10613"TARGET_EITHER"
10614"
10615 if (!arm_arch6)
10616 {
10617 if (!optimize_size)
10618 {
10619 rtx op2 = gen_reg_rtx (SImode);
10620 rtx op3 = gen_reg_rtx (SImode);
10621
10622 if (TARGET_THUMB)
10623 {
10624 rtx op4 = gen_reg_rtx (SImode);
10625 rtx op5 = gen_reg_rtx (SImode);
10626
10627 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10628 op2, op3, op4, op5));
10629 }
10630 else
10631 {
10632 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10633 op2, op3));
10634 }
10635
10636 DONE;
10637 }
10638 else
10639 FAIL;
10640 }
10641 "
10642)
10643
320ea44d 10644;; Load the load/store multiple patterns
10645(include "ldmstm.md")
7db9af5d 10646;; Load the FPA co-processor patterns
10647(include "fpa.md")
10648;; Load the Maverick co-processor patterns
10649(include "cirrus.md")
d98a3884 10650;; Vector bits common to IWMMXT and Neon
10651(include "vec-common.md")
755eb2b4 10652;; Load the Intel Wireless Multimedia Extension patterns
10653(include "iwmmxt.md")
a2cd141b 10654;; Load the VFP co-processor patterns
10655(include "vfp.md")
25f905c2 10656;; Thumb-2 patterns
10657(include "thumb2.md")
d98a3884 10658;; Neon patterns
10659(include "neon.md")
a2cd141b 10660