]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
2009-07-15 Robert Dewar <dewar@adacore.com>
[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,
cfaf579d 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
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.
e1159bbe 103 ]
104)
105
215b30b3 106;; UNSPEC_VOLATILE Usage:
e1159bbe 107
108(define_constants
109 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
110 ; insn in the code.
111 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
112 ; instruction epilogue sequence that isn't expanded
113 ; into normal RTL. Used for both normal and sibcall
114 ; epilogues.
115 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
116 ; for inlined constants.
117 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
118 ; table.
119 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
120 ; an 8-bit object.
121 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
122 ; a 16-bit object.
123 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
124 ; a 32-bit object.
125 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
126 ; a 64-bit object.
d98a3884 127 (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
128 ; a 128-bit object.
129 (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
130 (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
131 (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
132 (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
133 (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
134 (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 135 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 136 ; handling.
e1159bbe 137 ]
138)
b11cae9e 139\f
e1159bbe 140;;---------------------------------------------------------------------------
9c08d1fa 141;; Attributes
142
215b30b3 143; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
144; generating ARM code. This is used to control the length of some insn
145; patterns that share the same RTL in both ARM and Thumb code.
1c494086 146(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 147
215b30b3 148; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
149; scheduling decisions for the load unit and the multiplier.
74a71f7d 150(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
9c08d1fa 151
5ecb8da7 152; IS_XSCALE is set to 'yes' when compiling for XScale.
153(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
154
331beb1a 155;; Operand number of an input operand that is shifted. Zero if the
156;; given instruction does not shift one of its input operands.
331beb1a 157(define_attr "shift" "" (const_int 0))
158
3d91c5d6 159; Floating Point Unit. If we only have floating point emulation, then there
160; is no point in scheduling the floating point insns. (Well, for best
161; performance we should try and group them together).
9b8516be 162(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp,vfpv3d16,vfpv3,neon,neon_fp16"
c7f506fd 163 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 164
094e994f 165; LENGTH of an instruction (in bytes)
166(define_attr "length" "" (const_int 4))
9c08d1fa 167
56d27660 168; POOL_RANGE is how far away from a constant pool entry that this insn
169; can be placed. If the distance is zero, then this insn will never
170; reference the pool.
cffb2a26 171; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
172; before its address.
56d27660 173(define_attr "pool_range" "" (const_int 0))
cffb2a26 174(define_attr "neg_pool_range" "" (const_int 0))
56d27660 175
215b30b3 176; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 177; If such an insn references the pool, then we have no way of knowing how,
178; so use the most conservative value for pool_range.
9c08d1fa 179(define_asm_attributes
4d7a8451 180 [(set_attr "conds" "clob")
181 (set_attr "length" "4")
182 (set_attr "pool_range" "250")])
9c08d1fa 183
a2cd141b 184;; The instruction used to implement a particular pattern. This
185;; information is used by pipeline descriptions to provide accurate
186;; scheduling information.
187
188(define_attr "insn"
934a1e72 189 "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 190 (const_string "other"))
191
9c08d1fa 192; TYPE attribute is used to detect floating point instructions which, if
193; running on a co-processor can run in parallel with other, basic instructions
194; If write-buffer scheduling is enabled then it can also be used in the
195; scheduling of writes.
196
197; Classification of each insn
607978a1 198; Note: vfp.md has different meanings for some of these, and some further
199; types as well. See that file for details.
a2cd141b 200; alu any alu instruction that doesn't hit memory or fp
201; regs or have a shifted source operand
202; alu_shift any data instruction that doesn't hit memory or fp
203; regs, but has a source operand shifted by a constant
204; alu_shift_reg any data instruction that doesn't hit memory or fp
205; regs, but has a source operand shifted by a register value
f7fbdd4a 206; mult a multiply instruction
9c08d1fa 207; block blockage insn, this blocks all functional units
208; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 209; fdivd DFmode floating point division
210; fdivs SFmode floating point division
211; fmul Floating point multiply
212; ffmul Fast floating point multiply
213; farith Floating point arithmetic (4 cycle)
214; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 215; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 216; even on a machine with an fpa.
9c08d1fa 217; f_load a floating point load from memory
218; f_store a floating point store to memory
9aff9709 219; f_load[sd] single/double load from memory
220; f_store[sd] single/double store to memory
c0e1af52 221; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 222; f_mem_r a transfer of a floating point register to a real reg via mem
223; r_mem_f the reverse of f_mem_r
224; f_2_r fast transfer float to arm (no memory needed)
225; r_2_f fast transfer arm to float
c0e1af52 226; f_cvt convert floating<->integral
a2cd141b 227; branch a branch
9c08d1fa 228; call a subroutine call
a2cd141b 229; load_byte load byte(s) from memory to arm registers
230; load1 load 1 word from memory to arm registers
231; load2 load 2 words from memory to arm registers
232; load3 load 3 words from memory to arm registers
233; load4 load 4 words from memory to arm registers
234; store store 1 word to memory from arm registers
9c08d1fa 235; store2 store 2 words
236; store3 store 3 words
a2cd141b 237; store4 store 4 (or more) words
2c6c7d8b 238; Additions for Cirrus Maverick co-processor:
239; mav_farith Floating point arithmetic (4 cycle)
240; mav_dmult Double multiplies (7 cycle)
9c08d1fa 241;
bcaec148 242
9c08d1fa 243(define_attr "type"
e3879fd0 244 "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 245 (if_then_else
246 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
247 (const_string "mult")
248 (const_string "alu")))
9c08d1fa 249
9888ad6d 250; Load scheduling, set from the arm_ld_sched variable
457275b6 251; initialized by arm_override_options()
9888ad6d 252(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 253
c52acdd2 254;; Classification of NEON instructions for scheduling purposes.
255;; Do not set this attribute and the "type" attribute together in
256;; any one instruction pattern.
257(define_attr "neon_type"
258 "neon_int_1,\
259 neon_int_2,\
260 neon_int_3,\
261 neon_int_4,\
262 neon_int_5,\
263 neon_vqneg_vqabs,\
264 neon_vmov,\
265 neon_vaba,\
266 neon_vsma,\
267 neon_vaba_qqq,\
268 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
269 neon_mul_qqq_8_16_32_ddd_32,\
270 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
271 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
272 neon_mla_qqq_8_16,\
273 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
274 neon_mla_qqq_32_qqd_32_scalar,\
275 neon_mul_ddd_16_scalar_32_16_long_scalar,\
276 neon_mul_qqd_32_scalar,\
277 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
278 neon_shift_1,\
279 neon_shift_2,\
280 neon_shift_3,\
281 neon_vshl_ddd,\
282 neon_vqshl_vrshl_vqrshl_qqq,\
283 neon_vsra_vrsra,\
284 neon_fp_vadd_ddd_vabs_dd,\
285 neon_fp_vadd_qqq_vabs_qq,\
286 neon_fp_vsum,\
287 neon_fp_vmul_ddd,\
288 neon_fp_vmul_qqd,\
289 neon_fp_vmla_ddd,\
290 neon_fp_vmla_qqq,\
291 neon_fp_vmla_ddd_scalar,\
292 neon_fp_vmla_qqq_scalar,\
293 neon_fp_vrecps_vrsqrts_ddd,\
294 neon_fp_vrecps_vrsqrts_qqq,\
295 neon_bp_simple,\
296 neon_bp_2cycle,\
297 neon_bp_3cycle,\
298 neon_ldr,\
299 neon_str,\
300 neon_vld1_1_2_regs,\
301 neon_vld1_3_4_regs,\
302 neon_vld2_2_regs_vld1_vld2_all_lanes,\
303 neon_vld2_4_regs,\
304 neon_vld3_vld4,\
305 neon_vst1_1_2_regs_vst2_2_regs,\
306 neon_vst1_3_4_regs,\
307 neon_vst2_4_regs_vst3_vst4,\
308 neon_vst3_vst4,\
309 neon_vld1_vld2_lane,\
310 neon_vld3_vld4_lane,\
311 neon_vst1_vst2_lane,\
312 neon_vst3_vst4_lane,\
313 neon_vld3_vld4_all_lanes,\
314 neon_mcr,\
315 neon_mcr_2_mcrr,\
316 neon_mrc,\
317 neon_mrrc,\
318 neon_ldm_2,\
319 neon_stm_2,\
320 none"
321 (const_string "none"))
322
f7fbdd4a 323; condition codes: this one is used by final_prescan_insn to speed up
324; conditionalizing instructions. It saves having to scan the rtl to see if
325; it uses or alters the condition codes.
215b30b3 326;
f7fbdd4a 327; USE means that the condition codes are used by the insn in the process of
215b30b3 328; outputting code, this means (at present) that we can't use the insn in
329; inlined branches
330;
f7fbdd4a 331; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 332; well defined manner.
333;
f7fbdd4a 334; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 335; they are altered at all
336;
c52acdd2 337; UNCONDITIONAL means the instions can not be conditionally executed.
338;
f7fbdd4a 339; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 340; output of this insn
f7fbdd4a 341
b0694be0 342(define_attr "conds" "use,set,clob,unconditional,nocond"
f7fbdd4a 343 (if_then_else (eq_attr "type" "call")
c1a66faf 344 (const_string "clob")
c52acdd2 345 (if_then_else (eq_attr "neon_type" "none")
346 (const_string "nocond")
347 (const_string "unconditional"))))
f7fbdd4a 348
215b30b3 349; Predicable means that the insn can be conditionally executed based on
350; an automatically added predicate (additional patterns are generated by
351; gen...). We default to 'no' because no Thumb patterns match this rule
352; and not all ARM patterns do.
0d66636f 353(define_attr "predicable" "no,yes" (const_string "no"))
354
129a2fe4 355; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
356; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 357; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 358; affect the schedule).
74a71f7d 359(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 360
215b30b3 361; WRITE_CONFLICT implies that a read following an unrelated write is likely
362; to stall the processor. Used with model_wbuf above.
9c08d1fa 363(define_attr "write_conflict" "no,yes"
364 (if_then_else (eq_attr "type"
a2cd141b 365 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 366 (const_string "yes")
367 (const_string "no")))
368
215b30b3 369; Classify the insns into those that take one cycle and those that take more
370; than one on the main cpu execution unit.
f7fbdd4a 371(define_attr "core_cycles" "single,multi"
372 (if_then_else (eq_attr "type"
a2cd141b 373 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 374 (const_string "single")
375 (const_string "multi")))
376
cffb2a26 377;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 378;; distant label. Only applicable to Thumb code.
cffb2a26 379(define_attr "far_jump" "yes,no" (const_string "no"))
380
d51f92df 381
25f905c2 382;; The number of machine instructions this pattern expands to.
383;; Used for Thumb-2 conditional execution.
384(define_attr "ce_count" "" (const_int 1))
385
d51f92df 386;;---------------------------------------------------------------------------
fd781bb2 387;; Mode iterators
d51f92df 388
389; A list of modes that are exactly 64 bits in size. We use this to expand
390; some splits that are the same for all modes when operating on ARM
391; registers.
fd781bb2 392(define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
d51f92df 393
394;;---------------------------------------------------------------------------
395;; Predicates
396
9c9db025 397(include "predicates.md")
234f6557 398(include "constraints.md")
9c9db025 399
a2cd141b 400;;---------------------------------------------------------------------------
401;; Pipeline descriptions
215b30b3 402
06469f9e 403;; Processor type. This is created automatically from arm-cores.def.
404(include "arm-tune.md")
331beb1a 405
e3879fd0 406(define_attr "tune_cortexr4" "yes,no"
407 (const (if_then_else
408 (eq_attr "tune" "cortexr4,cortexr4f")
409 (const_string "yes")
410 (const_string "no"))))
411
a2cd141b 412;; True if the generic scheduling description should be used.
413
414(define_attr "generic_sched" "yes,no"
4d5cb40d 415 (const (if_then_else
036068af 416 (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
e3879fd0 417 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 418 (const_string "no")
419 (const_string "yes"))))
420
c0e1af52 421(define_attr "generic_vfp" "yes,no"
422 (const (if_then_else
423 (and (eq_attr "fpu" "vfp")
036068af 424 (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
e3879fd0 425 (eq_attr "tune_cortexr4" "no"))
c0e1af52 426 (const_string "yes")
427 (const_string "no"))))
428
a2cd141b 429(include "arm-generic.md")
430(include "arm926ejs.md")
c0e1af52 431(include "arm1020e.md")
a2cd141b 432(include "arm1026ejs.md")
433(include "arm1136jfs.md")
bcaec148 434(include "cortex-a8.md")
036068af 435(include "cortex-a9.md")
934a1e72 436(include "cortex-r4.md")
e3879fd0 437(include "cortex-r4f.md")
55e3ada8 438(include "vfp11.md")
3586df96 439
9c08d1fa 440\f
215b30b3 441;;---------------------------------------------------------------------------
e1159bbe 442;; Insn patterns
443;;
a0f94409 444;; Addition insns.
215b30b3 445
9c08d1fa 446;; Note: For DImode insns, there is normally no reason why operands should
447;; not be in the same register, what we don't want is for something being
448;; written to partially overlap something that is an input.
7d57ec45 449;; Cirrus 64bit additions should not be split because we have a native
450;; 64bit addition instructions.
9c08d1fa 451
cffb2a26 452(define_expand "adddi3"
453 [(parallel
215b30b3 454 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 455 (plus:DI (match_operand:DI 1 "s_register_operand" "")
456 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 457 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 458 "TARGET_EITHER"
459 "
a2cd141b 460 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 461 {
462 if (!cirrus_fp_register (operands[0], DImode))
463 operands[0] = force_reg (DImode, operands[0]);
464 if (!cirrus_fp_register (operands[1], DImode))
465 operands[1] = force_reg (DImode, operands[1]);
466 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
467 DONE;
468 }
469
25f905c2 470 if (TARGET_THUMB1)
cffb2a26 471 {
472 if (GET_CODE (operands[1]) != REG)
bc5a93af 473 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 474 if (GET_CODE (operands[2]) != REG)
bc5a93af 475 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 476 }
477 "
478)
479
25f905c2 480(define_insn "*thumb1_adddi3"
cffb2a26 481 [(set (match_operand:DI 0 "register_operand" "=l")
482 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 483 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 484 (clobber (reg:CC CC_REGNUM))
cffb2a26 485 ]
25f905c2 486 "TARGET_THUMB1"
cffb2a26 487 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
488 [(set_attr "length" "4")]
489)
490
a0f94409 491(define_insn_and_split "*arm_adddi3"
cffb2a26 492 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 493 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
494 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 495 (clobber (reg:CC CC_REGNUM))]
25f905c2 496 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 497 "#"
25f905c2 498 "TARGET_32BIT && reload_completed"
a0f94409 499 [(parallel [(set (reg:CC_C CC_REGNUM)
500 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
501 (match_dup 1)))
502 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
503 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
504 (plus:SI (match_dup 4) (match_dup 5))))]
505 "
506 {
507 operands[3] = gen_highpart (SImode, operands[0]);
508 operands[0] = gen_lowpart (SImode, operands[0]);
509 operands[4] = gen_highpart (SImode, operands[1]);
510 operands[1] = gen_lowpart (SImode, operands[1]);
511 operands[5] = gen_highpart (SImode, operands[2]);
512 operands[2] = gen_lowpart (SImode, operands[2]);
513 }"
cffb2a26 514 [(set_attr "conds" "clob")
515 (set_attr "length" "8")]
516)
9c08d1fa 517
a0f94409 518(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 519 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
520 (plus:DI (sign_extend:DI
97499065 521 (match_operand:SI 2 "s_register_operand" "r,r"))
522 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 523 (clobber (reg:CC CC_REGNUM))]
25f905c2 524 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 525 "#"
25f905c2 526 "TARGET_32BIT && reload_completed"
a0f94409 527 [(parallel [(set (reg:CC_C CC_REGNUM)
528 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
529 (match_dup 1)))
530 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
531 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
532 (plus:SI (ashiftrt:SI (match_dup 2)
533 (const_int 31))
534 (match_dup 4))))]
535 "
536 {
537 operands[3] = gen_highpart (SImode, operands[0]);
538 operands[0] = gen_lowpart (SImode, operands[0]);
539 operands[4] = gen_highpart (SImode, operands[1]);
540 operands[1] = gen_lowpart (SImode, operands[1]);
541 operands[2] = gen_lowpart (SImode, operands[2]);
542 }"
215b30b3 543 [(set_attr "conds" "clob")
544 (set_attr "length" "8")]
545)
9c08d1fa 546
a0f94409 547(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 548 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
549 (plus:DI (zero_extend:DI
97499065 550 (match_operand:SI 2 "s_register_operand" "r,r"))
551 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 552 (clobber (reg:CC CC_REGNUM))]
25f905c2 553 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 554 "#"
25f905c2 555 "TARGET_32BIT && reload_completed"
a0f94409 556 [(parallel [(set (reg:CC_C CC_REGNUM)
557 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
558 (match_dup 1)))
559 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
560 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
561 (plus:SI (match_dup 4) (const_int 0))))]
562 "
563 {
564 operands[3] = gen_highpart (SImode, operands[0]);
565 operands[0] = gen_lowpart (SImode, operands[0]);
566 operands[4] = gen_highpart (SImode, operands[1]);
567 operands[1] = gen_lowpart (SImode, operands[1]);
568 operands[2] = gen_lowpart (SImode, operands[2]);
569 }"
cffb2a26 570 [(set_attr "conds" "clob")
571 (set_attr "length" "8")]
572)
b11cae9e 573
87b22bf7 574(define_expand "addsi3"
cffb2a26 575 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 576 (plus:SI (match_operand:SI 1 "s_register_operand" "")
577 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 578 "TARGET_EITHER"
87b22bf7 579 "
25f905c2 580 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 581 {
96f57e36 582 arm_split_constant (PLUS, SImode, NULL_RTX,
583 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 584 optimize && can_create_pseudo_p ());
87b22bf7 585 DONE;
586 }
cffb2a26 587 "
588)
87b22bf7 589
5bd751ff 590; If there is a scratch available, this will be faster than synthesizing the
a0f94409 591; addition.
592(define_peephole2
593 [(match_scratch:SI 3 "r")
372575c7 594 (set (match_operand:SI 0 "arm_general_register_operand" "")
595 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 596 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 597 "TARGET_32BIT &&
a0f94409 598 !(const_ok_for_arm (INTVAL (operands[2]))
599 || const_ok_for_arm (-INTVAL (operands[2])))
600 && const_ok_for_arm (~INTVAL (operands[2]))"
601 [(set (match_dup 3) (match_dup 2))
602 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
603 ""
604)
87b22bf7 605
2f02c19f 606;; The r/r/k alternative is required when reloading the address
607;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
608;; put the duplicated register first, and not try the commutative version.
a0f94409 609(define_insn_and_split "*arm_addsi3"
2f02c19f 610 [(set (match_operand:SI 0 "s_register_operand" "=r, !k, r,r, !k,r")
611 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
612 (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
25f905c2 613 "TARGET_32BIT"
5565501b 614 "@
615 add%?\\t%0, %1, %2
aaa37ad6 616 add%?\\t%0, %1, %2
2f02c19f 617 add%?\\t%0, %2, %1
aaa37ad6 618 sub%?\\t%0, %1, #%n2
87b22bf7 619 sub%?\\t%0, %1, #%n2
620 #"
a3ffc315 621 "TARGET_32BIT
622 && GET_CODE (operands[2]) == CONST_INT
a0f94409 623 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 624 || const_ok_for_arm (-INTVAL (operands[2])))
625 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 626 [(clobber (const_int 0))]
627 "
96f57e36 628 arm_split_constant (PLUS, SImode, curr_insn,
629 INTVAL (operands[2]), operands[0],
a0f94409 630 operands[1], 0);
631 DONE;
632 "
2f02c19f 633 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 634 (set_attr "predicable" "yes")]
cffb2a26 635)
636
637;; Register group 'k' is a single register group containing only the stack
638;; register. Trying to reload it will always fail catastrophically,
639;; so never allow those alternatives to match if reloading is needed.
640
0bdb6455 641(define_insn_and_split "*thumb1_addsi3"
642 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
643 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
644 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
25f905c2 645 "TARGET_THUMB1"
cffb2a26 646 "*
0d66636f 647 static const char * const asms[] =
cffb2a26 648 {
649 \"add\\t%0, %0, %2\",
650 \"sub\\t%0, %0, #%n2\",
651 \"add\\t%0, %1, %2\",
652 \"add\\t%0, %0, %2\",
653 \"add\\t%0, %0, %2\",
654 \"add\\t%0, %1, %2\",
0bdb6455 655 \"add\\t%0, %1, %2\",
656 \"#\",
657 \"#\"
cffb2a26 658 };
659 if ((which_alternative == 2 || which_alternative == 6)
660 && GET_CODE (operands[2]) == CONST_INT
661 && INTVAL (operands[2]) < 0)
662 return \"sub\\t%0, %1, #%n2\";
663 return asms[which_alternative];
664 "
0bdb6455 665 "&& reload_completed && CONST_INT_P (operands[2])
666 && operands[1] != stack_pointer_rtx
667 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
668 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
669 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
670 {
671 HOST_WIDE_INT offset = INTVAL (operands[2]);
672 if (offset > 255)
673 offset = 255;
674 else if (offset < -255)
675 offset = -255;
676
677 operands[3] = GEN_INT (offset);
678 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
679 }
680 [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
cffb2a26 681)
682
683;; Reloading and elimination of the frame pointer can
684;; sometimes cause this optimization to be missed.
a0f94409 685(define_peephole2
372575c7 686 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 687 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 688 (set (match_dup 0)
372575c7 689 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 690 "TARGET_THUMB1
cffb2a26 691 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
692 && (INTVAL (operands[1]) & 3) == 0"
372575c7 693 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 694 ""
cffb2a26 695)
b11cae9e 696
25f905c2 697;; ??? Make Thumb-2 variants which prefer low regs
f7fbdd4a 698(define_insn "*addsi3_compare0"
bd5b4116 699 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 700 (compare:CC_NOOV
215b30b3 701 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
702 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 703 (const_int 0)))
704 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 705 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 706 "TARGET_32BIT"
5565501b 707 "@
25f905c2 708 add%.\\t%0, %1, %2
709 sub%.\\t%0, %1, #%n2"
cffb2a26 710 [(set_attr "conds" "set")]
711)
9c08d1fa 712
aea4c774 713(define_insn "*addsi3_compare0_scratch"
bd5b4116 714 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 715 (compare:CC_NOOV
215b30b3 716 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
717 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 718 (const_int 0)))]
25f905c2 719 "TARGET_32BIT"
cffb2a26 720 "@
721 cmn%?\\t%0, %1
722 cmp%?\\t%0, #%n1"
0d66636f 723 [(set_attr "conds" "set")]
724)
cffb2a26 725
aed179ae 726(define_insn "*compare_negsi_si"
727 [(set (reg:CC_Z CC_REGNUM)
728 (compare:CC_Z
729 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
730 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 731 "TARGET_32BIT"
aed179ae 732 "cmn%?\\t%1, %0"
0d66636f 733 [(set_attr "conds" "set")]
734)
aea4c774 735
203c488f 736;; This is the canonicalization of addsi3_compare0_for_combiner when the
737;; addend is a constant.
738(define_insn "*cmpsi2_addneg"
739 [(set (reg:CC CC_REGNUM)
740 (compare:CC
741 (match_operand:SI 1 "s_register_operand" "r,r")
742 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
743 (set (match_operand:SI 0 "s_register_operand" "=r,r")
744 (plus:SI (match_dup 1)
745 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
25f905c2 746 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 747 "@
25f905c2 748 sub%.\\t%0, %1, %2
749 add%.\\t%0, %1, #%n2"
203c488f 750 [(set_attr "conds" "set")]
751)
752
753;; Convert the sequence
754;; sub rd, rn, #1
755;; cmn rd, #1 (equivalent to cmp rd, #-1)
756;; bne dest
757;; into
758;; subs rd, rn, #1
759;; bcs dest ((unsigned)rn >= 1)
760;; similarly for the beq variant using bcc.
761;; This is a common looping idiom (while (n--))
762(define_peephole2
372575c7 763 [(set (match_operand:SI 0 "arm_general_register_operand" "")
764 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 765 (const_int -1)))
766 (set (match_operand 2 "cc_register" "")
767 (compare (match_dup 0) (const_int -1)))
768 (set (pc)
769 (if_then_else (match_operator 3 "equality_operator"
770 [(match_dup 2) (const_int 0)])
771 (match_operand 4 "" "")
772 (match_operand 5 "" "")))]
25f905c2 773 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 774 [(parallel[
775 (set (match_dup 2)
776 (compare:CC
777 (match_dup 1) (const_int 1)))
778 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
779 (set (pc)
780 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
781 (match_dup 4)
782 (match_dup 5)))]
783 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
784 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
785 ? GEU : LTU),
786 VOIDmode,
787 operands[2], const0_rtx);"
788)
789
ebcc79bc 790;; The next four insns work because they compare the result with one of
791;; the operands, and we know that the use of the condition code is
792;; either GEU or LTU, so we can use the carry flag from the addition
793;; instead of doing the compare a second time.
794(define_insn "*addsi3_compare_op1"
bd5b4116 795 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 796 (compare:CC_C
797 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
798 (match_operand:SI 2 "arm_add_operand" "rI,L"))
799 (match_dup 1)))
800 (set (match_operand:SI 0 "s_register_operand" "=r,r")
801 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 802 "TARGET_32BIT"
ebcc79bc 803 "@
25f905c2 804 add%.\\t%0, %1, %2
805 sub%.\\t%0, %1, #%n2"
0d66636f 806 [(set_attr "conds" "set")]
807)
ebcc79bc 808
809(define_insn "*addsi3_compare_op2"
bd5b4116 810 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 811 (compare:CC_C
812 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
813 (match_operand:SI 2 "arm_add_operand" "rI,L"))
814 (match_dup 2)))
5565501b 815 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 816 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 817 "TARGET_32BIT"
5565501b 818 "@
25f905c2 819 add%.\\t%0, %1, %2
820 sub%.\\t%0, %1, #%n2"
0d66636f 821 [(set_attr "conds" "set")]
822)
9c08d1fa 823
ebcc79bc 824(define_insn "*compare_addsi2_op0"
bd5b4116 825 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 826 (compare:CC_C
827 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
828 (match_operand:SI 1 "arm_add_operand" "rI,L"))
829 (match_dup 0)))]
25f905c2 830 "TARGET_32BIT"
ebcc79bc 831 "@
832 cmn%?\\t%0, %1
833 cmp%?\\t%0, #%n1"
0d66636f 834 [(set_attr "conds" "set")]
835)
ebcc79bc 836
837(define_insn "*compare_addsi2_op1"
bd5b4116 838 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 839 (compare:CC_C
840 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
841 (match_operand:SI 1 "arm_add_operand" "rI,L"))
842 (match_dup 1)))]
25f905c2 843 "TARGET_32BIT"
ebcc79bc 844 "@
845 cmn%?\\t%0, %1
846 cmp%?\\t%0, #%n1"
0d66636f 847 [(set_attr "conds" "set")]
848)
ebcc79bc 849
850(define_insn "*addsi3_carryin"
851 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 852 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 853 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
854 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
25f905c2 855 "TARGET_32BIT"
ebcc79bc 856 "adc%?\\t%0, %1, %2"
cffb2a26 857 [(set_attr "conds" "use")]
858)
ebcc79bc 859
33782ec7 860(define_insn "*addsi3_carryin_shift"
7b63a8dd 861 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 862 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 863 (plus:SI
864 (match_operator:SI 2 "shift_operator"
7b63a8dd 865 [(match_operand:SI 3 "s_register_operand" "r")
866 (match_operand:SI 4 "reg_or_int_operand" "rM")])
867 (match_operand:SI 1 "s_register_operand" "r"))))]
25f905c2 868 "TARGET_32BIT"
33782ec7 869 "adc%?\\t%0, %1, %3%S2"
a2cd141b 870 [(set_attr "conds" "use")
871 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
872 (const_string "alu_shift")
873 (const_string "alu_shift_reg")))]
33782ec7 874)
875
ebcc79bc 876(define_insn "*addsi3_carryin_alt1"
877 [(set (match_operand:SI 0 "s_register_operand" "=r")
878 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
879 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 880 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
25f905c2 881 "TARGET_32BIT"
ebcc79bc 882 "adc%?\\t%0, %1, %2"
cffb2a26 883 [(set_attr "conds" "use")]
884)
ebcc79bc 885
886(define_insn "*addsi3_carryin_alt2"
887 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 888 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 889 (match_operand:SI 1 "s_register_operand" "r"))
890 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 891 "TARGET_32BIT"
ebcc79bc 892 "adc%?\\t%0, %1, %2"
0d66636f 893 [(set_attr "conds" "use")]
894)
ebcc79bc 895
896(define_insn "*addsi3_carryin_alt3"
897 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 898 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 899 (match_operand:SI 2 "arm_rhs_operand" "rI"))
900 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 901 "TARGET_32BIT"
ebcc79bc 902 "adc%?\\t%0, %1, %2"
cffb2a26 903 [(set_attr "conds" "use")]
904)
ebcc79bc 905
25f905c2 906(define_expand "incscc"
907 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
908 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
909 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
910 (match_operand:SI 1 "s_register_operand" "0,?r")))]
911 "TARGET_32BIT"
912 ""
913)
914
915(define_insn "*arm_incscc"
9c08d1fa 916 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 917 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 918 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 919 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 920 "TARGET_ARM"
5565501b 921 "@
922 add%d2\\t%0, %1, #1
923 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 924 [(set_attr "conds" "use")
215b30b3 925 (set_attr "length" "4,8")]
926)
9c08d1fa 927
d795fb69 928; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
929(define_split
930 [(set (match_operand:SI 0 "s_register_operand" "")
931 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
932 (match_operand:SI 2 "s_register_operand" ""))
933 (const_int -1)))
934 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 935 "TARGET_32BIT"
d795fb69 936 [(set (match_dup 3) (match_dup 1))
937 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
938 "
939 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
940")
941
604f3a0a 942(define_expand "addsf3"
943 [(set (match_operand:SF 0 "s_register_operand" "")
944 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 945 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 946 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 947 "
a2cd141b 948 if (TARGET_MAVERICK
604f3a0a 949 && !cirrus_fp_register (operands[2], SFmode))
950 operands[2] = force_reg (SFmode, operands[2]);
951")
952
604f3a0a 953(define_expand "adddf3"
954 [(set (match_operand:DF 0 "s_register_operand" "")
955 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 956 (match_operand:DF 2 "arm_float_add_operand" "")))]
25f905c2 957 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 958 "
a2cd141b 959 if (TARGET_MAVERICK
604f3a0a 960 && !cirrus_fp_register (operands[2], DFmode))
961 operands[2] = force_reg (DFmode, operands[2]);
962")
963
cffb2a26 964(define_expand "subdi3"
965 [(parallel
966 [(set (match_operand:DI 0 "s_register_operand" "")
967 (minus:DI (match_operand:DI 1 "s_register_operand" "")
968 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 969 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 970 "TARGET_EITHER"
971 "
a2cd141b 972 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 973 && TARGET_32BIT
7d57ec45 974 && cirrus_fp_register (operands[0], DImode)
975 && cirrus_fp_register (operands[1], DImode))
976 {
977 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
978 DONE;
979 }
980
25f905c2 981 if (TARGET_THUMB1)
cffb2a26 982 {
983 if (GET_CODE (operands[1]) != REG)
984 operands[1] = force_reg (SImode, operands[1]);
985 if (GET_CODE (operands[2]) != REG)
986 operands[2] = force_reg (SImode, operands[2]);
987 }
988 "
989)
990
991(define_insn "*arm_subdi3"
992 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 993 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
994 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 995 (clobber (reg:CC CC_REGNUM))]
25f905c2 996 "TARGET_32BIT"
97499065 997 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 998 [(set_attr "conds" "clob")
999 (set_attr "length" "8")]
1000)
1001
1002(define_insn "*thumb_subdi3"
1003 [(set (match_operand:DI 0 "register_operand" "=l")
1004 (minus:DI (match_operand:DI 1 "register_operand" "0")
1005 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1006 (clobber (reg:CC CC_REGNUM))]
25f905c2 1007 "TARGET_THUMB1"
cffb2a26 1008 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1009 [(set_attr "length" "4")]
1010)
9c08d1fa 1011
f7fbdd4a 1012(define_insn "*subdi_di_zesidi"
cffb2a26 1013 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1014 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 1015 (zero_extend:DI
cffb2a26 1016 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1017 (clobber (reg:CC CC_REGNUM))]
25f905c2 1018 "TARGET_32BIT"
97499065 1019 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1020 [(set_attr "conds" "clob")
1021 (set_attr "length" "8")]
1022)
9c08d1fa 1023
f7fbdd4a 1024(define_insn "*subdi_di_sesidi"
cffb2a26 1025 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1026 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 1027 (sign_extend:DI
cffb2a26 1028 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1029 (clobber (reg:CC CC_REGNUM))]
25f905c2 1030 "TARGET_32BIT"
97499065 1031 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1032 [(set_attr "conds" "clob")
1033 (set_attr "length" "8")]
1034)
9c08d1fa 1035
f7fbdd4a 1036(define_insn "*subdi_zesidi_di"
cffb2a26 1037 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1038 (minus:DI (zero_extend:DI
cffb2a26 1039 (match_operand:SI 2 "s_register_operand" "r,r"))
1040 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 1041 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1042 "TARGET_ARM"
97499065 1043 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1044 [(set_attr "conds" "clob")
1045 (set_attr "length" "8")]
1046)
9c08d1fa 1047
f7fbdd4a 1048(define_insn "*subdi_sesidi_di"
cffb2a26 1049 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1050 (minus:DI (sign_extend:DI
cffb2a26 1051 (match_operand:SI 2 "s_register_operand" "r,r"))
1052 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 1053 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1054 "TARGET_ARM"
97499065 1055 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1056 [(set_attr "conds" "clob")
1057 (set_attr "length" "8")]
1058)
9c08d1fa 1059
f7fbdd4a 1060(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1061 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1062 (minus:DI (zero_extend:DI
cffb2a26 1063 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1064 (zero_extend:DI
cffb2a26 1065 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1066 (clobber (reg:CC CC_REGNUM))]
25f905c2 1067 "TARGET_32BIT"
1068 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1069 [(set_attr "conds" "clob")
1070 (set_attr "length" "8")]
1071)
b11cae9e 1072
87b22bf7 1073(define_expand "subsi3"
cffb2a26 1074 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1075 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1076 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1077 "TARGET_EITHER"
87b22bf7 1078 "
1079 if (GET_CODE (operands[1]) == CONST_INT)
1080 {
25f905c2 1081 if (TARGET_32BIT)
cffb2a26 1082 {
96f57e36 1083 arm_split_constant (MINUS, SImode, NULL_RTX,
1084 INTVAL (operands[1]), operands[0],
e1ba4a27 1085 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1086 DONE;
1087 }
25f905c2 1088 else /* TARGET_THUMB1 */
cffb2a26 1089 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1090 }
cffb2a26 1091 "
1092)
87b22bf7 1093
25f905c2 1094(define_insn "*thumb1_subsi3_insn"
cffb2a26 1095 [(set (match_operand:SI 0 "register_operand" "=l")
1096 (minus:SI (match_operand:SI 1 "register_operand" "l")
1097 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1098 "TARGET_THUMB1"
cffb2a26 1099 "sub\\t%0, %1, %2"
1100 [(set_attr "length" "2")]
1101)
1102
25f905c2 1103; ??? Check Thumb-2 split length
a0f94409 1104(define_insn_and_split "*arm_subsi3_insn"
aaa37ad6 1105 [(set (match_operand:SI 0 "s_register_operand" "=r,rk,r")
1106 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n")
1107 (match_operand:SI 2 "s_register_operand" "r, r, r")))]
25f905c2 1108 "TARGET_32BIT"
e2348bcb 1109 "@
87b22bf7 1110 rsb%?\\t%0, %2, %1
aaa37ad6 1111 sub%?\\t%0, %1, %2
87b22bf7 1112 #"
25f905c2 1113 "TARGET_32BIT
a0f94409 1114 && GET_CODE (operands[1]) == CONST_INT
1115 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 1116 [(clobber (const_int 0))]
1117 "
96f57e36 1118 arm_split_constant (MINUS, SImode, curr_insn,
1119 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1120 DONE;
cffb2a26 1121 "
aaa37ad6 1122 [(set_attr "length" "4,4,16")
a0f94409 1123 (set_attr "predicable" "yes")]
1124)
1125
1126(define_peephole2
1127 [(match_scratch:SI 3 "r")
372575c7 1128 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1129 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1130 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1131 "TARGET_32BIT
a0f94409 1132 && !const_ok_for_arm (INTVAL (operands[1]))
1133 && const_ok_for_arm (~INTVAL (operands[1]))"
1134 [(set (match_dup 3) (match_dup 1))
1135 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1136 ""
cffb2a26 1137)
b11cae9e 1138
f7fbdd4a 1139(define_insn "*subsi3_compare0"
bd5b4116 1140 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1141 (compare:CC_NOOV
1142 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1143 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1144 (const_int 0)))
9c08d1fa 1145 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1146 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1147 "TARGET_32BIT"
e2348bcb 1148 "@
25f905c2 1149 sub%.\\t%0, %1, %2
1150 rsb%.\\t%0, %2, %1"
cffb2a26 1151 [(set_attr "conds" "set")]
1152)
9c08d1fa 1153
25f905c2 1154(define_expand "decscc"
1155 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1156 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1157 (match_operator:SI 2 "arm_comparison_operator"
1158 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1159 "TARGET_32BIT"
1160 ""
1161)
1162
1163(define_insn "*arm_decscc"
cffb2a26 1164 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1165 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1166 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1167 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1168 "TARGET_ARM"
e2348bcb 1169 "@
215b30b3 1170 sub%d2\\t%0, %1, #1
1171 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1172 [(set_attr "conds" "use")
1173 (set_attr "length" "*,8")]
1174)
9c08d1fa 1175
604f3a0a 1176(define_expand "subsf3"
1177 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1178 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1179 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1180 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1181 "
a2cd141b 1182 if (TARGET_MAVERICK)
604f3a0a 1183 {
1184 if (!cirrus_fp_register (operands[1], SFmode))
1185 operands[1] = force_reg (SFmode, operands[1]);
1186 if (!cirrus_fp_register (operands[2], SFmode))
1187 operands[2] = force_reg (SFmode, operands[2]);
1188 }
1189")
1190
604f3a0a 1191(define_expand "subdf3"
1192 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1193 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1194 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1195 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1196 "
a2cd141b 1197 if (TARGET_MAVERICK)
604f3a0a 1198 {
1199 if (!cirrus_fp_register (operands[1], DFmode))
1200 operands[1] = force_reg (DFmode, operands[1]);
1201 if (!cirrus_fp_register (operands[2], DFmode))
1202 operands[2] = force_reg (DFmode, operands[2]);
1203 }
1204")
1205
b11cae9e 1206\f
1207;; Multiplication insns
1208
cffb2a26 1209(define_expand "mulsi3"
1210 [(set (match_operand:SI 0 "s_register_operand" "")
1211 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1212 (match_operand:SI 1 "s_register_operand" "")))]
1213 "TARGET_EITHER"
1214 ""
1215)
1216
9c08d1fa 1217;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1218(define_insn "*arm_mulsi3"
1219 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1220 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1221 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
58d7d654 1222 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1223 "mul%?\\t%0, %2, %1"
a2cd141b 1224 [(set_attr "insn" "mul")
0d66636f 1225 (set_attr "predicable" "yes")]
cffb2a26 1226)
1227
58d7d654 1228(define_insn "*arm_mulsi3_v6"
1229 [(set (match_operand:SI 0 "s_register_operand" "=r")
1230 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1231 (match_operand:SI 2 "s_register_operand" "r")))]
1232 "TARGET_32BIT && arm_arch6"
1233 "mul%?\\t%0, %1, %2"
1234 [(set_attr "insn" "mul")
1235 (set_attr "predicable" "yes")]
1236)
1237
215b30b3 1238; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1239; 1 and 2; are the same, because reload will make operand 0 match
1240; operand 1 without realizing that this conflicts with operand 2. We fix
1241; this by adding another alternative to match this case, and then `reload'
1242; it ourselves. This alternative must come first.
cffb2a26 1243(define_insn "*thumb_mulsi3"
1244 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1245 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1246 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1247 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1248 "*
1249 if (which_alternative < 2)
20c4e896 1250 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1251 else
20c4e896 1252 return \"mul\\t%0, %2\";
cffb2a26 1253 "
1254 [(set_attr "length" "4,4,2")
a2cd141b 1255 (set_attr "insn" "mul")]
cffb2a26 1256)
b11cae9e 1257
58d7d654 1258(define_insn "*thumb_mulsi3_v6"
1259 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1260 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1261 (match_operand:SI 2 "register_operand" "l,0,0")))]
1262 "TARGET_THUMB1 && arm_arch6"
1263 "@
1264 mul\\t%0, %2
1265 mul\\t%0, %1
1266 mul\\t%0, %1"
1267 [(set_attr "length" "2")
1268 (set_attr "insn" "mul")]
1269)
1270
f7fbdd4a 1271(define_insn "*mulsi3_compare0"
bd5b4116 1272 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1273 (compare:CC_NOOV (mult:SI
1274 (match_operand:SI 2 "s_register_operand" "r,r")
1275 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1276 (const_int 0)))
1277 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1278 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1279 "TARGET_ARM && !arm_arch6"
1280 "mul%.\\t%0, %2, %1"
1281 [(set_attr "conds" "set")
1282 (set_attr "insn" "muls")]
1283)
1284
1285(define_insn "*mulsi3_compare0_v6"
1286 [(set (reg:CC_NOOV CC_REGNUM)
1287 (compare:CC_NOOV (mult:SI
1288 (match_operand:SI 2 "s_register_operand" "r")
1289 (match_operand:SI 1 "s_register_operand" "r"))
1290 (const_int 0)))
1291 (set (match_operand:SI 0 "s_register_operand" "=r")
1292 (mult:SI (match_dup 2) (match_dup 1)))]
1293 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1294 "mul%.\\t%0, %2, %1"
cffb2a26 1295 [(set_attr "conds" "set")
a2cd141b 1296 (set_attr "insn" "muls")]
cffb2a26 1297)
9c08d1fa 1298
f7fbdd4a 1299(define_insn "*mulsi_compare0_scratch"
bd5b4116 1300 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1301 (compare:CC_NOOV (mult:SI
1302 (match_operand:SI 2 "s_register_operand" "r,r")
1303 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1304 (const_int 0)))
1305 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1306 "TARGET_ARM && !arm_arch6"
1307 "mul%.\\t%0, %2, %1"
1308 [(set_attr "conds" "set")
1309 (set_attr "insn" "muls")]
1310)
1311
1312(define_insn "*mulsi_compare0_scratch_v6"
1313 [(set (reg:CC_NOOV CC_REGNUM)
1314 (compare:CC_NOOV (mult:SI
1315 (match_operand:SI 2 "s_register_operand" "r")
1316 (match_operand:SI 1 "s_register_operand" "r"))
1317 (const_int 0)))
1318 (clobber (match_scratch:SI 0 "=r"))]
1319 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1320 "mul%.\\t%0, %2, %1"
cffb2a26 1321 [(set_attr "conds" "set")
a2cd141b 1322 (set_attr "insn" "muls")]
cffb2a26 1323)
9c08d1fa 1324
b11cae9e 1325;; Unnamed templates to match MLA instruction.
1326
f7fbdd4a 1327(define_insn "*mulsi3addsi"
9c08d1fa 1328 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1329 (plus:SI
9c08d1fa 1330 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1331 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1332 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
58d7d654 1333 "TARGET_32BIT && !arm_arch6"
1334 "mla%?\\t%0, %2, %1, %3"
1335 [(set_attr "insn" "mla")
1336 (set_attr "predicable" "yes")]
1337)
1338
1339(define_insn "*mulsi3addsi_v6"
1340 [(set (match_operand:SI 0 "s_register_operand" "=r")
1341 (plus:SI
1342 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1343 (match_operand:SI 1 "s_register_operand" "r"))
1344 (match_operand:SI 3 "s_register_operand" "r")))]
1345 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1346 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1347 [(set_attr "insn" "mla")
0d66636f 1348 (set_attr "predicable" "yes")]
1349)
b11cae9e 1350
f7fbdd4a 1351(define_insn "*mulsi3addsi_compare0"
bd5b4116 1352 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1353 (compare:CC_NOOV
1354 (plus:SI (mult:SI
1355 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1356 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1357 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1358 (const_int 0)))
9c08d1fa 1359 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1360 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1361 (match_dup 3)))]
58d7d654 1362 "TARGET_ARM && arm_arch6"
1363 "mla%.\\t%0, %2, %1, %3"
1364 [(set_attr "conds" "set")
1365 (set_attr "insn" "mlas")]
1366)
1367
1368(define_insn "*mulsi3addsi_compare0_v6"
1369 [(set (reg:CC_NOOV CC_REGNUM)
1370 (compare:CC_NOOV
1371 (plus:SI (mult:SI
1372 (match_operand:SI 2 "s_register_operand" "r")
1373 (match_operand:SI 1 "s_register_operand" "r"))
1374 (match_operand:SI 3 "s_register_operand" "r"))
1375 (const_int 0)))
1376 (set (match_operand:SI 0 "s_register_operand" "=r")
1377 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1378 (match_dup 3)))]
1379 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1380 "mla%.\\t%0, %2, %1, %3"
0d66636f 1381 [(set_attr "conds" "set")
a2cd141b 1382 (set_attr "insn" "mlas")]
0d66636f 1383)
9c08d1fa 1384
f7fbdd4a 1385(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1386 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1387 (compare:CC_NOOV
1388 (plus:SI (mult:SI
1389 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1390 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1391 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1392 (const_int 0)))
9c08d1fa 1393 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1394 "TARGET_ARM && !arm_arch6"
1395 "mla%.\\t%0, %2, %1, %3"
1396 [(set_attr "conds" "set")
1397 (set_attr "insn" "mlas")]
1398)
1399
1400(define_insn "*mulsi3addsi_compare0_scratch_v6"
1401 [(set (reg:CC_NOOV CC_REGNUM)
1402 (compare:CC_NOOV
1403 (plus:SI (mult:SI
1404 (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 (const_int 0)))
1408 (clobber (match_scratch:SI 0 "=r"))]
1409 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1410 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1411 [(set_attr "conds" "set")
a2cd141b 1412 (set_attr "insn" "mlas")]
cffb2a26 1413)
f7fbdd4a 1414
89545238 1415(define_insn "*mulsi3subsi"
1416 [(set (match_operand:SI 0 "s_register_operand" "=r")
1417 (minus:SI
1418 (match_operand:SI 3 "s_register_operand" "r")
1419 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1420 (match_operand:SI 1 "s_register_operand" "r"))))]
1421 "TARGET_32BIT && arm_arch_thumb2"
1422 "mls%?\\t%0, %2, %1, %3"
1423 [(set_attr "insn" "mla")
1424 (set_attr "predicable" "yes")]
1425)
1426
efee20da 1427;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1428
1429(define_insn "*mulsidi3adddi"
fe8dbf85 1430 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1431 (plus:DI
215b30b3 1432 (mult:DI
fe8dbf85 1433 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1434 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1435 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1436 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1437 "smlal%?\\t%Q0, %R0, %3, %2"
1438 [(set_attr "insn" "smlal")
1439 (set_attr "predicable" "yes")]
1440)
1441
1442(define_insn "*mulsidi3adddi_v6"
1443 [(set (match_operand:DI 0 "s_register_operand" "=r")
1444 (plus:DI
1445 (mult:DI
1446 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1447 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1448 (match_operand:DI 1 "s_register_operand" "0")))]
1449 "TARGET_32BIT && arm_arch6"
fe8dbf85 1450 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1451 [(set_attr "insn" "smlal")
0d66636f 1452 (set_attr "predicable" "yes")]
1453)
82b85d08 1454
957788b0 1455;; 32x32->64 widening multiply.
1456;; As with mulsi3, the only difference between the v3-5 and v6+
1457;; versions of these patterns is the requirement that the output not
1458;; overlap the inputs, but that still means we have to have a named
1459;; expander and two different starred insns.
1460
1461(define_expand "mulsidi3"
1462 [(set (match_operand:DI 0 "s_register_operand" "")
1463 (mult:DI
1464 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1465 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1466 "TARGET_32BIT && arm_arch3m"
1467 ""
1468)
1469
1470(define_insn "*mulsidi3_nov6"
f7fbdd4a 1471 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1472 (mult:DI
1473 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1474 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1475 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1476 "smull%?\\t%Q0, %R0, %1, %2"
1477 [(set_attr "insn" "smull")
1478 (set_attr "predicable" "yes")]
1479)
1480
957788b0 1481(define_insn "*mulsidi3_v6"
58d7d654 1482 [(set (match_operand:DI 0 "s_register_operand" "=r")
1483 (mult:DI
1484 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1485 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1486 "TARGET_32BIT && arm_arch6"
97499065 1487 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1488 [(set_attr "insn" "smull")
0d66636f 1489 (set_attr "predicable" "yes")]
1490)
f7fbdd4a 1491
957788b0 1492(define_expand "umulsidi3"
1493 [(set (match_operand:DI 0 "s_register_operand" "")
1494 (mult:DI
1495 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1496 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1497 "TARGET_32BIT && arm_arch3m"
1498 ""
1499)
1500
1501(define_insn "*umulsidi3_nov6"
f7fbdd4a 1502 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1503 (mult:DI
1504 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1505 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1506 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1507 "umull%?\\t%Q0, %R0, %1, %2"
1508 [(set_attr "insn" "umull")
1509 (set_attr "predicable" "yes")]
1510)
1511
957788b0 1512(define_insn "*umulsidi3_v6"
58d7d654 1513 [(set (match_operand:DI 0 "s_register_operand" "=r")
1514 (mult:DI
1515 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1516 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1517 "TARGET_32BIT && arm_arch6"
97499065 1518 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1519 [(set_attr "insn" "umull")
0d66636f 1520 (set_attr "predicable" "yes")]
1521)
b11cae9e 1522
efee20da 1523;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1524
1525(define_insn "*umulsidi3adddi"
8ead09f9 1526 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1527 (plus:DI
215b30b3 1528 (mult:DI
fe8dbf85 1529 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1530 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1531 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1532 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1533 "umlal%?\\t%Q0, %R0, %3, %2"
1534 [(set_attr "insn" "umlal")
1535 (set_attr "predicable" "yes")]
1536)
1537
1538(define_insn "*umulsidi3adddi_v6"
1539 [(set (match_operand:DI 0 "s_register_operand" "=r")
1540 (plus:DI
1541 (mult:DI
1542 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1543 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1544 (match_operand:DI 1 "s_register_operand" "0")))]
1545 "TARGET_32BIT && arm_arch6"
fe8dbf85 1546 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1547 [(set_attr "insn" "umlal")
0d66636f 1548 (set_attr "predicable" "yes")]
1549)
82b85d08 1550
957788b0 1551(define_expand "smulsi3_highpart"
1552 [(parallel
1553 [(set (match_operand:SI 0 "s_register_operand" "")
1554 (truncate:SI
1555 (lshiftrt:DI
1556 (mult:DI
1557 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1558 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1559 (const_int 32))))
1560 (clobber (match_scratch:SI 3 ""))])]
1561 "TARGET_32BIT && arm_arch3m"
1562 ""
1563)
1564
1565(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1566 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1567 (truncate:SI
1568 (lshiftrt:DI
215b30b3 1569 (mult:DI
1570 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1571 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1572 (const_int 32))))
1573 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1574 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1575 "smull%?\\t%3, %0, %2, %1"
1576 [(set_attr "insn" "smull")
1577 (set_attr "predicable" "yes")]
1578)
1579
957788b0 1580(define_insn "*smulsi3_highpart_v6"
58d7d654 1581 [(set (match_operand:SI 0 "s_register_operand" "=r")
1582 (truncate:SI
1583 (lshiftrt:DI
1584 (mult:DI
1585 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1586 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1587 (const_int 32))))
1588 (clobber (match_scratch:SI 3 "=r"))]
1589 "TARGET_32BIT && arm_arch6"
f082f1c4 1590 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1591 [(set_attr "insn" "smull")
0d66636f 1592 (set_attr "predicable" "yes")]
cffb2a26 1593)
f082f1c4 1594
957788b0 1595(define_expand "umulsi3_highpart"
1596 [(parallel
1597 [(set (match_operand:SI 0 "s_register_operand" "")
1598 (truncate:SI
1599 (lshiftrt:DI
1600 (mult:DI
1601 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1602 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1603 (const_int 32))))
1604 (clobber (match_scratch:SI 3 ""))])]
1605 "TARGET_32BIT && arm_arch3m"
1606 ""
1607)
1608
1609(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1610 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1611 (truncate:SI
1612 (lshiftrt:DI
215b30b3 1613 (mult:DI
1614 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1615 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1616 (const_int 32))))
1617 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1618 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1619 "umull%?\\t%3, %0, %2, %1"
1620 [(set_attr "insn" "umull")
1621 (set_attr "predicable" "yes")]
1622)
1623
957788b0 1624(define_insn "*umulsi3_highpart_v6"
58d7d654 1625 [(set (match_operand:SI 0 "s_register_operand" "=r")
1626 (truncate:SI
1627 (lshiftrt:DI
1628 (mult:DI
1629 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1630 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1631 (const_int 32))))
1632 (clobber (match_scratch:SI 3 "=r"))]
1633 "TARGET_32BIT && arm_arch6"
f082f1c4 1634 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1635 [(set_attr "insn" "umull")
0d66636f 1636 (set_attr "predicable" "yes")]
cffb2a26 1637)
f082f1c4 1638
331beb1a 1639(define_insn "mulhisi3"
1640 [(set (match_operand:SI 0 "s_register_operand" "=r")
1641 (mult:SI (sign_extend:SI
1642 (match_operand:HI 1 "s_register_operand" "%r"))
1643 (sign_extend:SI
1644 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1645 "TARGET_DSP_MULTIPLY"
61a2d04c 1646 "smulbb%?\\t%0, %1, %2"
a2cd141b 1647 [(set_attr "insn" "smulxy")
fec538d9 1648 (set_attr "predicable" "yes")]
1649)
1650
1651(define_insn "*mulhisi3tb"
1652 [(set (match_operand:SI 0 "s_register_operand" "=r")
1653 (mult:SI (ashiftrt:SI
1654 (match_operand:SI 1 "s_register_operand" "r")
1655 (const_int 16))
1656 (sign_extend:SI
1657 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1658 "TARGET_DSP_MULTIPLY"
fec538d9 1659 "smultb%?\\t%0, %1, %2"
a2cd141b 1660 [(set_attr "insn" "smulxy")
fec538d9 1661 (set_attr "predicable" "yes")]
1662)
1663
1664(define_insn "*mulhisi3bt"
1665 [(set (match_operand:SI 0 "s_register_operand" "=r")
1666 (mult:SI (sign_extend:SI
1667 (match_operand:HI 1 "s_register_operand" "r"))
1668 (ashiftrt:SI
1669 (match_operand:SI 2 "s_register_operand" "r")
1670 (const_int 16))))]
25f905c2 1671 "TARGET_DSP_MULTIPLY"
fec538d9 1672 "smulbt%?\\t%0, %1, %2"
a2cd141b 1673 [(set_attr "insn" "smulxy")
fec538d9 1674 (set_attr "predicable" "yes")]
1675)
1676
1677(define_insn "*mulhisi3tt"
1678 [(set (match_operand:SI 0 "s_register_operand" "=r")
1679 (mult:SI (ashiftrt:SI
1680 (match_operand:SI 1 "s_register_operand" "r")
1681 (const_int 16))
1682 (ashiftrt:SI
1683 (match_operand:SI 2 "s_register_operand" "r")
1684 (const_int 16))))]
25f905c2 1685 "TARGET_DSP_MULTIPLY"
fec538d9 1686 "smultt%?\\t%0, %1, %2"
a2cd141b 1687 [(set_attr "insn" "smulxy")
fec538d9 1688 (set_attr "predicable" "yes")]
331beb1a 1689)
1690
1691(define_insn "*mulhisi3addsi"
1692 [(set (match_operand:SI 0 "s_register_operand" "=r")
1693 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1694 (mult:SI (sign_extend:SI
1695 (match_operand:HI 2 "s_register_operand" "%r"))
1696 (sign_extend:SI
1697 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1698 "TARGET_DSP_MULTIPLY"
61a2d04c 1699 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1700 [(set_attr "insn" "smlaxy")
fec538d9 1701 (set_attr "predicable" "yes")]
331beb1a 1702)
1703
1704(define_insn "*mulhidi3adddi"
1705 [(set (match_operand:DI 0 "s_register_operand" "=r")
1706 (plus:DI
1707 (match_operand:DI 1 "s_register_operand" "0")
1708 (mult:DI (sign_extend:DI
1709 (match_operand:HI 2 "s_register_operand" "%r"))
1710 (sign_extend:DI
1711 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1712 "TARGET_DSP_MULTIPLY"
331beb1a 1713 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1714 [(set_attr "insn" "smlalxy")
fec538d9 1715 (set_attr "predicable" "yes")])
331beb1a 1716
604f3a0a 1717(define_expand "mulsf3"
1718 [(set (match_operand:SF 0 "s_register_operand" "")
1719 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1720 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1721 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1722 "
a2cd141b 1723 if (TARGET_MAVERICK
604f3a0a 1724 && !cirrus_fp_register (operands[2], SFmode))
1725 operands[2] = force_reg (SFmode, operands[2]);
1726")
1727
604f3a0a 1728(define_expand "muldf3"
1729 [(set (match_operand:DF 0 "s_register_operand" "")
1730 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1731 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1732 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1733 "
a2cd141b 1734 if (TARGET_MAVERICK
604f3a0a 1735 && !cirrus_fp_register (operands[2], DFmode))
1736 operands[2] = force_reg (DFmode, operands[2]);
1737")
b11cae9e 1738\f
1739;; Division insns
1740
7db9af5d 1741(define_expand "divsf3"
1742 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1743 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1744 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1745 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1746 "")
9c08d1fa 1747
7db9af5d 1748(define_expand "divdf3"
1749 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1750 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1751 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1752 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1753 "")
b11cae9e 1754\f
1755;; Modulo insns
1756
7db9af5d 1757(define_expand "modsf3"
1758 [(set (match_operand:SF 0 "s_register_operand" "")
1759 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1760 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1761 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1762 "")
9c08d1fa 1763
7db9af5d 1764(define_expand "moddf3"
1765 [(set (match_operand:DF 0 "s_register_operand" "")
1766 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1767 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1768 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1769 "")
b11cae9e 1770\f
1771;; Boolean and,ior,xor insns
1772
f6ebffac 1773;; Split up double word logical operations
1774
1775;; Split up simple DImode logical operations. Simply perform the logical
1776;; operation on the upper and lower halves of the registers.
1777(define_split
1778 [(set (match_operand:DI 0 "s_register_operand" "")
1779 (match_operator:DI 6 "logical_binary_operator"
1780 [(match_operand:DI 1 "s_register_operand" "")
1781 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1782 "TARGET_32BIT && reload_completed
1783 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1784 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1785 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1786 "
215b30b3 1787 {
1788 operands[3] = gen_highpart (SImode, operands[0]);
1789 operands[0] = gen_lowpart (SImode, operands[0]);
1790 operands[4] = gen_highpart (SImode, operands[1]);
1791 operands[1] = gen_lowpart (SImode, operands[1]);
1792 operands[5] = gen_highpart (SImode, operands[2]);
1793 operands[2] = gen_lowpart (SImode, operands[2]);
1794 }"
1795)
f6ebffac 1796
f6ebffac 1797(define_split
1798 [(set (match_operand:DI 0 "s_register_operand" "")
1799 (match_operator:DI 6 "logical_binary_operator"
1800 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1801 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1802 "TARGET_32BIT && reload_completed"
f6ebffac 1803 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1804 (set (match_dup 3) (match_op_dup:SI 6
1805 [(ashiftrt:SI (match_dup 2) (const_int 31))
1806 (match_dup 4)]))]
1807 "
215b30b3 1808 {
1809 operands[3] = gen_highpart (SImode, operands[0]);
1810 operands[0] = gen_lowpart (SImode, operands[0]);
1811 operands[4] = gen_highpart (SImode, operands[1]);
1812 operands[1] = gen_lowpart (SImode, operands[1]);
1813 operands[5] = gen_highpart (SImode, operands[2]);
1814 operands[2] = gen_lowpart (SImode, operands[2]);
1815 }"
1816)
f6ebffac 1817
f6ebffac 1818;; The zero extend of operand 2 means we can just copy the high part of
1819;; operand1 into operand0.
1820(define_split
1821 [(set (match_operand:DI 0 "s_register_operand" "")
1822 (ior:DI
1823 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1824 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1825 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1826 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1827 (set (match_dup 3) (match_dup 4))]
1828 "
215b30b3 1829 {
1830 operands[4] = gen_highpart (SImode, operands[1]);
1831 operands[3] = gen_highpart (SImode, operands[0]);
1832 operands[0] = gen_lowpart (SImode, operands[0]);
1833 operands[1] = gen_lowpart (SImode, operands[1]);
1834 }"
1835)
f6ebffac 1836
1837;; The zero extend of operand 2 means we can just copy the high part of
1838;; operand1 into operand0.
1839(define_split
1840 [(set (match_operand:DI 0 "s_register_operand" "")
1841 (xor:DI
1842 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1843 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1844 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1845 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1846 (set (match_dup 3) (match_dup 4))]
1847 "
215b30b3 1848 {
1849 operands[4] = gen_highpart (SImode, operands[1]);
1850 operands[3] = gen_highpart (SImode, operands[0]);
1851 operands[0] = gen_lowpart (SImode, operands[0]);
1852 operands[1] = gen_lowpart (SImode, operands[1]);
1853 }"
1854)
f6ebffac 1855
b11cae9e 1856(define_insn "anddi3"
cffb2a26 1857 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1858 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1859 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 1860 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 1861 "#"
215b30b3 1862 [(set_attr "length" "8")]
1863)
b11cae9e 1864
a0f94409 1865(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1866 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1867 (and:DI (zero_extend:DI
1868 (match_operand:SI 2 "s_register_operand" "r,r"))
1869 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1870 "TARGET_32BIT"
f6ebffac 1871 "#"
25f905c2 1872 "TARGET_32BIT && reload_completed"
a0f94409 1873 ; The zero extend of operand 2 clears the high word of the output
1874 ; operand.
1875 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1876 (set (match_dup 3) (const_int 0))]
1877 "
1878 {
1879 operands[3] = gen_highpart (SImode, operands[0]);
1880 operands[0] = gen_lowpart (SImode, operands[0]);
1881 operands[1] = gen_lowpart (SImode, operands[1]);
1882 }"
215b30b3 1883 [(set_attr "length" "8")]
1884)
b11cae9e 1885
f7fbdd4a 1886(define_insn "*anddi_sesdi_di"
cffb2a26 1887 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1888 (and:DI (sign_extend:DI
1889 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1890 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1891 "TARGET_32BIT"
f6ebffac 1892 "#"
cffb2a26 1893 [(set_attr "length" "8")]
1894)
b11cae9e 1895
87b22bf7 1896(define_expand "andsi3"
cffb2a26 1897 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1898 (and:SI (match_operand:SI 1 "s_register_operand" "")
1899 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1900 "TARGET_EITHER"
87b22bf7 1901 "
25f905c2 1902 if (TARGET_32BIT)
87b22bf7 1903 {
cffb2a26 1904 if (GET_CODE (operands[2]) == CONST_INT)
1905 {
96f57e36 1906 arm_split_constant (AND, SImode, NULL_RTX,
1907 INTVAL (operands[2]), operands[0],
e1ba4a27 1908 operands[1], optimize && can_create_pseudo_p ());
615caa51 1909
cffb2a26 1910 DONE;
1911 }
87b22bf7 1912 }
25f905c2 1913 else /* TARGET_THUMB1 */
cffb2a26 1914 {
1915 if (GET_CODE (operands[2]) != CONST_INT)
1916 operands[2] = force_reg (SImode, operands[2]);
1917 else
1918 {
1919 int i;
1920
215b30b3 1921 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1922 {
215b30b3 1923 operands[2] = force_reg (SImode,
1924 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1925
1926 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1927
1928 DONE;
1929 }
87b22bf7 1930
cffb2a26 1931 for (i = 9; i <= 31; i++)
1932 {
1933 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1934 {
1935 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1936 const0_rtx));
1937 DONE;
1938 }
215b30b3 1939 else if ((((HOST_WIDE_INT) 1) << i) - 1
1940 == ~INTVAL (operands[2]))
cffb2a26 1941 {
1942 rtx shift = GEN_INT (i);
1943 rtx reg = gen_reg_rtx (SImode);
1944
1945 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1946 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1947
1948 DONE;
1949 }
1950 }
1951
1952 operands[2] = force_reg (SImode, operands[2]);
1953 }
215b30b3 1954 }
1955 "
cffb2a26 1956)
1957
25f905c2 1958; ??? Check split length for Thumb-2
a0f94409 1959(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1960 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1961 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1962 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 1963 "TARGET_32BIT"
5565501b 1964 "@
1965 and%?\\t%0, %1, %2
87b22bf7 1966 bic%?\\t%0, %1, #%B2
1967 #"
25f905c2 1968 "TARGET_32BIT
a0f94409 1969 && GET_CODE (operands[2]) == CONST_INT
1970 && !(const_ok_for_arm (INTVAL (operands[2]))
1971 || const_ok_for_arm (~INTVAL (operands[2])))"
1972 [(clobber (const_int 0))]
1973 "
96f57e36 1974 arm_split_constant (AND, SImode, curr_insn,
1975 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1976 DONE;
1977 "
0d66636f 1978 [(set_attr "length" "4,4,16")
1979 (set_attr "predicable" "yes")]
cffb2a26 1980)
1981
25f905c2 1982(define_insn "*thumb1_andsi3_insn"
cffb2a26 1983 [(set (match_operand:SI 0 "register_operand" "=l")
1984 (and:SI (match_operand:SI 1 "register_operand" "%0")
1985 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1986 "TARGET_THUMB1"
cffb2a26 1987 "and\\t%0, %0, %2"
1988 [(set_attr "length" "2")]
1989)
87b22bf7 1990
f7fbdd4a 1991(define_insn "*andsi3_compare0"
bd5b4116 1992 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1993 (compare:CC_NOOV
1994 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1995 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1996 (const_int 0)))
cffb2a26 1997 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 1998 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 1999 "TARGET_32BIT"
5565501b 2000 "@
25f905c2 2001 and%.\\t%0, %1, %2
2002 bic%.\\t%0, %1, #%B2"
cffb2a26 2003 [(set_attr "conds" "set")]
2004)
9c08d1fa 2005
f7fbdd4a 2006(define_insn "*andsi3_compare0_scratch"
bd5b4116 2007 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2008 (compare:CC_NOOV
2009 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2010 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2011 (const_int 0)))
dd193d7c 2012 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2013 "TARGET_32BIT"
5565501b 2014 "@
2015 tst%?\\t%0, %1
25f905c2 2016 bic%.\\t%2, %0, #%B1"
0d66636f 2017 [(set_attr "conds" "set")]
2018)
9c08d1fa 2019
f7fbdd4a 2020(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2021 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2022 (compare:CC_NOOV (zero_extract:SI
2023 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2024 (match_operand 1 "const_int_operand" "n")
2025 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2026 (const_int 0)))]
25f905c2 2027 "TARGET_32BIT
cffb2a26 2028 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2029 && INTVAL (operands[1]) > 0
2030 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2031 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2032 "*
5c49a439 2033 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2034 << INTVAL (operands[2]));
40dbec34 2035 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2036 return \"\";
0d66636f 2037 "
2038 [(set_attr "conds" "set")]
2039)
9c08d1fa 2040
f4462328 2041(define_insn_and_split "*ne_zeroextractsi"
c4034607 2042 [(set (match_operand:SI 0 "s_register_operand" "=r")
2043 (ne:SI (zero_extract:SI
2044 (match_operand:SI 1 "s_register_operand" "r")
2045 (match_operand:SI 2 "const_int_operand" "n")
2046 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2047 (const_int 0)))
2048 (clobber (reg:CC CC_REGNUM))]
25f905c2 2049 "TARGET_32BIT
cffb2a26 2050 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2051 && INTVAL (operands[2]) > 0
2052 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2053 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2054 "#"
25f905c2 2055 "TARGET_32BIT
f4462328 2056 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2057 && INTVAL (operands[2]) > 0
2058 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2059 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2060 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2061 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2062 (const_int 0)))
2063 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2064 (set (match_dup 0)
2065 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2066 (match_dup 0) (const_int 1)))]
2067 "
2068 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2069 << INTVAL (operands[3]));
2070 "
2071 [(set_attr "conds" "clob")
25f905c2 2072 (set (attr "length")
2073 (if_then_else (eq_attr "is_thumb" "yes")
2074 (const_int 12)
2075 (const_int 8)))]
f4462328 2076)
2077
2078(define_insn_and_split "*ne_zeroextractsi_shifted"
2079 [(set (match_operand:SI 0 "s_register_operand" "=r")
2080 (ne:SI (zero_extract:SI
2081 (match_operand:SI 1 "s_register_operand" "r")
2082 (match_operand:SI 2 "const_int_operand" "n")
2083 (const_int 0))
2084 (const_int 0)))
2085 (clobber (reg:CC CC_REGNUM))]
2086 "TARGET_ARM"
2087 "#"
2088 "TARGET_ARM"
2089 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2090 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2091 (const_int 0)))
2092 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2093 (set (match_dup 0)
2094 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2095 (match_dup 0) (const_int 1)))]
2096 "
2097 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2098 "
2099 [(set_attr "conds" "clob")
2100 (set_attr "length" "8")]
2101)
2102
2103(define_insn_and_split "*ite_ne_zeroextractsi"
2104 [(set (match_operand:SI 0 "s_register_operand" "=r")
2105 (if_then_else:SI (ne (zero_extract:SI
2106 (match_operand:SI 1 "s_register_operand" "r")
2107 (match_operand:SI 2 "const_int_operand" "n")
2108 (match_operand:SI 3 "const_int_operand" "n"))
2109 (const_int 0))
2110 (match_operand:SI 4 "arm_not_operand" "rIK")
2111 (const_int 0)))
2112 (clobber (reg:CC CC_REGNUM))]
2113 "TARGET_ARM
2114 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2115 && INTVAL (operands[2]) > 0
2116 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2117 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2118 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2119 "#"
2120 "TARGET_ARM
2121 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2122 && INTVAL (operands[2]) > 0
2123 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2124 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2125 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2126 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2127 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2128 (const_int 0)))
2129 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2130 (set (match_dup 0)
2131 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2132 (match_dup 0) (match_dup 4)))]
2133 "
c4034607 2134 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2135 << INTVAL (operands[3]));
2136 "
2137 [(set_attr "conds" "clob")
2138 (set_attr "length" "8")]
2139)
2140
2141(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2142 [(set (match_operand:SI 0 "s_register_operand" "=r")
2143 (if_then_else:SI (ne (zero_extract:SI
2144 (match_operand:SI 1 "s_register_operand" "r")
2145 (match_operand:SI 2 "const_int_operand" "n")
2146 (const_int 0))
2147 (const_int 0))
2148 (match_operand:SI 3 "arm_not_operand" "rIK")
2149 (const_int 0)))
2150 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2151 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2152 "#"
f8d7bf2f 2153 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2154 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2155 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2156 (const_int 0)))
2157 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2158 (set (match_dup 0)
2159 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2160 (match_dup 0) (match_dup 3)))]
2161 "
2162 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2163 "
2164 [(set_attr "conds" "clob")
215b30b3 2165 (set_attr "length" "8")]
2166)
9c08d1fa 2167
58d6528b 2168(define_split
2169 [(set (match_operand:SI 0 "s_register_operand" "")
2170 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2171 (match_operand:SI 2 "const_int_operand" "")
2172 (match_operand:SI 3 "const_int_operand" "")))
2173 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2174 "TARGET_THUMB1"
58d6528b 2175 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2176 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2177 "{
2178 HOST_WIDE_INT temp = INTVAL (operands[2]);
2179
2180 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2181 operands[3] = GEN_INT (32 - temp);
2182 }"
2183)
2184
25f905c2 2185;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2186(define_split
2187 [(set (match_operand:SI 0 "s_register_operand" "")
2188 (match_operator:SI 1 "shiftable_operator"
2189 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2190 (match_operand:SI 3 "const_int_operand" "")
2191 (match_operand:SI 4 "const_int_operand" ""))
2192 (match_operand:SI 5 "s_register_operand" "")]))
2193 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2194 "TARGET_ARM"
2195 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2196 (set (match_dup 0)
2197 (match_op_dup 1
2198 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2199 (match_dup 5)]))]
2200 "{
2201 HOST_WIDE_INT temp = INTVAL (operands[3]);
2202
2203 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2204 operands[4] = GEN_INT (32 - temp);
2205 }"
2206)
2207
58d6528b 2208(define_split
2209 [(set (match_operand:SI 0 "s_register_operand" "")
2210 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2211 (match_operand:SI 2 "const_int_operand" "")
2212 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2213 "TARGET_THUMB1"
58d6528b 2214 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2215 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2216 "{
2217 HOST_WIDE_INT temp = INTVAL (operands[2]);
2218
2219 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2220 operands[3] = GEN_INT (32 - temp);
2221 }"
2222)
2223
d7863cfe 2224(define_split
2225 [(set (match_operand:SI 0 "s_register_operand" "")
2226 (match_operator:SI 1 "shiftable_operator"
2227 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2228 (match_operand:SI 3 "const_int_operand" "")
2229 (match_operand:SI 4 "const_int_operand" ""))
2230 (match_operand:SI 5 "s_register_operand" "")]))
2231 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2232 "TARGET_ARM"
2233 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2234 (set (match_dup 0)
2235 (match_op_dup 1
2236 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2237 (match_dup 5)]))]
2238 "{
2239 HOST_WIDE_INT temp = INTVAL (operands[3]);
2240
2241 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2242 operands[4] = GEN_INT (32 - temp);
2243 }"
2244)
2245
a42059fd 2246;;; ??? This pattern is bogus. If operand3 has bits outside the range
2247;;; represented by the bitfield, then this will produce incorrect results.
2248;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2249;;; which have a real bit-field insert instruction, the truncation happens
2250;;; in the bit-field insert instruction itself. Since arm does not have a
2251;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2252;;; the value before we insert. This loses some of the advantage of having
2253;;; this insv pattern, so this pattern needs to be reevalutated.
2254
8a18b90c 2255(define_expand "insv"
2256 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2257 (match_operand:SI 1 "general_operand" "")
2258 (match_operand:SI 2 "general_operand" ""))
19335226 2259 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2260 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2261 "
215b30b3 2262 {
2263 int start_bit = INTVAL (operands[2]);
2264 int width = INTVAL (operands[1]);
2265 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2266 rtx target, subtarget;
2267
8b054d5a 2268 if (arm_arch_thumb2)
2269 {
2270 bool use_bfi = TRUE;
2271
2272 if (GET_CODE (operands[3]) == CONST_INT)
2273 {
2274 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2275
2276 if (val == 0)
2277 {
2278 emit_insn (gen_insv_zero (operands[0], operands[1],
2279 operands[2]));
2280 DONE;
2281 }
2282
2283 /* See if the set can be done with a single orr instruction. */
2284 if (val == mask && const_ok_for_arm (val << start_bit))
2285 use_bfi = FALSE;
2286 }
2287
2288 if (use_bfi)
2289 {
2290 if (GET_CODE (operands[3]) != REG)
2291 operands[3] = force_reg (SImode, operands[3]);
2292
2293 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2294 operands[3]));
2295 DONE;
2296 }
2297 }
2298
3f8fde42 2299 target = copy_rtx (operands[0]);
215b30b3 2300 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2301 subreg as the final target. */
2302 if (GET_CODE (target) == SUBREG)
2303 {
2304 subtarget = gen_reg_rtx (SImode);
2305 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2306 < GET_MODE_SIZE (SImode))
2307 target = SUBREG_REG (target);
2308 }
2309 else
2310 subtarget = target;
8a18b90c 2311
215b30b3 2312 if (GET_CODE (operands[3]) == CONST_INT)
2313 {
2314 /* Since we are inserting a known constant, we may be able to
2315 reduce the number of bits that we have to clear so that
2316 the mask becomes simple. */
2317 /* ??? This code does not check to see if the new mask is actually
2318 simpler. It may not be. */
2319 rtx op1 = gen_reg_rtx (SImode);
2320 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2321 start of this pattern. */
2322 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2323 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2324
c5b3a71b 2325 emit_insn (gen_andsi3 (op1, operands[0],
2326 gen_int_mode (~mask2, SImode)));
215b30b3 2327 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2328 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2329 }
2330 else if (start_bit == 0
2331 && !(const_ok_for_arm (mask)
2332 || const_ok_for_arm (~mask)))
2333 {
2334 /* A Trick, since we are setting the bottom bits in the word,
2335 we can shift operand[3] up, operand[0] down, OR them together
2336 and rotate the result back again. This takes 3 insns, and
5910bb95 2337 the third might be mergeable into another op. */
215b30b3 2338 /* The shift up copes with the possibility that operand[3] is
2339 wider than the bitfield. */
2340 rtx op0 = gen_reg_rtx (SImode);
2341 rtx op1 = gen_reg_rtx (SImode);
2342
2343 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2344 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2345 emit_insn (gen_iorsi3 (op1, op1, op0));
2346 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2347 }
2348 else if ((width + start_bit == 32)
2349 && !(const_ok_for_arm (mask)
2350 || const_ok_for_arm (~mask)))
2351 {
2352 /* Similar trick, but slightly less efficient. */
8a18b90c 2353
215b30b3 2354 rtx op0 = gen_reg_rtx (SImode);
2355 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2356
215b30b3 2357 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2358 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2359 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2360 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2361 }
2362 else
2363 {
c5b3a71b 2364 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2365 rtx op1 = gen_reg_rtx (SImode);
2366 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2367
215b30b3 2368 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2369 {
2370 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2371
215b30b3 2372 emit_insn (gen_movsi (tmp, op0));
2373 op0 = tmp;
2374 }
8a18b90c 2375
215b30b3 2376 /* Mask out any bits in operand[3] that are not needed. */
2377 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2378
215b30b3 2379 if (GET_CODE (op0) == CONST_INT
2380 && (const_ok_for_arm (mask << start_bit)
2381 || const_ok_for_arm (~(mask << start_bit))))
2382 {
c5b3a71b 2383 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2384 emit_insn (gen_andsi3 (op2, operands[0], op0));
2385 }
2386 else
2387 {
2388 if (GET_CODE (op0) == CONST_INT)
2389 {
2390 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2391
215b30b3 2392 emit_insn (gen_movsi (tmp, op0));
2393 op0 = tmp;
2394 }
2395
2396 if (start_bit != 0)
2397 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2398
215b30b3 2399 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2400 }
8a18b90c 2401
215b30b3 2402 if (start_bit != 0)
2403 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2404
215b30b3 2405 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2406 }
f082f1c4 2407
215b30b3 2408 if (subtarget != target)
2409 {
2410 /* If TARGET is still a SUBREG, then it must be wider than a word,
2411 so we must be careful only to set the subword we were asked to. */
2412 if (GET_CODE (target) == SUBREG)
2413 emit_move_insn (target, subtarget);
2414 else
2415 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2416 }
8a18b90c 2417
215b30b3 2418 DONE;
2419 }"
2420)
8a18b90c 2421
8b054d5a 2422(define_insn "insv_zero"
2423 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2424 (match_operand:SI 1 "const_int_operand" "M")
2425 (match_operand:SI 2 "const_int_operand" "M"))
2426 (const_int 0))]
2427 "arm_arch_thumb2"
2428 "bfc%?\t%0, %2, %1"
2429 [(set_attr "length" "4")
2430 (set_attr "predicable" "yes")]
2431)
2432
2433(define_insn "insv_t2"
2434 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2435 (match_operand:SI 1 "const_int_operand" "M")
2436 (match_operand:SI 2 "const_int_operand" "M"))
2437 (match_operand:SI 3 "s_register_operand" "r"))]
2438 "arm_arch_thumb2"
2439 "bfi%?\t%0, %3, %2, %1"
2440 [(set_attr "length" "4")
2441 (set_attr "predicable" "yes")]
2442)
2443
215b30b3 2444; constants for op 2 will never be given to these patterns.
a0f94409 2445(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2446 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 2447 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2448 (match_operand:DI 2 "s_register_operand" "0,r")))]
25f905c2 2449 "TARGET_32BIT"
f6ebffac 2450 "#"
25f905c2 2451 "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2452 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2453 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2454 "
2455 {
2456 operands[3] = gen_highpart (SImode, operands[0]);
2457 operands[0] = gen_lowpart (SImode, operands[0]);
2458 operands[4] = gen_highpart (SImode, operands[1]);
2459 operands[1] = gen_lowpart (SImode, operands[1]);
2460 operands[5] = gen_highpart (SImode, operands[2]);
2461 operands[2] = gen_lowpart (SImode, operands[2]);
2462 }"
0d66636f 2463 [(set_attr "length" "8")
2464 (set_attr "predicable" "yes")]
2465)
9c08d1fa 2466
a0f94409 2467(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2468 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2469 (and:DI (not:DI (zero_extend:DI
2470 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2471 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2472 "TARGET_32BIT"
e2348bcb 2473 "@
97499065 2474 bic%?\\t%Q0, %Q1, %2
f6ebffac 2475 #"
a0f94409 2476 ; (not (zero_extend ...)) allows us to just copy the high word from
2477 ; operand1 to operand0.
25f905c2 2478 "TARGET_32BIT
a0f94409 2479 && reload_completed
2480 && operands[0] != operands[1]"
5a097f7d 2481 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2482 (set (match_dup 3) (match_dup 4))]
2483 "
2484 {
2485 operands[3] = gen_highpart (SImode, operands[0]);
2486 operands[0] = gen_lowpart (SImode, operands[0]);
2487 operands[4] = gen_highpart (SImode, operands[1]);
2488 operands[1] = gen_lowpart (SImode, operands[1]);
2489 }"
0d66636f 2490 [(set_attr "length" "4,8")
2491 (set_attr "predicable" "yes")]
2492)
9c08d1fa 2493
a0f94409 2494(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2495 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2496 (and:DI (not:DI (sign_extend:DI
2497 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2498 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2499 "TARGET_32BIT"
f6ebffac 2500 "#"
25f905c2 2501 "TARGET_32BIT && reload_completed"
5a097f7d 2502 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2503 (set (match_dup 3) (and:SI (not:SI
2504 (ashiftrt:SI (match_dup 2) (const_int 31)))
2505 (match_dup 4)))]
2506 "
2507 {
2508 operands[3] = gen_highpart (SImode, operands[0]);
2509 operands[0] = gen_lowpart (SImode, operands[0]);
2510 operands[4] = gen_highpart (SImode, operands[1]);
2511 operands[1] = gen_lowpart (SImode, operands[1]);
2512 }"
0d66636f 2513 [(set_attr "length" "8")
2514 (set_attr "predicable" "yes")]
2515)
9c08d1fa 2516
8a18b90c 2517(define_insn "andsi_notsi_si"
9c08d1fa 2518 [(set (match_operand:SI 0 "s_register_operand" "=r")
2519 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2520 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2521 "TARGET_32BIT"
0d66636f 2522 "bic%?\\t%0, %1, %2"
2523 [(set_attr "predicable" "yes")]
2524)
b11cae9e 2525
cffb2a26 2526(define_insn "bicsi3"
2527 [(set (match_operand:SI 0 "register_operand" "=l")
2528 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2529 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2530 "TARGET_THUMB1"
cffb2a26 2531 "bic\\t%0, %0, %1"
2532 [(set_attr "length" "2")]
2533)
2534
8a18b90c 2535(define_insn "andsi_not_shiftsi_si"
a2cd141b 2536 [(set (match_operand:SI 0 "s_register_operand" "=r")
2537 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2538 [(match_operand:SI 2 "s_register_operand" "r")
2539 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2540 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2541 "TARGET_ARM"
6c4c2133 2542 "bic%?\\t%0, %1, %2%S4"
344495ea 2543 [(set_attr "predicable" "yes")
331beb1a 2544 (set_attr "shift" "2")
a2cd141b 2545 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2546 (const_string "alu_shift")
2547 (const_string "alu_shift_reg")))]
6c4c2133 2548)
8a18b90c 2549
f7fbdd4a 2550(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2551 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2552 (compare:CC_NOOV
2553 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2554 (match_operand:SI 1 "s_register_operand" "r"))
2555 (const_int 0)))
9c08d1fa 2556 (set (match_operand:SI 0 "s_register_operand" "=r")
2557 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2558 "TARGET_32BIT"
2559 "bic%.\\t%0, %1, %2"
0d66636f 2560 [(set_attr "conds" "set")]
2561)
9c08d1fa 2562
f7fbdd4a 2563(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2564 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2565 (compare:CC_NOOV
2566 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2567 (match_operand:SI 1 "s_register_operand" "r"))
2568 (const_int 0)))
9c08d1fa 2569 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2570 "TARGET_32BIT"
2571 "bic%.\\t%0, %1, %2"
0d66636f 2572 [(set_attr "conds" "set")]
2573)
9c08d1fa 2574
2575(define_insn "iordi3"
cffb2a26 2576 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2577 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2578 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2579 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 2580 "#"
0d66636f 2581 [(set_attr "length" "8")
2582 (set_attr "predicable" "yes")]
cffb2a26 2583)
9c08d1fa 2584
f7fbdd4a 2585(define_insn "*iordi_zesidi_di"
9c08d1fa 2586 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2587 (ior:DI (zero_extend:DI
2588 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2589 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2590 "TARGET_32BIT"
e2348bcb 2591 "@
97499065 2592 orr%?\\t%Q0, %Q1, %2
f6ebffac 2593 #"
0d66636f 2594 [(set_attr "length" "4,8")
2595 (set_attr "predicable" "yes")]
cffb2a26 2596)
9c08d1fa 2597
f7fbdd4a 2598(define_insn "*iordi_sesidi_di"
9c08d1fa 2599 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2600 (ior:DI (sign_extend:DI
2601 (match_operand:SI 2 "s_register_operand" "r,r"))
2602 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2603 "TARGET_32BIT"
f6ebffac 2604 "#"
0d66636f 2605 [(set_attr "length" "8")
2606 (set_attr "predicable" "yes")]
cffb2a26 2607)
9c08d1fa 2608
87b22bf7 2609(define_expand "iorsi3"
cffb2a26 2610 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2611 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2612 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2613 "TARGET_EITHER"
87b22bf7 2614 "
2615 if (GET_CODE (operands[2]) == CONST_INT)
2616 {
25f905c2 2617 if (TARGET_32BIT)
cffb2a26 2618 {
96f57e36 2619 arm_split_constant (IOR, SImode, NULL_RTX,
2620 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2621 optimize && can_create_pseudo_p ());
cffb2a26 2622 DONE;
2623 }
25f905c2 2624 else /* TARGET_THUMB1 */
cffb2a26 2625 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2626 }
cffb2a26 2627 "
2628)
87b22bf7 2629
a0f94409 2630(define_insn_and_split "*arm_iorsi3"
cffb2a26 2631 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2632 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2633 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
90560cad 2634 "TARGET_ARM"
87b22bf7 2635 "@
2636 orr%?\\t%0, %1, %2
2637 #"
90560cad 2638 "TARGET_ARM
a0f94409 2639 && GET_CODE (operands[2]) == CONST_INT
2640 && !const_ok_for_arm (INTVAL (operands[2]))"
2641 [(clobber (const_int 0))]
2642 "
96f57e36 2643 arm_split_constant (IOR, SImode, curr_insn,
2644 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2645 DONE;
2646 "
0d66636f 2647 [(set_attr "length" "4,16")
2648 (set_attr "predicable" "yes")]
cffb2a26 2649)
2650
25f905c2 2651(define_insn "*thumb1_iorsi3"
cffb2a26 2652 [(set (match_operand:SI 0 "register_operand" "=l")
2653 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2654 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2655 "TARGET_THUMB1"
cffb2a26 2656 "orr\\t%0, %0, %2"
2657 [(set_attr "length" "2")]
2658)
9c08d1fa 2659
a0f94409 2660(define_peephole2
2661 [(match_scratch:SI 3 "r")
372575c7 2662 (set (match_operand:SI 0 "arm_general_register_operand" "")
2663 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2664 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2665 "TARGET_ARM
a0f94409 2666 && !const_ok_for_arm (INTVAL (operands[2]))
2667 && const_ok_for_arm (~INTVAL (operands[2]))"
2668 [(set (match_dup 3) (match_dup 2))
2669 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2670 ""
215b30b3 2671)
a0f94409 2672
f7fbdd4a 2673(define_insn "*iorsi3_compare0"
bd5b4116 2674 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2675 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2676 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2677 (const_int 0)))
2678 (set (match_operand:SI 0 "s_register_operand" "=r")
2679 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2680 "TARGET_32BIT"
2681 "orr%.\\t%0, %1, %2"
cffb2a26 2682 [(set_attr "conds" "set")]
2683)
9c08d1fa 2684
f7fbdd4a 2685(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2686 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2687 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2688 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2689 (const_int 0)))
2690 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2691 "TARGET_32BIT"
2692 "orr%.\\t%0, %1, %2"
0d66636f 2693 [(set_attr "conds" "set")]
2694)
9c08d1fa 2695
2696(define_insn "xordi3"
cffb2a26 2697 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2698 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2699 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2700 "TARGET_32BIT && !TARGET_IWMMXT"
f6ebffac 2701 "#"
0d66636f 2702 [(set_attr "length" "8")
2703 (set_attr "predicable" "yes")]
cffb2a26 2704)
9c08d1fa 2705
f7fbdd4a 2706(define_insn "*xordi_zesidi_di"
9c08d1fa 2707 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2708 (xor:DI (zero_extend:DI
2709 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2710 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2711 "TARGET_32BIT"
e2348bcb 2712 "@
97499065 2713 eor%?\\t%Q0, %Q1, %2
f6ebffac 2714 #"
0d66636f 2715 [(set_attr "length" "4,8")
2716 (set_attr "predicable" "yes")]
cffb2a26 2717)
9c08d1fa 2718
f7fbdd4a 2719(define_insn "*xordi_sesidi_di"
9c08d1fa 2720 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2721 (xor:DI (sign_extend:DI
2722 (match_operand:SI 2 "s_register_operand" "r,r"))
2723 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2724 "TARGET_32BIT"
f6ebffac 2725 "#"
0d66636f 2726 [(set_attr "length" "8")
2727 (set_attr "predicable" "yes")]
cffb2a26 2728)
9c08d1fa 2729
cffb2a26 2730(define_expand "xorsi3"
2731 [(set (match_operand:SI 0 "s_register_operand" "")
2732 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2733 (match_operand:SI 2 "arm_rhs_operand" "")))]
2734 "TARGET_EITHER"
25f905c2 2735 "if (TARGET_THUMB1)
cffb2a26 2736 if (GET_CODE (operands[2]) == CONST_INT)
2737 operands[2] = force_reg (SImode, operands[2]);
2738 "
2739)
2740
2741(define_insn "*arm_xorsi3"
2742 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2743 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2744 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2745 "TARGET_32BIT"
cffb2a26 2746 "eor%?\\t%0, %1, %2"
0d66636f 2747 [(set_attr "predicable" "yes")]
cffb2a26 2748)
2749
25f905c2 2750(define_insn "*thumb1_xorsi3"
cffb2a26 2751 [(set (match_operand:SI 0 "register_operand" "=l")
2752 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2753 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2754 "TARGET_THUMB1"
cffb2a26 2755 "eor\\t%0, %0, %2"
2756 [(set_attr "length" "2")]
2757)
9c08d1fa 2758
f7fbdd4a 2759(define_insn "*xorsi3_compare0"
bd5b4116 2760 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2761 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2762 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2763 (const_int 0)))
2764 (set (match_operand:SI 0 "s_register_operand" "=r")
2765 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2766 "TARGET_32BIT"
2767 "eor%.\\t%0, %1, %2"
0d66636f 2768 [(set_attr "conds" "set")]
2769)
9c08d1fa 2770
f7fbdd4a 2771(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2772 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2773 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2774 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2775 (const_int 0)))]
25f905c2 2776 "TARGET_32BIT"
40dbec34 2777 "teq%?\\t%0, %1"
cffb2a26 2778 [(set_attr "conds" "set")]
2779)
9c08d1fa 2780
215b30b3 2781; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2782; (NOT D) we can sometimes merge the final NOT into one of the following
2783; insns.
9c08d1fa 2784
2785(define_split
a058e94a 2786 [(set (match_operand:SI 0 "s_register_operand" "")
2787 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2788 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2789 (match_operand:SI 3 "arm_rhs_operand" "")))
2790 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2791 "TARGET_32BIT"
9c08d1fa 2792 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2793 (not:SI (match_dup 3))))
2794 (set (match_dup 0) (not:SI (match_dup 4)))]
2795 ""
2796)
2797
f7fbdd4a 2798(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2799 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2800 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2801 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2802 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2803 "TARGET_32BIT"
40dbec34 2804 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2805 [(set_attr "length" "8")
25f905c2 2806 (set_attr "ce_count" "2")
0d66636f 2807 (set_attr "predicable" "yes")]
cffb2a26 2808)
9c08d1fa 2809
25f905c2 2810; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2811; insns are available?
d7863cfe 2812(define_split
2813 [(set (match_operand:SI 0 "s_register_operand" "")
2814 (match_operator:SI 1 "logical_binary_operator"
2815 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2816 (match_operand:SI 3 "const_int_operand" "")
2817 (match_operand:SI 4 "const_int_operand" ""))
2818 (match_operator:SI 9 "logical_binary_operator"
2819 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2820 (match_operand:SI 6 "const_int_operand" ""))
2821 (match_operand:SI 7 "s_register_operand" "")])]))
2822 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2823 "TARGET_32BIT
d7863cfe 2824 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2825 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2826 [(set (match_dup 8)
2827 (match_op_dup 1
2828 [(ashift:SI (match_dup 2) (match_dup 4))
2829 (match_dup 5)]))
2830 (set (match_dup 0)
2831 (match_op_dup 1
2832 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2833 (match_dup 7)]))]
2834 "
2835 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2836")
2837
2838(define_split
2839 [(set (match_operand:SI 0 "s_register_operand" "")
2840 (match_operator:SI 1 "logical_binary_operator"
2841 [(match_operator:SI 9 "logical_binary_operator"
2842 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2843 (match_operand:SI 6 "const_int_operand" ""))
2844 (match_operand:SI 7 "s_register_operand" "")])
2845 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2846 (match_operand:SI 3 "const_int_operand" "")
2847 (match_operand:SI 4 "const_int_operand" ""))]))
2848 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2849 "TARGET_32BIT
d7863cfe 2850 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2851 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2852 [(set (match_dup 8)
2853 (match_op_dup 1
2854 [(ashift:SI (match_dup 2) (match_dup 4))
2855 (match_dup 5)]))
2856 (set (match_dup 0)
2857 (match_op_dup 1
2858 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2859 (match_dup 7)]))]
2860 "
2861 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2862")
2863
2864(define_split
2865 [(set (match_operand:SI 0 "s_register_operand" "")
2866 (match_operator:SI 1 "logical_binary_operator"
2867 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2868 (match_operand:SI 3 "const_int_operand" "")
2869 (match_operand:SI 4 "const_int_operand" ""))
2870 (match_operator:SI 9 "logical_binary_operator"
2871 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2872 (match_operand:SI 6 "const_int_operand" ""))
2873 (match_operand:SI 7 "s_register_operand" "")])]))
2874 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2875 "TARGET_32BIT
d7863cfe 2876 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2877 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2878 [(set (match_dup 8)
2879 (match_op_dup 1
2880 [(ashift:SI (match_dup 2) (match_dup 4))
2881 (match_dup 5)]))
2882 (set (match_dup 0)
2883 (match_op_dup 1
2884 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2885 (match_dup 7)]))]
2886 "
2887 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2888")
2889
2890(define_split
2891 [(set (match_operand:SI 0 "s_register_operand" "")
2892 (match_operator:SI 1 "logical_binary_operator"
2893 [(match_operator:SI 9 "logical_binary_operator"
2894 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2895 (match_operand:SI 6 "const_int_operand" ""))
2896 (match_operand:SI 7 "s_register_operand" "")])
2897 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2898 (match_operand:SI 3 "const_int_operand" "")
2899 (match_operand:SI 4 "const_int_operand" ""))]))
2900 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2901 "TARGET_32BIT
d7863cfe 2902 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2903 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2904 [(set (match_dup 8)
2905 (match_op_dup 1
2906 [(ashift:SI (match_dup 2) (match_dup 4))
2907 (match_dup 5)]))
2908 (set (match_dup 0)
2909 (match_op_dup 1
2910 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2911 (match_dup 7)]))]
2912 "
2913 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2914")
9c08d1fa 2915\f
2916
2917;; Minimum and maximum insns
2918
8b9dc177 2919(define_expand "smaxsi3"
2920 [(parallel [
2921 (set (match_operand:SI 0 "s_register_operand" "")
2922 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2923 (match_operand:SI 2 "arm_rhs_operand" "")))
2924 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2925 "TARGET_32BIT"
8b9dc177 2926 "
8774928b 2927 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 2928 {
2929 /* No need for a clobber of the condition code register here. */
2930 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2931 gen_rtx_SMAX (SImode, operands[1],
2932 operands[2])));
2933 DONE;
2934 }
2935")
2936
2937(define_insn "*smax_0"
2938 [(set (match_operand:SI 0 "s_register_operand" "=r")
2939 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2940 (const_int 0)))]
25f905c2 2941 "TARGET_32BIT"
8b9dc177 2942 "bic%?\\t%0, %1, %1, asr #31"
2943 [(set_attr "predicable" "yes")]
2944)
2945
8774928b 2946(define_insn "*smax_m1"
2947 [(set (match_operand:SI 0 "s_register_operand" "=r")
2948 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2949 (const_int -1)))]
25f905c2 2950 "TARGET_32BIT"
8774928b 2951 "orr%?\\t%0, %1, %1, asr #31"
2952 [(set_attr "predicable" "yes")]
2953)
2954
25f905c2 2955(define_insn "*arm_smax_insn"
8b9dc177 2956 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2957 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2958 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 2959 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2960 "TARGET_ARM"
e2348bcb 2961 "@
2962 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 2963 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2964 [(set_attr "conds" "clob")
8b9dc177 2965 (set_attr "length" "8,12")]
cffb2a26 2966)
9c08d1fa 2967
8b9dc177 2968(define_expand "sminsi3"
2969 [(parallel [
2970 (set (match_operand:SI 0 "s_register_operand" "")
2971 (smin:SI (match_operand:SI 1 "s_register_operand" "")
2972 (match_operand:SI 2 "arm_rhs_operand" "")))
2973 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2974 "TARGET_32BIT"
8b9dc177 2975 "
2976 if (operands[2] == const0_rtx)
2977 {
2978 /* No need for a clobber of the condition code register here. */
2979 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2980 gen_rtx_SMIN (SImode, operands[1],
2981 operands[2])));
2982 DONE;
2983 }
2984")
2985
2986(define_insn "*smin_0"
2987 [(set (match_operand:SI 0 "s_register_operand" "=r")
2988 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2989 (const_int 0)))]
25f905c2 2990 "TARGET_32BIT"
8b9dc177 2991 "and%?\\t%0, %1, %1, asr #31"
2992 [(set_attr "predicable" "yes")]
2993)
2994
25f905c2 2995(define_insn "*arm_smin_insn"
8b9dc177 2996 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2997 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2998 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 2999 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3000 "TARGET_ARM"
e2348bcb 3001 "@
3002 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3003 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3004 [(set_attr "conds" "clob")
8b9dc177 3005 (set_attr "length" "8,12")]
0d66636f 3006)
9c08d1fa 3007
25f905c2 3008(define_expand "umaxsi3"
3009 [(parallel [
3010 (set (match_operand:SI 0 "s_register_operand" "")
3011 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3012 (match_operand:SI 2 "arm_rhs_operand" "")))
3013 (clobber (reg:CC CC_REGNUM))])]
3014 "TARGET_32BIT"
3015 ""
3016)
3017
3018(define_insn "*arm_umaxsi3"
9c08d1fa 3019 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3020 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3021 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3022 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3023 "TARGET_ARM"
e2348bcb 3024 "@
3025 cmp\\t%1, %2\;movcc\\t%0, %2
3026 cmp\\t%1, %2\;movcs\\t%0, %1
3027 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3028 [(set_attr "conds" "clob")
3029 (set_attr "length" "8,8,12")]
3030)
9c08d1fa 3031
25f905c2 3032(define_expand "uminsi3"
3033 [(parallel [
3034 (set (match_operand:SI 0 "s_register_operand" "")
3035 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3036 (match_operand:SI 2 "arm_rhs_operand" "")))
3037 (clobber (reg:CC CC_REGNUM))])]
3038 "TARGET_32BIT"
3039 ""
3040)
3041
3042(define_insn "*arm_uminsi3"
9c08d1fa 3043 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3044 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3045 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3046 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3047 "TARGET_ARM"
e2348bcb 3048 "@
3049 cmp\\t%1, %2\;movcs\\t%0, %2
3050 cmp\\t%1, %2\;movcc\\t%0, %1
3051 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3052 [(set_attr "conds" "clob")
3053 (set_attr "length" "8,8,12")]
3054)
9c08d1fa 3055
8a18b90c 3056(define_insn "*store_minmaxsi"
9c08d1fa 3057 [(set (match_operand:SI 0 "memory_operand" "=m")
3058 (match_operator:SI 3 "minmax_operator"
3059 [(match_operand:SI 1 "s_register_operand" "r")
3060 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3061 (clobber (reg:CC CC_REGNUM))]
25f905c2 3062 "TARGET_32BIT"
9c08d1fa 3063 "*
dc55b8a9 3064 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3065 operands[1], operands[2]);
e2348bcb 3066 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3067 if (TARGET_THUMB2)
3068 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3069 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3070 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3071 return \"\";
0d66636f 3072 "
3073 [(set_attr "conds" "clob")
25f905c2 3074 (set (attr "length")
3075 (if_then_else (eq_attr "is_thumb" "yes")
3076 (const_int 14)
3077 (const_int 12)))
0d66636f 3078 (set_attr "type" "store1")]
3079)
9c08d1fa 3080
8a18b90c 3081; Reject the frame pointer in operand[1], since reloading this after
3082; it has been eliminated can cause carnage.
f7fbdd4a 3083(define_insn "*minmax_arithsi"
9c08d1fa 3084 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3085 (match_operator:SI 4 "shiftable_operator"
3086 [(match_operator:SI 5 "minmax_operator"
3087 [(match_operand:SI 2 "s_register_operand" "r,r")
3088 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3089 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3090 (clobber (reg:CC CC_REGNUM))]
25f905c2 3091 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3092 "*
0d66636f 3093 {
3094 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3095 bool need_else;
3096
3097 if (which_alternative != 0 || operands[3] != const0_rtx
3098 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3099 need_else = true;
3100 else
3101 need_else = false;
0d66636f 3102
dc55b8a9 3103 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3104 operands[2], operands[3]);
0d66636f 3105 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3106 if (TARGET_THUMB2)
3107 {
3108 if (need_else)
3109 output_asm_insn (\"ite\\t%d5\", operands);
3110 else
3111 output_asm_insn (\"it\\t%d5\", operands);
3112 }
0d66636f 3113 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3114 if (need_else)
0d66636f 3115 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3116 return \"\";
215b30b3 3117 }"
0d66636f 3118 [(set_attr "conds" "clob")
25f905c2 3119 (set (attr "length")
3120 (if_then_else (eq_attr "is_thumb" "yes")
3121 (const_int 14)
3122 (const_int 12)))]
0d66636f 3123)
9c08d1fa 3124
b11cae9e 3125\f
3126;; Shift and rotation insns
3127
a2cd141b 3128(define_expand "ashldi3"
3129 [(set (match_operand:DI 0 "s_register_operand" "")
3130 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3131 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3132 "TARGET_32BIT"
a2cd141b 3133 "
3134 if (GET_CODE (operands[2]) == CONST_INT)
3135 {
3136 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3137 {
3138 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3139 DONE;
3140 }
3141 /* Ideally we shouldn't fail here if we could know that operands[1]
3142 ends up already living in an iwmmxt register. Otherwise it's
3143 cheaper to have the alternate code being generated than moving
1d60d981 3144 values to iwmmxt regs and back. */
a2cd141b 3145 FAIL;
3146 }
3147 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3148 FAIL;
3149 "
3150)
3151
3152(define_insn "arm_ashldi3_1bit"
3153 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3154 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3155 (const_int 1)))
3156 (clobber (reg:CC CC_REGNUM))]
25f905c2 3157 "TARGET_32BIT"
a2cd141b 3158 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3159 [(set_attr "conds" "clob")
3160 (set_attr "length" "8")]
3161)
3162
87b22bf7 3163(define_expand "ashlsi3"
cffb2a26 3164 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3165 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3166 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3167 "TARGET_EITHER"
87b22bf7 3168 "
3169 if (GET_CODE (operands[2]) == CONST_INT
3170 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3171 {
3172 emit_insn (gen_movsi (operands[0], const0_rtx));
3173 DONE;
3174 }
cffb2a26 3175 "
3176)
3177
25f905c2 3178(define_insn "*thumb1_ashlsi3"
cffb2a26 3179 [(set (match_operand:SI 0 "register_operand" "=l,l")
3180 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3181 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3182 "TARGET_THUMB1"
cffb2a26 3183 "lsl\\t%0, %1, %2"
3184 [(set_attr "length" "2")]
3185)
b11cae9e 3186
a2cd141b 3187(define_expand "ashrdi3"
3188 [(set (match_operand:DI 0 "s_register_operand" "")
3189 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3190 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3191 "TARGET_32BIT"
a2cd141b 3192 "
3193 if (GET_CODE (operands[2]) == CONST_INT)
3194 {
3195 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3196 {
3197 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3198 DONE;
3199 }
3200 /* Ideally we shouldn't fail here if we could know that operands[1]
3201 ends up already living in an iwmmxt register. Otherwise it's
3202 cheaper to have the alternate code being generated than moving
1d60d981 3203 values to iwmmxt regs and back. */
a2cd141b 3204 FAIL;
3205 }
3206 else if (!TARGET_REALLY_IWMMXT)
3207 FAIL;
3208 "
3209)
3210
3211(define_insn "arm_ashrdi3_1bit"
3212 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3213 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3214 (const_int 1)))
3215 (clobber (reg:CC CC_REGNUM))]
25f905c2 3216 "TARGET_32BIT"
a2cd141b 3217 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3218 [(set_attr "conds" "clob")
3219 (set_attr "length" "8")]
3220)
3221
87b22bf7 3222(define_expand "ashrsi3"
cffb2a26 3223 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3224 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3225 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3226 "TARGET_EITHER"
87b22bf7 3227 "
3228 if (GET_CODE (operands[2]) == CONST_INT
3229 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3230 operands[2] = GEN_INT (31);
cffb2a26 3231 "
3232)
3233
25f905c2 3234(define_insn "*thumb1_ashrsi3"
cffb2a26 3235 [(set (match_operand:SI 0 "register_operand" "=l,l")
3236 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3237 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3238 "TARGET_THUMB1"
cffb2a26 3239 "asr\\t%0, %1, %2"
3240 [(set_attr "length" "2")]
3241)
b11cae9e 3242
a2cd141b 3243(define_expand "lshrdi3"
3244 [(set (match_operand:DI 0 "s_register_operand" "")
3245 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3246 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3247 "TARGET_32BIT"
a2cd141b 3248 "
3249 if (GET_CODE (operands[2]) == CONST_INT)
3250 {
3251 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3252 {
3253 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3254 DONE;
3255 }
3256 /* Ideally we shouldn't fail here if we could know that operands[1]
3257 ends up already living in an iwmmxt register. Otherwise it's
3258 cheaper to have the alternate code being generated than moving
1d60d981 3259 values to iwmmxt regs and back. */
a2cd141b 3260 FAIL;
3261 }
3262 else if (!TARGET_REALLY_IWMMXT)
3263 FAIL;
3264 "
3265)
3266
3267(define_insn "arm_lshrdi3_1bit"
3268 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3269 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3270 (const_int 1)))
3271 (clobber (reg:CC CC_REGNUM))]
25f905c2 3272 "TARGET_32BIT"
a2cd141b 3273 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3274 [(set_attr "conds" "clob")
3275 (set_attr "length" "8")]
3276)
3277
87b22bf7 3278(define_expand "lshrsi3"
cffb2a26 3279 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3280 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3281 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3282 "TARGET_EITHER"
87b22bf7 3283 "
3284 if (GET_CODE (operands[2]) == CONST_INT
3285 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3286 {
3287 emit_insn (gen_movsi (operands[0], const0_rtx));
3288 DONE;
3289 }
cffb2a26 3290 "
3291)
3292
25f905c2 3293(define_insn "*thumb1_lshrsi3"
cffb2a26 3294 [(set (match_operand:SI 0 "register_operand" "=l,l")
3295 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3296 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3297 "TARGET_THUMB1"
cffb2a26 3298 "lsr\\t%0, %1, %2"
3299 [(set_attr "length" "2")]
3300)
b11cae9e 3301
87b22bf7 3302(define_expand "rotlsi3"
cffb2a26 3303 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3304 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3305 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3306 "TARGET_32BIT"
87b22bf7 3307 "
3308 if (GET_CODE (operands[2]) == CONST_INT)
3309 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3310 else
b11cae9e 3311 {
87b22bf7 3312 rtx reg = gen_reg_rtx (SImode);
3313 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3314 operands[2] = reg;
b11cae9e 3315 }
cffb2a26 3316 "
3317)
9c08d1fa 3318
87b22bf7 3319(define_expand "rotrsi3"
cffb2a26 3320 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3321 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3322 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3323 "TARGET_EITHER"
87b22bf7 3324 "
25f905c2 3325 if (TARGET_32BIT)
cffb2a26 3326 {
3327 if (GET_CODE (operands[2]) == CONST_INT
3328 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3329 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3330 }
25f905c2 3331 else /* TARGET_THUMB1 */
cffb2a26 3332 {
3333 if (GET_CODE (operands [2]) == CONST_INT)
3334 operands [2] = force_reg (SImode, operands[2]);
3335 }
3336 "
3337)
87b22bf7 3338
25f905c2 3339(define_insn "*thumb1_rotrsi3"
cffb2a26 3340 [(set (match_operand:SI 0 "register_operand" "=l")
3341 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3342 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3343 "TARGET_THUMB1"
cffb2a26 3344 "ror\\t%0, %0, %2"
3345 [(set_attr "length" "2")]
3346)
3347
3348(define_insn "*arm_shiftsi3"
3349 [(set (match_operand:SI 0 "s_register_operand" "=r")
3350 (match_operator:SI 3 "shift_operator"
3351 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3352 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3353 "TARGET_32BIT"
3354 "* return arm_output_shift(operands, 0);"
344495ea 3355 [(set_attr "predicable" "yes")
331beb1a 3356 (set_attr "shift" "1")
a2cd141b 3357 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3358 (const_string "alu_shift")
3359 (const_string "alu_shift_reg")))]
6c4c2133 3360)
87b22bf7 3361
f7fbdd4a 3362(define_insn "*shiftsi3_compare0"
bd5b4116 3363 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3364 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3365 [(match_operand:SI 1 "s_register_operand" "r")
3366 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3367 (const_int 0)))
3368 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3369 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3370 "TARGET_32BIT"
3371 "* return arm_output_shift(operands, 1);"
344495ea 3372 [(set_attr "conds" "set")
331beb1a 3373 (set_attr "shift" "1")
a2cd141b 3374 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3375 (const_string "alu_shift")
3376 (const_string "alu_shift_reg")))]
0d66636f 3377)
9c08d1fa 3378
f7fbdd4a 3379(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3380 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3381 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3382 [(match_operand:SI 1 "s_register_operand" "r")
3383 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3384 (const_int 0)))
3385 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3386 "TARGET_32BIT"
3387 "* return arm_output_shift(operands, 1);"
344495ea 3388 [(set_attr "conds" "set")
a2cd141b 3389 (set_attr "shift" "1")]
0d66636f 3390)
9c08d1fa 3391
25f905c2 3392(define_insn "*arm_notsi_shiftsi"
9c08d1fa 3393 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3394 (not:SI (match_operator:SI 3 "shift_operator"
3395 [(match_operand:SI 1 "s_register_operand" "r")
3396 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 3397 "TARGET_ARM"
6c4c2133 3398 "mvn%?\\t%0, %1%S3"
344495ea 3399 [(set_attr "predicable" "yes")
331beb1a 3400 (set_attr "shift" "1")
a2cd141b 3401 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3402 (const_string "alu_shift")
3403 (const_string "alu_shift_reg")))]
0d66636f 3404)
9c08d1fa 3405
25f905c2 3406(define_insn "*arm_notsi_shiftsi_compare0"
bd5b4116 3407 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3408 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3409 [(match_operand:SI 1 "s_register_operand" "r")
3410 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3411 (const_int 0)))
3412 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3413 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 3414 "TARGET_ARM"
25f905c2 3415 "mvn%.\\t%0, %1%S3"
344495ea 3416 [(set_attr "conds" "set")
331beb1a 3417 (set_attr "shift" "1")
a2cd141b 3418 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3419 (const_string "alu_shift")
3420 (const_string "alu_shift_reg")))]
0d66636f 3421)
9c08d1fa 3422
25f905c2 3423(define_insn "*arm_not_shiftsi_compare0_scratch"
bd5b4116 3424 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3425 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3426 [(match_operand:SI 1 "s_register_operand" "r")
3427 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3428 (const_int 0)))
3429 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3430 "TARGET_ARM"
25f905c2 3431 "mvn%.\\t%0, %1%S3"
344495ea 3432 [(set_attr "conds" "set")
331beb1a 3433 (set_attr "shift" "1")
a2cd141b 3434 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3435 (const_string "alu_shift")
3436 (const_string "alu_shift_reg")))]
0d66636f 3437)
9c08d1fa 3438
cffb2a26 3439;; We don't really have extzv, but defining this using shifts helps
3440;; to reduce register pressure later on.
3441
3442(define_expand "extzv"
3443 [(set (match_dup 4)
3444 (ashift:SI (match_operand:SI 1 "register_operand" "")
3445 (match_operand:SI 2 "const_int_operand" "")))
3446 (set (match_operand:SI 0 "register_operand" "")
3447 (lshiftrt:SI (match_dup 4)
215b30b3 3448 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3449 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3450 "
3451 {
3452 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3453 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3454
8b054d5a 3455 if (arm_arch_thumb2)
3456 {
3457 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3458 operands[3]));
3459 DONE;
3460 }
3461
cffb2a26 3462 operands[3] = GEN_INT (rshift);
3463
3464 if (lshift == 0)
3465 {
3466 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3467 DONE;
3468 }
3469
3470 operands[2] = GEN_INT (lshift);
3471 operands[4] = gen_reg_rtx (SImode);
215b30b3 3472 }"
cffb2a26 3473)
3474
8b054d5a 3475(define_insn "extv"
3476 [(set (match_operand:SI 0 "s_register_operand" "=r")
3477 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3478 (match_operand:SI 2 "const_int_operand" "M")
3479 (match_operand:SI 3 "const_int_operand" "M")))]
3480 "arm_arch_thumb2"
3481 "sbfx%?\t%0, %1, %3, %2"
3482 [(set_attr "length" "4")
3483 (set_attr "predicable" "yes")]
3484)
3485
3486(define_insn "extzv_t2"
3487 [(set (match_operand:SI 0 "s_register_operand" "=r")
3488 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3489 (match_operand:SI 2 "const_int_operand" "M")
3490 (match_operand:SI 3 "const_int_operand" "M")))]
3491 "arm_arch_thumb2"
3492 "ubfx%?\t%0, %1, %3, %2"
3493 [(set_attr "length" "4")
3494 (set_attr "predicable" "yes")]
3495)
3496
b11cae9e 3497\f
3498;; Unary arithmetic insns
3499
cffb2a26 3500(define_expand "negdi2"
3501 [(parallel
3502 [(set (match_operand:DI 0 "s_register_operand" "")
3503 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3504 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3505 "TARGET_EITHER"
3506 "
25f905c2 3507 if (TARGET_THUMB1)
cffb2a26 3508 {
3509 if (GET_CODE (operands[1]) != REG)
3510 operands[1] = force_reg (SImode, operands[1]);
3511 }
215b30b3 3512 "
cffb2a26 3513)
3514
3515;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3516;; The second alternative is to allow the common case of a *full* overlap.
3517(define_insn "*arm_negdi2"
3518 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3519 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 3520 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3521 "TARGET_ARM"
97499065 3522 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3523 [(set_attr "conds" "clob")
3524 (set_attr "length" "8")]
3525)
b11cae9e 3526
25f905c2 3527(define_insn "*thumb1_negdi2"
cffb2a26 3528 [(set (match_operand:DI 0 "register_operand" "=&l")
3529 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3530 (clobber (reg:CC CC_REGNUM))]
25f905c2 3531 "TARGET_THUMB1"
cffb2a26 3532 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3533 [(set_attr "length" "6")]
3534)
3535
3536(define_expand "negsi2"
3537 [(set (match_operand:SI 0 "s_register_operand" "")
3538 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3539 "TARGET_EITHER"
b11cae9e 3540 ""
cffb2a26 3541)
3542
3543(define_insn "*arm_negsi2"
3544 [(set (match_operand:SI 0 "s_register_operand" "=r")
3545 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3546 "TARGET_32BIT"
cffb2a26 3547 "rsb%?\\t%0, %1, #0"
0d66636f 3548 [(set_attr "predicable" "yes")]
cffb2a26 3549)
3550
25f905c2 3551(define_insn "*thumb1_negsi2"
cffb2a26 3552 [(set (match_operand:SI 0 "register_operand" "=l")
3553 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3554 "TARGET_THUMB1"
cffb2a26 3555 "neg\\t%0, %1"
3556 [(set_attr "length" "2")]
3557)
b11cae9e 3558
604f3a0a 3559(define_expand "negsf2"
3560 [(set (match_operand:SF 0 "s_register_operand" "")
3561 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3562 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3563 ""
3564)
3565
3566(define_expand "negdf2"
3567 [(set (match_operand:DF 0 "s_register_operand" "")
3568 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3569 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3570 "")
3571
9c08d1fa 3572;; abssi2 doesn't really clobber the condition codes if a different register
3573;; is being set. To keep things simple, assume during rtl manipulations that
3574;; it does, but tell the final scan operator the truth. Similarly for
3575;; (neg (abs...))
3576
604f3a0a 3577(define_expand "abssi2"
3578 [(parallel
3579 [(set (match_operand:SI 0 "s_register_operand" "")
3580 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3581 (clobber (match_dup 2))])]
3582 "TARGET_EITHER"
3583 "
25f905c2 3584 if (TARGET_THUMB1)
ba156559 3585 operands[2] = gen_rtx_SCRATCH (SImode);
3586 else
3587 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3588")
604f3a0a 3589
7d57ec45 3590(define_insn "*arm_abssi2"
ba156559 3591 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3592 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3593 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3594 "TARGET_ARM"
e2348bcb 3595 "@
3596 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3597 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3598 [(set_attr "conds" "clob,*")
331beb1a 3599 (set_attr "shift" "1")
0d66636f 3600 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3601 (set_attr "length" "8")]
3602)
9c08d1fa 3603
25f905c2 3604(define_insn_and_split "*thumb1_abssi2"
ba156559 3605 [(set (match_operand:SI 0 "s_register_operand" "=l")
3606 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3607 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3608 "TARGET_THUMB1"
ba156559 3609 "#"
25f905c2 3610 "TARGET_THUMB1 && reload_completed"
ba156559 3611 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3612 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3613 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3614 ""
3615 [(set_attr "length" "6")]
3616)
3617
3618(define_insn "*arm_neg_abssi2"
9c08d1fa 3619 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3620 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3621 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3622 "TARGET_ARM"
e2348bcb 3623 "@
3624 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3625 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3626 [(set_attr "conds" "clob,*")
331beb1a 3627 (set_attr "shift" "1")
0d66636f 3628 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3629 (set_attr "length" "8")]
3630)
b11cae9e 3631
25f905c2 3632(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3633 [(set (match_operand:SI 0 "s_register_operand" "=l")
3634 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3635 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3636 "TARGET_THUMB1"
ba156559 3637 "#"
25f905c2 3638 "TARGET_THUMB1 && reload_completed"
ba156559 3639 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3640 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3641 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3642 ""
3643 [(set_attr "length" "6")]
3644)
3645
604f3a0a 3646(define_expand "abssf2"
3647 [(set (match_operand:SF 0 "s_register_operand" "")
3648 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3649 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3650 "")
3651
604f3a0a 3652(define_expand "absdf2"
3653 [(set (match_operand:DF 0 "s_register_operand" "")
3654 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3655 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3656 "")
3657
7db9af5d 3658(define_expand "sqrtsf2"
3659 [(set (match_operand:SF 0 "s_register_operand" "")
3660 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3661 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3662 "")
9c08d1fa 3663
7db9af5d 3664(define_expand "sqrtdf2"
3665 [(set (match_operand:DF 0 "s_register_operand" "")
3666 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3667 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3668 "")
9c08d1fa 3669
a0f94409 3670(define_insn_and_split "one_cmpldi2"
9c08d1fa 3671 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3672 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 3673 "TARGET_32BIT"
f6ebffac 3674 "#"
25f905c2 3675 "TARGET_32BIT && reload_completed"
a0f94409 3676 [(set (match_dup 0) (not:SI (match_dup 1)))
3677 (set (match_dup 2) (not:SI (match_dup 3)))]
3678 "
3679 {
3680 operands[2] = gen_highpart (SImode, operands[0]);
3681 operands[0] = gen_lowpart (SImode, operands[0]);
3682 operands[3] = gen_highpart (SImode, operands[1]);
3683 operands[1] = gen_lowpart (SImode, operands[1]);
3684 }"
0d66636f 3685 [(set_attr "length" "8")
3686 (set_attr "predicable" "yes")]
cffb2a26 3687)
b11cae9e 3688
cffb2a26 3689(define_expand "one_cmplsi2"
3690 [(set (match_operand:SI 0 "s_register_operand" "")
3691 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3692 "TARGET_EITHER"
b11cae9e 3693 ""
cffb2a26 3694)
3695
3696(define_insn "*arm_one_cmplsi2"
3697 [(set (match_operand:SI 0 "s_register_operand" "=r")
3698 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3699 "TARGET_32BIT"
cffb2a26 3700 "mvn%?\\t%0, %1"
0d66636f 3701 [(set_attr "predicable" "yes")]
cffb2a26 3702)
3703
25f905c2 3704(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3705 [(set (match_operand:SI 0 "register_operand" "=l")
3706 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3707 "TARGET_THUMB1"
cffb2a26 3708 "mvn\\t%0, %1"
3709 [(set_attr "length" "2")]
3710)
9c08d1fa 3711
f7fbdd4a 3712(define_insn "*notsi_compare0"
bd5b4116 3713 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3714 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3715 (const_int 0)))
3716 (set (match_operand:SI 0 "s_register_operand" "=r")
3717 (not:SI (match_dup 1)))]
25f905c2 3718 "TARGET_32BIT"
3719 "mvn%.\\t%0, %1"
cffb2a26 3720 [(set_attr "conds" "set")]
3721)
9c08d1fa 3722
f7fbdd4a 3723(define_insn "*notsi_compare0_scratch"
bd5b4116 3724 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3725 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3726 (const_int 0)))
3727 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3728 "TARGET_32BIT"
3729 "mvn%.\\t%0, %1"
cffb2a26 3730 [(set_attr "conds" "set")]
3731)
b11cae9e 3732\f
3733;; Fixed <--> Floating conversion insns
3734
9b8516be 3735(define_expand "floatsihf2"
3736 [(set (match_operand:HF 0 "general_operand" "")
3737 (float:HF (match_operand:SI 1 "general_operand" "")))]
3738 "TARGET_EITHER"
3739 "
3740 {
3741 rtx op1 = gen_reg_rtx (SFmode);
3742 expand_float (op1, operands[1], 0);
3743 op1 = convert_to_mode (HFmode, op1, 0);
3744 emit_move_insn (operands[0], op1);
3745 DONE;
3746 }"
3747)
3748
3749(define_expand "floatdihf2"
3750 [(set (match_operand:HF 0 "general_operand" "")
3751 (float:HF (match_operand:DI 1 "general_operand" "")))]
3752 "TARGET_EITHER"
3753 "
3754 {
3755 rtx op1 = gen_reg_rtx (SFmode);
3756 expand_float (op1, operands[1], 0);
3757 op1 = convert_to_mode (HFmode, op1, 0);
3758 emit_move_insn (operands[0], op1);
3759 DONE;
3760 }"
3761)
3762
604f3a0a 3763(define_expand "floatsisf2"
3764 [(set (match_operand:SF 0 "s_register_operand" "")
3765 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3766 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3767 "
a2cd141b 3768 if (TARGET_MAVERICK)
604f3a0a 3769 {
3770 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3771 DONE;
3772 }
3773")
3774
604f3a0a 3775(define_expand "floatsidf2"
3776 [(set (match_operand:DF 0 "s_register_operand" "")
3777 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3778 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3779 "
a2cd141b 3780 if (TARGET_MAVERICK)
604f3a0a 3781 {
3782 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3783 DONE;
3784 }
3785")
3786
9b8516be 3787(define_expand "fix_trunchfsi2"
3788 [(set (match_operand:SI 0 "general_operand" "")
3789 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3790 "TARGET_EITHER"
3791 "
3792 {
3793 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3794 expand_fix (operands[0], op1, 0);
3795 DONE;
3796 }"
3797)
3798
3799(define_expand "fix_trunchfdi2"
3800 [(set (match_operand:DI 0 "general_operand" "")
3801 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3802 "TARGET_EITHER"
3803 "
3804 {
3805 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3806 expand_fix (operands[0], op1, 0);
3807 DONE;
3808 }"
3809)
3810
604f3a0a 3811(define_expand "fix_truncsfsi2"
3812 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3813 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3814 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3815 "
a2cd141b 3816 if (TARGET_MAVERICK)
604f3a0a 3817 {
3818 if (!cirrus_fp_register (operands[0], SImode))
3819 operands[0] = force_reg (SImode, operands[0]);
3820 if (!cirrus_fp_register (operands[1], SFmode))
3821 operands[1] = force_reg (SFmode, operands[0]);
3822 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3823 DONE;
3824 }
3825")
3826
604f3a0a 3827(define_expand "fix_truncdfsi2"
3828 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3829 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
25f905c2 3830 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3831 "
a2cd141b 3832 if (TARGET_MAVERICK)
604f3a0a 3833 {
3834 if (!cirrus_fp_register (operands[1], DFmode))
3835 operands[1] = force_reg (DFmode, operands[0]);
3836 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3837 DONE;
3838 }
3839")
3840
f544c6d2 3841;; Truncation insns
b11cae9e 3842
604f3a0a 3843(define_expand "truncdfsf2"
3844 [(set (match_operand:SF 0 "s_register_operand" "")
3845 (float_truncate:SF
3846 (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3847 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3848 ""
3849)
9b8516be 3850
3851/* DFmode -> HFmode conversions have to go through SFmode. */
3852(define_expand "truncdfhf2"
3853 [(set (match_operand:HF 0 "general_operand" "")
3854 (float_truncate:HF
3855 (match_operand:DF 1 "general_operand" "")))]
3856 "TARGET_EITHER"
3857 "
3858 {
3859 rtx op1;
3860 op1 = convert_to_mode (SFmode, operands[1], 0);
3861 op1 = convert_to_mode (HFmode, op1, 0);
3862 emit_move_insn (operands[0], op1);
3863 DONE;
3864 }"
3865)
b11cae9e 3866\f
9c08d1fa 3867;; Zero and sign extension instructions.
b11cae9e 3868
25f905c2 3869(define_expand "zero_extendsidi2"
3870 [(set (match_operand:DI 0 "s_register_operand" "")
3871 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3872 "TARGET_32BIT"
3873 ""
3874)
3875
3876(define_insn "*arm_zero_extendsidi2"
9c08d1fa 3877 [(set (match_operand:DI 0 "s_register_operand" "=r")
3878 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3879 "TARGET_ARM"
9c08d1fa 3880 "*
0d66636f 3881 if (REGNO (operands[1])
3882 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3883 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3884 return \"mov%?\\t%R0, #0\";
3885 "
3886 [(set_attr "length" "8")
3887 (set_attr "predicable" "yes")]
3888)
9c08d1fa 3889
25f905c2 3890(define_expand "zero_extendqidi2"
3891 [(set (match_operand:DI 0 "s_register_operand" "")
3892 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3893 "TARGET_32BIT"
3894 ""
3895)
3896
3897(define_insn "*arm_zero_extendqidi2"
cffb2a26 3898 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3899 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3900 "TARGET_ARM"
e2348bcb 3901 "@
97499065 3902 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
25f905c2 3903 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3904 [(set_attr "length" "8")
0d66636f 3905 (set_attr "predicable" "yes")
a2cd141b 3906 (set_attr "type" "*,load_byte")
cffb2a26 3907 (set_attr "pool_range" "*,4092")
3908 (set_attr "neg_pool_range" "*,4084")]
3909)
9c08d1fa 3910
25f905c2 3911(define_expand "extendsidi2"
3912 [(set (match_operand:DI 0 "s_register_operand" "")
3913 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3914 "TARGET_32BIT"
3915 ""
3916)
3917
3918(define_insn "*arm_extendsidi2"
9c08d1fa 3919 [(set (match_operand:DI 0 "s_register_operand" "=r")
3920 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3921 "TARGET_ARM"
9c08d1fa 3922 "*
0d66636f 3923 if (REGNO (operands[1])
3924 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3925 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3926 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3927 "
3928 [(set_attr "length" "8")
331beb1a 3929 (set_attr "shift" "1")
0d66636f 3930 (set_attr "predicable" "yes")]
3931)
9c08d1fa 3932
3933(define_expand "zero_extendhisi2"
cffb2a26 3934 [(set (match_dup 2)
0d66636f 3935 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3936 (const_int 16)))
9c08d1fa 3937 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3938 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3939 "TARGET_EITHER"
9c08d1fa 3940 "
cffb2a26 3941 {
25f905c2 3942 if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3943 {
a2cd141b 3944 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3945 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3946 DONE;
cffb2a26 3947 }
cffb2a26 3948
c1a66faf 3949 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3950 {
3951 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3952 DONE;
3953 }
cffb2a26 3954
a2cd141b 3955 if (!s_register_operand (operands[1], HImode))
3956 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3957
a2cd141b 3958 if (arm_arch6)
3959 {
3960 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3961 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3962 DONE;
cffb2a26 3963 }
a2cd141b 3964
3965 operands[1] = gen_lowpart (SImode, operands[1]);
3966 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3967 }"
3968)
3969
25f905c2 3970(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 3971 [(set (match_operand:SI 0 "register_operand" "=l")
3972 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
25f905c2 3973 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 3974 "*
3975 rtx mem = XEXP (operands[1], 0);
3976
3977 if (GET_CODE (mem) == CONST)
3978 mem = XEXP (mem, 0);
3979
3980 if (GET_CODE (mem) == LABEL_REF)
3981 return \"ldr\\t%0, %1\";
3982
3983 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3984 {
cffb2a26 3985 rtx a = XEXP (mem, 0);
3986 rtx b = XEXP (mem, 1);
3987
3988 /* This can happen due to bugs in reload. */
3989 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3990 {
3991 rtx ops[2];
3992 ops[0] = operands[0];
3993 ops[1] = a;
3994
3995 output_asm_insn (\"mov %0, %1\", ops);
3996
3997 XEXP (mem, 0) = operands[0];
3998 }
3999
4000 else if ( GET_CODE (a) == LABEL_REF
4001 && GET_CODE (b) == CONST_INT)
4002 return \"ldr\\t%0, %1\";
25f7a26e 4003 }
cffb2a26 4004
4005 return \"ldrh\\t%0, %1\";
4006 "
4007 [(set_attr "length" "4")
a2cd141b 4008 (set_attr "type" "load_byte")
cffb2a26 4009 (set_attr "pool_range" "60")]
4010)
9c08d1fa 4011
25f905c2 4012(define_insn "*thumb1_zero_extendhisi2_v6"
a2cd141b 4013 [(set (match_operand:SI 0 "register_operand" "=l,l")
4014 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4015 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4016 "*
4017 rtx mem;
4018
4019 if (which_alternative == 0)
4020 return \"uxth\\t%0, %1\";
4021
4022 mem = XEXP (operands[1], 0);
4023
4024 if (GET_CODE (mem) == CONST)
4025 mem = XEXP (mem, 0);
4026
4027 if (GET_CODE (mem) == LABEL_REF)
4028 return \"ldr\\t%0, %1\";
4029
4030 if (GET_CODE (mem) == PLUS)
4031 {
4032 rtx a = XEXP (mem, 0);
4033 rtx b = XEXP (mem, 1);
4034
4035 /* This can happen due to bugs in reload. */
4036 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4037 {
4038 rtx ops[2];
4039 ops[0] = operands[0];
4040 ops[1] = a;
4041
4042 output_asm_insn (\"mov %0, %1\", ops);
4043
4044 XEXP (mem, 0) = operands[0];
4045 }
4046
4047 else if ( GET_CODE (a) == LABEL_REF
4048 && GET_CODE (b) == CONST_INT)
4049 return \"ldr\\t%0, %1\";
4050 }
4051
4052 return \"ldrh\\t%0, %1\";
4053 "
4054 [(set_attr "length" "2,4")
4055 (set_attr "type" "alu_shift,load_byte")
4056 (set_attr "pool_range" "*,60")]
4057)
4058
cffb2a26 4059(define_insn "*arm_zero_extendhisi2"
a2cd141b 4060 [(set (match_operand:SI 0 "s_register_operand" "=r")
4061 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4062 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4063 "ldr%(h%)\\t%0, %1"
a2cd141b 4064 [(set_attr "type" "load_byte")
0d66636f 4065 (set_attr "predicable" "yes")
cffb2a26 4066 (set_attr "pool_range" "256")
4067 (set_attr "neg_pool_range" "244")]
4068)
f7fbdd4a 4069
a2cd141b 4070(define_insn "*arm_zero_extendhisi2_v6"
4071 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4072 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4073 "TARGET_ARM && arm_arch6"
4074 "@
4075 uxth%?\\t%0, %1
25f905c2 4076 ldr%(h%)\\t%0, %1"
a2cd141b 4077 [(set_attr "type" "alu_shift,load_byte")
4078 (set_attr "predicable" "yes")
4079 (set_attr "pool_range" "*,256")
4080 (set_attr "neg_pool_range" "*,244")]
4081)
4082
4083(define_insn "*arm_zero_extendhisi2addsi"
4084 [(set (match_operand:SI 0 "s_register_operand" "=r")
4085 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4086 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4087 "TARGET_INT_SIMD"
a2cd141b 4088 "uxtah%?\\t%0, %2, %1"
4089 [(set_attr "type" "alu_shift")
4090 (set_attr "predicable" "yes")]
4091)
4092
87b22bf7 4093(define_expand "zero_extendqisi2"
cffb2a26 4094 [(set (match_operand:SI 0 "s_register_operand" "")
4095 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4096 "TARGET_EITHER"
87b22bf7 4097 "
a2cd141b 4098 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4099 {
cffb2a26 4100 if (TARGET_ARM)
4101 {
215b30b3 4102 emit_insn (gen_andsi3 (operands[0],
4103 gen_lowpart (SImode, operands[1]),
cffb2a26 4104 GEN_INT (255)));
4105 }
4106 else /* TARGET_THUMB */
4107 {
4108 rtx temp = gen_reg_rtx (SImode);
4109 rtx ops[3];
4110
4111 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4112 operands[1] = gen_lowpart (SImode, operands[1]);
4113
4114 ops[0] = temp;
4115 ops[1] = operands[1];
4116 ops[2] = GEN_INT (24);
4117
215b30b3 4118 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4119 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 4120
4121 ops[0] = operands[0];
4122 ops[1] = temp;
4123 ops[2] = GEN_INT (24);
4124
215b30b3 4125 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4126 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 4127 }
87b22bf7 4128 DONE;
4129 }
215b30b3 4130 "
4131)
9c08d1fa 4132
25f905c2 4133(define_insn "*thumb1_zero_extendqisi2"
a2cd141b 4134 [(set (match_operand:SI 0 "register_operand" "=l")
4135 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
25f905c2 4136 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4137 "ldrb\\t%0, %1"
4138 [(set_attr "length" "2")
a2cd141b 4139 (set_attr "type" "load_byte")
cffb2a26 4140 (set_attr "pool_range" "32")]
4141)
4142
25f905c2 4143(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4144 [(set (match_operand:SI 0 "register_operand" "=l,l")
4145 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4146 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4147 "@
4148 uxtb\\t%0, %1
4149 ldrb\\t%0, %1"
4150 [(set_attr "length" "2,2")
4151 (set_attr "type" "alu_shift,load_byte")
4152 (set_attr "pool_range" "*,32")]
4153)
4154
cffb2a26 4155(define_insn "*arm_zero_extendqisi2"
a2cd141b 4156 [(set (match_operand:SI 0 "s_register_operand" "=r")
4157 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4158 "TARGET_ARM && !arm_arch6"
25f905c2 4159 "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4160 [(set_attr "type" "load_byte")
0d66636f 4161 (set_attr "predicable" "yes")
cffb2a26 4162 (set_attr "pool_range" "4096")
4163 (set_attr "neg_pool_range" "4084")]
4164)
87b22bf7 4165
a2cd141b 4166(define_insn "*arm_zero_extendqisi2_v6"
4167 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4168 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4169 "TARGET_ARM && arm_arch6"
4170 "@
25f905c2 4171 uxtb%(%)\\t%0, %1
4172 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4173 [(set_attr "type" "alu_shift,load_byte")
4174 (set_attr "predicable" "yes")
4175 (set_attr "pool_range" "*,4096")
4176 (set_attr "neg_pool_range" "*,4084")]
4177)
4178
4179(define_insn "*arm_zero_extendqisi2addsi"
4180 [(set (match_operand:SI 0 "s_register_operand" "=r")
4181 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4182 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4183 "TARGET_INT_SIMD"
a2cd141b 4184 "uxtab%?\\t%0, %2, %1"
4185 [(set_attr "predicable" "yes")
bcaec148 4186 (set_attr "insn" "xtab")
a2cd141b 4187 (set_attr "type" "alu_shift")]
4188)
4189
87b22bf7 4190(define_split
4191 [(set (match_operand:SI 0 "s_register_operand" "")
4192 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4193 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4194 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4195 [(set (match_dup 2) (match_dup 1))
4196 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4197 ""
4198)
9c08d1fa 4199
8a4d25d6 4200(define_split
4201 [(set (match_operand:SI 0 "s_register_operand" "")
4202 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4203 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4204 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4205 [(set (match_dup 2) (match_dup 1))
4206 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4207 ""
4208)
4209
f7fbdd4a 4210(define_insn "*compareqi_eq0"
bd5b4116 4211 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4212 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4213 (const_int 0)))]
25f905c2 4214 "TARGET_32BIT"
87b22bf7 4215 "tst\\t%0, #255"
cffb2a26 4216 [(set_attr "conds" "set")]
4217)
b11cae9e 4218
b11cae9e 4219(define_expand "extendhisi2"
c8f69309 4220 [(set (match_dup 2)
25f7a26e 4221 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 4222 (const_int 16)))
9c08d1fa 4223 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4224 (ashiftrt:SI (match_dup 2)
4225 (const_int 16)))]
cffb2a26 4226 "TARGET_EITHER"
b11cae9e 4227 "
cffb2a26 4228 {
a2cd141b 4229 if (GET_CODE (operands[1]) == MEM)
cffb2a26 4230 {
25f905c2 4231 if (TARGET_THUMB1)
a2cd141b 4232 {
25f905c2 4233 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4234 DONE;
4235 }
4236 else if (arm_arch4)
4237 {
a2cd141b 4238 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4239 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4240 DONE;
4241 }
cffb2a26 4242 }
7bd8ccc9 4243
c1a66faf 4244 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 4245 {
4246 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4247 DONE;
4248 }
a2cd141b 4249
215b30b3 4250 if (!s_register_operand (operands[1], HImode))
cffb2a26 4251 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 4252
a2cd141b 4253 if (arm_arch6)
cffb2a26 4254 {
25f905c2 4255 if (TARGET_THUMB1)
4256 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4257 else
4258 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4259 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4260
cffb2a26 4261 DONE;
4262 }
a2cd141b 4263
4264 operands[1] = gen_lowpart (SImode, operands[1]);
4265 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4266 }"
4267)
4268
25f905c2 4269(define_insn "thumb1_extendhisi2"
a2cd141b 4270 [(set (match_operand:SI 0 "register_operand" "=l")
4271 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4272 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4273 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4274 "*
4275 {
4276 rtx ops[4];
4277 rtx mem = XEXP (operands[1], 0);
4278
4279 /* This code used to try to use 'V', and fix the address only if it was
4280 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4281 range of QImode offsets, and offsettable_address_p does a QImode
4282 address check. */
4283
4284 if (GET_CODE (mem) == CONST)
4285 mem = XEXP (mem, 0);
4286
4287 if (GET_CODE (mem) == LABEL_REF)
4288 return \"ldr\\t%0, %1\";
4289
4290 if (GET_CODE (mem) == PLUS)
4291 {
4292 rtx a = XEXP (mem, 0);
4293 rtx b = XEXP (mem, 1);
4294
4295 if (GET_CODE (a) == LABEL_REF
4296 && GET_CODE (b) == CONST_INT)
4297 return \"ldr\\t%0, %1\";
4298
4299 if (GET_CODE (b) == REG)
4300 return \"ldrsh\\t%0, %1\";
4301
4302 ops[1] = a;
4303 ops[2] = b;
4304 }
4305 else
4306 {
4307 ops[1] = mem;
4308 ops[2] = const0_rtx;
4309 }
ed29c566 4310
4311 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 4312
4313 ops[0] = operands[0];
4314 ops[3] = operands[2];
4315 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4316 return \"\";
4317 }"
4318 [(set_attr "length" "4")
a2cd141b 4319 (set_attr "type" "load_byte")
cffb2a26 4320 (set_attr "pool_range" "1020")]
4321)
25f7a26e 4322
a2cd141b 4323;; We used to have an early-clobber on the scratch register here.
4324;; However, there's a bug somewhere in reload which means that this
4325;; can be partially ignored during spill allocation if the memory
ed29c566 4326;; address also needs reloading; this causes us to die later on when
a2cd141b 4327;; we try to verify the operands. Fortunately, we don't really need
4328;; the early-clobber: we can always use operand 0 if operand 2
4329;; overlaps the address.
25f905c2 4330(define_insn "*thumb1_extendhisi2_insn_v6"
a2cd141b 4331 [(set (match_operand:SI 0 "register_operand" "=l,l")
4332 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4333 (clobber (match_scratch:SI 2 "=X,l"))]
25f905c2 4334 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4335 "*
4336 {
4337 rtx ops[4];
4338 rtx mem;
4339
4340 if (which_alternative == 0)
4341 return \"sxth\\t%0, %1\";
4342
4343 mem = XEXP (operands[1], 0);
4344
4345 /* This code used to try to use 'V', and fix the address only if it was
4346 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4347 range of QImode offsets, and offsettable_address_p does a QImode
4348 address check. */
4349
4350 if (GET_CODE (mem) == CONST)
4351 mem = XEXP (mem, 0);
4352
4353 if (GET_CODE (mem) == LABEL_REF)
4354 return \"ldr\\t%0, %1\";
4355
4356 if (GET_CODE (mem) == PLUS)
4357 {
4358 rtx a = XEXP (mem, 0);
4359 rtx b = XEXP (mem, 1);
4360
4361 if (GET_CODE (a) == LABEL_REF
4362 && GET_CODE (b) == CONST_INT)
4363 return \"ldr\\t%0, %1\";
4364
4365 if (GET_CODE (b) == REG)
4366 return \"ldrsh\\t%0, %1\";
4367
4368 ops[1] = a;
4369 ops[2] = b;
4370 }
4371 else
4372 {
4373 ops[1] = mem;
4374 ops[2] = const0_rtx;
4375 }
4376
ed29c566 4377 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4378
4379 ops[0] = operands[0];
4380 if (reg_mentioned_p (operands[2], ops[1]))
4381 ops[3] = ops[0];
4382 else
4383 ops[3] = operands[2];
4384 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4385 return \"\";
4386 }"
4387 [(set_attr "length" "2,4")
4388 (set_attr "type" "alu_shift,load_byte")
4389 (set_attr "pool_range" "*,1020")]
4390)
4391
25f905c2 4392;; This pattern will only be used when ldsh is not available
25f7a26e 4393(define_expand "extendhisi2_mem"
eab14235 4394 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4395 (set (match_dup 3)
eab14235 4396 (zero_extend:SI (match_dup 7)))
25f7a26e 4397 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4398 (set (match_operand:SI 0 "" "")
4399 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4400 "TARGET_ARM"
25f7a26e 4401 "
215b30b3 4402 {
4403 rtx mem1, mem2;
4404 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4405
788fcce0 4406 mem1 = change_address (operands[1], QImode, addr);
4407 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4408 operands[0] = gen_lowpart (SImode, operands[0]);
4409 operands[1] = mem1;
4410 operands[2] = gen_reg_rtx (SImode);
4411 operands[3] = gen_reg_rtx (SImode);
4412 operands[6] = gen_reg_rtx (SImode);
4413 operands[7] = mem2;
25f7a26e 4414
215b30b3 4415 if (BYTES_BIG_ENDIAN)
4416 {
4417 operands[4] = operands[2];
4418 operands[5] = operands[3];
4419 }
4420 else
4421 {
4422 operands[4] = operands[3];
4423 operands[5] = operands[2];
4424 }
4425 }"
4426)
b11cae9e 4427
a2cd141b 4428(define_insn "*arm_extendhisi2"
4429 [(set (match_operand:SI 0 "s_register_operand" "=r")
4430 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4431 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4432 "ldr%(sh%)\\t%0, %1"
a2cd141b 4433 [(set_attr "type" "load_byte")
0d66636f 4434 (set_attr "predicable" "yes")
cffb2a26 4435 (set_attr "pool_range" "256")
4436 (set_attr "neg_pool_range" "244")]
4437)
f7fbdd4a 4438
25f905c2 4439;; ??? Check Thumb-2 pool range
a2cd141b 4440(define_insn "*arm_extendhisi2_v6"
4441 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4442 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4443 "TARGET_32BIT && arm_arch6"
a2cd141b 4444 "@
4445 sxth%?\\t%0, %1
25f905c2 4446 ldr%(sh%)\\t%0, %1"
a2cd141b 4447 [(set_attr "type" "alu_shift,load_byte")
4448 (set_attr "predicable" "yes")
4449 (set_attr "pool_range" "*,256")
4450 (set_attr "neg_pool_range" "*,244")]
4451)
4452
4453(define_insn "*arm_extendhisi2addsi"
4454 [(set (match_operand:SI 0 "s_register_operand" "=r")
4455 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4456 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4457 "TARGET_INT_SIMD"
a2cd141b 4458 "sxtah%?\\t%0, %2, %1"
4459)
4460
c8f69309 4461(define_expand "extendqihi2"
4462 [(set (match_dup 2)
bed7d9a5 4463 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4464 (const_int 24)))
9c08d1fa 4465 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4466 (ashiftrt:SI (match_dup 2)
4467 (const_int 24)))]
cffb2a26 4468 "TARGET_ARM"
c8f69309 4469 "
215b30b3 4470 {
4471 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4472 {
4473 emit_insn (gen_rtx_SET (VOIDmode,
4474 operands[0],
4475 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4476 DONE;
4477 }
4478 if (!s_register_operand (operands[1], QImode))
4479 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4480 operands[0] = gen_lowpart (SImode, operands[0]);
4481 operands[1] = gen_lowpart (SImode, operands[1]);
4482 operands[2] = gen_reg_rtx (SImode);
4483 }"
4484)
f7fbdd4a 4485
25f905c2 4486(define_insn "*arm_extendqihi_insn"
b4e8a300 4487 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4488 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4489 "TARGET_ARM && arm_arch4"
25f905c2 4490 "ldr%(sb%)\\t%0, %1"
a2cd141b 4491 [(set_attr "type" "load_byte")
0d66636f 4492 (set_attr "predicable" "yes")
cffb2a26 4493 (set_attr "pool_range" "256")
4494 (set_attr "neg_pool_range" "244")]
4495)
3fc2009e 4496
b11cae9e 4497(define_expand "extendqisi2"
c8f69309 4498 [(set (match_dup 2)
bed7d9a5 4499 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
b11cae9e 4500 (const_int 24)))
9c08d1fa 4501 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4502 (ashiftrt:SI (match_dup 2)
4503 (const_int 24)))]
cffb2a26 4504 "TARGET_EITHER"
b11cae9e 4505 "
cffb2a26 4506 {
a2cd141b 4507 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 4508 {
a2cd141b 4509 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 4510 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4511 DONE;
4512 }
a2cd141b 4513
215b30b3 4514 if (!s_register_operand (operands[1], QImode))
cffb2a26 4515 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 4516
a2cd141b 4517 if (arm_arch6)
4518 {
4519 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4520 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4521 DONE;
cffb2a26 4522 }
a2cd141b 4523
4524 operands[1] = gen_lowpart (SImode, operands[1]);
4525 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4526 }"
4527)
f7fbdd4a 4528
a2cd141b 4529(define_insn "*arm_extendqisi"
4530 [(set (match_operand:SI 0 "s_register_operand" "=r")
bed7d9a5 4531 (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
a2cd141b 4532 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4533 "ldr%(sb%)\\t%0, %1"
a2cd141b 4534 [(set_attr "type" "load_byte")
0d66636f 4535 (set_attr "predicable" "yes")
cffb2a26 4536 (set_attr "pool_range" "256")
4537 (set_attr "neg_pool_range" "244")]
4538)
3fc2009e 4539
a2cd141b 4540(define_insn "*arm_extendqisi_v6"
4541 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4542 (sign_extend:SI
4543 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4544 "TARGET_ARM && arm_arch6"
b4e8a300 4545 "@
4546 sxtb%?\\t%0, %1
25f905c2 4547 ldr%(sb%)\\t%0, %1"
a2cd141b 4548 [(set_attr "type" "alu_shift,load_byte")
4549 (set_attr "predicable" "yes")
a2cd141b 4550 (set_attr "pool_range" "*,256")
4551 (set_attr "neg_pool_range" "*,244")]
4552)
4553
4554(define_insn "*arm_extendqisi2addsi"
4555 [(set (match_operand:SI 0 "s_register_operand" "=r")
4556 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4557 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4558 "TARGET_INT_SIMD"
a2cd141b 4559 "sxtab%?\\t%0, %2, %1"
4560 [(set_attr "type" "alu_shift")
bcaec148 4561 (set_attr "insn" "xtab")
a2cd141b 4562 (set_attr "predicable" "yes")]
4563)
4564
25f905c2 4565(define_insn "*thumb1_extendqisi2"
a2cd141b 4566 [(set (match_operand:SI 0 "register_operand" "=l,l")
4567 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
25f905c2 4568 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4569 "*
4570 {
4571 rtx ops[3];
4572 rtx mem = XEXP (operands[1], 0);
4573
4574 if (GET_CODE (mem) == CONST)
4575 mem = XEXP (mem, 0);
4576
4577 if (GET_CODE (mem) == LABEL_REF)
4578 return \"ldr\\t%0, %1\";
4579
4580 if (GET_CODE (mem) == PLUS
4581 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4582 return \"ldr\\t%0, %1\";
4583
4584 if (which_alternative == 0)
4585 return \"ldrsb\\t%0, %1\";
4586
4587 ops[0] = operands[0];
4588
4589 if (GET_CODE (mem) == PLUS)
4590 {
4591 rtx a = XEXP (mem, 0);
4592 rtx b = XEXP (mem, 1);
4593
4594 ops[1] = a;
4595 ops[2] = b;
4596
4597 if (GET_CODE (a) == REG)
4598 {
4599 if (GET_CODE (b) == REG)
4600 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4601 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 4602 {
4603 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4604 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4605 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4606 }
cffb2a26 4607 else
4608 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4609 }
cffb2a26 4610 else
4611 {
ed29c566 4612 gcc_assert (GET_CODE (b) == REG);
cffb2a26 4613 if (REGNO (b) == REGNO (ops[0]))
215b30b3 4614 {
4615 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4616 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4617 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4618 }
cffb2a26 4619 else
4620 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4621 }
4622 }
4623 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4624 {
215b30b3 4625 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4626 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4627 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 4628 }
4629 else
4630 {
4631 ops[1] = mem;
4632 ops[2] = const0_rtx;
4633
4634 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4635 }
4636 return \"\";
4637 }"
4638 [(set_attr "length" "2,6")
a2cd141b 4639 (set_attr "type" "load_byte,load_byte")
cffb2a26 4640 (set_attr "pool_range" "32,32")]
4641)
4642
25f905c2 4643(define_insn "*thumb1_extendqisi2_v6"
a2cd141b 4644 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4645 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
25f905c2 4646 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4647 "*
4648 {
4649 rtx ops[3];
4650 rtx mem;
4651
4652 if (which_alternative == 0)
4653 return \"sxtb\\t%0, %1\";
4654
4655 mem = XEXP (operands[1], 0);
4656
4657 if (GET_CODE (mem) == CONST)
4658 mem = XEXP (mem, 0);
4659
4660 if (GET_CODE (mem) == LABEL_REF)
4661 return \"ldr\\t%0, %1\";
4662
4663 if (GET_CODE (mem) == PLUS
4664 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4665 return \"ldr\\t%0, %1\";
4666
4667 if (which_alternative == 0)
4668 return \"ldrsb\\t%0, %1\";
4669
4670 ops[0] = operands[0];
4671
4672 if (GET_CODE (mem) == PLUS)
4673 {
4674 rtx a = XEXP (mem, 0);
4675 rtx b = XEXP (mem, 1);
4676
4677 ops[1] = a;
4678 ops[2] = b;
4679
4680 if (GET_CODE (a) == REG)
4681 {
4682 if (GET_CODE (b) == REG)
4683 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4684 else if (REGNO (a) == REGNO (ops[0]))
4685 {
4686 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4687 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4688 }
4689 else
4690 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4691 }
a2cd141b 4692 else
4693 {
ed29c566 4694 gcc_assert (GET_CODE (b) == REG);
a2cd141b 4695 if (REGNO (b) == REGNO (ops[0]))
4696 {
4697 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4698 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4699 }
4700 else
4701 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4702 }
4703 }
4704 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4705 {
4706 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4707 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4708 }
4709 else
4710 {
4711 ops[1] = mem;
4712 ops[2] = const0_rtx;
4713
4714 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4715 }
4716 return \"\";
4717 }"
4718 [(set_attr "length" "2,2,4")
4719 (set_attr "type" "alu_shift,load_byte,load_byte")
4720 (set_attr "pool_range" "*,32,32")]
4721)
4722
caedf871 4723(define_expand "extendsfdf2"
4724 [(set (match_operand:DF 0 "s_register_operand" "")
4725 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4726 "TARGET_32BIT && TARGET_HARD_FLOAT"
caedf871 4727 ""
4728)
9b8516be 4729
4730/* HFmode -> DFmode conversions have to go through SFmode. */
4731(define_expand "extendhfdf2"
4732 [(set (match_operand:DF 0 "general_operand" "")
4733 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4734 "TARGET_EITHER"
4735 "
4736 {
4737 rtx op1;
4738 op1 = convert_to_mode (SFmode, operands[1], 0);
4739 op1 = convert_to_mode (DFmode, op1, 0);
4740 emit_insn (gen_movdf (operands[0], op1));
4741 DONE;
4742 }"
4743)
b11cae9e 4744\f
4745;; Move insns (including loads and stores)
4746
4747;; XXX Just some ideas about movti.
9c08d1fa 4748;; I don't think these are a good idea on the arm, there just aren't enough
4749;; registers
b11cae9e 4750;;(define_expand "loadti"
9c08d1fa 4751;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4752;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4753;; "" "")
4754
4755;;(define_expand "storeti"
4756;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4757;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4758;; "" "")
4759
4760;;(define_expand "movti"
4761;; [(set (match_operand:TI 0 "general_operand" "")
4762;; (match_operand:TI 1 "general_operand" ""))]
4763;; ""
4764;; "
4765;;{
4766;; rtx insn;
4767;;
4768;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4769;; operands[1] = copy_to_reg (operands[1]);
4770;; if (GET_CODE (operands[0]) == MEM)
4771;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4772;; else if (GET_CODE (operands[1]) == MEM)
4773;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4774;; else
4775;; FAIL;
4776;;
4777;; emit_insn (insn);
4778;; DONE;
4779;;}")
4780
a2f10574 4781;; Recognize garbage generated above.
b11cae9e 4782
4783;;(define_insn ""
4784;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4785;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4786;; ""
4787;; "*
4788;; {
4789;; register mem = (which_alternative < 3);
0d66636f 4790;; register const char *template;
b11cae9e 4791;;
4792;; operands[mem] = XEXP (operands[mem], 0);
4793;; switch (which_alternative)
4794;; {
4795;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4796;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4797;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4798;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4799;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4800;; case 5: template = \"stmia\\t%0, %M1\"; break;
4801;; }
e2348bcb 4802;; output_asm_insn (template, operands);
4803;; return \"\";
b11cae9e 4804;; }")
4805
cffb2a26 4806(define_expand "movdi"
4807 [(set (match_operand:DI 0 "general_operand" "")
4808 (match_operand:DI 1 "general_operand" ""))]
4809 "TARGET_EITHER"
4810 "
e1ba4a27 4811 if (can_create_pseudo_p ())
cffb2a26 4812 {
b2778788 4813 if (GET_CODE (operands[0]) != REG)
4814 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4815 }
4816 "
4817)
b11cae9e 4818
cffb2a26 4819(define_insn "*arm_movdi"
d51f92df 4820 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4821 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4822 "TARGET_ARM
b2778788 4823 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4824 && !TARGET_IWMMXT
4825 && ( register_operand (operands[0], DImode)
4826 || register_operand (operands[1], DImode))"
b11cae9e 4827 "*
d51f92df 4828 switch (which_alternative)
4829 {
4830 case 0:
4831 case 1:
4832 case 2:
4833 return \"#\";
4834 default:
4835 return output_move_double (operands);
4836 }
cffb2a26 4837 "
359a6e9f 4838 [(set_attr "length" "8,12,16,8,8")
4839 (set_attr "type" "*,*,*,load2,store2")
4840 (set_attr "pool_range" "*,*,*,1020,*")
4841 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4842)
4843
d51f92df 4844(define_split
4845 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4846 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4847 "TARGET_32BIT
d51f92df 4848 && reload_completed
4849 && (arm_const_double_inline_cost (operands[1])
4850 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4851 [(const_int 0)]
4852 "
4853 arm_split_constant (SET, SImode, curr_insn,
4854 INTVAL (gen_lowpart (SImode, operands[1])),
4855 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4856 arm_split_constant (SET, SImode, curr_insn,
4857 INTVAL (gen_highpart_mode (SImode,
4858 GET_MODE (operands[0]),
4859 operands[1])),
4860 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4861 DONE;
4862 "
4863)
4864
e5ba9289 4865; If optimizing for size, or if we have load delay slots, then
4866; we want to split the constant into two separate operations.
4867; In both cases this may split a trivial part into a single data op
4868; leaving a single complex constant to load. We can also get longer
4869; offsets in a LDR which means we get better chances of sharing the pool
4870; entries. Finally, we can normally do a better job of scheduling
4871; LDR instructions than we can with LDM.
4872; This pattern will only match if the one above did not.
4873(define_split
4874 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4875 (match_operand:ANY64 1 "const_double_operand" ""))]
4876 "TARGET_ARM && reload_completed
4877 && arm_const_double_by_parts (operands[1])"
4878 [(set (match_dup 0) (match_dup 1))
4879 (set (match_dup 2) (match_dup 3))]
4880 "
4881 operands[2] = gen_highpart (SImode, operands[0]);
4882 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4883 operands[1]);
4884 operands[0] = gen_lowpart (SImode, operands[0]);
4885 operands[1] = gen_lowpart (SImode, operands[1]);
4886 "
4887)
4888
d51f92df 4889(define_split
4890 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4891 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4892 "TARGET_EITHER && reload_completed"
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 (SImode, operands[1]);
4898 operands[0] = gen_lowpart (SImode, operands[0]);
4899 operands[1] = gen_lowpart (SImode, operands[1]);
4900
4901 /* Handle a partial overlap. */
4902 if (rtx_equal_p (operands[0], operands[3]))
4903 {
4904 rtx tmp0 = operands[0];
4905 rtx tmp1 = operands[1];
4906
4907 operands[0] = operands[2];
4908 operands[1] = operands[3];
4909 operands[2] = tmp0;
4910 operands[3] = tmp1;
4911 }
4912 "
4913)
4914
a8a3b539 4915;; We can't actually do base+index doubleword loads if the index and
4916;; destination overlap. Split here so that we at least have chance to
4917;; schedule.
4918(define_split
4919 [(set (match_operand:DI 0 "s_register_operand" "")
4920 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4921 (match_operand:SI 2 "s_register_operand" ""))))]
4922 "TARGET_LDRD
4923 && reg_overlap_mentioned_p (operands[0], operands[1])
4924 && reg_overlap_mentioned_p (operands[0], operands[2])"
4925 [(set (match_dup 4)
4926 (plus:SI (match_dup 1)
4927 (match_dup 2)))
4928 (set (match_dup 0)
4929 (mem:DI (match_dup 4)))]
4930 "
4931 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4932 "
4933)
4934
cffb2a26 4935;;; ??? This should have alternatives for constants.
4936;;; ??? This was originally identical to the movdf_insn pattern.
4937;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4938;;; thumb_reorg with a memory reference.
25f905c2 4939(define_insn "*thumb1_movdi_insn"
215b30b3 4940 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4941 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4942 "TARGET_THUMB1
a2cd141b 4943 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4944 && ( register_operand (operands[0], DImode)
4945 || register_operand (operands[1], DImode))"
4946 "*
4947 {
4948 switch (which_alternative)
4949 {
4950 default:
4951 case 0:
4952 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4953 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4954 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4955 case 1:
4956 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4957 case 2:
4958 operands[1] = GEN_INT (- INTVAL (operands[1]));
4959 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4960 case 3:
4961 return \"ldmia\\t%1, {%0, %H0}\";
4962 case 4:
4963 return \"stmia\\t%0, {%1, %H1}\";
4964 case 5:
4965 return thumb_load_double_from_address (operands);
4966 case 6:
1a83b3ff 4967 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4968 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4969 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4970 return \"\";
4971 case 7:
4972 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4973 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4974 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4975 }
4976 }"
4977 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4978 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4979 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4980)
b11cae9e 4981
9c08d1fa 4982(define_expand "movsi"
4983 [(set (match_operand:SI 0 "general_operand" "")
4984 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4985 "TARGET_EITHER"
9c08d1fa 4986 "
befb0bac 4987 {
e348ff3e 4988 rtx base, offset, tmp;
4989
25f905c2 4990 if (TARGET_32BIT)
9c08d1fa 4991 {
674a8f0b 4992 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4993 if (GET_CODE (operands[0]) == MEM)
4994 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4995 if (arm_general_register_operand (operands[0], SImode)
4996 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4997 && !(const_ok_for_arm (INTVAL (operands[1]))
4998 || const_ok_for_arm (~INTVAL (operands[1]))))
4999 {
96f57e36 5000 arm_split_constant (SET, SImode, NULL_RTX,
5001 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5002 optimize && can_create_pseudo_p ());
cffb2a26 5003 DONE;
5004 }
d0e6a121 5005
5006 if (TARGET_USE_MOVT && !target_word_relocations
5007 && GET_CODE (operands[1]) == SYMBOL_REF
5008 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5009 {
5010 arm_emit_movpair (operands[0], operands[1]);
5011 DONE;
5012 }
cffb2a26 5013 }
25f905c2 5014 else /* TARGET_THUMB1... */
cffb2a26 5015 {
e1ba4a27 5016 if (can_create_pseudo_p ())
cffb2a26 5017 {
5018 if (GET_CODE (operands[0]) != REG)
5019 operands[1] = force_reg (SImode, operands[1]);
5020 }
9c08d1fa 5021 }
f655717d 5022
e348ff3e 5023 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5024 {
5025 split_const (operands[1], &base, &offset);
5026 if (GET_CODE (base) == SYMBOL_REF
5027 && !offset_within_block_p (base, INTVAL (offset)))
5028 {
b308ddcf 5029 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5030 emit_move_insn (tmp, base);
5031 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5032 DONE;
5033 }
5034 }
5035
f655717d 5036 /* Recognize the case where operand[1] is a reference to thread-local
5037 data and load its address to a register. */
5038 if (arm_tls_referenced_p (operands[1]))
5039 {
5040 rtx tmp = operands[1];
5041 rtx addend = NULL;
5042
5043 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5044 {
5045 addend = XEXP (XEXP (tmp, 0), 1);
5046 tmp = XEXP (XEXP (tmp, 0), 0);
5047 }
5048
5049 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5050 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5051
e1ba4a27 5052 tmp = legitimize_tls_address (tmp,
5053 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5054 if (addend)
5055 {
5056 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5057 tmp = force_operand (tmp, operands[0]);
5058 }
5059 operands[1] = tmp;
5060 }
5061 else if (flag_pic
5062 && (CONSTANT_P (operands[1])
5063 || symbol_mentioned_p (operands[1])
5064 || label_mentioned_p (operands[1])))
5065 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5066 (!can_create_pseudo_p ()
5067 ? operands[0]
5068 : 0));
befb0bac 5069 }
215b30b3 5070 "
5071)
9c08d1fa 5072
d0e6a121 5073;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5074;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5075;; so this does not matter.
5076(define_insn "*arm_movt"
5077 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5078 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5079 (match_operand:SI 2 "general_operand" "i")))]
5080 "TARGET_32BIT"
5081 "movt%?\t%0, #:upper16:%c2"
5082 [(set_attr "predicable" "yes")
5083 (set_attr "length" "4")]
5084)
5085
cffb2a26 5086(define_insn "*arm_movsi_insn"
aaa37ad6 5087 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5088 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5089 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5090 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5091 && ( register_operand (operands[0], SImode)
5092 || register_operand (operands[1], SImode))"
f7fbdd4a 5093 "@
aaa37ad6 5094 mov%?\\t%0, %1
f7fbdd4a 5095 mov%?\\t%0, %1
5096 mvn%?\\t%0, #%B1
25f905c2 5097 movw%?\\t%0, %1
f7fbdd4a 5098 ldr%?\\t%0, %1
5099 str%?\\t%1, %0"
aaa37ad6 5100 [(set_attr "type" "*,*,*,*,load1,store1")
0d66636f 5101 (set_attr "predicable" "yes")
aaa37ad6 5102 (set_attr "pool_range" "*,*,*,*,4096,*")
5103 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5104)
87b22bf7 5105
5106(define_split
a2cd141b 5107 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5108 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5109 "TARGET_32BIT
215b30b3 5110 && (!(const_ok_for_arm (INTVAL (operands[1]))
5111 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5112 [(clobber (const_int 0))]
5113 "
96f57e36 5114 arm_split_constant (SET, SImode, NULL_RTX,
5115 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5116 DONE;
215b30b3 5117 "
5118)
9c08d1fa 5119
25f905c2 5120(define_insn "*thumb1_movsi_insn"
aaa37ad6 5121 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5122 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
25f905c2 5123 "TARGET_THUMB1
cffb2a26 5124 && ( register_operand (operands[0], SImode)
5125 || register_operand (operands[1], SImode))"
5126 "@
5127 mov %0, %1
5128 mov %0, %1
5129 #
5130 #
5131 ldmia\\t%1, {%0}
5132 stmia\\t%0, {%1}
5133 ldr\\t%0, %1
5134 str\\t%1, %0
5135 mov\\t%0, %1"
5136 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5137 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 5138 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5139)
5140
5141(define_split
5142 [(set (match_operand:SI 0 "register_operand" "")
5143 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5144 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
cffb2a26 5145 [(set (match_dup 0) (match_dup 1))
5146 (set (match_dup 0) (neg:SI (match_dup 0)))]
5147 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5148)
5149
5150(define_split
5151 [(set (match_operand:SI 0 "register_operand" "")
5152 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5153 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
cffb2a26 5154 [(set (match_dup 0) (match_dup 1))
5155 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5156 "
5157 {
e4aeee53 5158 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5159 unsigned HOST_WIDE_INT mask = 0xff;
5160 int i;
5161
5162 for (i = 0; i < 25; i++)
5163 if ((val & (mask << i)) == val)
5164 break;
5165
f5b3169c 5166 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 5167 if (i == 0)
5168 FAIL;
5169
5170 operands[1] = GEN_INT (val >> i);
5171 operands[2] = GEN_INT (i);
5172 }"
5173)
5174
67336bcf 5175;; When generating pic, we need to load the symbol offset into a register.
5176;; So that the optimizer does not confuse this with a normal symbol load
5177;; we use an unspec. The offset will be loaded from a constant pool entry,
5178;; since that is the only type of relocation we can use.
5179
5180;; The rather odd constraints on the following are to force reload to leave
5181;; the insn alone, and to force the minipool generation pass to then move
5182;; the GOT symbol to memory.
849170fd 5183
8c4d8060 5184(define_insn "pic_load_addr_arm"
849170fd 5185 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5186 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 5187 "TARGET_ARM && flag_pic"
67336bcf 5188 "ldr%?\\t%0, %1"
a2cd141b 5189 [(set_attr "type" "load1")
8c4d8060 5190 (set (attr "pool_range") (const_int 4096))
5191 (set (attr "neg_pool_range") (const_int 4084))]
5192)
5193
25f905c2 5194(define_insn "pic_load_addr_thumb1"
8c4d8060 5195 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5196 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5197 "TARGET_THUMB1 && flag_pic"
8c4d8060 5198 "ldr\\t%0, %1"
a2cd141b 5199 [(set_attr "type" "load1")
8c4d8060 5200 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5201)
849170fd 5202
cffb2a26 5203(define_insn "pic_add_dot_plus_four"
15d5d060 5204 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5205 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5206 (const_int 4)
beef0fb5 5207 (match_operand 2 "" "")]
5208 UNSPEC_PIC_BASE))]
25f905c2 5209 "TARGET_THUMB1"
cffb2a26 5210 "*
6cdcb15c 5211 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5212 INTVAL (operands[2]));
cffb2a26 5213 return \"add\\t%0, %|pc\";
5214 "
5215 [(set_attr "length" "2")]
5216)
849170fd 5217
5218(define_insn "pic_add_dot_plus_eight"
15d5d060 5219 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5220 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5221 (const_int 8)
beef0fb5 5222 (match_operand 2 "" "")]
5223 UNSPEC_PIC_BASE))]
f655717d 5224 "TARGET_ARM"
c4034607 5225 "*
6cdcb15c 5226 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5227 INTVAL (operands[2]));
15d5d060 5228 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5229 "
0d66636f 5230 [(set_attr "predicable" "yes")]
cffb2a26 5231)
849170fd 5232
f655717d 5233(define_insn "tls_load_dot_plus_eight"
5234 [(set (match_operand:SI 0 "register_operand" "+r")
c0c1fba5 5235 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5236 (const_int 8)
beef0fb5 5237 (match_operand 2 "" "")]
5238 UNSPEC_PIC_BASE)))]
f655717d 5239 "TARGET_ARM"
5240 "*
6cdcb15c 5241 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5242 INTVAL (operands[2]));
f655717d 5243 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5244 "
5245 [(set_attr "predicable" "yes")]
5246)
5247
5248;; PIC references to local variables can generate pic_add_dot_plus_eight
5249;; followed by a load. These sequences can be crunched down to
5250;; tls_load_dot_plus_eight by a peephole.
5251
5252(define_peephole2
c0c1fba5 5253 [(set (match_operand:SI 0 "register_operand" "")
5254 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5255 (const_int 8)
5256 (match_operand 1 "" "")]
5257 UNSPEC_PIC_BASE))
f655717d 5258 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5259 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5260 [(set (match_dup 2)
5261 (mem:SI (unspec:SI [(match_dup 3)
5262 (const_int 8)
5263 (match_dup 1)]
5264 UNSPEC_PIC_BASE)))]
f655717d 5265 ""
5266)
5267
bac7fc85 5268(define_insn "pic_offset_arm"
5269 [(set (match_operand:SI 0 "register_operand" "=r")
5270 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5271 (unspec:SI [(match_operand:SI 2 "" "X")]
5272 UNSPEC_PIC_OFFSET))))]
5273 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5274 "ldr%?\\t%0, [%1,%2]"
5275 [(set_attr "type" "load1")]
5276)
5277
95373f08 5278(define_expand "builtin_setjmp_receiver"
5279 [(label_ref (match_operand 0 "" ""))]
5280 "flag_pic"
5281 "
5282{
b935b306 5283 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5284 register. */
2cb7d577 5285 if (arm_pic_register != INVALID_REGNUM)
5286 arm_load_pic_register (1UL << 3);
95373f08 5287 DONE;
5288}")
5289
9c08d1fa 5290;; If copying one reg to another we can set the condition codes according to
5291;; its value. Such a move is common after a return from subroutine and the
5292;; result is being tested against zero.
5293
f7fbdd4a 5294(define_insn "*movsi_compare0"
bd5b4116 5295 [(set (reg:CC CC_REGNUM)
cffb2a26 5296 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5297 (const_int 0)))
5298 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5299 (match_dup 1))]
25f905c2 5300 "TARGET_32BIT"
e2348bcb 5301 "@
40dbec34 5302 cmp%?\\t%0, #0
25f905c2 5303 sub%.\\t%0, %1, #0"
cffb2a26 5304 [(set_attr "conds" "set")]
5305)
b11cae9e 5306
b11cae9e 5307;; Subroutine to store a half word from a register into memory.
5308;; Operand 0 is the source register (HImode)
c8f69309 5309;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5310
9c08d1fa 5311;; In both this routine and the next, we must be careful not to spill
01cc3b75 5312;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5313;; can generate unrecognizable rtl.
5314
b11cae9e 5315(define_expand "storehi"
c8f69309 5316 [;; store the low byte
f082f1c4 5317 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5318 ;; extract the high byte
c8f69309 5319 (set (match_dup 2)
5320 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5321 ;; store the high byte
787f8210 5322 (set (match_dup 4) (match_dup 5))]
cffb2a26 5323 "TARGET_ARM"
b11cae9e 5324 "
215b30b3 5325 {
537ffcfc 5326 rtx op1 = operands[1];
5327 rtx addr = XEXP (op1, 0);
215b30b3 5328 enum rtx_code code = GET_CODE (addr);
5329
5330 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5331 || code == MINUS)
537ffcfc 5332 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5333
537ffcfc 5334 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5335 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5336 operands[3] = gen_lowpart (QImode, operands[0]);
5337 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5338 operands[2] = gen_reg_rtx (SImode);
5339 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5340 }"
5341)
b11cae9e 5342
c7597b5d 5343(define_expand "storehi_bigend"
f082f1c4 5344 [(set (match_dup 4) (match_dup 3))
c7597b5d 5345 (set (match_dup 2)
5346 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5347 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5348 "TARGET_ARM"
b11cae9e 5349 "
215b30b3 5350 {
537ffcfc 5351 rtx op1 = operands[1];
5352 rtx addr = XEXP (op1, 0);
215b30b3 5353 enum rtx_code code = GET_CODE (addr);
5354
5355 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5356 || code == MINUS)
537ffcfc 5357 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5358
537ffcfc 5359 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5360 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5361 operands[3] = gen_lowpart (QImode, operands[0]);
5362 operands[0] = gen_lowpart (SImode, operands[0]);
5363 operands[2] = gen_reg_rtx (SImode);
787f8210 5364 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5365 }"
5366)
c7597b5d 5367
5368;; Subroutine to store a half word integer constant into memory.
5369(define_expand "storeinthi"
f082f1c4 5370 [(set (match_operand 0 "" "")
787f8210 5371 (match_operand 1 "" ""))
9e8503e6 5372 (set (match_dup 3) (match_dup 2))]
cffb2a26 5373 "TARGET_ARM"
c7597b5d 5374 "
215b30b3 5375 {
5376 HOST_WIDE_INT value = INTVAL (operands[1]);
5377 rtx addr = XEXP (operands[0], 0);
537ffcfc 5378 rtx op0 = operands[0];
215b30b3 5379 enum rtx_code code = GET_CODE (addr);
c7597b5d 5380
215b30b3 5381 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5382 || code == MINUS)
537ffcfc 5383 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5384
215b30b3 5385 operands[1] = gen_reg_rtx (SImode);
5386 if (BYTES_BIG_ENDIAN)
5387 {
5388 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5389 if ((value & 255) == ((value >> 8) & 255))
5390 operands[2] = operands[1];
5391 else
5392 {
5393 operands[2] = gen_reg_rtx (SImode);
5394 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5395 }
5396 }
5397 else
5398 {
5399 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5400 if ((value & 255) == ((value >> 8) & 255))
5401 operands[2] = operands[1];
5402 else
5403 {
5404 operands[2] = gen_reg_rtx (SImode);
5405 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5406 }
5407 }
c7597b5d 5408
537ffcfc 5409 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5410 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5411 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5412 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5413 }"
5414)
b11cae9e 5415
f7fbdd4a 5416(define_expand "storehi_single_op"
5417 [(set (match_operand:HI 0 "memory_operand" "")
5418 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5419 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5420 "
215b30b3 5421 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5422 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5423 "
5424)
f7fbdd4a 5425
b11cae9e 5426(define_expand "movhi"
5427 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5428 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5429 "TARGET_EITHER"
b11cae9e 5430 "
cffb2a26 5431 if (TARGET_ARM)
b11cae9e 5432 {
e1ba4a27 5433 if (can_create_pseudo_p ())
cffb2a26 5434 {
5435 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5436 {
cffb2a26 5437 if (arm_arch4)
5438 {
5439 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5440 DONE;
5441 }
5442 if (GET_CODE (operands[1]) == CONST_INT)
5443 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5444 else
cffb2a26 5445 {
5446 if (GET_CODE (operands[1]) == MEM)
5447 operands[1] = force_reg (HImode, operands[1]);
5448 if (BYTES_BIG_ENDIAN)
5449 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5450 else
5451 emit_insn (gen_storehi (operands[1], operands[0]));
5452 }
5453 DONE;
b11cae9e 5454 }
cffb2a26 5455 /* Sign extend a constant, and keep it in an SImode reg. */
5456 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5457 {
cffb2a26 5458 rtx reg = gen_reg_rtx (SImode);
5459 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5460
5461 /* If the constant is already valid, leave it alone. */
215b30b3 5462 if (!const_ok_for_arm (val))
cffb2a26 5463 {
5464 /* If setting all the top bits will make the constant
5465 loadable in a single instruction, then set them.
5466 Otherwise, sign extend the number. */
5467
215b30b3 5468 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5469 val |= ~0xffff;
5470 else if (val & 0x8000)
5471 val |= ~0xffff;
5472 }
5473
5474 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5475 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5476 }
e1ba4a27 5477 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5478 && GET_CODE (operands[1]) == MEM)
5479 {
5480 rtx reg = gen_reg_rtx (SImode);
5481
5482 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5483 operands[1] = gen_lowpart (HImode, reg);
5484 }
215b30b3 5485 else if (!arm_arch4)
f7fbdd4a 5486 {
cffb2a26 5487 if (GET_CODE (operands[1]) == MEM)
5488 {
c1a66faf 5489 rtx base;
5490 rtx offset = const0_rtx;
5491 rtx reg = gen_reg_rtx (SImode);
5492
5493 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5494 || (GET_CODE (base) == PLUS
5495 && (GET_CODE (offset = XEXP (base, 1))
5496 == CONST_INT)
5497 && ((INTVAL(offset) & 1) != 1)
5498 && GET_CODE (base = XEXP (base, 0)) == REG))
5499 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5500 {
8deb3959 5501 rtx new_rtx;
c1a66faf 5502
8deb3959 5503 new_rtx = widen_memory_access (operands[1], SImode,
5504 ((INTVAL (offset) & ~3)
5505 - INTVAL (offset)));
5506 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5507 if (((INTVAL (offset) & 2) != 0)
5508 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5509 {
5510 rtx reg2 = gen_reg_rtx (SImode);
5511
5512 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5513 reg = reg2;
5514 }
206ee9a2 5515 }
c1a66faf 5516 else
5517 emit_insn (gen_movhi_bytes (reg, operands[1]));
5518
5519 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5520 }
5521 }
5522 }
674a8f0b 5523 /* Handle loading a large integer during reload. */
cffb2a26 5524 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5525 && !const_ok_for_arm (INTVAL (operands[1]))
5526 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5527 {
5528 /* Writing a constant to memory needs a scratch, which should
5529 be handled with SECONDARY_RELOADs. */
ed29c566 5530 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5531
5532 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5533 emit_insn (gen_movsi (operands[0], operands[1]));
5534 DONE;
5535 }
5536 }
25f905c2 5537 else if (TARGET_THUMB2)
5538 {
5539 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5540 if (can_create_pseudo_p ())
25f905c2 5541 {
5542 if (GET_CODE (operands[0]) != REG)
5543 operands[1] = force_reg (HImode, operands[1]);
5544 /* Zero extend a constant, and keep it in an SImode reg. */
5545 else if (GET_CODE (operands[1]) == CONST_INT)
5546 {
5547 rtx reg = gen_reg_rtx (SImode);
5548 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5549
5550 emit_insn (gen_movsi (reg, GEN_INT (val)));
5551 operands[1] = gen_lowpart (HImode, reg);
5552 }
5553 }
5554 }
5555 else /* TARGET_THUMB1 */
cffb2a26 5556 {
e1ba4a27 5557 if (can_create_pseudo_p ())
cffb2a26 5558 {
6cffc037 5559 if (GET_CODE (operands[1]) == CONST_INT)
5560 {
5561 rtx reg = gen_reg_rtx (SImode);
5562
5563 emit_insn (gen_movsi (reg, operands[1]));
5564 operands[1] = gen_lowpart (HImode, reg);
5565 }
cffb2a26 5566
5567 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5568 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5569 virtual register (also rejected as illegitimate for HImode/QImode)
5570 relative address. */
cffb2a26 5571 /* ??? This should perhaps be fixed elsewhere, for instance, in
5572 fixup_stack_1, by checking for other kinds of invalid addresses,
5573 e.g. a bare reference to a virtual register. This may confuse the
5574 alpha though, which must handle this case differently. */
5575 if (GET_CODE (operands[0]) == MEM
215b30b3 5576 && !memory_address_p (GET_MODE (operands[0]),
5577 XEXP (operands[0], 0)))
537ffcfc 5578 operands[0]
5579 = replace_equiv_address (operands[0],
5580 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5581
5582 if (GET_CODE (operands[1]) == MEM
215b30b3 5583 && !memory_address_p (GET_MODE (operands[1]),
5584 XEXP (operands[1], 0)))
537ffcfc 5585 operands[1]
5586 = replace_equiv_address (operands[1],
5587 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5588
5589 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5590 {
5591 rtx reg = gen_reg_rtx (SImode);
5592
5593 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5594 operands[1] = gen_lowpart (HImode, reg);
5595 }
5596
5597 if (GET_CODE (operands[0]) == MEM)
5598 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5599 }
cffb2a26 5600 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5601 && !satisfies_constraint_I (operands[1]))
cffb2a26 5602 {
6cffc037 5603 /* Handle loading a large integer during reload. */
5604
cffb2a26 5605 /* Writing a constant to memory needs a scratch, which should
5606 be handled with SECONDARY_RELOADs. */
ed29c566 5607 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5608
1a83b3ff 5609 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5610 emit_insn (gen_movsi (operands[0], operands[1]));
5611 DONE;
5612 }
b11cae9e 5613 }
cffb2a26 5614 "
5615)
5616
25f905c2 5617(define_insn "*thumb1_movhi_insn"
a941568e 5618 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5619 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5620 "TARGET_THUMB1
cffb2a26 5621 && ( register_operand (operands[0], HImode)
5622 || register_operand (operands[1], HImode))"
5623 "*
5624 switch (which_alternative)
d79300ac 5625 {
cffb2a26 5626 case 0: return \"add %0, %1, #0\";
5627 case 2: return \"strh %1, %0\";
5628 case 3: return \"mov %0, %1\";
5629 case 4: return \"mov %0, %1\";
5630 case 5: return \"mov %0, %1\";
ed29c566 5631 default: gcc_unreachable ();
cffb2a26 5632 case 1:
5633 /* The stack pointer can end up being taken as an index register.
5634 Catch this case here and deal with it. */
5635 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5636 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5637 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5638 {
5639 rtx ops[2];
5640 ops[0] = operands[0];
5641 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5642
5643 output_asm_insn (\"mov %0, %1\", ops);
5644
5645 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5646
5647 }
5648 return \"ldrh %0, %1\";
5649 }"
5650 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 5651 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 5652)
d79300ac 5653
b11cae9e 5654
25f7a26e 5655(define_expand "movhi_bytes"
eab14235 5656 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5657 (set (match_dup 3)
eab14235 5658 (zero_extend:SI (match_dup 6)))
25f7a26e 5659 (set (match_operand:SI 0 "" "")
5660 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5661 "TARGET_ARM"
25f7a26e 5662 "
215b30b3 5663 {
5664 rtx mem1, mem2;
5665 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5666
788fcce0 5667 mem1 = change_address (operands[1], QImode, addr);
5668 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5669 operands[0] = gen_lowpart (SImode, operands[0]);
5670 operands[1] = mem1;
5671 operands[2] = gen_reg_rtx (SImode);
5672 operands[3] = gen_reg_rtx (SImode);
5673 operands[6] = mem2;
25f7a26e 5674
215b30b3 5675 if (BYTES_BIG_ENDIAN)
5676 {
5677 operands[4] = operands[2];
5678 operands[5] = operands[3];
5679 }
5680 else
5681 {
5682 operands[4] = operands[3];
5683 operands[5] = operands[2];
5684 }
5685 }"
5686)
25f7a26e 5687
c7597b5d 5688(define_expand "movhi_bigend"
5689 [(set (match_dup 2)
5690 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5691 (const_int 16)))
5692 (set (match_dup 3)
5693 (ashiftrt:SI (match_dup 2) (const_int 16)))
5694 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5695 (match_dup 4))]
cffb2a26 5696 "TARGET_ARM"
c7597b5d 5697 "
5698 operands[2] = gen_reg_rtx (SImode);
5699 operands[3] = gen_reg_rtx (SImode);
787f8210 5700 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5701 "
5702)
b11cae9e 5703
a2f10574 5704;; Pattern to recognize insn generated default case above
f7fbdd4a 5705(define_insn "*movhi_insn_arch4"
cffb2a26 5706 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5707 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5708 "TARGET_ARM
5709 && arm_arch4
f7fbdd4a 5710 && (GET_CODE (operands[1]) != CONST_INT
5711 || const_ok_for_arm (INTVAL (operands[1]))
5712 || const_ok_for_arm (~INTVAL (operands[1])))"
5713 "@
5714 mov%?\\t%0, %1\\t%@ movhi
5715 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5716 str%(h%)\\t%1, %0\\t%@ movhi
5717 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5718 [(set_attr "type" "*,*,store1,load1")
0d66636f 5719 (set_attr "predicable" "yes")
cffb2a26 5720 (set_attr "pool_range" "*,*,*,256")
5721 (set_attr "neg_pool_range" "*,*,*,244")]
5722)
f7fbdd4a 5723
f7fbdd4a 5724(define_insn "*movhi_bytes"
25f7a26e 5725 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5726 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5727 "TARGET_ARM"
25f7a26e 5728 "@
5729 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5730 mvn%?\\t%0, #%B1\\t%@ movhi"
5731 [(set_attr "predicable" "yes")]
5732)
25f7a26e 5733
f90b51f1 5734(define_expand "thumb_movhi_clobber"
5735 [(set (match_operand:HI 0 "memory_operand" "")
5736 (match_operand:HI 1 "register_operand" ""))
5737 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5738 "TARGET_THUMB1"
f90b51f1 5739 "
5740 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5741 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5742 {
5743 emit_insn (gen_movhi (operands[0], operands[1]));
5744 DONE;
5745 }
5746 /* XXX Fixme, need to handle other cases here as well. */
5747 gcc_unreachable ();
5748 "
cffb2a26 5749)
5750
bc5c7e08 5751;; We use a DImode scratch because we may occasionally need an additional
5752;; temporary if the address isn't offsettable -- push_reload doesn't seem
5753;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5754(define_expand "reload_outhi"
cffb2a26 5755 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5756 (match_operand:HI 1 "s_register_operand" "r")
5757 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5758 "TARGET_EITHER"
5759 "if (TARGET_ARM)
5760 arm_reload_out_hi (operands);
5761 else
5762 thumb_reload_out_hi (operands);
d3373b54 5763 DONE;
cffb2a26 5764 "
5765)
d3373b54 5766
25f7a26e 5767(define_expand "reload_inhi"
5768 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5769 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5770 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5771 "TARGET_EITHER"
25f7a26e 5772 "
cffb2a26 5773 if (TARGET_ARM)
5774 arm_reload_in_hi (operands);
5775 else
5776 thumb_reload_out_hi (operands);
25f7a26e 5777 DONE;
5778")
5779
9c08d1fa 5780(define_expand "movqi"
5781 [(set (match_operand:QI 0 "general_operand" "")
5782 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5783 "TARGET_EITHER"
9c08d1fa 5784 "
6cffc037 5785 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5786
e1ba4a27 5787 if (can_create_pseudo_p ())
cffb2a26 5788 {
6cffc037 5789 if (GET_CODE (operands[1]) == CONST_INT)
5790 {
5791 rtx reg = gen_reg_rtx (SImode);
5792
5793 emit_insn (gen_movsi (reg, operands[1]));
5794 operands[1] = gen_lowpart (QImode, reg);
5795 }
cffb2a26 5796
6cffc037 5797 if (TARGET_THUMB)
5798 {
cffb2a26 5799 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5800 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5801 virtual register (also rejected as illegitimate for HImode/QImode)
5802 relative address. */
cffb2a26 5803 /* ??? This should perhaps be fixed elsewhere, for instance, in
5804 fixup_stack_1, by checking for other kinds of invalid addresses,
5805 e.g. a bare reference to a virtual register. This may confuse the
5806 alpha though, which must handle this case differently. */
5807 if (GET_CODE (operands[0]) == MEM
215b30b3 5808 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5809 XEXP (operands[0], 0)))
537ffcfc 5810 operands[0]
5811 = replace_equiv_address (operands[0],
5812 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5813 if (GET_CODE (operands[1]) == MEM
5814 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5815 XEXP (operands[1], 0)))
537ffcfc 5816 operands[1]
5817 = replace_equiv_address (operands[1],
5818 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5819 }
5820
5821 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5822 {
5823 rtx reg = gen_reg_rtx (SImode);
5824
5825 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5826 operands[1] = gen_lowpart (QImode, reg);
5827 }
5828
5829 if (GET_CODE (operands[0]) == MEM)
5830 operands[1] = force_reg (QImode, operands[1]);
5831 }
5832 else if (TARGET_THUMB
5833 && GET_CODE (operands[1]) == CONST_INT
234f6557 5834 && !satisfies_constraint_I (operands[1]))
6cffc037 5835 {
674a8f0b 5836 /* Handle loading a large integer during reload. */
cffb2a26 5837
6cffc037 5838 /* Writing a constant to memory needs a scratch, which should
5839 be handled with SECONDARY_RELOADs. */
5840 gcc_assert (GET_CODE (operands[0]) == REG);
5841
5842 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5843 emit_insn (gen_movsi (operands[0], operands[1]));
5844 DONE;
cffb2a26 5845 }
5846 "
5847)
b11cae9e 5848
9c08d1fa 5849
cffb2a26 5850(define_insn "*arm_movqi_insn"
5851 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5852 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5853 "TARGET_32BIT
cffb2a26 5854 && ( register_operand (operands[0], QImode)
5855 || register_operand (operands[1], QImode))"
5565501b 5856 "@
5857 mov%?\\t%0, %1
5858 mvn%?\\t%0, #%B1
25f905c2 5859 ldr%(b%)\\t%0, %1
5860 str%(b%)\\t%1, %0"
a2cd141b 5861 [(set_attr "type" "*,*,load1,store1")
0d66636f 5862 (set_attr "predicable" "yes")]
cffb2a26 5863)
5864
25f905c2 5865(define_insn "*thumb1_movqi_insn"
cffb2a26 5866 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5867 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5868 "TARGET_THUMB1
cffb2a26 5869 && ( register_operand (operands[0], QImode)
5870 || register_operand (operands[1], QImode))"
5871 "@
5872 add\\t%0, %1, #0
5873 ldrb\\t%0, %1
5874 strb\\t%1, %0
5875 mov\\t%0, %1
5876 mov\\t%0, %1
5877 mov\\t%0, %1"
5878 [(set_attr "length" "2")
a2cd141b 5879 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5880 (set_attr "pool_range" "*,32,*,*,*,*")]
5881)
b11cae9e 5882
9b8516be 5883;; HFmode moves
5884(define_expand "movhf"
5885 [(set (match_operand:HF 0 "general_operand" "")
5886 (match_operand:HF 1 "general_operand" ""))]
5887 "TARGET_EITHER"
5888 "
5889 if (TARGET_32BIT)
5890 {
5891 if (GET_CODE (operands[0]) == MEM)
5892 operands[1] = force_reg (HFmode, operands[1]);
5893 }
5894 else /* TARGET_THUMB1 */
5895 {
5896 if (can_create_pseudo_p ())
5897 {
5898 if (GET_CODE (operands[0]) != REG)
5899 operands[1] = force_reg (HFmode, operands[1]);
5900 }
5901 }
5902 "
5903)
5904
5905(define_insn "*arm32_movhf"
5906 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5907 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
5908 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_NEON_FP16)
5909 && ( s_register_operand (operands[0], HFmode)
5910 || s_register_operand (operands[1], HFmode))"
5911 "*
5912 switch (which_alternative)
5913 {
5914 case 0: /* ARM register from memory */
5915 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5916 case 1: /* memory from ARM register */
5917 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5918 case 2: /* ARM register from ARM register */
5919 return \"mov%?\\t%0, %1\\t%@ __fp16\";
5920 case 3: /* ARM register from constant */
5921 {
5922 REAL_VALUE_TYPE r;
5923 long bits;
5924 rtx ops[4];
5925
5926 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
5927 bits = real_to_target (NULL, &r, HFmode);
5928 ops[0] = operands[0];
5929 ops[1] = GEN_INT (bits);
5930 ops[2] = GEN_INT (bits & 0xff00);
5931 ops[3] = GEN_INT (bits & 0x00ff);
5932
5933 if (arm_arch_thumb2)
5934 output_asm_insn (\"movw%?\\t%0, %1\", ops);
5935 else
5936 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
5937 return \"\";
5938 }
5939 default:
5940 gcc_unreachable ();
5941 }
5942 "
5943 [(set_attr "conds" "unconditional")
5944 (set_attr "type" "load1,store1,*,*")
5945 (set_attr "length" "4,4,4,8")
5946 (set_attr "predicable" "yes")
5947 ]
5948)
5949
5950(define_insn "*thumb1_movhf"
5951 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
5952 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
5953 "TARGET_THUMB1
5954 && ( s_register_operand (operands[0], HFmode)
5955 || s_register_operand (operands[1], HFmode))"
5956 "*
5957 switch (which_alternative)
5958 {
5959 case 1:
5960 {
5961 rtx addr;
5962 gcc_assert (GET_CODE(operands[1]) == MEM);
5963 addr = XEXP (operands[1], 0);
5964 if (GET_CODE (addr) == LABEL_REF
5965 || (GET_CODE (addr) == CONST
5966 && GET_CODE (XEXP (addr, 0)) == PLUS
5967 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
5968 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
5969 {
5970 /* Constant pool entry. */
5971 return \"ldr\\t%0, %1\";
5972 }
5973 return \"ldrh\\t%0, %1\";
5974 }
5975 case 2: return \"strh\\t%1, %0\";
5976 default: return \"mov\\t%0, %1\";
5977 }
5978 "
5979 [(set_attr "length" "2")
5980 (set_attr "type" "*,load1,store1,*,*")
5981 (set_attr "pool_range" "*,1020,*,*,*")]
5982)
5983
87b22bf7 5984(define_expand "movsf"
5985 [(set (match_operand:SF 0 "general_operand" "")
5986 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5987 "TARGET_EITHER"
87b22bf7 5988 "
25f905c2 5989 if (TARGET_32BIT)
cffb2a26 5990 {
5991 if (GET_CODE (operands[0]) == MEM)
5992 operands[1] = force_reg (SFmode, operands[1]);
5993 }
25f905c2 5994 else /* TARGET_THUMB1 */
cffb2a26 5995 {
e1ba4a27 5996 if (can_create_pseudo_p ())
cffb2a26 5997 {
5998 if (GET_CODE (operands[0]) != REG)
5999 operands[1] = force_reg (SFmode, operands[1]);
6000 }
6001 }
6002 "
6003)
6004
03d440a6 6005;; Transform a floating-point move of a constant into a core register into
6006;; an SImode operation.
cffb2a26 6007(define_split
03d440a6 6008 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6009 (match_operand:SF 1 "immediate_operand" ""))]
25f905c2 6010 "TARGET_32BIT
cffb2a26 6011 && reload_completed
6012 && GET_CODE (operands[1]) == CONST_DOUBLE"
6013 [(set (match_dup 2) (match_dup 3))]
6014 "
6015 operands[2] = gen_lowpart (SImode, operands[0]);
6016 operands[3] = gen_lowpart (SImode, operands[1]);
6017 if (operands[2] == 0 || operands[3] == 0)
6018 FAIL;
215b30b3 6019 "
6020)
87b22bf7 6021
cffb2a26 6022(define_insn "*arm_movsf_soft_insn"
6023 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6024 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6025 "TARGET_ARM
6026 && TARGET_SOFT_FLOAT
215b30b3 6027 && (GET_CODE (operands[0]) != MEM
6028 || register_operand (operands[1], SFmode))"
9a1112d7 6029 "@
6030 mov%?\\t%0, %1
6031 ldr%?\\t%0, %1\\t%@ float
6032 str%?\\t%1, %0\\t%@ float"
cffb2a26 6033 [(set_attr "length" "4,4,4")
0d66636f 6034 (set_attr "predicable" "yes")
a2cd141b 6035 (set_attr "type" "*,load1,store1")
cffb2a26 6036 (set_attr "pool_range" "*,4096,*")
6037 (set_attr "neg_pool_range" "*,4084,*")]
6038)
6039
6040;;; ??? This should have alternatives for constants.
25f905c2 6041(define_insn "*thumb1_movsf_insn"
215b30b3 6042 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6043 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6044 "TARGET_THUMB1
cffb2a26 6045 && ( register_operand (operands[0], SFmode)
6046 || register_operand (operands[1], SFmode))"
6047 "@
6048 add\\t%0, %1, #0
6049 ldmia\\t%1, {%0}
6050 stmia\\t%0, {%1}
6051 ldr\\t%0, %1
6052 str\\t%1, %0
6053 mov\\t%0, %1
6054 mov\\t%0, %1"
6055 [(set_attr "length" "2")
a2cd141b 6056 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 6057 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
6058)
9a1112d7 6059
9c08d1fa 6060(define_expand "movdf"
87b22bf7 6061 [(set (match_operand:DF 0 "general_operand" "")
6062 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6063 "TARGET_EITHER"
9c08d1fa 6064 "
25f905c2 6065 if (TARGET_32BIT)
cffb2a26 6066 {
6067 if (GET_CODE (operands[0]) == MEM)
6068 operands[1] = force_reg (DFmode, operands[1]);
6069 }
6070 else /* TARGET_THUMB */
6071 {
e1ba4a27 6072 if (can_create_pseudo_p ())
cffb2a26 6073 {
6074 if (GET_CODE (operands[0]) != REG)
6075 operands[1] = force_reg (DFmode, operands[1]);
6076 }
6077 }
6078 "
6079)
b11cae9e 6080
9c08d1fa 6081;; Reloading a df mode value stored in integer regs to memory can require a
6082;; scratch reg.
6083(define_expand "reload_outdf"
cffb2a26 6084 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6085 (match_operand:DF 1 "s_register_operand" "r")
6086 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6087 "TARGET_32BIT"
87b22bf7 6088 "
215b30b3 6089 {
6090 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6091
215b30b3 6092 if (code == REG)
6093 operands[2] = XEXP (operands[0], 0);
6094 else if (code == POST_INC || code == PRE_DEC)
6095 {
6096 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6097 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6098 emit_insn (gen_movdi (operands[0], operands[1]));
6099 DONE;
6100 }
6101 else if (code == PRE_INC)
6102 {
6103 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6104
215b30b3 6105 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6106 operands[2] = reg;
6107 }
6108 else if (code == POST_DEC)
6109 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6110 else
6111 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6112 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6113
788fcce0 6114 emit_insn (gen_rtx_SET (VOIDmode,
6115 replace_equiv_address (operands[0], operands[2]),
215b30b3 6116 operands[1]));
f7fbdd4a 6117
215b30b3 6118 if (code == POST_DEC)
6119 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6120
6121 DONE;
6122 }"
6123)
9c08d1fa 6124
9a1112d7 6125(define_insn "*movdf_soft_insn"
359a6e9f 6126 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6127 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 6128 "TARGET_ARM && TARGET_SOFT_FLOAT
b2778788 6129 && ( register_operand (operands[0], DFmode)
6130 || register_operand (operands[1], DFmode))"
d51f92df 6131 "*
6132 switch (which_alternative)
6133 {
6134 case 0:
6135 case 1:
6136 case 2:
6137 return \"#\";
6138 default:
6139 return output_move_double (operands);
6140 }
6141 "
359a6e9f 6142 [(set_attr "length" "8,12,16,8,8")
6143 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 6144 (set_attr "pool_range" "1020")
6145 (set_attr "neg_pool_range" "1008")]
cffb2a26 6146)
6147
6148;;; ??? This should have alternatives for constants.
6149;;; ??? This was originally identical to the movdi_insn pattern.
6150;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6151;;; thumb_reorg with a memory reference.
6152(define_insn "*thumb_movdf_insn"
215b30b3 6153 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6154 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6155 "TARGET_THUMB1
cffb2a26 6156 && ( register_operand (operands[0], DFmode)
6157 || register_operand (operands[1], DFmode))"
6158 "*
6159 switch (which_alternative)
6160 {
6161 default:
6162 case 0:
6163 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6164 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6165 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6166 case 1:
6167 return \"ldmia\\t%1, {%0, %H0}\";
6168 case 2:
6169 return \"stmia\\t%0, {%1, %H1}\";
6170 case 3:
6171 return thumb_load_double_from_address (operands);
6172 case 4:
1a83b3ff 6173 operands[2] = gen_rtx_MEM (SImode,
6174 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6175 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6176 return \"\";
6177 case 5:
6178 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6179 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6180 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6181 }
6182 "
6183 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6184 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 6185 (set_attr "pool_range" "*,*,*,1020,*,*")]
6186)
755eb2b4 6187
ccd90aaa 6188(define_expand "movxf"
6189 [(set (match_operand:XF 0 "general_operand" "")
6190 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6191 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6192 "
6193 if (GET_CODE (operands[0]) == MEM)
6194 operands[1] = force_reg (XFmode, operands[1]);
6195 "
6196)
6197
b11cae9e 6198\f
b11cae9e 6199
9c08d1fa 6200;; load- and store-multiple insns
6201;; The arm can load/store any set of registers, provided that they are in
6202;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 6203
9c08d1fa 6204(define_expand "load_multiple"
6205 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6206 (match_operand:SI 1 "" ""))
6207 (use (match_operand:SI 2 "" ""))])]
25f905c2 6208 "TARGET_32BIT"
9580c25f 6209{
6210 HOST_WIDE_INT offset = 0;
6211
bd5b4116 6212 /* Support only fixed point registers. */
9c08d1fa 6213 if (GET_CODE (operands[2]) != CONST_INT
6214 || INTVAL (operands[2]) > 14
6215 || INTVAL (operands[2]) < 2
6216 || GET_CODE (operands[1]) != MEM
6217 || GET_CODE (operands[0]) != REG
bd5b4116 6218 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6219 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6220 FAIL;
6221
6222 operands[3]
f082f1c4 6223 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6224 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 6225 TRUE, FALSE, operands[1], &offset);
6226})
b11cae9e 6227
9c08d1fa 6228;; Load multiple with write-back
6229
2162064c 6230(define_insn "*ldmsi_postinc4"
9c08d1fa 6231 [(match_parallel 0 "load_multiple_operation"
13e9316a 6232 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6233 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6234 (const_int 16)))
6235 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6236 (mem:SI (match_dup 2)))
a0a72ac3 6237 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 6238 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6239 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6240 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6241 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6242 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6243 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6244 "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
a2cd141b 6245 [(set_attr "type" "load4")
2162064c 6246 (set_attr "predicable" "yes")]
6247)
b11cae9e 6248
25f905c2 6249(define_insn "*ldmsi_postinc4_thumb1"
ccd90aaa 6250 [(match_parallel 0 "load_multiple_operation"
6251 [(set (match_operand:SI 1 "s_register_operand" "=l")
6252 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6253 (const_int 16)))
6254 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6255 (mem:SI (match_dup 2)))
6256 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6257 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6258 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6259 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6260 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6261 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6262 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6263 "ldmia\\t%1!, {%3, %4, %5, %6}"
6264 [(set_attr "type" "load4")]
6265)
6266
2162064c 6267(define_insn "*ldmsi_postinc3"
6268 [(match_parallel 0 "load_multiple_operation"
13e9316a 6269 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6270 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6271 (const_int 12)))
6272 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6273 (mem:SI (match_dup 2)))
6274 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6275 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6276 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6277 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
25f905c2 6278 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6279 "ldm%(ia%)\\t%1!, {%3, %4, %5}"
a2cd141b 6280 [(set_attr "type" "load3")
2162064c 6281 (set_attr "predicable" "yes")]
6282)
b11cae9e 6283
2162064c 6284(define_insn "*ldmsi_postinc2"
6285 [(match_parallel 0 "load_multiple_operation"
13e9316a 6286 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6287 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6288 (const_int 8)))
6289 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6290 (mem:SI (match_dup 2)))
6291 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6292 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
25f905c2 6293 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6294 "ldm%(ia%)\\t%1!, {%3, %4}"
a2cd141b 6295 [(set_attr "type" "load2")
0d66636f 6296 (set_attr "predicable" "yes")]
6297)
b11cae9e 6298
9c08d1fa 6299;; Ordinary load multiple
b11cae9e 6300
2162064c 6301(define_insn "*ldmsi4"
9c08d1fa 6302 [(match_parallel 0 "load_multiple_operation"
2162064c 6303 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6304 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6305 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6306 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6307 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6308 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6309 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6310 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
25f905c2 6311 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6312 "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
a2cd141b 6313 [(set_attr "type" "load4")
2162064c 6314 (set_attr "predicable" "yes")]
6315)
9c08d1fa 6316
2162064c 6317(define_insn "*ldmsi3"
6318 [(match_parallel 0 "load_multiple_operation"
6319 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6320 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6321 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6322 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6323 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6324 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
25f905c2 6325 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6326 "ldm%(ia%)\\t%1, {%2, %3, %4}"
a2cd141b 6327 [(set_attr "type" "load3")
2162064c 6328 (set_attr "predicable" "yes")]
6329)
9c08d1fa 6330
2162064c 6331(define_insn "*ldmsi2"
6332 [(match_parallel 0 "load_multiple_operation"
6333 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6334 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6335 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6336 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
25f905c2 6337 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6338 "ldm%(ia%)\\t%1, {%2, %3}"
a2cd141b 6339 [(set_attr "type" "load2")
0d66636f 6340 (set_attr "predicable" "yes")]
6341)
9c08d1fa 6342
6343(define_expand "store_multiple"
6344 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6345 (match_operand:SI 1 "" ""))
6346 (use (match_operand:SI 2 "" ""))])]
25f905c2 6347 "TARGET_32BIT"
9580c25f 6348{
6349 HOST_WIDE_INT offset = 0;
6350
674a8f0b 6351 /* Support only fixed point registers. */
9c08d1fa 6352 if (GET_CODE (operands[2]) != CONST_INT
6353 || INTVAL (operands[2]) > 14
6354 || INTVAL (operands[2]) < 2
6355 || GET_CODE (operands[1]) != REG
6356 || GET_CODE (operands[0]) != MEM
bd5b4116 6357 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6358 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6359 FAIL;
6360
6361 operands[3]
f082f1c4 6362 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6363 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 6364 TRUE, FALSE, operands[0], &offset);
6365})
b11cae9e 6366
9c08d1fa 6367;; Store multiple with write-back
6368
2162064c 6369(define_insn "*stmsi_postinc4"
9c08d1fa 6370 [(match_parallel 0 "store_multiple_operation"
13e9316a 6371 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6372 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6373 (const_int 16)))
a0a72ac3 6374 (set (mem:SI (match_dup 2))
2162064c 6375 (match_operand:SI 3 "arm_hard_register_operand" ""))
6376 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6377 (match_operand:SI 4 "arm_hard_register_operand" ""))
6378 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6379 (match_operand:SI 5 "arm_hard_register_operand" ""))
6380 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6381 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6382 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6383 "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
2162064c 6384 [(set_attr "predicable" "yes")
6385 (set_attr "type" "store4")]
6386)
b11cae9e 6387
25f905c2 6388(define_insn "*stmsi_postinc4_thumb1"
ccd90aaa 6389 [(match_parallel 0 "store_multiple_operation"
6390 [(set (match_operand:SI 1 "s_register_operand" "=l")
6391 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6392 (const_int 16)))
6393 (set (mem:SI (match_dup 2))
6394 (match_operand:SI 3 "arm_hard_register_operand" ""))
6395 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6396 (match_operand:SI 4 "arm_hard_register_operand" ""))
6397 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6398 (match_operand:SI 5 "arm_hard_register_operand" ""))
6399 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6400 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6401 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6402 "stmia\\t%1!, {%3, %4, %5, %6}"
6403 [(set_attr "type" "store4")]
6404)
6405
2162064c 6406(define_insn "*stmsi_postinc3"
6407 [(match_parallel 0 "store_multiple_operation"
13e9316a 6408 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6409 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6410 (const_int 12)))
6411 (set (mem:SI (match_dup 2))
6412 (match_operand:SI 3 "arm_hard_register_operand" ""))
6413 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6414 (match_operand:SI 4 "arm_hard_register_operand" ""))
6415 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6416 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6417 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6418 "stm%(ia%)\\t%1!, {%3, %4, %5}"
2162064c 6419 [(set_attr "predicable" "yes")
6420 (set_attr "type" "store3")]
6421)
9c08d1fa 6422
2162064c 6423(define_insn "*stmsi_postinc2"
6424 [(match_parallel 0 "store_multiple_operation"
13e9316a 6425 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6426 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6427 (const_int 8)))
6428 (set (mem:SI (match_dup 2))
6429 (match_operand:SI 3 "arm_hard_register_operand" ""))
6430 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6431 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6432 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6433 "stm%(ia%)\\t%1!, {%3, %4}"
0d66636f 6434 [(set_attr "predicable" "yes")
2162064c 6435 (set_attr "type" "store2")]
cffb2a26 6436)
9c08d1fa 6437
6438;; Ordinary store multiple
6439
2162064c 6440(define_insn "*stmsi4"
9c08d1fa 6441 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 6442 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 6443 (match_operand:SI 2 "arm_hard_register_operand" ""))
6444 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6445 (match_operand:SI 3 "arm_hard_register_operand" ""))
6446 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6447 (match_operand:SI 4 "arm_hard_register_operand" ""))
6448 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6449 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6450 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6451 "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
2162064c 6452 [(set_attr "predicable" "yes")
6453 (set_attr "type" "store4")]
6454)
9c08d1fa 6455
2162064c 6456(define_insn "*stmsi3"
6457 [(match_parallel 0 "store_multiple_operation"
6458 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6459 (match_operand:SI 2 "arm_hard_register_operand" ""))
6460 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6461 (match_operand:SI 3 "arm_hard_register_operand" ""))
6462 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6463 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6464 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6465 "stm%(ia%)\\t%1, {%2, %3, %4}"
2162064c 6466 [(set_attr "predicable" "yes")
6467 (set_attr "type" "store3")]
6468)
9c08d1fa 6469
2162064c 6470(define_insn "*stmsi2"
6471 [(match_parallel 0 "store_multiple_operation"
6472 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6473 (match_operand:SI 2 "arm_hard_register_operand" ""))
6474 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6475 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
25f905c2 6476 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6477 "stm%(ia%)\\t%1, {%2, %3}"
0d66636f 6478 [(set_attr "predicable" "yes")
2162064c 6479 (set_attr "type" "store2")]
cffb2a26 6480)
9c08d1fa 6481
6482;; Move a block of memory if it is word aligned and MORE than 2 words long.
6483;; We could let this apply for blocks of less than this, but it clobbers so
6484;; many registers that there is then probably a better way.
6485
008c057d 6486(define_expand "movmemqi"
34191dd1 6487 [(match_operand:BLK 0 "general_operand" "")
6488 (match_operand:BLK 1 "general_operand" "")
6489 (match_operand:SI 2 "const_int_operand" "")
6490 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6491 "TARGET_EITHER"
9c08d1fa 6492 "
25f905c2 6493 if (TARGET_32BIT)
cffb2a26 6494 {
008c057d 6495 if (arm_gen_movmemqi (operands))
cffb2a26 6496 DONE;
6497 FAIL;
6498 }
25f905c2 6499 else /* TARGET_THUMB1 */
cffb2a26 6500 {
6501 if ( INTVAL (operands[3]) != 4
6502 || INTVAL (operands[2]) > 48)
6503 FAIL;
6504
008c057d 6505 thumb_expand_movmemqi (operands);
cffb2a26 6506 DONE;
6507 }
6508 "
6509)
6510
2162064c 6511;; Thumb block-move insns
cffb2a26 6512
6513(define_insn "movmem12b"
960f3acf 6514 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6515 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6516 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6517 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6518 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6519 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6520 (set (match_operand:SI 0 "register_operand" "=l")
6521 (plus:SI (match_dup 2) (const_int 12)))
6522 (set (match_operand:SI 1 "register_operand" "=l")
6523 (plus:SI (match_dup 3) (const_int 12)))
6524 (clobber (match_scratch:SI 4 "=&l"))
6525 (clobber (match_scratch:SI 5 "=&l"))
6526 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6527 "TARGET_THUMB1"
cffb2a26 6528 "* return thumb_output_move_mem_multiple (3, operands);"
6529 [(set_attr "length" "4")
215b30b3 6530 ; This isn't entirely accurate... It loads as well, but in terms of
6531 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6532 (set_attr "type" "store3")]
6533)
6534
6535(define_insn "movmem8b"
960f3acf 6536 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6537 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6538 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6539 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6540 (set (match_operand:SI 0 "register_operand" "=l")
6541 (plus:SI (match_dup 2) (const_int 8)))
6542 (set (match_operand:SI 1 "register_operand" "=l")
6543 (plus:SI (match_dup 3) (const_int 8)))
6544 (clobber (match_scratch:SI 4 "=&l"))
6545 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6546 "TARGET_THUMB1"
cffb2a26 6547 "* return thumb_output_move_mem_multiple (2, operands);"
6548 [(set_attr "length" "4")
215b30b3 6549 ; This isn't entirely accurate... It loads as well, but in terms of
6550 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6551 (set_attr "type" "store2")]
6552)
6553
9c08d1fa 6554\f
b11cae9e 6555
341940e8 6556;; Compare & branch insns
8d232dc7 6557;; The range calculations are based as follows:
341940e8 6558;; For forward branches, the address calculation returns the address of
6559;; the next instruction. This is 2 beyond the branch instruction.
6560;; For backward branches, the address calculation returns the address of
6561;; the first instruction in this pattern (cmp). This is 2 before the branch
6562;; instruction for the shortest sequence, and 4 before the branch instruction
6563;; if we have to jump around an unconditional branch.
6564;; To the basic branch range the PC offset must be added (this is +4).
6565;; So for forward branches we have
6566;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6567;; And for backward branches we have
6568;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6569;;
6570;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6571;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6572
aeac46d4 6573(define_expand "cbranchsi4"
6574 [(set (pc) (if_then_else
6575 (match_operator 0 "arm_comparison_operator"
6576 [(match_operand:SI 1 "s_register_operand" "")
6577 (match_operand:SI 2 "nonmemory_operand" "")])
6578 (label_ref (match_operand 3 "" ""))
6579 (pc)))]
74f4459c 6580 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6581 "
74f4459c 6582 if (!TARGET_THUMB1)
6583 {
6584 if (!arm_add_operand (operands[2], SImode))
6585 operands[2] = force_reg (SImode, operands[2]);
6586 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6587 operands[3]));
6588 DONE;
6589 }
25f905c2 6590 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6591 {
6592 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6593 operands[3], operands[0]));
6594 DONE;
6595 }
25f905c2 6596 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6597 operands[2] = force_reg (SImode, operands[2]);
6598 ")
6599
74f4459c 6600(define_expand "cbranchsf4"
6601 [(set (pc) (if_then_else
6602 (match_operator 0 "arm_comparison_operator"
6603 [(match_operand:SF 1 "s_register_operand" "")
6604 (match_operand:SF 2 "arm_float_compare_operand" "")])
6605 (label_ref (match_operand 3 "" ""))
6606 (pc)))]
6607 "TARGET_32BIT && TARGET_HARD_FLOAT"
6608 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6609 operands[3])); DONE;"
6610)
6611
6612(define_expand "cbranchdf4"
6613 [(set (pc) (if_then_else
6614 (match_operator 0 "arm_comparison_operator"
6615 [(match_operand:DF 1 "s_register_operand" "")
6616 (match_operand:DF 2 "arm_float_compare_operand" "")])
6617 (label_ref (match_operand 3 "" ""))
6618 (pc)))]
6619 "TARGET_32BIT && TARGET_HARD_FLOAT"
6620 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6621 operands[3])); DONE;"
6622)
6623
6624;; this uses the Cirrus DI compare instruction
6625(define_expand "cbranchdi4"
6626 [(set (pc) (if_then_else
6627 (match_operator 0 "arm_comparison_operator"
6628 [(match_operand:DI 1 "cirrus_fp_register" "")
6629 (match_operand:DI 2 "cirrus_fp_register" "")])
6630 (label_ref (match_operand 3 "" ""))
6631 (pc)))]
6632 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6633 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6634 operands[3])); DONE;"
6635)
6636
aeac46d4 6637(define_insn "*cbranchsi4_insn"
6638 [(set (pc) (if_then_else
6639 (match_operator 0 "arm_comparison_operator"
6640 [(match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 6641 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6642 (label_ref (match_operand 3 "" ""))
6643 (pc)))]
25f905c2 6644 "TARGET_THUMB1"
cffb2a26 6645 "*
6646 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 6647
cffb2a26 6648 switch (get_attr_length (insn))
6649 {
6650 case 4: return \"b%d0\\t%l3\";
6651 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6652 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6653 }
6654 "
6655 [(set (attr "far_jump")
6656 (if_then_else
6657 (eq_attr "length" "8")
6658 (const_string "yes")
6659 (const_string "no")))
6660 (set (attr "length")
6661 (if_then_else
6662 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6663 (le (minus (match_dup 3) (pc)) (const_int 256)))
6664 (const_int 4)
6665 (if_then_else
6666 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6667 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6668 (const_int 6)
6669 (const_int 8))))]
6670)
6671
aeac46d4 6672(define_insn "cbranchsi4_scratch"
6673 [(set (pc) (if_then_else
6674 (match_operator 4 "arm_comparison_operator"
6675 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6676 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6677 (label_ref (match_operand 3 "" ""))
6678 (pc)))
6679 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6680 "TARGET_THUMB1"
aeac46d4 6681 "*
6682 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6683
6684 switch (get_attr_length (insn))
6685 {
6686 case 4: return \"b%d4\\t%l3\";
6687 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6688 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6689 }
6690 "
6691 [(set (attr "far_jump")
6692 (if_then_else
6693 (eq_attr "length" "8")
6694 (const_string "yes")
6695 (const_string "no")))
6696 (set (attr "length")
6697 (if_then_else
6698 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6699 (le (minus (match_dup 3) (pc)) (const_int 256)))
6700 (const_int 4)
6701 (if_then_else
6702 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6703 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6704 (const_int 6)
6705 (const_int 8))))]
6706)
6707(define_insn "*movsi_cbranchsi4"
6708 [(set (pc)
6709 (if_then_else
6710 (match_operator 3 "arm_comparison_operator"
6711 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6712 (const_int 0)])
6713 (label_ref (match_operand 2 "" ""))
6714 (pc)))
6715 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6716 (match_dup 1))]
25f905c2 6717 "TARGET_THUMB1"
aeac46d4 6718 "*{
6719 if (which_alternative == 0)
6720 output_asm_insn (\"cmp\t%0, #0\", operands);
6721 else if (which_alternative == 1)
6722 output_asm_insn (\"sub\t%0, %1, #0\", operands);
6723 else
6724 {
6725 output_asm_insn (\"cmp\t%1, #0\", operands);
6726 if (which_alternative == 2)
6727 output_asm_insn (\"mov\t%0, %1\", operands);
6728 else
6729 output_asm_insn (\"str\t%1, %0\", operands);
6730 }
6731 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6732 {
6733 case 4: return \"b%d3\\t%l2\";
6734 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6735 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6736 }
6737 }"
6738 [(set (attr "far_jump")
6739 (if_then_else
6740 (ior (and (gt (symbol_ref ("which_alternative"))
6741 (const_int 1))
6742 (eq_attr "length" "8"))
6743 (eq_attr "length" "10"))
6744 (const_string "yes")
6745 (const_string "no")))
6746 (set (attr "length")
6747 (if_then_else
6748 (le (symbol_ref ("which_alternative"))
6749 (const_int 1))
6750 (if_then_else
6751 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6752 (le (minus (match_dup 2) (pc)) (const_int 256)))
6753 (const_int 4)
6754 (if_then_else
6755 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6756 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6757 (const_int 6)
6758 (const_int 8)))
6759 (if_then_else
6760 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6761 (le (minus (match_dup 2) (pc)) (const_int 256)))
6762 (const_int 6)
6763 (if_then_else
6764 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6765 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6766 (const_int 8)
6767 (const_int 10)))))]
6768)
6769
cffb2a26 6770(define_insn "*negated_cbranchsi4"
6771 [(set (pc)
6772 (if_then_else
aed179ae 6773 (match_operator 0 "equality_operator"
aeac46d4 6774 [(match_operand:SI 1 "s_register_operand" "l")
6775 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6776 (label_ref (match_operand 3 "" ""))
215b30b3 6777 (pc)))]
25f905c2 6778 "TARGET_THUMB1"
cffb2a26 6779 "*
6780 output_asm_insn (\"cmn\\t%1, %2\", operands);
6781 switch (get_attr_length (insn))
6782 {
6783 case 4: return \"b%d0\\t%l3\";
6784 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6785 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6786 }
6787 "
6788 [(set (attr "far_jump")
6789 (if_then_else
6790 (eq_attr "length" "8")
6791 (const_string "yes")
6792 (const_string "no")))
6793 (set (attr "length")
6794 (if_then_else
6795 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6796 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6797 (const_int 4)
6798 (if_then_else
341940e8 6799 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6800 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6801 (const_int 6)
6802 (const_int 8))))]
6803)
6804
58d6528b 6805(define_insn "*tbit_cbranch"
6806 [(set (pc)
6807 (if_then_else
6808 (match_operator 0 "equality_operator"
6809 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6810 (const_int 1)
6811 (match_operand:SI 2 "const_int_operand" "i"))
6812 (const_int 0)])
6813 (label_ref (match_operand 3 "" ""))
6814 (pc)))
6815 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6816 "TARGET_THUMB1"
58d6528b 6817 "*
6818 {
6819 rtx op[3];
6820 op[0] = operands[4];
6821 op[1] = operands[1];
6822 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6823
86efa74d 6824 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6825 switch (get_attr_length (insn))
6826 {
6827 case 4: return \"b%d0\\t%l3\";
6828 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6829 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6830 }
6831 }"
6832 [(set (attr "far_jump")
6833 (if_then_else
6834 (eq_attr "length" "8")
6835 (const_string "yes")
6836 (const_string "no")))
6837 (set (attr "length")
6838 (if_then_else
6839 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6840 (le (minus (match_dup 3) (pc)) (const_int 256)))
6841 (const_int 4)
6842 (if_then_else
6843 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6844 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6845 (const_int 6)
6846 (const_int 8))))]
6847)
6848
6849(define_insn "*tlobits_cbranch"
6850 [(set (pc)
6851 (if_then_else
6852 (match_operator 0 "equality_operator"
6853 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6854 (match_operand:SI 2 "const_int_operand" "i")
6855 (const_int 0))
6856 (const_int 0)])
6857 (label_ref (match_operand 3 "" ""))
6858 (pc)))
6859 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6860 "TARGET_THUMB1"
86efa74d 6861 "*
6862 {
6863 rtx op[3];
6864 op[0] = operands[4];
6865 op[1] = operands[1];
6866 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6867
58d6528b 6868 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6869 switch (get_attr_length (insn))
6870 {
6871 case 4: return \"b%d0\\t%l3\";
6872 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6873 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6874 }
6875 }"
6876 [(set (attr "far_jump")
6877 (if_then_else
6878 (eq_attr "length" "8")
6879 (const_string "yes")
6880 (const_string "no")))
6881 (set (attr "length")
6882 (if_then_else
6883 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6884 (le (minus (match_dup 3) (pc)) (const_int 256)))
6885 (const_int 4)
6886 (if_then_else
6887 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6888 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6889 (const_int 6)
6890 (const_int 8))))]
6891)
6892
aeac46d4 6893(define_insn "*tstsi3_cbranch"
58d6528b 6894 [(set (pc)
6895 (if_then_else
aeac46d4 6896 (match_operator 3 "equality_operator"
6897 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6898 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6899 (const_int 0)])
aeac46d4 6900 (label_ref (match_operand 2 "" ""))
6901 (pc)))]
25f905c2 6902 "TARGET_THUMB1"
58d6528b 6903 "*
6904 {
aeac46d4 6905 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6906 switch (get_attr_length (insn))
6907 {
aeac46d4 6908 case 4: return \"b%d3\\t%l2\";
6909 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6910 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6911 }
6912 }"
6913 [(set (attr "far_jump")
6914 (if_then_else
6915 (eq_attr "length" "8")
6916 (const_string "yes")
6917 (const_string "no")))
6918 (set (attr "length")
6919 (if_then_else
aeac46d4 6920 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6921 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6922 (const_int 4)
6923 (if_then_else
aeac46d4 6924 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6925 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6926 (const_int 6)
6927 (const_int 8))))]
6928)
6929
6930(define_insn "*andsi3_cbranch"
6931 [(set (pc)
6932 (if_then_else
6933 (match_operator 5 "equality_operator"
6934 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6935 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6936 (const_int 0)])
6937 (label_ref (match_operand 4 "" ""))
6938 (pc)))
aeac46d4 6939 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6940 (and:SI (match_dup 2) (match_dup 3)))
6941 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6942 "TARGET_THUMB1"
58d6528b 6943 "*
6944 {
6945 if (which_alternative == 0)
6946 output_asm_insn (\"and\\t%0, %3\", operands);
6947 else if (which_alternative == 1)
6948 {
6949 output_asm_insn (\"and\\t%1, %3\", operands);
6950 output_asm_insn (\"mov\\t%0, %1\", operands);
6951 }
6952 else
6953 {
6954 output_asm_insn (\"and\\t%1, %3\", operands);
6955 output_asm_insn (\"str\\t%1, %0\", operands);
6956 }
6957
6958 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6959 {
6960 case 4: return \"b%d5\\t%l4\";
6961 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6962 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6963 }
6964 }"
6965 [(set (attr "far_jump")
6966 (if_then_else
6967 (ior (and (eq (symbol_ref ("which_alternative"))
6968 (const_int 0))
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 (eq (symbol_ref ("which_alternative"))
6976 (const_int 0))
6977 (if_then_else
6978 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6979 (le (minus (match_dup 4) (pc)) (const_int 256)))
6980 (const_int 4)
6981 (if_then_else
6982 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6983 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6984 (const_int 6)
6985 (const_int 8)))
6986 (if_then_else
6987 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6988 (le (minus (match_dup 4) (pc)) (const_int 256)))
6989 (const_int 6)
6990 (if_then_else
6991 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6992 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6993 (const_int 8)
6994 (const_int 10)))))]
6995)
6996
6997(define_insn "*orrsi3_cbranch_scratch"
6998 [(set (pc)
6999 (if_then_else
7000 (match_operator 4 "equality_operator"
7001 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
7002 (match_operand:SI 2 "s_register_operand" "l"))
7003 (const_int 0)])
7004 (label_ref (match_operand 3 "" ""))
7005 (pc)))
7006 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7007 "TARGET_THUMB1"
58d6528b 7008 "*
7009 {
7010 output_asm_insn (\"orr\\t%0, %2\", operands);
7011 switch (get_attr_length (insn))
7012 {
7013 case 4: return \"b%d4\\t%l3\";
7014 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7015 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7016 }
7017 }"
7018 [(set (attr "far_jump")
7019 (if_then_else
7020 (eq_attr "length" "8")
7021 (const_string "yes")
7022 (const_string "no")))
7023 (set (attr "length")
7024 (if_then_else
7025 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7026 (le (minus (match_dup 3) (pc)) (const_int 256)))
7027 (const_int 4)
7028 (if_then_else
7029 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7030 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7031 (const_int 6)
7032 (const_int 8))))]
7033)
7034
7035(define_insn "*orrsi3_cbranch"
7036 [(set (pc)
7037 (if_then_else
7038 (match_operator 5 "equality_operator"
7039 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7040 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7041 (const_int 0)])
7042 (label_ref (match_operand 4 "" ""))
7043 (pc)))
aeac46d4 7044 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7045 (ior:SI (match_dup 2) (match_dup 3)))
7046 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7047 "TARGET_THUMB1"
58d6528b 7048 "*
7049 {
7050 if (which_alternative == 0)
7051 output_asm_insn (\"orr\\t%0, %3\", operands);
7052 else if (which_alternative == 1)
7053 {
7054 output_asm_insn (\"orr\\t%1, %3\", operands);
7055 output_asm_insn (\"mov\\t%0, %1\", operands);
7056 }
7057 else
7058 {
7059 output_asm_insn (\"orr\\t%1, %3\", operands);
7060 output_asm_insn (\"str\\t%1, %0\", operands);
7061 }
7062
7063 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7064 {
7065 case 4: return \"b%d5\\t%l4\";
7066 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7067 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7068 }
7069 }"
7070 [(set (attr "far_jump")
7071 (if_then_else
7072 (ior (and (eq (symbol_ref ("which_alternative"))
7073 (const_int 0))
7074 (eq_attr "length" "8"))
7075 (eq_attr "length" "10"))
7076 (const_string "yes")
7077 (const_string "no")))
7078 (set (attr "length")
7079 (if_then_else
7080 (eq (symbol_ref ("which_alternative"))
7081 (const_int 0))
7082 (if_then_else
7083 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7084 (le (minus (match_dup 4) (pc)) (const_int 256)))
7085 (const_int 4)
7086 (if_then_else
7087 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7088 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7089 (const_int 6)
7090 (const_int 8)))
7091 (if_then_else
7092 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7093 (le (minus (match_dup 4) (pc)) (const_int 256)))
7094 (const_int 6)
7095 (if_then_else
7096 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7097 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7098 (const_int 8)
7099 (const_int 10)))))]
7100)
7101
7102(define_insn "*xorsi3_cbranch_scratch"
7103 [(set (pc)
7104 (if_then_else
7105 (match_operator 4 "equality_operator"
7106 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
7107 (match_operand:SI 2 "s_register_operand" "l"))
7108 (const_int 0)])
7109 (label_ref (match_operand 3 "" ""))
7110 (pc)))
7111 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7112 "TARGET_THUMB1"
58d6528b 7113 "*
7114 {
7115 output_asm_insn (\"eor\\t%0, %2\", operands);
7116 switch (get_attr_length (insn))
7117 {
7118 case 4: return \"b%d4\\t%l3\";
7119 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7120 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7121 }
7122 }"
7123 [(set (attr "far_jump")
7124 (if_then_else
7125 (eq_attr "length" "8")
7126 (const_string "yes")
7127 (const_string "no")))
7128 (set (attr "length")
7129 (if_then_else
7130 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7131 (le (minus (match_dup 3) (pc)) (const_int 256)))
7132 (const_int 4)
7133 (if_then_else
7134 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7135 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7136 (const_int 6)
7137 (const_int 8))))]
7138)
7139
7140(define_insn "*xorsi3_cbranch"
7141 [(set (pc)
7142 (if_then_else
7143 (match_operator 5 "equality_operator"
7144 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7145 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7146 (const_int 0)])
7147 (label_ref (match_operand 4 "" ""))
7148 (pc)))
aeac46d4 7149 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7150 (xor:SI (match_dup 2) (match_dup 3)))
7151 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7152 "TARGET_THUMB1"
58d6528b 7153 "*
7154 {
7155 if (which_alternative == 0)
7156 output_asm_insn (\"eor\\t%0, %3\", operands);
7157 else if (which_alternative == 1)
7158 {
7159 output_asm_insn (\"eor\\t%1, %3\", operands);
7160 output_asm_insn (\"mov\\t%0, %1\", operands);
7161 }
7162 else
7163 {
7164 output_asm_insn (\"eor\\t%1, %3\", operands);
7165 output_asm_insn (\"str\\t%1, %0\", operands);
7166 }
7167
7168 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7169 {
7170 case 4: return \"b%d5\\t%l4\";
7171 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7172 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7173 }
7174 }"
7175 [(set (attr "far_jump")
7176 (if_then_else
7177 (ior (and (eq (symbol_ref ("which_alternative"))
7178 (const_int 0))
7179 (eq_attr "length" "8"))
7180 (eq_attr "length" "10"))
7181 (const_string "yes")
7182 (const_string "no")))
7183 (set (attr "length")
7184 (if_then_else
7185 (eq (symbol_ref ("which_alternative"))
7186 (const_int 0))
7187 (if_then_else
7188 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7189 (le (minus (match_dup 4) (pc)) (const_int 256)))
7190 (const_int 4)
7191 (if_then_else
7192 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7193 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7194 (const_int 6)
7195 (const_int 8)))
7196 (if_then_else
7197 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7198 (le (minus (match_dup 4) (pc)) (const_int 256)))
7199 (const_int 6)
7200 (if_then_else
7201 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7202 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7203 (const_int 8)
7204 (const_int 10)))))]
7205)
7206
aeac46d4 7207(define_insn "*bicsi3_cbranch_scratch"
7208 [(set (pc)
7209 (if_then_else
7210 (match_operator 4 "equality_operator"
7211 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7212 (match_operand:SI 1 "s_register_operand" "0"))
7213 (const_int 0)])
7214 (label_ref (match_operand 3 "" ""))
7215 (pc)))
7216 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7217 "TARGET_THUMB1"
aeac46d4 7218 "*
7219 {
7220 output_asm_insn (\"bic\\t%0, %2\", operands);
7221 switch (get_attr_length (insn))
7222 {
7223 case 4: return \"b%d4\\t%l3\";
7224 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7225 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7226 }
7227 }"
7228 [(set (attr "far_jump")
7229 (if_then_else
7230 (eq_attr "length" "8")
7231 (const_string "yes")
7232 (const_string "no")))
7233 (set (attr "length")
7234 (if_then_else
7235 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7236 (le (minus (match_dup 3) (pc)) (const_int 256)))
7237 (const_int 4)
7238 (if_then_else
7239 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7240 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7241 (const_int 6)
7242 (const_int 8))))]
7243)
7244
7245(define_insn "*bicsi3_cbranch"
7246 [(set (pc)
7247 (if_then_else
7248 (match_operator 5 "equality_operator"
01145ae6 7249 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7250 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 7251 (const_int 0)])
7252 (label_ref (match_operand 4 "" ""))
7253 (pc)))
01145ae6 7254 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 7255 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 7256 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
25f905c2 7257 "TARGET_THUMB1"
aeac46d4 7258 "*
7259 {
7260 if (which_alternative == 0)
7261 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 7262 else if (which_alternative <= 2)
aeac46d4 7263 {
7264 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 7265 /* It's ok if OP0 is a lo-reg, even though the mov will set the
7266 conditions again, since we're only testing for equality. */
aeac46d4 7267 output_asm_insn (\"mov\\t%0, %1\", operands);
7268 }
7269 else
7270 {
7271 output_asm_insn (\"bic\\t%1, %3\", operands);
7272 output_asm_insn (\"str\\t%1, %0\", operands);
7273 }
7274
7275 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7276 {
7277 case 4: return \"b%d5\\t%l4\";
7278 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7279 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7280 }
7281 }"
7282 [(set (attr "far_jump")
7283 (if_then_else
7284 (ior (and (eq (symbol_ref ("which_alternative"))
7285 (const_int 0))
7286 (eq_attr "length" "8"))
7287 (eq_attr "length" "10"))
7288 (const_string "yes")
7289 (const_string "no")))
7290 (set (attr "length")
7291 (if_then_else
7292 (eq (symbol_ref ("which_alternative"))
7293 (const_int 0))
7294 (if_then_else
7295 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7296 (le (minus (match_dup 4) (pc)) (const_int 256)))
7297 (const_int 4)
7298 (if_then_else
7299 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7300 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7301 (const_int 6)
7302 (const_int 8)))
7303 (if_then_else
7304 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7305 (le (minus (match_dup 4) (pc)) (const_int 256)))
7306 (const_int 6)
7307 (if_then_else
7308 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7309 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7310 (const_int 8)
7311 (const_int 10)))))]
7312)
7313
203c488f 7314(define_insn "*cbranchne_decr1"
7315 [(set (pc)
7316 (if_then_else (match_operator 3 "equality_operator"
7317 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7318 (const_int 0)])
7319 (label_ref (match_operand 4 "" ""))
7320 (pc)))
aeac46d4 7321 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7322 (plus:SI (match_dup 2) (const_int -1)))
7323 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7324 "TARGET_THUMB1"
203c488f 7325 "*
7326 {
7327 rtx cond[2];
7328 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7329 ? GEU : LTU),
58d6528b 7330 VOIDmode, operands[2], const1_rtx);
203c488f 7331 cond[1] = operands[4];
7332
7333 if (which_alternative == 0)
7334 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7335 else if (which_alternative == 1)
7336 {
7337 /* We must provide an alternative for a hi reg because reload
7338 cannot handle output reloads on a jump instruction, but we
7339 can't subtract into that. Fortunately a mov from lo to hi
7340 does not clobber the condition codes. */
7341 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7342 output_asm_insn (\"mov\\t%0, %1\", operands);
7343 }
7344 else
7345 {
7346 /* Similarly, but the target is memory. */
7347 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7348 output_asm_insn (\"str\\t%1, %0\", operands);
7349 }
7350
7351 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7352 {
7353 case 4:
8aea555f 7354 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7355 return \"\";
7356 case 6:
8aea555f 7357 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7358 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7359 default:
8aea555f 7360 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7361 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7362 }
7363 }
7364 "
7365 [(set (attr "far_jump")
7366 (if_then_else
7367 (ior (and (eq (symbol_ref ("which_alternative"))
7368 (const_int 0))
7369 (eq_attr "length" "8"))
7370 (eq_attr "length" "10"))
7371 (const_string "yes")
7372 (const_string "no")))
7373 (set_attr_alternative "length"
7374 [
7375 ;; Alternative 0
7376 (if_then_else
7377 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7378 (le (minus (match_dup 4) (pc)) (const_int 256)))
7379 (const_int 4)
7380 (if_then_else
7381 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7382 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7383 (const_int 6)
7384 (const_int 8)))
7385 ;; Alternative 1
7386 (if_then_else
7387 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7388 (le (minus (match_dup 4) (pc)) (const_int 256)))
7389 (const_int 6)
7390 (if_then_else
7391 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7392 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7393 (const_int 8)
7394 (const_int 10)))
7395 ;; Alternative 2
7396 (if_then_else
7397 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7398 (le (minus (match_dup 4) (pc)) (const_int 256)))
7399 (const_int 6)
7400 (if_then_else
7401 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7402 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7403 (const_int 8)
7404 (const_int 10)))
7405 ;; Alternative 3
7406 (if_then_else
7407 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7408 (le (minus (match_dup 4) (pc)) (const_int 256)))
7409 (const_int 6)
7410 (if_then_else
7411 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7412 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7413 (const_int 8)
7414 (const_int 10)))])]
7415)
cffb2a26 7416
58d6528b 7417(define_insn "*addsi3_cbranch"
7418 [(set (pc)
7419 (if_then_else
b0694be0 7420 (match_operator 4 "arm_comparison_operator"
58d6528b 7421 [(plus:SI
7422 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
7423 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
7424 (const_int 0)])
7425 (label_ref (match_operand 5 "" ""))
7426 (pc)))
aeac46d4 7427 (set
7428 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7429 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 7430 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
25f905c2 7431 "TARGET_THUMB1
58d6528b 7432 && (GET_CODE (operands[4]) == EQ
7433 || GET_CODE (operands[4]) == NE
7434 || GET_CODE (operands[4]) == GE
7435 || GET_CODE (operands[4]) == LT)"
7436 "*
7437 {
7438 rtx cond[3];
7439
7440
7441 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
7442 cond[1] = operands[2];
7443 cond[2] = operands[3];
7444
7445 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7446 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7447 else
7448 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7449
7450 if (which_alternative >= 3
7451 && which_alternative < 4)
7452 output_asm_insn (\"mov\\t%0, %1\", operands);
7453 else if (which_alternative >= 4)
7454 output_asm_insn (\"str\\t%1, %0\", operands);
7455
7456 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7457 {
7458 case 4:
7459 return \"b%d4\\t%l5\";
7460 case 6:
7461 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7462 default:
7463 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7464 }
7465 }
7466 "
7467 [(set (attr "far_jump")
7468 (if_then_else
7469 (ior (and (lt (symbol_ref ("which_alternative"))
7470 (const_int 3))
7471 (eq_attr "length" "8"))
7472 (eq_attr "length" "10"))
7473 (const_string "yes")
7474 (const_string "no")))
7475 (set (attr "length")
7476 (if_then_else
7477 (lt (symbol_ref ("which_alternative"))
7478 (const_int 3))
7479 (if_then_else
7480 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7481 (le (minus (match_dup 5) (pc)) (const_int 256)))
7482 (const_int 4)
7483 (if_then_else
7484 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7485 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7486 (const_int 6)
7487 (const_int 8)))
7488 (if_then_else
7489 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7490 (le (minus (match_dup 5) (pc)) (const_int 256)))
7491 (const_int 6)
7492 (if_then_else
7493 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7494 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7495 (const_int 8)
7496 (const_int 10)))))]
7497)
7498
7499(define_insn "*addsi3_cbranch_scratch"
7500 [(set (pc)
7501 (if_then_else
b0694be0 7502 (match_operator 3 "arm_comparison_operator"
58d6528b 7503 [(plus:SI
7504 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7505 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7506 (const_int 0)])
7507 (label_ref (match_operand 4 "" ""))
7508 (pc)))
7509 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7510 "TARGET_THUMB1
58d6528b 7511 && (GET_CODE (operands[3]) == EQ
7512 || GET_CODE (operands[3]) == NE
7513 || GET_CODE (operands[3]) == GE
7514 || GET_CODE (operands[3]) == LT)"
7515 "*
7516 {
7517 switch (which_alternative)
7518 {
7519 case 0:
7520 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7521 break;
7522 case 1:
7523 output_asm_insn (\"cmn\t%1, %2\", operands);
7524 break;
0f5e9701 7525 case 2:
3a445a04 7526 if (INTVAL (operands[2]) < 0)
7527 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7528 else
7529 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7530 break;
0f5e9701 7531 case 3:
3a445a04 7532 if (INTVAL (operands[2]) < 0)
7533 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7534 else
7535 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7536 break;
7537 }
7538
7539 switch (get_attr_length (insn))
7540 {
7541 case 4:
7542 return \"b%d3\\t%l4\";
7543 case 6:
7544 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7545 default:
7546 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7547 }
7548 }
7549 "
7550 [(set (attr "far_jump")
7551 (if_then_else
7552 (eq_attr "length" "8")
7553 (const_string "yes")
7554 (const_string "no")))
7555 (set (attr "length")
7556 (if_then_else
7557 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7558 (le (minus (match_dup 4) (pc)) (const_int 256)))
7559 (const_int 4)
7560 (if_then_else
7561 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7562 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7563 (const_int 6)
7564 (const_int 8))))]
7565)
7566
7567(define_insn "*subsi3_cbranch"
7568 [(set (pc)
7569 (if_then_else
b0694be0 7570 (match_operator 4 "arm_comparison_operator"
58d6528b 7571 [(minus:SI
7572 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7573 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7574 (const_int 0)])
7575 (label_ref (match_operand 5 "" ""))
7576 (pc)))
aeac46d4 7577 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7578 (minus:SI (match_dup 2) (match_dup 3)))
7579 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7580 "TARGET_THUMB1
58d6528b 7581 && (GET_CODE (operands[4]) == EQ
7582 || GET_CODE (operands[4]) == NE
7583 || GET_CODE (operands[4]) == GE
7584 || GET_CODE (operands[4]) == LT)"
7585 "*
7586 {
7587 if (which_alternative == 0)
7588 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7589 else if (which_alternative == 1)
7590 {
7591 /* We must provide an alternative for a hi reg because reload
7592 cannot handle output reloads on a jump instruction, but we
7593 can't subtract into that. Fortunately a mov from lo to hi
7594 does not clobber the condition codes. */
7595 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7596 output_asm_insn (\"mov\\t%0, %1\", operands);
7597 }
7598 else
7599 {
7600 /* Similarly, but the target is memory. */
7601 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7602 output_asm_insn (\"str\\t%1, %0\", operands);
7603 }
7604
7605 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7606 {
7607 case 4:
7608 return \"b%d4\\t%l5\";
7609 case 6:
7610 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7611 default:
7612 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7613 }
7614 }
7615 "
7616 [(set (attr "far_jump")
7617 (if_then_else
7618 (ior (and (eq (symbol_ref ("which_alternative"))
7619 (const_int 0))
7620 (eq_attr "length" "8"))
7621 (eq_attr "length" "10"))
7622 (const_string "yes")
7623 (const_string "no")))
7624 (set (attr "length")
7625 (if_then_else
7626 (eq (symbol_ref ("which_alternative"))
7627 (const_int 0))
7628 (if_then_else
7629 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7630 (le (minus (match_dup 5) (pc)) (const_int 256)))
7631 (const_int 4)
7632 (if_then_else
7633 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7634 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7635 (const_int 6)
7636 (const_int 8)))
7637 (if_then_else
7638 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7639 (le (minus (match_dup 5) (pc)) (const_int 256)))
7640 (const_int 6)
7641 (if_then_else
7642 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7643 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7644 (const_int 8)
7645 (const_int 10)))))]
7646)
7647
7648(define_insn "*subsi3_cbranch_scratch"
7649 [(set (pc)
7650 (if_then_else
7651 (match_operator 0 "arm_comparison_operator"
7652 [(minus:SI (match_operand:SI 1 "register_operand" "l")
7653 (match_operand:SI 2 "nonmemory_operand" "l"))
7654 (const_int 0)])
7655 (label_ref (match_operand 3 "" ""))
7656 (pc)))]
25f905c2 7657 "TARGET_THUMB1
58d6528b 7658 && (GET_CODE (operands[0]) == EQ
7659 || GET_CODE (operands[0]) == NE
7660 || GET_CODE (operands[0]) == GE
7661 || GET_CODE (operands[0]) == LT)"
7662 "*
7663 output_asm_insn (\"cmp\\t%1, %2\", operands);
7664 switch (get_attr_length (insn))
7665 {
7666 case 4: return \"b%d0\\t%l3\";
7667 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7668 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7669 }
7670 "
7671 [(set (attr "far_jump")
7672 (if_then_else
7673 (eq_attr "length" "8")
7674 (const_string "yes")
7675 (const_string "no")))
7676 (set (attr "length")
7677 (if_then_else
7678 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7679 (le (minus (match_dup 3) (pc)) (const_int 256)))
7680 (const_int 4)
7681 (if_then_else
7682 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7683 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7684 (const_int 6)
7685 (const_int 8))))]
7686)
7687
9c08d1fa 7688;; Comparison and test insns
7689
cffb2a26 7690(define_insn "*arm_cmpsi_insn"
bd5b4116 7691 [(set (reg:CC CC_REGNUM)
aea4c774 7692 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7693 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7694 "TARGET_32BIT"
5565501b 7695 "@
aea4c774 7696 cmp%?\\t%0, %1
7697 cmn%?\\t%0, #%n1"
cffb2a26 7698 [(set_attr "conds" "set")]
7699)
b11cae9e 7700
25f905c2 7701(define_insn "*arm_cmpsi_shiftsi"
bd5b4116 7702 [(set (reg:CC CC_REGNUM)
cffb2a26 7703 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
7704 (match_operator:SI 3 "shift_operator"
aea4c774 7705 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 7706 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
7707 "TARGET_ARM"
aea4c774 7708 "cmp%?\\t%0, %1%S3"
344495ea 7709 [(set_attr "conds" "set")
331beb1a 7710 (set_attr "shift" "1")
a2cd141b 7711 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7712 (const_string "alu_shift")
7713 (const_string "alu_shift_reg")))]
0d66636f 7714)
b11cae9e 7715
25f905c2 7716(define_insn "*arm_cmpsi_shiftsi_swp"
bd5b4116 7717 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7718 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7719 [(match_operand:SI 1 "s_register_operand" "r")
7720 (match_operand:SI 2 "reg_or_int_operand" "rM")])
7721 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7722 "TARGET_ARM"
aea4c774 7723 "cmp%?\\t%0, %1%S3"
344495ea 7724 [(set_attr "conds" "set")
331beb1a 7725 (set_attr "shift" "1")
a2cd141b 7726 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7727 (const_string "alu_shift")
7728 (const_string "alu_shift_reg")))]
0d66636f 7729)
b11cae9e 7730
25f905c2 7731(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7732 [(set (reg:CC_Z CC_REGNUM)
7733 (compare:CC_Z
7734 (neg:SI (match_operator:SI 1 "shift_operator"
7735 [(match_operand:SI 2 "s_register_operand" "r")
7736 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7737 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7738 "TARGET_ARM"
aed179ae 7739 "cmn%?\\t%0, %2%S1"
344495ea 7740 [(set_attr "conds" "set")
aed179ae 7741 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7742 (const_string "alu_shift")
7743 (const_string "alu_shift_reg")))]
0d66636f 7744)
b11cae9e 7745
7d57ec45 7746;; Cirrus SF compare instruction
7747(define_insn "*cirrus_cmpsf"
7748 [(set (reg:CCFP CC_REGNUM)
7749 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7750 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7751 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7752 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7753 [(set_attr "type" "mav_farith")
7d57ec45 7754 (set_attr "cirrus" "compare")]
7755)
7756
7757;; Cirrus DF compare instruction
7758(define_insn "*cirrus_cmpdf"
7759 [(set (reg:CCFP CC_REGNUM)
7760 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7761 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7762 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7763 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7764 [(set_attr "type" "mav_farith")
7d57ec45 7765 (set_attr "cirrus" "compare")]
7766)
7767
7d57ec45 7768(define_insn "*cirrus_cmpdi"
7769 [(set (reg:CC CC_REGNUM)
7770 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7771 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7772 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7773 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7774 [(set_attr "type" "mav_farith")
7d57ec45 7775 (set_attr "cirrus" "compare")]
7776)
7777
9c08d1fa 7778; This insn allows redundant compares to be removed by cse, nothing should
7779; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7780; is deleted later on. The match_dup will match the mode here, so that
7781; mode changes of the condition codes aren't lost by this even though we don't
7782; specify what they are.
7783
8a18b90c 7784(define_insn "*deleted_compare"
9c08d1fa 7785 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7786 "TARGET_32BIT"
40dbec34 7787 "\\t%@ deleted compare"
cffb2a26 7788 [(set_attr "conds" "set")
7789 (set_attr "length" "0")]
7790)
9c08d1fa 7791
7792\f
7793;; Conditional branch insns
7794
74f4459c 7795(define_expand "cbranch_cc"
9c08d1fa 7796 [(set (pc)
74f4459c 7797 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7798 (match_operand 2 "" "")])
7799 (label_ref (match_operand 3 "" ""))
9c08d1fa 7800 (pc)))]
25f905c2 7801 "TARGET_32BIT"
74f4459c 7802 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7803 operands[1], operands[2]);
7804 operands[2] = const0_rtx;"
8fa3ba89 7805)
7806
7807;;
7808;; Patterns to match conditional branch insns.
7809;;
7810
cffb2a26 7811(define_insn "*arm_cond_branch"
9c08d1fa 7812 [(set (pc)
8fa3ba89 7813 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7814 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7815 (label_ref (match_operand 0 "" ""))
7816 (pc)))]
25f905c2 7817 "TARGET_32BIT"
d75350ce 7818 "*
9c08d1fa 7819 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7820 {
7821 arm_ccfsm_state += 2;
7822 return \"\";
7823 }
e2348bcb 7824 return \"b%d1\\t%l0\";
cffb2a26 7825 "
a2cd141b 7826 [(set_attr "conds" "use")
7827 (set_attr "type" "branch")]
cffb2a26 7828)
d75350ce 7829
cffb2a26 7830(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7831 [(set (pc)
8fa3ba89 7832 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7833 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7834 (pc)
7835 (label_ref (match_operand 0 "" ""))))]
25f905c2 7836 "TARGET_32BIT"
d75350ce 7837 "*
9c08d1fa 7838 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7839 {
7840 arm_ccfsm_state += 2;
7841 return \"\";
7842 }
e2348bcb 7843 return \"b%D1\\t%l0\";
cffb2a26 7844 "
a2cd141b 7845 [(set_attr "conds" "use")
7846 (set_attr "type" "branch")]
cffb2a26 7847)
7848
b11cae9e 7849\f
9c08d1fa 7850
7851; scc insns
7852
74f4459c 7853(define_expand "cstore_cc"
7db9af5d 7854 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7855 (match_operator:SI 1 "" [(match_operand 2 "" "")
7856 (match_operand 3 "" "")]))]
25f905c2 7857 "TARGET_32BIT"
74f4459c 7858 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7859 operands[2], operands[3]);
7860 operands[3] = const0_rtx;"
8fa3ba89 7861)
7862
f7fbdd4a 7863(define_insn "*mov_scc"
9c08d1fa 7864 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7865 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7866 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7867 "TARGET_ARM"
4d61e570 7868 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7869 [(set_attr "conds" "use")
7870 (set_attr "length" "8")]
7871)
9c08d1fa 7872
f7fbdd4a 7873(define_insn "*mov_negscc"
9c08d1fa 7874 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7875 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7876 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7877 "TARGET_ARM"
4d61e570 7878 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7879 [(set_attr "conds" "use")
7880 (set_attr "length" "8")]
7881)
9c08d1fa 7882
f7fbdd4a 7883(define_insn "*mov_notscc"
9c08d1fa 7884 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7885 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7886 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7887 "TARGET_ARM"
4d61e570 7888 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7889 [(set_attr "conds" "use")
7890 (set_attr "length" "8")]
7891)
9c08d1fa 7892
595d88b5 7893(define_expand "cstoresi4"
7894 [(set (match_operand:SI 0 "s_register_operand" "")
7895 (match_operator:SI 1 "arm_comparison_operator"
7896 [(match_operand:SI 2 "s_register_operand" "")
7897 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7898 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7899 "{
7900 rtx op3, scratch, scratch2;
7901
74f4459c 7902 if (!TARGET_THUMB1)
7903 {
7904 if (!arm_add_operand (operands[3], SImode))
7905 operands[3] = force_reg (SImode, operands[3]);
7906 emit_insn (gen_cstore_cc (operands[0], operands[1],
7907 operands[2], operands[3]));
7908 DONE;
7909 }
7910
595d88b5 7911 if (operands[3] == const0_rtx)
7912 {
7913 switch (GET_CODE (operands[1]))
7914 {
7915 case EQ:
25f905c2 7916 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7917 break;
7918
7919 case NE:
25f905c2 7920 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7921 break;
7922
7923 case LE:
7924 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7925 NULL_RTX, 0, OPTAB_WIDEN);
7926 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7927 NULL_RTX, 0, OPTAB_WIDEN);
7928 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7929 operands[0], 1, OPTAB_WIDEN);
7930 break;
7931
7932 case GE:
7933 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7934 NULL_RTX, 1);
7935 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7936 NULL_RTX, 1, OPTAB_WIDEN);
7937 break;
7938
7939 case GT:
7940 scratch = expand_binop (SImode, ashr_optab, operands[2],
7941 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7942 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7943 NULL_RTX, 0, OPTAB_WIDEN);
7944 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7945 0, OPTAB_WIDEN);
7946 break;
7947
7948 /* LT is handled by generic code. No need for unsigned with 0. */
7949 default:
7950 FAIL;
7951 }
7952 DONE;
7953 }
7954
7955 switch (GET_CODE (operands[1]))
7956 {
7957 case EQ:
7958 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7959 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7960 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7961 break;
7962
7963 case NE:
7964 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7965 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7966 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7967 break;
7968
7969 case LE:
7970 op3 = force_reg (SImode, operands[3]);
7971
7972 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7973 NULL_RTX, 1, OPTAB_WIDEN);
7974 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7975 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7976 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7977 op3, operands[2]));
7978 break;
7979
7980 case GE:
7981 op3 = operands[3];
25f905c2 7982 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7983 op3 = force_reg (SImode, op3);
7984 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7985 NULL_RTX, 0, OPTAB_WIDEN);
7986 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7987 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7988 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7989 operands[2], op3));
7990 break;
7991
7992 case LEU:
7993 op3 = force_reg (SImode, operands[3]);
7994 scratch = force_reg (SImode, const0_rtx);
25f905c2 7995 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7996 op3, operands[2]));
7997 break;
7998
7999 case GEU:
8000 op3 = operands[3];
25f905c2 8001 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8002 op3 = force_reg (SImode, op3);
8003 scratch = force_reg (SImode, const0_rtx);
25f905c2 8004 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8005 operands[2], op3));
8006 break;
8007
8008 case LTU:
8009 op3 = operands[3];
25f905c2 8010 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8011 op3 = force_reg (SImode, op3);
8012 scratch = gen_reg_rtx (SImode);
25f905c2 8013 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
595d88b5 8014 emit_insn (gen_negsi2 (operands[0], scratch));
8015 break;
8016
8017 case GTU:
8018 op3 = force_reg (SImode, operands[3]);
8019 scratch = gen_reg_rtx (SImode);
25f905c2 8020 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
595d88b5 8021 emit_insn (gen_negsi2 (operands[0], scratch));
8022 break;
8023
8024 /* No good sequences for GT, LT. */
8025 default:
8026 FAIL;
8027 }
8028 DONE;
8029}")
8030
74f4459c 8031(define_expand "cstoresf4"
8032 [(set (match_operand:SI 0 "s_register_operand" "")
8033 (match_operator:SI 1 "arm_comparison_operator"
8034 [(match_operand:SF 2 "s_register_operand" "")
8035 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8036 "TARGET_32BIT && TARGET_HARD_FLOAT"
8037 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8038 operands[2], operands[3])); DONE;"
8039)
8040
8041(define_expand "cstoredf4"
8042 [(set (match_operand:SI 0 "s_register_operand" "")
8043 (match_operator:SI 1 "arm_comparison_operator"
8044 [(match_operand:DF 2 "s_register_operand" "")
8045 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8046 "TARGET_32BIT && TARGET_HARD_FLOAT"
8047 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8048 operands[2], operands[3])); DONE;"
8049)
8050
8051;; this uses the Cirrus DI compare instruction
8052(define_expand "cstoredi4"
8053 [(set (match_operand:SI 0 "s_register_operand" "")
8054 (match_operator:SI 1 "arm_comparison_operator"
8055 [(match_operand:DI 2 "cirrus_fp_register" "")
8056 (match_operand:DI 3 "cirrus_fp_register" "")]))]
8057 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
8058 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8059 operands[2], operands[3])); DONE;"
8060)
8061
8062
25f905c2 8063(define_expand "cstoresi_eq0_thumb1"
595d88b5 8064 [(parallel
8065 [(set (match_operand:SI 0 "s_register_operand" "")
8066 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8067 (const_int 0)))
8068 (clobber (match_dup:SI 2))])]
25f905c2 8069 "TARGET_THUMB1"
595d88b5 8070 "operands[2] = gen_reg_rtx (SImode);"
8071)
8072
25f905c2 8073(define_expand "cstoresi_ne0_thumb1"
595d88b5 8074 [(parallel
8075 [(set (match_operand:SI 0 "s_register_operand" "")
8076 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8077 (const_int 0)))
8078 (clobber (match_dup:SI 2))])]
25f905c2 8079 "TARGET_THUMB1"
595d88b5 8080 "operands[2] = gen_reg_rtx (SImode);"
8081)
8082
25f905c2 8083(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 8084 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8085 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8086 (const_int 0)))
8087 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 8088 "TARGET_THUMB1"
595d88b5 8089 "@
8090 neg\\t%0, %1\;adc\\t%0, %0, %1
8091 neg\\t%2, %1\;adc\\t%0, %1, %2"
8092 [(set_attr "length" "4")]
8093)
8094
25f905c2 8095(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 8096 [(set (match_operand:SI 0 "s_register_operand" "=l")
8097 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8098 (const_int 0)))
8099 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8100 "TARGET_THUMB1"
595d88b5 8101 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8102 [(set_attr "length" "4")]
8103)
8104
25f905c2 8105(define_insn "cstoresi_nltu_thumb1"
595d88b5 8106 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8107 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8108 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8109 "TARGET_THUMB1"
595d88b5 8110 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8111 [(set_attr "length" "4")]
8112)
8113
8114;; Used as part of the expansion of thumb les sequence.
25f905c2 8115(define_insn "thumb1_addsi3_addgeu"
595d88b5 8116 [(set (match_operand:SI 0 "s_register_operand" "=l")
8117 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8118 (match_operand:SI 2 "s_register_operand" "l"))
8119 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8120 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8121 "TARGET_THUMB1"
595d88b5 8122 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8123 [(set_attr "length" "4")]
8124)
8125
9c08d1fa 8126\f
39b5e676 8127;; Conditional move insns
8128
8129(define_expand "movsicc"
8a18b90c 8130 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 8131 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 8132 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8133 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8134 "TARGET_32BIT"
39b5e676 8135 "
215b30b3 8136 {
8137 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8138 rtx ccreg;
8139
8140 if (code == UNEQ || code == LTGT)
8141 FAIL;
39b5e676 8142
74f4459c 8143 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8144 XEXP (operands[1], 1));
29bb088d 8145 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8146 }"
8147)
39b5e676 8148
8149(define_expand "movsfcc"
8a18b90c 8150 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 8151 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8152 (match_operand:SF 2 "s_register_operand" "")
8153 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 8154 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8155 "
215b30b3 8156 {
8157 enum rtx_code code = GET_CODE (operands[1]);
8158 rtx ccreg;
f082f1c4 8159
278b301d 8160 if (code == UNEQ || code == LTGT)
8161 FAIL;
8162
215b30b3 8163 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 8164 Otherwise, ensure it is a valid FP add operand */
8165 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8166 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 8167 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8168
74f4459c 8169 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8170 XEXP (operands[1], 1));
29bb088d 8171 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8172 }"
8173)
39b5e676 8174
8175(define_expand "movdfcc"
8a18b90c 8176 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 8177 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8178 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8179 (match_operand:DF 3 "arm_float_add_operand" "")))]
25f905c2 8180 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 8181 "
215b30b3 8182 {
8183 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8184 rtx ccreg;
39b5e676 8185
278b301d 8186 if (code == UNEQ || code == LTGT)
8187 FAIL;
8188
74f4459c 8189 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8190 XEXP (operands[1], 1));
29bb088d 8191 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8192 }"
8193)
39b5e676 8194
8195(define_insn "*movsicc_insn"
f082f1c4 8196 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8197 (if_then_else:SI
8fa3ba89 8198 (match_operator 3 "arm_comparison_operator"
8a18b90c 8199 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8200 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8201 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8202 "TARGET_ARM"
39b5e676 8203 "@
8a18b90c 8204 mov%D3\\t%0, %2
8205 mvn%D3\\t%0, #%B2
f082f1c4 8206 mov%d3\\t%0, %1
8207 mvn%d3\\t%0, #%B1
8a18b90c 8208 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8209 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8210 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8211 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8212 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 8213 (set_attr "conds" "use")]
8214)
39b5e676 8215
39b5e676 8216(define_insn "*movsfcc_soft_insn"
f082f1c4 8217 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8218 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8219 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8220 (match_operand:SF 1 "s_register_operand" "0,r")
8221 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8222 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8223 "@
8224 mov%D3\\t%0, %2
8225 mov%d3\\t%0, %1"
8fa3ba89 8226 [(set_attr "conds" "use")]
8227)
39b5e676 8228
39b5e676 8229\f
9c08d1fa 8230;; Jump and linkage insns
8231
cffb2a26 8232(define_expand "jump"
9c08d1fa 8233 [(set (pc)
8234 (label_ref (match_operand 0 "" "")))]
cffb2a26 8235 "TARGET_EITHER"
9c08d1fa 8236 ""
cffb2a26 8237)
8238
8239(define_insn "*arm_jump"
8240 [(set (pc)
8241 (label_ref (match_operand 0 "" "")))]
25f905c2 8242 "TARGET_32BIT"
9c08d1fa 8243 "*
0d66636f 8244 {
8245 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8246 {
8247 arm_ccfsm_state += 2;
8248 return \"\";
8249 }
8250 return \"b%?\\t%l0\";
8251 }
8252 "
8253 [(set_attr "predicable" "yes")]
8254)
9c08d1fa 8255
cffb2a26 8256(define_insn "*thumb_jump"
8257 [(set (pc)
8258 (label_ref (match_operand 0 "" "")))]
25f905c2 8259 "TARGET_THUMB1"
cffb2a26 8260 "*
8261 if (get_attr_length (insn) == 2)
8262 return \"b\\t%l0\";
8263 return \"bl\\t%l0\\t%@ far jump\";
8264 "
8265 [(set (attr "far_jump")
8266 (if_then_else
8267 (eq_attr "length" "4")
8268 (const_string "yes")
8269 (const_string "no")))
8270 (set (attr "length")
8271 (if_then_else
911ed8af 8272 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8273 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8274 (const_int 2)
8275 (const_int 4)))]
8276)
8277
d3373b54 8278(define_expand "call"
8279 [(parallel [(call (match_operand 0 "memory_operand" "")
8280 (match_operand 1 "general_operand" ""))
cffb2a26 8281 (use (match_operand 2 "" ""))
bd5b4116 8282 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8283 "TARGET_EITHER"
6c4c2133 8284 "
8285 {
bac7fc85 8286 rtx callee, pat;
bbe777ea 8287
bbe777ea 8288 /* In an untyped call, we can get NULL for operand 2. */
8289 if (operands[2] == NULL_RTX)
8290 operands[2] = const0_rtx;
8291
de55252a 8292 /* Decide if we should generate indirect calls by loading the
85c36fd1 8293 32-bit address of the callee into a register before performing the
de55252a 8294 branch and link. */
8295 callee = XEXP (operands[0], 0);
8296 if (GET_CODE (callee) == SYMBOL_REF
8297 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8298 : !REG_P (callee))
bbe777ea 8299 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8300
8301 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8302 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8303 DONE;
6c4c2133 8304 }"
8305)
d3373b54 8306
bac7fc85 8307(define_expand "call_internal"
8308 [(parallel [(call (match_operand 0 "memory_operand" "")
8309 (match_operand 1 "general_operand" ""))
8310 (use (match_operand 2 "" ""))
8311 (clobber (reg:SI LR_REGNUM))])])
8312
f1039640 8313(define_insn "*call_reg_armv5"
d3373b54 8314 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8315 (match_operand 1 "" ""))
8316 (use (match_operand 2 "" ""))
bd5b4116 8317 (clobber (reg:SI LR_REGNUM))]
f1039640 8318 "TARGET_ARM && arm_arch5"
8319 "blx%?\\t%0"
8320 [(set_attr "type" "call")]
8321)
8322
8323(define_insn "*call_reg_arm"
8324 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8325 (match_operand 1 "" ""))
8326 (use (match_operand 2 "" ""))
8327 (clobber (reg:SI LR_REGNUM))]
8328 "TARGET_ARM && !arm_arch5"
9c08d1fa 8329 "*
5565501b 8330 return output_call (operands);
cffb2a26 8331 "
8332 ;; length is worst case, normally it is only two
8333 [(set_attr "length" "12")
8334 (set_attr "type" "call")]
8335)
9c08d1fa 8336
f7fbdd4a 8337(define_insn "*call_mem"
a3c63a9d 8338 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8339 (match_operand 1 "" ""))
8340 (use (match_operand 2 "" ""))
bd5b4116 8341 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8342 "TARGET_ARM"
9c08d1fa 8343 "*
5565501b 8344 return output_call_mem (operands);
cffb2a26 8345 "
8346 [(set_attr "length" "12")
8347 (set_attr "type" "call")]
8348)
8349
25f905c2 8350(define_insn "*call_reg_thumb1_v5"
cffb2a26 8351 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8352 (match_operand 1 "" ""))
8353 (use (match_operand 2 "" ""))
bd5b4116 8354 (clobber (reg:SI LR_REGNUM))]
25f905c2 8355 "TARGET_THUMB1 && arm_arch5"
f1039640 8356 "blx\\t%0"
8357 [(set_attr "length" "2")
8358 (set_attr "type" "call")]
cffb2a26 8359)
8360
25f905c2 8361(define_insn "*call_reg_thumb1"
f1039640 8362 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8363 (match_operand 1 "" ""))
8364 (use (match_operand 2 "" ""))
bd5b4116 8365 (clobber (reg:SI LR_REGNUM))]
25f905c2 8366 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8367 "*
8368 {
150502c9 8369 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8370 return thumb_call_via_reg (operands[0]);
150502c9 8371 else if (operands[1] == const0_rtx)
f1039640 8372 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8373 else if (frame_pointer_needed)
8374 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8375 else
150502c9 8376 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8377 }"
8378 [(set_attr "type" "call")]
8379)
9c08d1fa 8380
d3373b54 8381(define_expand "call_value"
e0698af7 8382 [(parallel [(set (match_operand 0 "" "")
8383 (call (match_operand 1 "memory_operand" "")
8384 (match_operand 2 "general_operand" "")))
cffb2a26 8385 (use (match_operand 3 "" ""))
bd5b4116 8386 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8387 "TARGET_EITHER"
6c4c2133 8388 "
8389 {
bac7fc85 8390 rtx pat, callee;
bbe777ea 8391
8392 /* In an untyped call, we can get NULL for operand 2. */
8393 if (operands[3] == 0)
8394 operands[3] = const0_rtx;
8395
de55252a 8396 /* Decide if we should generate indirect calls by loading the
8397 32-bit address of the callee into a register before performing the
8398 branch and link. */
8399 callee = XEXP (operands[1], 0);
8400 if (GET_CODE (callee) == SYMBOL_REF
8401 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8402 : !REG_P (callee))
78fe751b 8403 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8404
8405 pat = gen_call_value_internal (operands[0], operands[1],
8406 operands[2], operands[3]);
8407 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8408 DONE;
6c4c2133 8409 }"
8410)
d3373b54 8411
bac7fc85 8412(define_expand "call_value_internal"
8413 [(parallel [(set (match_operand 0 "" "")
8414 (call (match_operand 1 "memory_operand" "")
8415 (match_operand 2 "general_operand" "")))
8416 (use (match_operand 3 "" ""))
8417 (clobber (reg:SI LR_REGNUM))])])
8418
f1039640 8419(define_insn "*call_value_reg_armv5"
27ed6835 8420 [(set (match_operand 0 "" "")
755eb2b4 8421 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8422 (match_operand 2 "" "")))
bbe777ea 8423 (use (match_operand 3 "" ""))
bd5b4116 8424 (clobber (reg:SI LR_REGNUM))]
f1039640 8425 "TARGET_ARM && arm_arch5"
8426 "blx%?\\t%1"
8427 [(set_attr "type" "call")]
8428)
8429
8430(define_insn "*call_value_reg_arm"
8431 [(set (match_operand 0 "" "")
8432 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8433 (match_operand 2 "" "")))
8434 (use (match_operand 3 "" ""))
8435 (clobber (reg:SI LR_REGNUM))]
8436 "TARGET_ARM && !arm_arch5"
9c08d1fa 8437 "*
215b30b3 8438 return output_call (&operands[1]);
cffb2a26 8439 "
8440 [(set_attr "length" "12")
8441 (set_attr "type" "call")]
8442)
9c08d1fa 8443
f7fbdd4a 8444(define_insn "*call_value_mem"
27ed6835 8445 [(set (match_operand 0 "" "")
a3c63a9d 8446 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8447 (match_operand 2 "" "")))
bbe777ea 8448 (use (match_operand 3 "" ""))
bd5b4116 8449 (clobber (reg:SI LR_REGNUM))]
215b30b3 8450 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8451 "*
215b30b3 8452 return output_call_mem (&operands[1]);
cffb2a26 8453 "
8454 [(set_attr "length" "12")
8455 (set_attr "type" "call")]
8456)
9c08d1fa 8457
25f905c2 8458(define_insn "*call_value_reg_thumb1_v5"
f1039640 8459 [(set (match_operand 0 "" "")
8460 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8461 (match_operand 2 "" "")))
8462 (use (match_operand 3 "" ""))
8463 (clobber (reg:SI LR_REGNUM))]
25f905c2 8464 "TARGET_THUMB1 && arm_arch5"
f1039640 8465 "blx\\t%1"
8466 [(set_attr "length" "2")
8467 (set_attr "type" "call")]
8468)
8469
25f905c2 8470(define_insn "*call_value_reg_thumb1"
f1039640 8471 [(set (match_operand 0 "" "")
8472 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8473 (match_operand 2 "" "")))
8474 (use (match_operand 3 "" ""))
8475 (clobber (reg:SI LR_REGNUM))]
25f905c2 8476 "TARGET_THUMB1 && !arm_arch5"
f1039640 8477 "*
8478 {
150502c9 8479 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8480 return thumb_call_via_reg (operands[1]);
150502c9 8481 else if (operands[2] == const0_rtx)
f1039640 8482 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8483 else if (frame_pointer_needed)
8484 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8485 else
150502c9 8486 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8487 }"
8488 [(set_attr "type" "call")]
8489)
8490
9c08d1fa 8491;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8492;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8493
f7fbdd4a 8494(define_insn "*call_symbol"
27ed6835 8495 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8496 (match_operand 1 "" ""))
bbe777ea 8497 (use (match_operand 2 "" ""))
bd5b4116 8498 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8499 "TARGET_ARM
8500 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8501 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8502 "*
8503 {
55c1e470 8504 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8505 }"
cffb2a26 8506 [(set_attr "type" "call")]
8507)
9c08d1fa 8508
f7fbdd4a 8509(define_insn "*call_value_symbol"
ccd90aaa 8510 [(set (match_operand 0 "" "")
27ed6835 8511 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8512 (match_operand:SI 2 "" "")))
bbe777ea 8513 (use (match_operand 3 "" ""))
bd5b4116 8514 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8515 "TARGET_ARM
8516 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8517 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8518 "*
8519 {
55c1e470 8520 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8521 }"
cffb2a26 8522 [(set_attr "type" "call")]
8523)
8524
8525(define_insn "*call_insn"
27ed6835 8526 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8527 (match_operand:SI 1 "" ""))
8528 (use (match_operand 2 "" ""))
bd5b4116 8529 (clobber (reg:SI LR_REGNUM))]
1c494086 8530 "TARGET_THUMB
1675c6e9 8531 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8532 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8533 "bl\\t%a0"
8534 [(set_attr "length" "4")
8535 (set_attr "type" "call")]
8536)
8537
8538(define_insn "*call_value_insn"
ccd90aaa 8539 [(set (match_operand 0 "" "")
27ed6835 8540 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8541 (match_operand 2 "" "")))
8542 (use (match_operand 3 "" ""))
bd5b4116 8543 (clobber (reg:SI LR_REGNUM))]
1c494086 8544 "TARGET_THUMB
1675c6e9 8545 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8546 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8547 "bl\\t%a1"
8548 [(set_attr "length" "4")
8549 (set_attr "type" "call")]
8550)
9c08d1fa 8551
1c494086 8552;; We may also be able to do sibcalls for Thumb, but it's much harder...
8553(define_expand "sibcall"
8554 [(parallel [(call (match_operand 0 "memory_operand" "")
8555 (match_operand 1 "general_operand" ""))
2ba80634 8556 (return)
8557 (use (match_operand 2 "" ""))])]
1c494086 8558 "TARGET_ARM"
8559 "
8560 {
8561 if (operands[2] == NULL_RTX)
8562 operands[2] = const0_rtx;
1c494086 8563 }"
8564)
8565
8566(define_expand "sibcall_value"
ccd90aaa 8567 [(parallel [(set (match_operand 0 "" "")
1c494086 8568 (call (match_operand 1 "memory_operand" "")
8569 (match_operand 2 "general_operand" "")))
2ba80634 8570 (return)
8571 (use (match_operand 3 "" ""))])]
1c494086 8572 "TARGET_ARM"
8573 "
8574 {
8575 if (operands[3] == NULL_RTX)
8576 operands[3] = const0_rtx;
1c494086 8577 }"
8578)
8579
8580(define_insn "*sibcall_insn"
8581 [(call (mem:SI (match_operand:SI 0 "" "X"))
8582 (match_operand 1 "" ""))
2ba80634 8583 (return)
8584 (use (match_operand 2 "" ""))]
1c494086 8585 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8586 "*
8587 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8588 "
8589 [(set_attr "type" "call")]
8590)
8591
8592(define_insn "*sibcall_value_insn"
ccd90aaa 8593 [(set (match_operand 0 "" "")
755eb2b4 8594 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8595 (match_operand 2 "" "")))
2ba80634 8596 (return)
8597 (use (match_operand 3 "" ""))]
1c494086 8598 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8599 "*
8600 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8601 "
8602 [(set_attr "type" "call")]
8603)
8604
9c08d1fa 8605;; Often the return insn will be the same as loading from memory, so set attr
8606(define_insn "return"
8607 [(return)]
cffb2a26 8608 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8609 "*
9c08d1fa 8610 {
cffb2a26 8611 if (arm_ccfsm_state == 2)
8612 {
8613 arm_ccfsm_state += 2;
8614 return \"\";
8615 }
5db468b7 8616 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8617 }"
a2cd141b 8618 [(set_attr "type" "load1")
755eb2b4 8619 (set_attr "length" "12")
0d66636f 8620 (set_attr "predicable" "yes")]
cffb2a26 8621)
9c08d1fa 8622
f7fbdd4a 8623(define_insn "*cond_return"
9c08d1fa 8624 [(set (pc)
8fa3ba89 8625 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8626 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8627 (return)
8628 (pc)))]
cffb2a26 8629 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8630 "*
8fa3ba89 8631 {
8632 if (arm_ccfsm_state == 2)
8633 {
8634 arm_ccfsm_state += 2;
8635 return \"\";
8636 }
8637 return output_return_instruction (operands[0], TRUE, FALSE);
8638 }"
8639 [(set_attr "conds" "use")
755eb2b4 8640 (set_attr "length" "12")
a2cd141b 8641 (set_attr "type" "load1")]
8fa3ba89 8642)
9c08d1fa 8643
f7fbdd4a 8644(define_insn "*cond_return_inverted"
9c08d1fa 8645 [(set (pc)
8fa3ba89 8646 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8647 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8648 (pc)
8649 (return)))]
cffb2a26 8650 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8651 "*
8fa3ba89 8652 {
8653 if (arm_ccfsm_state == 2)
8654 {
8655 arm_ccfsm_state += 2;
8656 return \"\";
8657 }
8658 return output_return_instruction (operands[0], TRUE, TRUE);
8659 }"
8660 [(set_attr "conds" "use")
37a1317b 8661 (set_attr "length" "12")
a2cd141b 8662 (set_attr "type" "load1")]
8fa3ba89 8663)
9c08d1fa 8664
68121397 8665;; Generate a sequence of instructions to determine if the processor is
8666;; in 26-bit or 32-bit mode, and return the appropriate return address
8667;; mask.
8668
8669(define_expand "return_addr_mask"
8670 [(set (match_dup 1)
8671 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8672 (const_int 0)))
8673 (set (match_operand:SI 0 "s_register_operand" "")
8674 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8675 (const_int -1)
8676 (const_int 67108860)))] ; 0x03fffffc
8677 "TARGET_ARM"
8678 "
62eddbd4 8679 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8680 ")
8681
8682(define_insn "*check_arch2"
8683 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8684 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8685 (const_int 0)))]
8686 "TARGET_ARM"
8687 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8688 [(set_attr "length" "8")
8689 (set_attr "conds" "set")]
8690)
8691
9c08d1fa 8692;; Call subroutine returning any type.
8693
8694(define_expand "untyped_call"
8695 [(parallel [(call (match_operand 0 "" "")
8696 (const_int 0))
8697 (match_operand 1 "" "")
8698 (match_operand 2 "" "")])]
ccd90aaa 8699 "TARGET_EITHER"
9c08d1fa 8700 "
215b30b3 8701 {
8702 int i;
ccd90aaa 8703 rtx par = gen_rtx_PARALLEL (VOIDmode,
8704 rtvec_alloc (XVECLEN (operands[2], 0)));
8705 rtx addr = gen_reg_rtx (Pmode);
8706 rtx mem;
8707 int size = 0;
9c08d1fa 8708
ccd90aaa 8709 emit_move_insn (addr, XEXP (operands[1], 0));
8710 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8711
215b30b3 8712 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8713 {
ccd90aaa 8714 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8715
ccd90aaa 8716 /* Default code only uses r0 as a return value, but we could
8717 be using anything up to 4 registers. */
8718 if (REGNO (src) == R0_REGNUM)
8719 src = gen_rtx_REG (TImode, R0_REGNUM);
8720
8721 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8722 GEN_INT (size));
8723 size += GET_MODE_SIZE (GET_MODE (src));
8724 }
8725
8726 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8727 const0_rtx));
8728
8729 size = 0;
8730
8731 for (i = 0; i < XVECLEN (par, 0); i++)
8732 {
8733 HOST_WIDE_INT offset = 0;
8734 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8735
8736 if (size != 0)
8737 emit_move_insn (addr, plus_constant (addr, size));
8738
8739 mem = change_address (mem, GET_MODE (reg), NULL);
8740 if (REGNO (reg) == R0_REGNUM)
8741 {
8742 /* On thumb we have to use a write-back instruction. */
8743 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8744 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8745 size = TARGET_ARM ? 16 : 0;
8746 }
8747 else
8748 {
8749 emit_move_insn (mem, reg);
8750 size = GET_MODE_SIZE (GET_MODE (reg));
8751 }
215b30b3 8752 }
9c08d1fa 8753
215b30b3 8754 /* The optimizer does not know that the call sets the function value
8755 registers we stored in the result block. We avoid problems by
8756 claiming that all hard registers are used and clobbered at this
8757 point. */
8758 emit_insn (gen_blockage ());
8759
8760 DONE;
8761 }"
8762)
9c08d1fa 8763
ccd90aaa 8764(define_expand "untyped_return"
8765 [(match_operand:BLK 0 "memory_operand" "")
8766 (match_operand 1 "" "")]
8767 "TARGET_EITHER"
8768 "
8769 {
8770 int i;
8771 rtx addr = gen_reg_rtx (Pmode);
8772 rtx mem;
8773 int size = 0;
8774
8775 emit_move_insn (addr, XEXP (operands[0], 0));
8776 mem = change_address (operands[0], BLKmode, addr);
8777
8778 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8779 {
8780 HOST_WIDE_INT offset = 0;
8781 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8782
8783 if (size != 0)
8784 emit_move_insn (addr, plus_constant (addr, size));
8785
8786 mem = change_address (mem, GET_MODE (reg), NULL);
8787 if (REGNO (reg) == R0_REGNUM)
8788 {
8789 /* On thumb we have to use a write-back instruction. */
8790 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8791 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8792 size = TARGET_ARM ? 16 : 0;
8793 }
8794 else
8795 {
8796 emit_move_insn (reg, mem);
8797 size = GET_MODE_SIZE (GET_MODE (reg));
8798 }
8799 }
8800
8801 /* Emit USE insns before the return. */
8802 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8803 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8804
8805 /* Construct the return. */
8806 expand_naked_return ();
8807
8808 DONE;
8809 }"
8810)
8811
9c08d1fa 8812;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8813;; all of memory. This blocks insns from being moved across this point.
8814
8815(define_insn "blockage"
e1159bbe 8816 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8817 "TARGET_EITHER"
9c08d1fa 8818 ""
cffb2a26 8819 [(set_attr "length" "0")
8820 (set_attr "type" "block")]
8821)
9c08d1fa 8822
f7fbdd4a 8823(define_expand "casesi"
8824 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8825 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8826 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8827 (match_operand:SI 3 "" "") ; table label
8828 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8829 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8830 "
215b30b3 8831 {
e6ac8414 8832 enum insn_code code;
215b30b3 8833 if (operands[1] != const0_rtx)
8834 {
e6ac8414 8835 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8836
215b30b3 8837 emit_insn (gen_addsi3 (reg, operands[0],
8838 GEN_INT (-INTVAL (operands[1]))));
8839 operands[0] = reg;
8840 }
9c08d1fa 8841
25f905c2 8842 if (TARGET_ARM)
e6ac8414 8843 code = CODE_FOR_arm_casesi_internal;
3db2019b 8844 else if (TARGET_THUMB1)
e6ac8414 8845 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8846 else if (flag_pic)
e6ac8414 8847 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8848 else
e6ac8414 8849 code = CODE_FOR_thumb2_casesi_internal;
8850
8851 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8852 operands[2] = force_reg (SImode, operands[2]);
8853
8854 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8855 operands[3], operands[4]));
215b30b3 8856 DONE;
8857 }"
8858)
f7fbdd4a 8859
f082f1c4 8860;; The USE in this pattern is needed to tell flow analysis that this is
8861;; a CASESI insn. It has no other purpose.
25f905c2 8862(define_insn "arm_casesi_internal"
f082f1c4 8863 [(parallel [(set (pc)
8864 (if_then_else
8865 (leu (match_operand:SI 0 "s_register_operand" "r")
8866 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8867 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8868 (label_ref (match_operand 2 "" ""))))
8869 (label_ref (match_operand 3 "" ""))))
bd5b4116 8870 (clobber (reg:CC CC_REGNUM))
f082f1c4 8871 (use (label_ref (match_dup 2)))])]
cffb2a26 8872 "TARGET_ARM"
f7fbdd4a 8873 "*
0d66636f 8874 if (flag_pic)
8875 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8876 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8877 "
8878 [(set_attr "conds" "clob")
8879 (set_attr "length" "12")]
8880)
9c08d1fa 8881
e6ac8414 8882(define_expand "thumb1_casesi_internal_pic"
8883 [(match_operand:SI 0 "s_register_operand" "")
8884 (match_operand:SI 1 "thumb1_cmp_operand" "")
8885 (match_operand 2 "" "")
8886 (match_operand 3 "" "")]
3db2019b 8887 "TARGET_THUMB1"
e6ac8414 8888 {
8889 rtx reg0;
8890 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8891 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8892 operands[3]));
8893 reg0 = gen_rtx_REG (SImode, 0);
8894 emit_move_insn (reg0, operands[0]);
8895 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8896 DONE;
8897 }
8898)
8899
8900(define_insn "thumb1_casesi_dispatch"
8901 [(parallel [(set (pc) (unspec [(reg:SI 0)
8902 (label_ref (match_operand 0 "" ""))
8903;; (label_ref (match_operand 1 "" ""))
8904]
8905 UNSPEC_THUMB1_CASESI))
8906 (clobber (reg:SI IP_REGNUM))
8907 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8908 "TARGET_THUMB1"
e6ac8414 8909 "* return thumb1_output_casesi(operands);"
8910 [(set_attr "length" "4")]
8911)
8912
cffb2a26 8913(define_expand "indirect_jump"
9c08d1fa 8914 [(set (pc)
cffb2a26 8915 (match_operand:SI 0 "s_register_operand" ""))]
8916 "TARGET_EITHER"
25f905c2 8917 "
8918 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8919 address and use bx. */
8920 if (TARGET_THUMB2)
8921 {
8922 rtx tmp;
8923 tmp = gen_reg_rtx (SImode);
8924 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8925 operands[0] = tmp;
8926 }
8927 "
cffb2a26 8928)
8929
f1039640 8930;; NB Never uses BX.
cffb2a26 8931(define_insn "*arm_indirect_jump"
8932 [(set (pc)
8933 (match_operand:SI 0 "s_register_operand" "r"))]
8934 "TARGET_ARM"
8935 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8936 [(set_attr "predicable" "yes")]
cffb2a26 8937)
9c08d1fa 8938
f7fbdd4a 8939(define_insn "*load_indirect_jump"
9c08d1fa 8940 [(set (pc)
8941 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8942 "TARGET_ARM"
8943 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8944 [(set_attr "type" "load1")
61a2d04c 8945 (set_attr "pool_range" "4096")
8946 (set_attr "neg_pool_range" "4084")
0d66636f 8947 (set_attr "predicable" "yes")]
cffb2a26 8948)
8949
f1039640 8950;; NB Never uses BX.
25f905c2 8951(define_insn "*thumb1_indirect_jump"
cffb2a26 8952 [(set (pc)
8953 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8954 "TARGET_THUMB1"
cffb2a26 8955 "mov\\tpc, %0"
8956 [(set_attr "conds" "clob")
8957 (set_attr "length" "2")]
8958)
8959
9c08d1fa 8960\f
8961;; Misc insns
8962
8963(define_insn "nop"
8964 [(const_int 0)]
cffb2a26 8965 "TARGET_EITHER"
8966 "*
25f905c2 8967 if (TARGET_UNIFIED_ASM)
8968 return \"nop\";
cffb2a26 8969 if (TARGET_ARM)
8970 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8971 return \"mov\\tr8, r8\";
8972 "
8973 [(set (attr "length")
8974 (if_then_else (eq_attr "is_thumb" "yes")
8975 (const_int 2)
8976 (const_int 4)))]
8977)
8978
9c08d1fa 8979\f
8980;; Patterns to allow combination of arithmetic, cond code and shifts
8981
f7fbdd4a 8982(define_insn "*arith_shiftsi"
9c08d1fa 8983 [(set (match_operand:SI 0 "s_register_operand" "=r")
8984 (match_operator:SI 1 "shiftable_operator"
8985 [(match_operator:SI 3 "shift_operator"
8986 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8987 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8988 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 8989 "TARGET_ARM"
6c4c2133 8990 "%i1%?\\t%0, %2, %4%S3"
344495ea 8991 [(set_attr "predicable" "yes")
331beb1a 8992 (set_attr "shift" "4")
a2cd141b 8993 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8994 (const_string "alu_shift")
8995 (const_string "alu_shift_reg")))]
6c4c2133 8996)
9c08d1fa 8997
d7863cfe 8998(define_split
8999 [(set (match_operand:SI 0 "s_register_operand" "")
9000 (match_operator:SI 1 "shiftable_operator"
9001 [(match_operator:SI 2 "shiftable_operator"
9002 [(match_operator:SI 3 "shift_operator"
9003 [(match_operand:SI 4 "s_register_operand" "")
9004 (match_operand:SI 5 "reg_or_int_operand" "")])
9005 (match_operand:SI 6 "s_register_operand" "")])
9006 (match_operand:SI 7 "arm_rhs_operand" "")]))
9007 (clobber (match_operand:SI 8 "s_register_operand" ""))]
9008 "TARGET_ARM"
9009 [(set (match_dup 8)
9010 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9011 (match_dup 6)]))
9012 (set (match_dup 0)
9013 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9014 "")
9015
f7fbdd4a 9016(define_insn "*arith_shiftsi_compare0"
bd5b4116 9017 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 9018 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9019 [(match_operator:SI 3 "shift_operator"
9020 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9021 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9022 (match_operand:SI 2 "s_register_operand" "r")])
9023 (const_int 0)))
9024 (set (match_operand:SI 0 "s_register_operand" "=r")
9025 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9026 (match_dup 2)]))]
cffb2a26 9027 "TARGET_ARM"
25f905c2 9028 "%i1%.\\t%0, %2, %4%S3"
344495ea 9029 [(set_attr "conds" "set")
331beb1a 9030 (set_attr "shift" "4")
a2cd141b 9031 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9032 (const_string "alu_shift")
9033 (const_string "alu_shift_reg")))]
0d66636f 9034)
9c08d1fa 9035
f7fbdd4a 9036(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9037 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 9038 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9039 [(match_operator:SI 3 "shift_operator"
9040 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9041 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9042 (match_operand:SI 2 "s_register_operand" "r")])
9043 (const_int 0)))
9044 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 9045 "TARGET_ARM"
25f905c2 9046 "%i1%.\\t%0, %2, %4%S3"
344495ea 9047 [(set_attr "conds" "set")
331beb1a 9048 (set_attr "shift" "4")
a2cd141b 9049 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9050 (const_string "alu_shift")
9051 (const_string "alu_shift_reg")))]
0d66636f 9052)
9c08d1fa 9053
f7fbdd4a 9054(define_insn "*sub_shiftsi"
9c08d1fa 9055 [(set (match_operand:SI 0 "s_register_operand" "=r")
9056 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9057 (match_operator:SI 2 "shift_operator"
9058 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9059 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 9060 "TARGET_ARM"
6c4c2133 9061 "sub%?\\t%0, %1, %3%S2"
344495ea 9062 [(set_attr "predicable" "yes")
331beb1a 9063 (set_attr "shift" "3")
a2cd141b 9064 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9065 (const_string "alu_shift")
9066 (const_string "alu_shift_reg")))]
6c4c2133 9067)
9c08d1fa 9068
f7fbdd4a 9069(define_insn "*sub_shiftsi_compare0"
bd5b4116 9070 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9071 (compare:CC_NOOV
9072 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9073 (match_operator:SI 2 "shift_operator"
9074 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9075 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 9076 (const_int 0)))
9c08d1fa 9077 (set (match_operand:SI 0 "s_register_operand" "=r")
9078 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9079 (match_dup 4)])))]
cffb2a26 9080 "TARGET_ARM"
25f905c2 9081 "sub%.\\t%0, %1, %3%S2"
344495ea 9082 [(set_attr "conds" "set")
a2cd141b 9083 (set_attr "shift" "3")
9084 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9085 (const_string "alu_shift")
9086 (const_string "alu_shift_reg")))]
0d66636f 9087)
9c08d1fa 9088
f7fbdd4a 9089(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9090 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9091 (compare:CC_NOOV
9092 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9093 (match_operator:SI 2 "shift_operator"
9094 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9095 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 9096 (const_int 0)))
9c08d1fa 9097 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 9098 "TARGET_ARM"
25f905c2 9099 "sub%.\\t%0, %1, %3%S2"
344495ea 9100 [(set_attr "conds" "set")
a2cd141b 9101 (set_attr "shift" "3")
9102 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9103 (const_string "alu_shift")
9104 (const_string "alu_shift_reg")))]
0d66636f 9105)
9c08d1fa 9106
9c08d1fa 9107\f
9108
f7fbdd4a 9109(define_insn "*and_scc"
9c08d1fa 9110 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9111 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9112 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9113 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9114 "TARGET_ARM"
e2348bcb 9115 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9116 [(set_attr "conds" "use")
9117 (set_attr "length" "8")]
9118)
9c08d1fa 9119
f7fbdd4a 9120(define_insn "*ior_scc"
9c08d1fa 9121 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9122 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9123 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9124 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9125 "TARGET_ARM"
e2348bcb 9126 "@
899850b0 9127 orr%d2\\t%0, %1, #1
9128 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9129 [(set_attr "conds" "use")
9130 (set_attr "length" "4,8")]
9131)
9c08d1fa 9132
f7fbdd4a 9133(define_insn "*compare_scc"
5565501b 9134 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9135 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9136 [(match_operand:SI 2 "s_register_operand" "r,r")
9137 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9138 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9139 "TARGET_ARM"
9c08d1fa 9140 "*
601f584c 9141 if (operands[3] == const0_rtx)
9142 {
9143 if (GET_CODE (operands[1]) == LT)
9144 return \"mov\\t%0, %2, lsr #31\";
9145
9146 if (GET_CODE (operands[1]) == GE)
9147 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 9148
601f584c 9149 if (GET_CODE (operands[1]) == EQ)
9150 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9151 }
e2348bcb 9152
8fa3ba89 9153 if (GET_CODE (operands[1]) == NE)
9154 {
9155 if (which_alternative == 1)
9156 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9157 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9158 }
9159 if (which_alternative == 1)
9160 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9161 else
9162 output_asm_insn (\"cmp\\t%2, %3\", operands);
9163 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9164 "
9165 [(set_attr "conds" "clob")
9166 (set_attr "length" "12")]
9167)
9c08d1fa 9168
f7fbdd4a 9169(define_insn "*cond_move"
9c08d1fa 9170 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9171 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9172 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9173 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9174 (const_int 0)])
9175 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9176 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9177 "TARGET_ARM"
9c08d1fa 9178 "*
8fa3ba89 9179 if (GET_CODE (operands[3]) == NE)
9180 {
9181 if (which_alternative != 1)
9182 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9183 if (which_alternative != 0)
9184 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9185 return \"\";
9186 }
9187 if (which_alternative != 0)
9188 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9189 if (which_alternative != 1)
9190 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9191 return \"\";
9192 "
9193 [(set_attr "conds" "use")
9194 (set_attr "length" "4,4,8")]
9195)
9c08d1fa 9196
f7fbdd4a 9197(define_insn "*cond_arith"
9c08d1fa 9198 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9199 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9200 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9201 [(match_operand:SI 2 "s_register_operand" "r,r")
9202 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9203 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9204 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9205 "TARGET_ARM"
9c08d1fa 9206 "*
8fa3ba89 9207 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9208 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9209
8fa3ba89 9210 output_asm_insn (\"cmp\\t%2, %3\", operands);
9211 if (GET_CODE (operands[5]) == AND)
9212 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9213 else if (GET_CODE (operands[5]) == MINUS)
9214 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9215 else if (which_alternative != 0)
9216 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9217 return \"%i5%d4\\t%0, %1, #1\";
9218 "
9219 [(set_attr "conds" "clob")
9220 (set_attr "length" "12")]
9221)
9c08d1fa 9222
f7fbdd4a 9223(define_insn "*cond_sub"
9c08d1fa 9224 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9225 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9226 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9227 [(match_operand:SI 2 "s_register_operand" "r,r")
9228 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9229 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9230 "TARGET_ARM"
9c08d1fa 9231 "*
8fa3ba89 9232 output_asm_insn (\"cmp\\t%2, %3\", operands);
9233 if (which_alternative != 0)
9234 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9235 return \"sub%d4\\t%0, %1, #1\";
9236 "
9237 [(set_attr "conds" "clob")
9238 (set_attr "length" "8,12")]
9239)
9c08d1fa 9240
25f905c2 9241;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 9242(define_insn "*cmp_ite0"
cffb2a26 9243 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9244 (compare
9245 (if_then_else:SI
8fa3ba89 9246 (match_operator 4 "arm_comparison_operator"
aea4c774 9247 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9248 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9249 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9250 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9251 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9252 (const_int 0))
9253 (const_int 0)))]
cffb2a26 9254 "TARGET_ARM"
9c08d1fa 9255 "*
aea4c774 9256 {
8fa3ba89 9257 static const char * const opcodes[4][2] =
9258 {
9259 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9260 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9261 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9262 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9263 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9264 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9265 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9266 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9267 };
9268 int swap =
9269 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9270
9271 return opcodes[which_alternative][swap];
9272 }"
9273 [(set_attr "conds" "set")
9274 (set_attr "length" "8")]
9275)
9c08d1fa 9276
aea4c774 9277(define_insn "*cmp_ite1"
cffb2a26 9278 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9279 (compare
9280 (if_then_else:SI
8fa3ba89 9281 (match_operator 4 "arm_comparison_operator"
aea4c774 9282 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 9283 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9284 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9285 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 9286 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 9287 (const_int 1))
9288 (const_int 0)))]
cffb2a26 9289 "TARGET_ARM"
9c08d1fa 9290 "*
9c08d1fa 9291 {
215b30b3 9292 static const char * const opcodes[4][2] =
9293 {
9294 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9295 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9296 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9297 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9298 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9299 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9300 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9301 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9302 };
9303 int swap =
9304 comparison_dominates_p (GET_CODE (operands[5]),
9305 reverse_condition (GET_CODE (operands[4])));
9306
9307 return opcodes[which_alternative][swap];
9308 }"
8fa3ba89 9309 [(set_attr "conds" "set")
9310 (set_attr "length" "8")]
9311)
9c08d1fa 9312
f6c53574 9313(define_insn "*cmp_and"
9314 [(set (match_operand 6 "dominant_cc_register" "")
9315 (compare
9316 (and:SI
9317 (match_operator 4 "arm_comparison_operator"
9318 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9319 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9320 (match_operator:SI 5 "arm_comparison_operator"
9321 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9322 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9323 (const_int 0)))]
9324 "TARGET_ARM"
9325 "*
9326 {
35823b64 9327 static const char *const opcodes[4][2] =
f6c53574 9328 {
9329 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9330 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9331 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9332 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9333 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9334 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9335 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9336 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9337 };
9338 int swap =
9339 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9340
9341 return opcodes[which_alternative][swap];
9342 }"
9343 [(set_attr "conds" "set")
9344 (set_attr "predicable" "no")
9345 (set_attr "length" "8")]
9346)
9347
9348(define_insn "*cmp_ior"
9349 [(set (match_operand 6 "dominant_cc_register" "")
9350 (compare
9351 (ior:SI
9352 (match_operator 4 "arm_comparison_operator"
9353 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9354 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9355 (match_operator:SI 5 "arm_comparison_operator"
9356 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9357 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9358 (const_int 0)))]
9359 "TARGET_ARM"
9360 "*
9361{
35823b64 9362 static const char *const opcodes[4][2] =
f6c53574 9363 {
9364 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9365 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9366 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9367 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9368 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9369 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9370 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9371 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9372 };
9373 int swap =
9374 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9375
9376 return opcodes[which_alternative][swap];
9377}
9378"
9379 [(set_attr "conds" "set")
9380 (set_attr "length" "8")]
9381)
9382
3c5afce6 9383(define_insn_and_split "*ior_scc_scc"
9384 [(set (match_operand:SI 0 "s_register_operand" "=r")
9385 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9386 [(match_operand:SI 1 "s_register_operand" "r")
9387 (match_operand:SI 2 "arm_add_operand" "rIL")])
9388 (match_operator:SI 6 "arm_comparison_operator"
9389 [(match_operand:SI 4 "s_register_operand" "r")
9390 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9391 (clobber (reg:CC CC_REGNUM))]
9392 "TARGET_ARM
9393 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9394 != CCmode)"
9395 "#"
9396 "TARGET_ARM && reload_completed"
9397 [(set (match_dup 7)
9398 (compare
9399 (ior:SI
9400 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9401 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9402 (const_int 0)))
9403 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9404 "operands[7]
9405 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9406 DOM_CC_X_OR_Y),
601f584c 9407 CC_REGNUM);"
9408 [(set_attr "conds" "clob")
9409 (set_attr "length" "16")])
9410
9411; If the above pattern is followed by a CMP insn, then the compare is
9412; redundant, since we can rework the conditional instruction that follows.
9413(define_insn_and_split "*ior_scc_scc_cmp"
9414 [(set (match_operand 0 "dominant_cc_register" "")
9415 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9416 [(match_operand:SI 1 "s_register_operand" "r")
9417 (match_operand:SI 2 "arm_add_operand" "rIL")])
9418 (match_operator:SI 6 "arm_comparison_operator"
9419 [(match_operand:SI 4 "s_register_operand" "r")
9420 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9421 (const_int 0)))
9422 (set (match_operand:SI 7 "s_register_operand" "=r")
9423 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9424 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9425 "TARGET_ARM"
9426 "#"
9427 "TARGET_ARM && reload_completed"
9428 [(set (match_dup 0)
9429 (compare
9430 (ior:SI
9431 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9432 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9433 (const_int 0)))
9434 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9435 ""
9436 [(set_attr "conds" "set")
9437 (set_attr "length" "16")])
3c5afce6 9438
9439(define_insn_and_split "*and_scc_scc"
9440 [(set (match_operand:SI 0 "s_register_operand" "=r")
9441 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9442 [(match_operand:SI 1 "s_register_operand" "r")
9443 (match_operand:SI 2 "arm_add_operand" "rIL")])
9444 (match_operator:SI 6 "arm_comparison_operator"
9445 [(match_operand:SI 4 "s_register_operand" "r")
9446 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9447 (clobber (reg:CC CC_REGNUM))]
9448 "TARGET_ARM
9449 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9450 != CCmode)"
9451 "#"
601f584c 9452 "TARGET_ARM && reload_completed
9453 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9454 != CCmode)"
3c5afce6 9455 [(set (match_dup 7)
9456 (compare
9457 (and:SI
9458 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9459 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9460 (const_int 0)))
9461 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9462 "operands[7]
9463 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9464 DOM_CC_X_AND_Y),
601f584c 9465 CC_REGNUM);"
9466 [(set_attr "conds" "clob")
9467 (set_attr "length" "16")])
9468
9469; If the above pattern is followed by a CMP insn, then the compare is
9470; redundant, since we can rework the conditional instruction that follows.
9471(define_insn_and_split "*and_scc_scc_cmp"
9472 [(set (match_operand 0 "dominant_cc_register" "")
9473 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9474 [(match_operand:SI 1 "s_register_operand" "r")
9475 (match_operand:SI 2 "arm_add_operand" "rIL")])
9476 (match_operator:SI 6 "arm_comparison_operator"
9477 [(match_operand:SI 4 "s_register_operand" "r")
9478 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9479 (const_int 0)))
9480 (set (match_operand:SI 7 "s_register_operand" "=r")
9481 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9482 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9483 "TARGET_ARM"
9484 "#"
9485 "TARGET_ARM && reload_completed"
9486 [(set (match_dup 0)
9487 (compare
9488 (and:SI
9489 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9490 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9491 (const_int 0)))
9492 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9493 ""
9494 [(set_attr "conds" "set")
9495 (set_attr "length" "16")])
9496
9497;; If there is no dominance in the comparison, then we can still save an
9498;; instruction in the AND case, since we can know that the second compare
9499;; need only zero the value if false (if true, then the value is already
9500;; correct).
9501(define_insn_and_split "*and_scc_scc_nodom"
9502 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9503 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9504 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9505 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9506 (match_operator:SI 6 "arm_comparison_operator"
9507 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9508 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9509 (clobber (reg:CC CC_REGNUM))]
9510 "TARGET_ARM
9511 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9512 == CCmode)"
9513 "#"
9514 "TARGET_ARM && reload_completed"
9515 [(parallel [(set (match_dup 0)
9516 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9517 (clobber (reg:CC CC_REGNUM))])
9518 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9519 (set (match_dup 0)
9520 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9521 (match_dup 0)
9522 (const_int 0)))]
9523 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9524 operands[4], operands[5]),
9525 CC_REGNUM);
9526 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9527 operands[5]);"
9528 [(set_attr "conds" "clob")
9529 (set_attr "length" "20")])
3c5afce6 9530
3a0bdee0 9531(define_split
9532 [(set (reg:CC_NOOV CC_REGNUM)
9533 (compare:CC_NOOV (ior:SI
9534 (and:SI (match_operand:SI 0 "s_register_operand" "")
9535 (const_int 1))
b0694be0 9536 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9537 [(match_operand:SI 2 "s_register_operand" "")
9538 (match_operand:SI 3 "arm_add_operand" "")]))
9539 (const_int 0)))
9540 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9541 "TARGET_ARM"
9542 [(set (match_dup 4)
9543 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9544 (match_dup 0)))
9545 (set (reg:CC_NOOV CC_REGNUM)
9546 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9547 (const_int 0)))]
9548 "")
9549
9550(define_split
9551 [(set (reg:CC_NOOV CC_REGNUM)
9552 (compare:CC_NOOV (ior:SI
b0694be0 9553 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9554 [(match_operand:SI 2 "s_register_operand" "")
9555 (match_operand:SI 3 "arm_add_operand" "")])
9556 (and:SI (match_operand:SI 0 "s_register_operand" "")
9557 (const_int 1)))
9558 (const_int 0)))
9559 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9560 "TARGET_ARM"
9561 [(set (match_dup 4)
9562 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9563 (match_dup 0)))
9564 (set (reg:CC_NOOV CC_REGNUM)
9565 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9566 (const_int 0)))]
9567 "")
25f905c2 9568;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9569
f7fbdd4a 9570(define_insn "*negscc"
9c08d1fa 9571 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9572 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9573 [(match_operand:SI 1 "s_register_operand" "r")
9574 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9575 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9576 "TARGET_ARM"
9c08d1fa 9577 "*
2ca2ec2e 9578 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9579 return \"mov\\t%0, %1, asr #31\";
9580
9c08d1fa 9581 if (GET_CODE (operands[3]) == NE)
e2348bcb 9582 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9583
e2348bcb 9584 output_asm_insn (\"cmp\\t%1, %2\", operands);
9585 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9586 return \"mvn%d3\\t%0, #0\";
215b30b3 9587 "
8fa3ba89 9588 [(set_attr "conds" "clob")
9589 (set_attr "length" "12")]
9590)
9c08d1fa 9591
9592(define_insn "movcond"
9593 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9594 (if_then_else:SI
8fa3ba89 9595 (match_operator 5 "arm_comparison_operator"
5565501b 9596 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9597 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9598 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9599 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9600 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9601 "TARGET_ARM"
9c08d1fa 9602 "*
9603 if (GET_CODE (operands[5]) == LT
9604 && (operands[4] == const0_rtx))
9605 {
5565501b 9606 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9607 {
9c08d1fa 9608 if (operands[2] == const0_rtx)
e2348bcb 9609 return \"and\\t%0, %1, %3, asr #31\";
9610 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9611 }
9612 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9613 {
9c08d1fa 9614 if (operands[1] == const0_rtx)
e2348bcb 9615 return \"bic\\t%0, %2, %3, asr #31\";
9616 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9617 }
9618 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9619 are constants. */
9c08d1fa 9620 }
e2348bcb 9621
9c08d1fa 9622 if (GET_CODE (operands[5]) == GE
9623 && (operands[4] == const0_rtx))
9624 {
9625 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9626 {
9c08d1fa 9627 if (operands[2] == const0_rtx)
e2348bcb 9628 return \"bic\\t%0, %1, %3, asr #31\";
9629 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9630 }
9631 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9632 {
9c08d1fa 9633 if (operands[1] == const0_rtx)
e2348bcb 9634 return \"and\\t%0, %2, %3, asr #31\";
9635 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9636 }
9637 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9638 are constants. */
9c08d1fa 9639 }
9640 if (GET_CODE (operands[4]) == CONST_INT
9641 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9642 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9643 else
e2348bcb 9644 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9645 if (which_alternative != 0)
e2348bcb 9646 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9647 if (which_alternative != 1)
e2348bcb 9648 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9649 return \"\";
215b30b3 9650 "
8fa3ba89 9651 [(set_attr "conds" "clob")
9652 (set_attr "length" "8,8,12")]
9653)
9c08d1fa 9654
25f905c2 9655;; ??? The patterns below need checking for Thumb-2 usefulness.
9656
8a18b90c 9657(define_insn "*ifcompare_plus_move"
9658 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9659 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9660 [(match_operand:SI 4 "s_register_operand" "r,r")
9661 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9662 (plus:SI
9663 (match_operand:SI 2 "s_register_operand" "r,r")
9664 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9665 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9666 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9667 "TARGET_ARM"
8a18b90c 9668 "#"
8fa3ba89 9669 [(set_attr "conds" "clob")
9670 (set_attr "length" "8,12")]
9671)
8a18b90c 9672
9673(define_insn "*if_plus_move"
129a2fe4 9674 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9675 (if_then_else:SI
8fa3ba89 9676 (match_operator 4 "arm_comparison_operator"
8a18b90c 9677 [(match_operand 5 "cc_register" "") (const_int 0)])
9678 (plus:SI
129a2fe4 9679 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9680 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9681 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9682 "TARGET_ARM"
8a18b90c 9683 "@
9684 add%d4\\t%0, %2, %3
9685 sub%d4\\t%0, %2, #%n3
9686 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9687 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9688 [(set_attr "conds" "use")
9689 (set_attr "length" "4,4,8,8")
9690 (set_attr "type" "*,*,*,*")]
9691)
8a18b90c 9692
9693(define_insn "*ifcompare_move_plus"
5565501b 9694 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9695 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9696 [(match_operand:SI 4 "s_register_operand" "r,r")
9697 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9698 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9699 (plus:SI
9700 (match_operand:SI 2 "s_register_operand" "r,r")
9701 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9702 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9703 "TARGET_ARM"
8a18b90c 9704 "#"
8fa3ba89 9705 [(set_attr "conds" "clob")
9706 (set_attr "length" "8,12")]
9707)
8a18b90c 9708
9709(define_insn "*if_move_plus"
129a2fe4 9710 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9711 (if_then_else:SI
8fa3ba89 9712 (match_operator 4 "arm_comparison_operator"
8a18b90c 9713 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9714 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9715 (plus:SI
129a2fe4 9716 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9717 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9718 "TARGET_ARM"
8a18b90c 9719 "@
9720 add%D4\\t%0, %2, %3
9721 sub%D4\\t%0, %2, #%n3
9722 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9723 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9724 [(set_attr "conds" "use")
9725 (set_attr "length" "4,4,8,8")
9726 (set_attr "type" "*,*,*,*")]
9727)
8a18b90c 9728
9729(define_insn "*ifcompare_arith_arith"
9730 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9731 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9732 [(match_operand:SI 5 "s_register_operand" "r")
9733 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9734 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9735 [(match_operand:SI 1 "s_register_operand" "r")
9736 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9737 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9738 [(match_operand:SI 3 "s_register_operand" "r")
9739 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9740 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9741 "TARGET_ARM"
8a18b90c 9742 "#"
8fa3ba89 9743 [(set_attr "conds" "clob")
9744 (set_attr "length" "12")]
9745)
9c08d1fa 9746
8a18b90c 9747(define_insn "*if_arith_arith"
9748 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9749 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9750 [(match_operand 8 "cc_register" "") (const_int 0)])
9751 (match_operator:SI 6 "shiftable_operator"
9752 [(match_operand:SI 1 "s_register_operand" "r")
9753 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9754 (match_operator:SI 7 "shiftable_operator"
9755 [(match_operand:SI 3 "s_register_operand" "r")
9756 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9757 "TARGET_ARM"
8a18b90c 9758 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9759 [(set_attr "conds" "use")
9760 (set_attr "length" "8")]
9761)
8a18b90c 9762
f7fbdd4a 9763(define_insn "*ifcompare_arith_move"
9c08d1fa 9764 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9765 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9766 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9767 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9768 (match_operator:SI 7 "shiftable_operator"
9769 [(match_operand:SI 4 "s_register_operand" "r,r")
9770 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9771 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9772 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9773 "TARGET_ARM"
9c08d1fa 9774 "*
9c08d1fa 9775 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9776 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9777 everything is in registers then we can do this in two instructions. */
9c08d1fa 9778 if (operands[3] == const0_rtx
9779 && GET_CODE (operands[7]) != AND
9780 && GET_CODE (operands[5]) == REG
9781 && GET_CODE (operands[1]) == REG
9782 && REGNO (operands[1]) == REGNO (operands[4])
9783 && REGNO (operands[4]) != REGNO (operands[0]))
9784 {
9785 if (GET_CODE (operands[6]) == LT)
40dbec34 9786 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9787 else if (GET_CODE (operands[6]) == GE)
40dbec34 9788 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9789 }
9790 if (GET_CODE (operands[3]) == CONST_INT
9791 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9792 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9793 else
e2348bcb 9794 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9795 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9796 if (which_alternative != 0)
129a2fe4 9797 return \"mov%D6\\t%0, %1\";
9c08d1fa 9798 return \"\";
215b30b3 9799 "
8fa3ba89 9800 [(set_attr "conds" "clob")
9801 (set_attr "length" "8,12")]
9802)
9c08d1fa 9803
8a18b90c 9804(define_insn "*if_arith_move"
129a2fe4 9805 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9806 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9807 [(match_operand 6 "cc_register" "") (const_int 0)])
9808 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9809 [(match_operand:SI 2 "s_register_operand" "r,r")
9810 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9811 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9812 "TARGET_ARM"
8a18b90c 9813 "@
9814 %I5%d4\\t%0, %2, %3
129a2fe4 9815 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9816 [(set_attr "conds" "use")
9817 (set_attr "length" "4,8")
9818 (set_attr "type" "*,*")]
9819)
8a18b90c 9820
f7fbdd4a 9821(define_insn "*ifcompare_move_arith"
9c08d1fa 9822 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9823 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9824 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9825 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9826 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9827 (match_operator:SI 7 "shiftable_operator"
9828 [(match_operand:SI 2 "s_register_operand" "r,r")
9829 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9830 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9831 "TARGET_ARM"
9c08d1fa 9832 "*
9c08d1fa 9833 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9834 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9835 everything is in registers then we can do this in two instructions */
9836 if (operands[5] == const0_rtx
9837 && GET_CODE (operands[7]) != AND
9838 && GET_CODE (operands[3]) == REG
9839 && GET_CODE (operands[1]) == REG
9840 && REGNO (operands[1]) == REGNO (operands[2])
9841 && REGNO (operands[2]) != REGNO (operands[0]))
9842 {
9843 if (GET_CODE (operands[6]) == GE)
40dbec34 9844 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9845 else if (GET_CODE (operands[6]) == LT)
40dbec34 9846 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9847 }
40dbec34 9848
9c08d1fa 9849 if (GET_CODE (operands[5]) == CONST_INT
9850 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9851 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9852 else
e2348bcb 9853 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9854
9c08d1fa 9855 if (which_alternative != 0)
129a2fe4 9856 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9857 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9858 "
8fa3ba89 9859 [(set_attr "conds" "clob")
9860 (set_attr "length" "8,12")]
9861)
9c08d1fa 9862
8a18b90c 9863(define_insn "*if_move_arith"
129a2fe4 9864 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9865 (if_then_else:SI
8fa3ba89 9866 (match_operator 4 "arm_comparison_operator"
8a18b90c 9867 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9868 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9869 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9870 [(match_operand:SI 2 "s_register_operand" "r,r")
9871 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9872 "TARGET_ARM"
8a18b90c 9873 "@
9874 %I5%D4\\t%0, %2, %3
129a2fe4 9875 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9876 [(set_attr "conds" "use")
9877 (set_attr "length" "4,8")
9878 (set_attr "type" "*,*")]
9879)
8a18b90c 9880
9881(define_insn "*ifcompare_move_not"
9c08d1fa 9882 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9883 (if_then_else:SI
8fa3ba89 9884 (match_operator 5 "arm_comparison_operator"
8a18b90c 9885 [(match_operand:SI 3 "s_register_operand" "r,r")
9886 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9887 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9888 (not:SI
9889 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9890 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9891 "TARGET_ARM"
8a18b90c 9892 "#"
8fa3ba89 9893 [(set_attr "conds" "clob")
9894 (set_attr "length" "8,12")]
9895)
9c08d1fa 9896
8a18b90c 9897(define_insn "*if_move_not"
9898 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9899 (if_then_else:SI
8fa3ba89 9900 (match_operator 4 "arm_comparison_operator"
8a18b90c 9901 [(match_operand 3 "cc_register" "") (const_int 0)])
9902 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9903 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9904 "TARGET_ARM"
8a18b90c 9905 "@
9906 mvn%D4\\t%0, %2
9907 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9908 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9909 [(set_attr "conds" "use")
9910 (set_attr "length" "4,8,8")]
9911)
8a18b90c 9912
9913(define_insn "*ifcompare_not_move"
9c08d1fa 9914 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9915 (if_then_else:SI
8fa3ba89 9916 (match_operator 5 "arm_comparison_operator"
8a18b90c 9917 [(match_operand:SI 3 "s_register_operand" "r,r")
9918 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9919 (not:SI
9920 (match_operand:SI 2 "s_register_operand" "r,r"))
9921 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9922 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9923 "TARGET_ARM"
8a18b90c 9924 "#"
8fa3ba89 9925 [(set_attr "conds" "clob")
9926 (set_attr "length" "8,12")]
9927)
9c08d1fa 9928
8a18b90c 9929(define_insn "*if_not_move"
9930 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9931 (if_then_else:SI
8fa3ba89 9932 (match_operator 4 "arm_comparison_operator"
8a18b90c 9933 [(match_operand 3 "cc_register" "") (const_int 0)])
9934 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9935 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9936 "TARGET_ARM"
8a18b90c 9937 "@
9938 mvn%d4\\t%0, %2
9939 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9940 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9941 [(set_attr "conds" "use")
9942 (set_attr "length" "4,8,8")]
9943)
8a18b90c 9944
9945(define_insn "*ifcompare_shift_move"
9c08d1fa 9946 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9947 (if_then_else:SI
8fa3ba89 9948 (match_operator 6 "arm_comparison_operator"
8a18b90c 9949 [(match_operand:SI 4 "s_register_operand" "r,r")
9950 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9951 (match_operator:SI 7 "shift_operator"
9952 [(match_operand:SI 2 "s_register_operand" "r,r")
9953 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9954 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9955 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9956 "TARGET_ARM"
9c08d1fa 9957 "#"
8fa3ba89 9958 [(set_attr "conds" "clob")
9959 (set_attr "length" "8,12")]
9960)
9c08d1fa 9961
8a18b90c 9962(define_insn "*if_shift_move"
9963 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9964 (if_then_else:SI
8fa3ba89 9965 (match_operator 5 "arm_comparison_operator"
8a18b90c 9966 [(match_operand 6 "cc_register" "") (const_int 0)])
9967 (match_operator:SI 4 "shift_operator"
9968 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9969 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9970 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9971 "TARGET_ARM"
5565501b 9972 "@
8a18b90c 9973 mov%d5\\t%0, %2%S4
9974 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9975 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9976 [(set_attr "conds" "use")
331beb1a 9977 (set_attr "shift" "2")
a2cd141b 9978 (set_attr "length" "4,8,8")
9979 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9980 (const_string "alu_shift")
9981 (const_string "alu_shift_reg")))]
8fa3ba89 9982)
5565501b 9983
8a18b90c 9984(define_insn "*ifcompare_move_shift"
9985 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9986 (if_then_else:SI
8fa3ba89 9987 (match_operator 6 "arm_comparison_operator"
8a18b90c 9988 [(match_operand:SI 4 "s_register_operand" "r,r")
9989 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9990 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9991 (match_operator:SI 7 "shift_operator"
8a18b90c 9992 [(match_operand:SI 2 "s_register_operand" "r,r")
9993 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9994 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9995 "TARGET_ARM"
8a18b90c 9996 "#"
8fa3ba89 9997 [(set_attr "conds" "clob")
9998 (set_attr "length" "8,12")]
9999)
5565501b 10000
8a18b90c 10001(define_insn "*if_move_shift"
10002 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10003 (if_then_else:SI
8fa3ba89 10004 (match_operator 5 "arm_comparison_operator"
8a18b90c 10005 [(match_operand 6 "cc_register" "") (const_int 0)])
10006 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10007 (match_operator:SI 4 "shift_operator"
10008 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10009 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10010 "TARGET_ARM"
5565501b 10011 "@
8a18b90c 10012 mov%D5\\t%0, %2%S4
10013 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10014 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10015 [(set_attr "conds" "use")
331beb1a 10016 (set_attr "shift" "2")
a2cd141b 10017 (set_attr "length" "4,8,8")
10018 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10019 (const_string "alu_shift")
10020 (const_string "alu_shift_reg")))]
8fa3ba89 10021)
9c08d1fa 10022
f7fbdd4a 10023(define_insn "*ifcompare_shift_shift"
8a18b90c 10024 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10025 (if_then_else:SI
8fa3ba89 10026 (match_operator 7 "arm_comparison_operator"
8a18b90c 10027 [(match_operand:SI 5 "s_register_operand" "r")
10028 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10029 (match_operator:SI 8 "shift_operator"
8a18b90c 10030 [(match_operand:SI 1 "s_register_operand" "r")
10031 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10032 (match_operator:SI 9 "shift_operator"
8a18b90c 10033 [(match_operand:SI 3 "s_register_operand" "r")
10034 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10035 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10036 "TARGET_ARM"
8a18b90c 10037 "#"
8fa3ba89 10038 [(set_attr "conds" "clob")
10039 (set_attr "length" "12")]
10040)
9c08d1fa 10041
8a18b90c 10042(define_insn "*if_shift_shift"
10043 [(set (match_operand:SI 0 "s_register_operand" "=r")
10044 (if_then_else:SI
8fa3ba89 10045 (match_operator 5 "arm_comparison_operator"
8a18b90c 10046 [(match_operand 8 "cc_register" "") (const_int 0)])
10047 (match_operator:SI 6 "shift_operator"
10048 [(match_operand:SI 1 "s_register_operand" "r")
10049 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10050 (match_operator:SI 7 "shift_operator"
10051 [(match_operand:SI 3 "s_register_operand" "r")
10052 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10053 "TARGET_ARM"
8a18b90c 10054 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10055 [(set_attr "conds" "use")
331beb1a 10056 (set_attr "shift" "1")
a2cd141b 10057 (set_attr "length" "8")
10058 (set (attr "type") (if_then_else
10059 (and (match_operand 2 "const_int_operand" "")
10060 (match_operand 4 "const_int_operand" ""))
10061 (const_string "alu_shift")
10062 (const_string "alu_shift_reg")))]
8fa3ba89 10063)
8a18b90c 10064
f7fbdd4a 10065(define_insn "*ifcompare_not_arith"
8a18b90c 10066 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10067 (if_then_else:SI
8fa3ba89 10068 (match_operator 6 "arm_comparison_operator"
8a18b90c 10069 [(match_operand:SI 4 "s_register_operand" "r")
10070 (match_operand:SI 5 "arm_add_operand" "rIL")])
10071 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10072 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10073 [(match_operand:SI 2 "s_register_operand" "r")
10074 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10075 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10076 "TARGET_ARM"
8a18b90c 10077 "#"
8fa3ba89 10078 [(set_attr "conds" "clob")
10079 (set_attr "length" "12")]
10080)
9c08d1fa 10081
8a18b90c 10082(define_insn "*if_not_arith"
10083 [(set (match_operand:SI 0 "s_register_operand" "=r")
10084 (if_then_else:SI
8fa3ba89 10085 (match_operator 5 "arm_comparison_operator"
8a18b90c 10086 [(match_operand 4 "cc_register" "") (const_int 0)])
10087 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10088 (match_operator:SI 6 "shiftable_operator"
10089 [(match_operand:SI 2 "s_register_operand" "r")
10090 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10091 "TARGET_ARM"
8a18b90c 10092 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10093 [(set_attr "conds" "use")
10094 (set_attr "length" "8")]
10095)
8a18b90c 10096
10097(define_insn "*ifcompare_arith_not"
10098 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10099 (if_then_else:SI
8fa3ba89 10100 (match_operator 6 "arm_comparison_operator"
8a18b90c 10101 [(match_operand:SI 4 "s_register_operand" "r")
10102 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10103 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10104 [(match_operand:SI 2 "s_register_operand" "r")
10105 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10106 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10107 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10108 "TARGET_ARM"
8a18b90c 10109 "#"
8fa3ba89 10110 [(set_attr "conds" "clob")
10111 (set_attr "length" "12")]
10112)
9c08d1fa 10113
8a18b90c 10114(define_insn "*if_arith_not"
10115 [(set (match_operand:SI 0 "s_register_operand" "=r")
10116 (if_then_else:SI
8fa3ba89 10117 (match_operator 5 "arm_comparison_operator"
8a18b90c 10118 [(match_operand 4 "cc_register" "") (const_int 0)])
10119 (match_operator:SI 6 "shiftable_operator"
10120 [(match_operand:SI 2 "s_register_operand" "r")
10121 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10122 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10123 "TARGET_ARM"
8a18b90c 10124 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10125 [(set_attr "conds" "use")
10126 (set_attr "length" "8")]
10127)
8a18b90c 10128
f7fbdd4a 10129(define_insn "*ifcompare_neg_move"
8a18b90c 10130 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10131 (if_then_else:SI
8fa3ba89 10132 (match_operator 5 "arm_comparison_operator"
8a18b90c 10133 [(match_operand:SI 3 "s_register_operand" "r,r")
10134 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10135 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10136 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10137 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10138 "TARGET_ARM"
8a18b90c 10139 "#"
8fa3ba89 10140 [(set_attr "conds" "clob")
10141 (set_attr "length" "8,12")]
10142)
8a18b90c 10143
10144(define_insn "*if_neg_move"
10145 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10146 (if_then_else:SI
8fa3ba89 10147 (match_operator 4 "arm_comparison_operator"
8a18b90c 10148 [(match_operand 3 "cc_register" "") (const_int 0)])
10149 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10150 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10151 "TARGET_ARM"
8a18b90c 10152 "@
10153 rsb%d4\\t%0, %2, #0
10154 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10155 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10156 [(set_attr "conds" "use")
10157 (set_attr "length" "4,8,8")]
10158)
9c08d1fa 10159
f7fbdd4a 10160(define_insn "*ifcompare_move_neg"
8a18b90c 10161 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10162 (if_then_else:SI
8fa3ba89 10163 (match_operator 5 "arm_comparison_operator"
8a18b90c 10164 [(match_operand:SI 3 "s_register_operand" "r,r")
10165 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10166 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10167 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10168 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10169 "TARGET_ARM"
8a18b90c 10170 "#"
8fa3ba89 10171 [(set_attr "conds" "clob")
10172 (set_attr "length" "8,12")]
10173)
8a18b90c 10174
10175(define_insn "*if_move_neg"
10176 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10177 (if_then_else:SI
8fa3ba89 10178 (match_operator 4 "arm_comparison_operator"
8a18b90c 10179 [(match_operand 3 "cc_register" "") (const_int 0)])
10180 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10181 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10182 "TARGET_ARM"
8a18b90c 10183 "@
10184 rsb%D4\\t%0, %2, #0
10185 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10186 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10187 [(set_attr "conds" "use")
10188 (set_attr "length" "4,8,8")]
10189)
9c08d1fa 10190
f7fbdd4a 10191(define_insn "*arith_adjacentmem"
9c08d1fa 10192 [(set (match_operand:SI 0 "s_register_operand" "=r")
10193 (match_operator:SI 1 "shiftable_operator"
10194 [(match_operand:SI 2 "memory_operand" "m")
10195 (match_operand:SI 3 "memory_operand" "m")]))
10196 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10197 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10198 "*
215b30b3 10199 {
10200 rtx ldm[3];
10201 rtx arith[4];
94dee231 10202 rtx base_reg;
10203 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10204
215b30b3 10205 if (REGNO (operands[0]) > REGNO (operands[4]))
10206 {
10207 ldm[1] = operands[4];
10208 ldm[2] = operands[0];
10209 }
10210 else
10211 {
10212 ldm[1] = operands[0];
10213 ldm[2] = operands[4];
10214 }
94dee231 10215
10216 base_reg = XEXP (operands[2], 0);
10217
10218 if (!REG_P (base_reg))
10219 {
10220 val1 = INTVAL (XEXP (base_reg, 1));
10221 base_reg = XEXP (base_reg, 0);
10222 }
10223
10224 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10225 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10226
215b30b3 10227 arith[0] = operands[0];
10228 arith[3] = operands[1];
94dee231 10229
215b30b3 10230 if (val1 < val2)
10231 {
10232 arith[1] = ldm[1];
10233 arith[2] = ldm[2];
10234 }
10235 else
10236 {
10237 arith[1] = ldm[2];
10238 arith[2] = ldm[1];
10239 }
94dee231 10240
10241 ldm[0] = base_reg;
10242 if (val1 !=0 && val2 != 0)
215b30b3 10243 {
cdb1295a 10244 rtx ops[3];
10245
94dee231 10246 if (val1 == 4 || val2 == 4)
10247 /* Other val must be 8, since we know they are adjacent and neither
10248 is zero. */
25f905c2 10249 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10250 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10251 {
94dee231 10252 ldm[0] = ops[0] = operands[4];
10253 ops[1] = base_reg;
10254 ops[2] = GEN_INT (val1);
10255 output_add_immediate (ops);
10256 if (val1 < val2)
25f905c2 10257 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10258 else
25f905c2 10259 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10260 }
cdb1295a 10261 else
10262 {
10263 /* Offset is out of range for a single add, so use two ldr. */
10264 ops[0] = ldm[1];
10265 ops[1] = base_reg;
10266 ops[2] = GEN_INT (val1);
10267 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10268 ops[0] = ldm[2];
10269 ops[2] = GEN_INT (val2);
10270 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10271 }
215b30b3 10272 }
94dee231 10273 else if (val1 != 0)
215b30b3 10274 {
215b30b3 10275 if (val1 < val2)
25f905c2 10276 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10277 else
25f905c2 10278 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10279 }
10280 else
10281 {
215b30b3 10282 if (val1 < val2)
25f905c2 10283 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10284 else
25f905c2 10285 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10286 }
10287 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10288 return \"\";
10289 }"
10290 [(set_attr "length" "12")
10291 (set_attr "predicable" "yes")
a2cd141b 10292 (set_attr "type" "load1")]
215b30b3 10293)
9c08d1fa 10294
9c08d1fa 10295; This pattern is never tried by combine, so do it as a peephole
10296
a0f94409 10297(define_peephole2
372575c7 10298 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10299 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10300 (set (reg:CC CC_REGNUM)
aea4c774 10301 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10302 "TARGET_ARM"
a0f94409 10303 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10304 (set (match_dup 0) (match_dup 1))])]
10305 ""
0d66636f 10306)
9c08d1fa 10307
675d848d 10308; Peepholes to spot possible load- and store-multiples, if the ordering is
10309; reversed, check that the memory references aren't volatile.
9c08d1fa 10310
10311(define_peephole
aaa37ad6 10312 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10313 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10314 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10315 (match_operand:SI 5 "memory_operand" "m"))
aaa37ad6 10316 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10317 (match_operand:SI 6 "memory_operand" "m"))
aaa37ad6 10318 (set (match_operand:SI 3 "s_register_operand" "=rk")
aea4c774 10319 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 10320 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10321 "*
10322 return emit_ldm_seq (operands, 4);
215b30b3 10323 "
10324)
9c08d1fa 10325
10326(define_peephole
aaa37ad6 10327 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10328 (match_operand:SI 3 "memory_operand" "m"))
aaa37ad6 10329 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10330 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10331 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10332 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 10333 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10334 "*
10335 return emit_ldm_seq (operands, 3);
215b30b3 10336 "
10337)
9c08d1fa 10338
10339(define_peephole
aaa37ad6 10340 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10341 (match_operand:SI 2 "memory_operand" "m"))
aaa37ad6 10342 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10343 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 10344 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10345 "*
10346 return emit_ldm_seq (operands, 2);
215b30b3 10347 "
10348)
9c08d1fa 10349
10350(define_peephole
aea4c774 10351 [(set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10352 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10353 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10354 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10355 (set (match_operand:SI 6 "memory_operand" "=m")
aaa37ad6 10356 (match_operand:SI 2 "s_register_operand" "rk"))
aea4c774 10357 (set (match_operand:SI 7 "memory_operand" "=m")
aaa37ad6 10358 (match_operand:SI 3 "s_register_operand" "rk"))]
cffb2a26 10359 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10360 "*
10361 return emit_stm_seq (operands, 4);
215b30b3 10362 "
10363)
9c08d1fa 10364
10365(define_peephole
aea4c774 10366 [(set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10367 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10368 (set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10369 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10370 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10371 (match_operand:SI 2 "s_register_operand" "rk"))]
cffb2a26 10372 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10373 "*
10374 return emit_stm_seq (operands, 3);
215b30b3 10375 "
10376)
9c08d1fa 10377
10378(define_peephole
aea4c774 10379 [(set (match_operand:SI 2 "memory_operand" "=m")
aaa37ad6 10380 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10381 (set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10382 (match_operand:SI 1 "s_register_operand" "rk"))]
cffb2a26 10383 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10384 "*
10385 return emit_stm_seq (operands, 2);
215b30b3 10386 "
10387)
9c08d1fa 10388
9c08d1fa 10389(define_split
10390 [(set (match_operand:SI 0 "s_register_operand" "")
10391 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10392 (const_int 0))
8fa3ba89 10393 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10394 [(match_operand:SI 3 "s_register_operand" "")
10395 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10396 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10397 "TARGET_ARM"
9c08d1fa 10398 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10399 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10400 (match_dup 5)))]
215b30b3 10401 ""
10402)
9c08d1fa 10403
aea4c774 10404;; This split can be used because CC_Z mode implies that the following
10405;; branch will be an equality, or an unsigned inequality, so the sign
10406;; extension is not needed.
9c08d1fa 10407
aea4c774 10408(define_split
bd5b4116 10409 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10410 (compare:CC_Z
10411 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10412 (const_int 24))
aea4c774 10413 (match_operand 1 "const_int_operand" "")))
10414 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10415 "TARGET_ARM
10416 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10417 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10418 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10419 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10420 "
9c08d1fa 10421 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10422 "
10423)
25f905c2 10424;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10425
87b22bf7 10426(define_expand "prologue"
10427 [(clobber (const_int 0))]
cffb2a26 10428 "TARGET_EITHER"
25f905c2 10429 "if (TARGET_32BIT)
cffb2a26 10430 arm_expand_prologue ();
10431 else
25f905c2 10432 thumb1_expand_prologue ();
87b22bf7 10433 DONE;
cffb2a26 10434 "
10435)
87b22bf7 10436
56d27660 10437(define_expand "epilogue"
4c44712e 10438 [(clobber (const_int 0))]
cffb2a26 10439 "TARGET_EITHER"
56d27660 10440 "
18d50ae6 10441 if (crtl->calls_eh_return)
4c44712e 10442 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10443 if (TARGET_THUMB1)
10444 thumb1_expand_epilogue ();
cffb2a26 10445 else if (USE_RETURN_INSN (FALSE))
56d27660 10446 {
10447 emit_jump_insn (gen_return ());
10448 DONE;
10449 }
cffb2a26 10450 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10451 gen_rtvec (1,
10452 gen_rtx_RETURN (VOIDmode)),
e1159bbe 10453 VUNSPEC_EPILOGUE));
cffb2a26 10454 DONE;
10455 "
10456)
56d27660 10457
ef5651d0 10458;; Note - although unspec_volatile's USE all hard registers,
10459;; USEs are ignored after relaod has completed. Thus we need
10460;; to add an unspec of the link register to ensure that flow
10461;; does not think that it is unused by the sibcall branch that
10462;; will replace the standard function epilogue.
1c494086 10463(define_insn "sibcall_epilogue"
ef5651d0 10464 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10465 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10466 "TARGET_32BIT"
1c494086 10467 "*
ffc9d00c 10468 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10469 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10470 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10471 "
10472;; Length is absolute worst case
10473 [(set_attr "length" "44")
defc47cf 10474 (set_attr "type" "block")
10475 ;; We don't clobber the conditions, but the potential length of this
10476 ;; operation is sufficient to make conditionalizing the sequence
10477 ;; unlikely to be profitable.
10478 (set_attr "conds" "clob")]
1c494086 10479)
10480
cffb2a26 10481(define_insn "*epilogue_insns"
e1159bbe 10482 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10483 "TARGET_EITHER"
56d27660 10484 "*
25f905c2 10485 if (TARGET_32BIT)
ffc9d00c 10486 return arm_output_epilogue (NULL);
25f905c2 10487 else /* TARGET_THUMB1 */
cffb2a26 10488 return thumb_unexpanded_epilogue ();
10489 "
215b30b3 10490 ; Length is absolute worst case
cffb2a26 10491 [(set_attr "length" "44")
defc47cf 10492 (set_attr "type" "block")
10493 ;; We don't clobber the conditions, but the potential length of this
10494 ;; operation is sufficient to make conditionalizing the sequence
10495 ;; unlikely to be profitable.
10496 (set_attr "conds" "clob")]
cffb2a26 10497)
10498
10499(define_expand "eh_epilogue"
7db9af5d 10500 [(use (match_operand:SI 0 "register_operand" ""))
10501 (use (match_operand:SI 1 "register_operand" ""))
10502 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10503 "TARGET_EITHER"
10504 "
215b30b3 10505 {
10506 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10507 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10508 {
10509 rtx ra = gen_rtx_REG (Pmode, 2);
10510
10511 emit_move_insn (ra, operands[2]);
10512 operands[2] = ra;
10513 }
5cf3595a 10514 /* This is a hack -- we may have crystalized the function type too
10515 early. */
10516 cfun->machine->func_type = 0;
215b30b3 10517 }"
10518)
56d27660 10519
9c08d1fa 10520;; This split is only used during output to reduce the number of patterns
10521;; that need assembler instructions adding to them. We allowed the setting
10522;; of the conditions to be implicit during rtl generation so that
10523;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10524;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10525;; up again here.
10526
25f905c2 10527;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10528;; conditional execution sufficient?
10529
9c08d1fa 10530(define_split
10531 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10532 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10533 [(match_operand 2 "" "") (match_operand 3 "" "")])
10534 (match_dup 0)
10535 (match_operand 4 "" "")))
bd5b4116 10536 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10537 "TARGET_ARM && reload_completed"
8fa3ba89 10538 [(set (match_dup 5) (match_dup 6))
10539 (cond_exec (match_dup 7)
10540 (set (match_dup 0) (match_dup 4)))]
10541 "
10542 {
10543 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10544 operands[2], operands[3]);
10545 enum rtx_code rc = GET_CODE (operands[1]);
10546
bd5b4116 10547 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10548 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10549 if (mode == CCFPmode || mode == CCFPEmode)
10550 rc = reverse_condition_maybe_unordered (rc);
10551 else
10552 rc = reverse_condition (rc);
10553
10554 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10555 }"
10556)
10557
10558(define_split
10559 [(set (match_operand:SI 0 "s_register_operand" "")
10560 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10561 [(match_operand 2 "" "") (match_operand 3 "" "")])
10562 (match_operand 4 "" "")
10563 (match_dup 0)))
bd5b4116 10564 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10565 "TARGET_ARM && reload_completed"
8fa3ba89 10566 [(set (match_dup 5) (match_dup 6))
10567 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10568 (set (match_dup 0) (match_dup 4)))]
10569 "
10570 {
10571 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10572 operands[2], operands[3]);
10573
bd5b4116 10574 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10575 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10576 }"
10577)
10578
10579(define_split
10580 [(set (match_operand:SI 0 "s_register_operand" "")
10581 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10582 [(match_operand 2 "" "") (match_operand 3 "" "")])
10583 (match_operand 4 "" "")
10584 (match_operand 5 "" "")))
bd5b4116 10585 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10586 "TARGET_ARM && reload_completed"
8fa3ba89 10587 [(set (match_dup 6) (match_dup 7))
10588 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10589 (set (match_dup 0) (match_dup 4)))
10590 (cond_exec (match_dup 8)
10591 (set (match_dup 0) (match_dup 5)))]
10592 "
10593 {
10594 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10595 operands[2], operands[3]);
10596 enum rtx_code rc = GET_CODE (operands[1]);
10597
bd5b4116 10598 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10599 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10600 if (mode == CCFPmode || mode == CCFPEmode)
10601 rc = reverse_condition_maybe_unordered (rc);
10602 else
10603 rc = reverse_condition (rc);
10604
10605 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10606 }"
10607)
10608
cffb2a26 10609(define_split
10610 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10611 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10612 [(match_operand:SI 2 "s_register_operand" "")
10613 (match_operand:SI 3 "arm_add_operand" "")])
10614 (match_operand:SI 4 "arm_rhs_operand" "")
10615 (not:SI
10616 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10617 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10618 "TARGET_ARM && reload_completed"
cffb2a26 10619 [(set (match_dup 6) (match_dup 7))
f6c53574 10620 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10621 (set (match_dup 0) (match_dup 4)))
10622 (cond_exec (match_dup 8)
10623 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10624 "
215b30b3 10625 {
10626 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10627 operands[2], operands[3]);
f6c53574 10628 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10629
bd5b4116 10630 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10631 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10632 if (mode == CCFPmode || mode == CCFPEmode)
10633 rc = reverse_condition_maybe_unordered (rc);
10634 else
10635 rc = reverse_condition (rc);
10636
10637 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10638 }"
10639)
cffb2a26 10640
10641(define_insn "*cond_move_not"
10642 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10643 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10644 [(match_operand 3 "cc_register" "") (const_int 0)])
10645 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10646 (not:SI
10647 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10648 "TARGET_ARM"
10649 "@
10650 mvn%D4\\t%0, %2
10651 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10652 [(set_attr "conds" "use")
10653 (set_attr "length" "4,8")]
10654)
cffb2a26 10655
9c08d1fa 10656;; The next two patterns occur when an AND operation is followed by a
10657;; scc insn sequence
10658
f7fbdd4a 10659(define_insn "*sign_extract_onebit"
9c08d1fa 10660 [(set (match_operand:SI 0 "s_register_operand" "=r")
10661 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10662 (const_int 1)
ed750274 10663 (match_operand:SI 2 "const_int_operand" "n")))
10664 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10665 "TARGET_ARM"
9c08d1fa 10666 "*
0d66636f 10667 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10668 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10669 return \"mvnne\\t%0, #0\";
10670 "
10671 [(set_attr "conds" "clob")
10672 (set_attr "length" "8")]
10673)
9c08d1fa 10674
f7fbdd4a 10675(define_insn "*not_signextract_onebit"
9c08d1fa 10676 [(set (match_operand:SI 0 "s_register_operand" "=r")
10677 (not:SI
10678 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10679 (const_int 1)
ed750274 10680 (match_operand:SI 2 "const_int_operand" "n"))))
10681 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10682 "TARGET_ARM"
9c08d1fa 10683 "*
0d66636f 10684 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10685 output_asm_insn (\"tst\\t%1, %2\", operands);
10686 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10687 return \"movne\\t%0, #0\";
10688 "
10689 [(set_attr "conds" "clob")
10690 (set_attr "length" "12")]
10691)
25f905c2 10692;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10693
0d66636f 10694;; Push multiple registers to the stack. Registers are in parallel (use ...)
10695;; expressions. For simplicity, the first register is also in the unspec
10696;; part.
f7fbdd4a 10697(define_insn "*push_multi"
87b22bf7 10698 [(match_parallel 2 "multi_register_push"
10699 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10700 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10701 UNSPEC_PUSH_MULT))])]
25f905c2 10702 "TARGET_32BIT"
87b22bf7 10703 "*
215b30b3 10704 {
10705 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10706
215b30b3 10707 /* For the StrongARM at least it is faster to
25f905c2 10708 use STR to store only a single register.
542d5028 10709 In Thumb mode always use push, and the assembler will pick
10710 something appropriate. */
25f905c2 10711 if (num_saves == 1 && TARGET_ARM)
215b30b3 10712 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10713 else
10714 {
10715 int i;
10716 char pattern[100];
ed593f11 10717
25f905c2 10718 if (TARGET_ARM)
10719 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10720 else
10721 strcpy (pattern, \"push\\t{%1\");
215b30b3 10722
6079f055 10723 for (i = 1; i < num_saves; i++)
215b30b3 10724 {
10725 strcat (pattern, \", %|\");
10726 strcat (pattern,
10727 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10728 }
10729
10730 strcat (pattern, \"}\");
10731 output_asm_insn (pattern, operands);
10732 }
10733
10734 return \"\";
10735 }"
10736 [(set_attr "type" "store4")]
10737)
f7fbdd4a 10738
4c58c898 10739(define_insn "stack_tie"
10740 [(set (mem:BLK (scratch))
aaa37ad6 10741 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10742 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10743 UNSPEC_PRLG_STK))]
10744 ""
10745 ""
10746 [(set_attr "length" "0")]
10747)
10748
3398e91d 10749;; Similarly for the floating point registers
7b1d2fc4 10750(define_insn "*push_fp_multi"
10751 [(match_parallel 2 "multi_register_push"
10752 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10753 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10754 UNSPEC_PUSH_MULT))])]
25f905c2 10755 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10756 "*
215b30b3 10757 {
10758 char pattern[100];
7b1d2fc4 10759
215b30b3 10760 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10761 output_asm_insn (pattern, operands);
10762 return \"\";
10763 }"
10764 [(set_attr "type" "f_store")]
10765)
7b1d2fc4 10766
f7fbdd4a 10767;; Special patterns for dealing with the constant pool
10768
cffb2a26 10769(define_insn "align_4"
e1159bbe 10770 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10771 "TARGET_EITHER"
f7fbdd4a 10772 "*
cffb2a26 10773 assemble_align (32);
f7fbdd4a 10774 return \"\";
cffb2a26 10775 "
10776)
f7fbdd4a 10777
755eb2b4 10778(define_insn "align_8"
10779 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10780 "TARGET_EITHER"
755eb2b4 10781 "*
10782 assemble_align (64);
10783 return \"\";
10784 "
10785)
10786
cffb2a26 10787(define_insn "consttable_end"
e1159bbe 10788 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10789 "TARGET_EITHER"
f7fbdd4a 10790 "*
cffb2a26 10791 making_const_table = FALSE;
f7fbdd4a 10792 return \"\";
cffb2a26 10793 "
10794)
f7fbdd4a 10795
cffb2a26 10796(define_insn "consttable_1"
e1159bbe 10797 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10798 "TARGET_THUMB1"
f7fbdd4a 10799 "*
cffb2a26 10800 making_const_table = TRUE;
09d688ff 10801 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10802 assemble_zeros (3);
f7fbdd4a 10803 return \"\";
cffb2a26 10804 "
10805 [(set_attr "length" "4")]
10806)
f7fbdd4a 10807
cffb2a26 10808(define_insn "consttable_2"
e1159bbe 10809 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10810 "TARGET_THUMB1"
f7fbdd4a 10811 "*
cffb2a26 10812 making_const_table = TRUE;
9b8516be 10813 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10814 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10815 assemble_zeros (2);
f7fbdd4a 10816 return \"\";
cffb2a26 10817 "
10818 [(set_attr "length" "4")]
10819)
10820
10821(define_insn "consttable_4"
e1159bbe 10822 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10823 "TARGET_EITHER"
10824 "*
10825 {
9b8516be 10826 rtx x = operands[0];
cffb2a26 10827 making_const_table = TRUE;
9b8516be 10828 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10829 {
10830 case MODE_FLOAT:
9b8516be 10831 if (GET_MODE (x) == HFmode)
10832 arm_emit_fp16_const (x);
10833 else
10834 {
10835 REAL_VALUE_TYPE r;
10836 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10837 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10838 }
10839 break;
cffb2a26 10840 default:
9b8516be 10841 assemble_integer (x, 4, BITS_PER_WORD, 1);
10842 mark_symbol_refs_as_used (x);
cffb2a26 10843 break;
10844 }
10845 return \"\";
10846 }"
10847 [(set_attr "length" "4")]
10848)
10849
10850(define_insn "consttable_8"
e1159bbe 10851 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10852 "TARGET_EITHER"
10853 "*
10854 {
10855 making_const_table = TRUE;
10856 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10857 {
10858 case MODE_FLOAT:
10859 {
badfe841 10860 REAL_VALUE_TYPE r;
10861 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10862 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10863 break;
10864 }
10865 default:
09d688ff 10866 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10867 break;
10868 }
10869 return \"\";
10870 }"
10871 [(set_attr "length" "8")]
10872)
10873
d98a3884 10874(define_insn "consttable_16"
10875 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10876 "TARGET_EITHER"
10877 "*
10878 {
10879 making_const_table = TRUE;
10880 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10881 {
10882 case MODE_FLOAT:
10883 {
10884 REAL_VALUE_TYPE r;
10885 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10886 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10887 break;
10888 }
10889 default:
10890 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10891 break;
10892 }
10893 return \"\";
10894 }"
10895 [(set_attr "length" "16")]
10896)
10897
cffb2a26 10898;; Miscellaneous Thumb patterns
10899
fd957ef3 10900(define_expand "tablejump"
7db9af5d 10901 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10902 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10903 "TARGET_THUMB1"
fd957ef3 10904 "
10905 if (flag_pic)
10906 {
10907 /* Hopefully, CSE will eliminate this copy. */
10908 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10909 rtx reg2 = gen_reg_rtx (SImode);
10910
10911 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10912 operands[0] = reg2;
10913 }
10914 "
10915)
10916
f1039640 10917;; NB never uses BX.
25f905c2 10918(define_insn "*thumb1_tablejump"
cffb2a26 10919 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10920 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10921 "TARGET_THUMB1"
fd957ef3 10922 "mov\\t%|pc, %0"
cffb2a26 10923 [(set_attr "length" "2")]
10924)
0d66636f 10925
331beb1a 10926;; V5 Instructions,
10927
8f4be2be 10928(define_insn "clzsi2"
10929 [(set (match_operand:SI 0 "s_register_operand" "=r")
10930 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10931 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10932 "clz%?\\t%0, %1"
bcaec148 10933 [(set_attr "predicable" "yes")
10934 (set_attr "insn" "clz")])
331beb1a 10935
e1159bbe 10936;; V5E instructions.
331beb1a 10937
10938(define_insn "prefetch"
f4e79814 10939 [(prefetch (match_operand:SI 0 "address_operand" "p")
10940 (match_operand:SI 1 "" "")
10941 (match_operand:SI 2 "" ""))]
25f905c2 10942 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10943 "pld\\t%a0")
331beb1a 10944
0d66636f 10945;; General predication pattern
10946
10947(define_cond_exec
10948 [(match_operator 0 "arm_comparison_operator"
10949 [(match_operand 1 "cc_register" "")
10950 (const_int 0)])]
25f905c2 10951 "TARGET_32BIT"
0d66636f 10952 ""
10953)
10954
063a05c7 10955(define_insn "prologue_use"
10956 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10957 ""
10958 "%@ %0 needed for prologue"
02cfc9c9 10959 [(set_attr "length" "0")]
063a05c7 10960)
7db9af5d 10961
4c44712e 10962
10963;; Patterns for exception handling
10964
10965(define_expand "eh_return"
10966 [(use (match_operand 0 "general_operand" ""))]
10967 "TARGET_EITHER"
10968 "
10969 {
25f905c2 10970 if (TARGET_32BIT)
4c44712e 10971 emit_insn (gen_arm_eh_return (operands[0]));
10972 else
10973 emit_insn (gen_thumb_eh_return (operands[0]));
10974 DONE;
10975 }"
10976)
10977
10978;; We can't expand this before we know where the link register is stored.
10979(define_insn_and_split "arm_eh_return"
10980 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10981 VUNSPEC_EH_RETURN)
10982 (clobber (match_scratch:SI 1 "=&r"))]
10983 "TARGET_ARM"
10984 "#"
10985 "&& reload_completed"
10986 [(const_int 0)]
10987 "
10988 {
10989 arm_set_return_address (operands[0], operands[1]);
10990 DONE;
10991 }"
10992)
10993
10994(define_insn_and_split "thumb_eh_return"
10995 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10996 VUNSPEC_EH_RETURN)
10997 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10998 "TARGET_THUMB1"
4c44712e 10999 "#"
11000 "&& reload_completed"
11001 [(const_int 0)]
11002 "
11003 {
11004 thumb_set_return_address (operands[0], operands[1]);
11005 DONE;
11006 }"
11007)
11008
f655717d 11009\f
11010;; TLS support
11011
11012(define_insn "load_tp_hard"
11013 [(set (match_operand:SI 0 "register_operand" "=r")
11014 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11015 "TARGET_HARD_TP"
11016 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11017 [(set_attr "predicable" "yes")]
11018)
11019
11020;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11021(define_insn "load_tp_soft"
11022 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11023 (clobber (reg:SI LR_REGNUM))
11024 (clobber (reg:SI IP_REGNUM))
11025 (clobber (reg:CC CC_REGNUM))]
11026 "TARGET_SOFT_TP"
11027 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11028 [(set_attr "conds" "clob")]
11029)
11030
7db9af5d 11031;; Load the FPA co-processor patterns
11032(include "fpa.md")
11033;; Load the Maverick co-processor patterns
11034(include "cirrus.md")
d98a3884 11035;; Vector bits common to IWMMXT and Neon
11036(include "vec-common.md")
755eb2b4 11037;; Load the Intel Wireless Multimedia Extension patterns
11038(include "iwmmxt.md")
a2cd141b 11039;; Load the VFP co-processor patterns
11040(include "vfp.md")
25f905c2 11041;; Thumb-2 patterns
11042(include "thumb2.md")
d98a3884 11043;; Neon patterns
11044(include "neon.md")
a2cd141b 11045