]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* convert.c (convert_to_integer): Convert (int)logb() into ilogb().
[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.
e1159bbe 102 ]
103)
104
215b30b3 105;; UNSPEC_VOLATILE Usage:
e1159bbe 106
107(define_constants
108 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
109 ; insn in the code.
110 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
111 ; instruction epilogue sequence that isn't expanded
112 ; into normal RTL. Used for both normal and sibcall
113 ; epilogues.
114 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
115 ; for inlined constants.
116 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
117 ; table.
118 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
119 ; an 8-bit object.
120 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
121 ; a 16-bit object.
122 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
123 ; a 32-bit object.
124 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
125 ; a 64-bit object.
d98a3884 126 (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
127 ; a 128-bit object.
128 (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
129 (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
130 (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
131 (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
132 (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
133 (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 134 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 135 ; handling.
e1159bbe 136 ]
137)
b11cae9e 138\f
e1159bbe 139;;---------------------------------------------------------------------------
9c08d1fa 140;; Attributes
141
215b30b3 142; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
143; generating ARM code. This is used to control the length of some insn
144; patterns that share the same RTL in both ARM and Thumb code.
1c494086 145(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 146
215b30b3 147; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
148; scheduling decisions for the load unit and the multiplier.
74a71f7d 149(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
9c08d1fa 150
5ecb8da7 151; IS_XSCALE is set to 'yes' when compiling for XScale.
152(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
153
331beb1a 154;; Operand number of an input operand that is shifted. Zero if the
155;; given instruction does not shift one of its input operands.
331beb1a 156(define_attr "shift" "" (const_int 0))
157
3d91c5d6 158; Floating Point Unit. If we only have floating point emulation, then there
159; is no point in scheduling the floating point insns. (Well, for best
160; performance we should try and group them together).
e3879fd0 161(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp,vfpv3d16,vfpv3,neon"
c7f506fd 162 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 163
094e994f 164; LENGTH of an instruction (in bytes)
165(define_attr "length" "" (const_int 4))
9c08d1fa 166
56d27660 167; POOL_RANGE is how far away from a constant pool entry that this insn
168; can be placed. If the distance is zero, then this insn will never
169; reference the pool.
cffb2a26 170; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
171; before its address.
56d27660 172(define_attr "pool_range" "" (const_int 0))
cffb2a26 173(define_attr "neg_pool_range" "" (const_int 0))
56d27660 174
215b30b3 175; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 176; If such an insn references the pool, then we have no way of knowing how,
177; so use the most conservative value for pool_range.
9c08d1fa 178(define_asm_attributes
4d7a8451 179 [(set_attr "conds" "clob")
180 (set_attr "length" "4")
181 (set_attr "pool_range" "250")])
9c08d1fa 182
a2cd141b 183;; The instruction used to implement a particular pattern. This
184;; information is used by pipeline descriptions to provide accurate
185;; scheduling information.
186
187(define_attr "insn"
934a1e72 188 "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 189 (const_string "other"))
190
9c08d1fa 191; TYPE attribute is used to detect floating point instructions which, if
192; running on a co-processor can run in parallel with other, basic instructions
193; If write-buffer scheduling is enabled then it can also be used in the
194; scheduling of writes.
195
196; Classification of each insn
607978a1 197; Note: vfp.md has different meanings for some of these, and some further
198; types as well. See that file for details.
a2cd141b 199; alu any alu instruction that doesn't hit memory or fp
200; regs or have a shifted source operand
201; alu_shift any data instruction that doesn't hit memory or fp
202; regs, but has a source operand shifted by a constant
203; alu_shift_reg any data instruction that doesn't hit memory or fp
204; regs, but has a source operand shifted by a register value
f7fbdd4a 205; mult a multiply instruction
9c08d1fa 206; block blockage insn, this blocks all functional units
207; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 208; fdivd DFmode floating point division
209; fdivs SFmode floating point division
210; fmul Floating point multiply
211; ffmul Fast floating point multiply
212; farith Floating point arithmetic (4 cycle)
213; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 214; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 215; even on a machine with an fpa.
9c08d1fa 216; f_load a floating point load from memory
217; f_store a floating point store to memory
9aff9709 218; f_load[sd] single/double load from memory
219; f_store[sd] single/double store to memory
c0e1af52 220; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 221; f_mem_r a transfer of a floating point register to a real reg via mem
222; r_mem_f the reverse of f_mem_r
223; f_2_r fast transfer float to arm (no memory needed)
224; r_2_f fast transfer arm to float
c0e1af52 225; f_cvt convert floating<->integral
a2cd141b 226; branch a branch
9c08d1fa 227; call a subroutine call
a2cd141b 228; load_byte load byte(s) from memory to arm registers
229; load1 load 1 word from memory to arm registers
230; load2 load 2 words from memory to arm registers
231; load3 load 3 words from memory to arm registers
232; load4 load 4 words from memory to arm registers
233; store store 1 word to memory from arm registers
9c08d1fa 234; store2 store 2 words
235; store3 store 3 words
a2cd141b 236; store4 store 4 (or more) words
2c6c7d8b 237; Additions for Cirrus Maverick co-processor:
238; mav_farith Floating point arithmetic (4 cycle)
239; mav_dmult Double multiplies (7 cycle)
9c08d1fa 240;
bcaec148 241
9c08d1fa 242(define_attr "type"
e3879fd0 243 "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 244 (if_then_else
245 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
246 (const_string "mult")
247 (const_string "alu")))
9c08d1fa 248
9888ad6d 249; Load scheduling, set from the arm_ld_sched variable
457275b6 250; initialized by arm_override_options()
9888ad6d 251(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 252
c52acdd2 253;; Classification of NEON instructions for scheduling purposes.
254;; Do not set this attribute and the "type" attribute together in
255;; any one instruction pattern.
256(define_attr "neon_type"
257 "neon_int_1,\
258 neon_int_2,\
259 neon_int_3,\
260 neon_int_4,\
261 neon_int_5,\
262 neon_vqneg_vqabs,\
263 neon_vmov,\
264 neon_vaba,\
265 neon_vsma,\
266 neon_vaba_qqq,\
267 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
268 neon_mul_qqq_8_16_32_ddd_32,\
269 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
270 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
271 neon_mla_qqq_8_16,\
272 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
273 neon_mla_qqq_32_qqd_32_scalar,\
274 neon_mul_ddd_16_scalar_32_16_long_scalar,\
275 neon_mul_qqd_32_scalar,\
276 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
277 neon_shift_1,\
278 neon_shift_2,\
279 neon_shift_3,\
280 neon_vshl_ddd,\
281 neon_vqshl_vrshl_vqrshl_qqq,\
282 neon_vsra_vrsra,\
283 neon_fp_vadd_ddd_vabs_dd,\
284 neon_fp_vadd_qqq_vabs_qq,\
285 neon_fp_vsum,\
286 neon_fp_vmul_ddd,\
287 neon_fp_vmul_qqd,\
288 neon_fp_vmla_ddd,\
289 neon_fp_vmla_qqq,\
290 neon_fp_vmla_ddd_scalar,\
291 neon_fp_vmla_qqq_scalar,\
292 neon_fp_vrecps_vrsqrts_ddd,\
293 neon_fp_vrecps_vrsqrts_qqq,\
294 neon_bp_simple,\
295 neon_bp_2cycle,\
296 neon_bp_3cycle,\
297 neon_ldr,\
298 neon_str,\
299 neon_vld1_1_2_regs,\
300 neon_vld1_3_4_regs,\
301 neon_vld2_2_regs_vld1_vld2_all_lanes,\
302 neon_vld2_4_regs,\
303 neon_vld3_vld4,\
304 neon_vst1_1_2_regs_vst2_2_regs,\
305 neon_vst1_3_4_regs,\
306 neon_vst2_4_regs_vst3_vst4,\
307 neon_vst3_vst4,\
308 neon_vld1_vld2_lane,\
309 neon_vld3_vld4_lane,\
310 neon_vst1_vst2_lane,\
311 neon_vst3_vst4_lane,\
312 neon_vld3_vld4_all_lanes,\
313 neon_mcr,\
314 neon_mcr_2_mcrr,\
315 neon_mrc,\
316 neon_mrrc,\
317 neon_ldm_2,\
318 neon_stm_2,\
319 none"
320 (const_string "none"))
321
f7fbdd4a 322; condition codes: this one is used by final_prescan_insn to speed up
323; conditionalizing instructions. It saves having to scan the rtl to see if
324; it uses or alters the condition codes.
215b30b3 325;
f7fbdd4a 326; USE means that the condition codes are used by the insn in the process of
215b30b3 327; outputting code, this means (at present) that we can't use the insn in
328; inlined branches
329;
f7fbdd4a 330; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 331; well defined manner.
332;
f7fbdd4a 333; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 334; they are altered at all
335;
8fa3ba89 336; JUMP_CLOB is used when the condition cannot be represented by a single
215b30b3 337; instruction (UNEQ and LTGT). These cannot be predicated.
338;
c52acdd2 339; UNCONDITIONAL means the instions can not be conditionally executed.
340;
f7fbdd4a 341; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 342; output of this insn
f7fbdd4a 343
c52acdd2 344(define_attr "conds" "use,set,clob,jump_clob,unconditional,nocond"
f7fbdd4a 345 (if_then_else (eq_attr "type" "call")
c1a66faf 346 (const_string "clob")
c52acdd2 347 (if_then_else (eq_attr "neon_type" "none")
348 (const_string "nocond")
349 (const_string "unconditional"))))
f7fbdd4a 350
215b30b3 351; Predicable means that the insn can be conditionally executed based on
352; an automatically added predicate (additional patterns are generated by
353; gen...). We default to 'no' because no Thumb patterns match this rule
354; and not all ARM patterns do.
0d66636f 355(define_attr "predicable" "no,yes" (const_string "no"))
356
129a2fe4 357; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
358; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 359; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 360; affect the schedule).
74a71f7d 361(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 362
215b30b3 363; WRITE_CONFLICT implies that a read following an unrelated write is likely
364; to stall the processor. Used with model_wbuf above.
9c08d1fa 365(define_attr "write_conflict" "no,yes"
366 (if_then_else (eq_attr "type"
a2cd141b 367 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 368 (const_string "yes")
369 (const_string "no")))
370
215b30b3 371; Classify the insns into those that take one cycle and those that take more
372; than one on the main cpu execution unit.
f7fbdd4a 373(define_attr "core_cycles" "single,multi"
374 (if_then_else (eq_attr "type"
a2cd141b 375 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 376 (const_string "single")
377 (const_string "multi")))
378
cffb2a26 379;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 380;; distant label. Only applicable to Thumb code.
cffb2a26 381(define_attr "far_jump" "yes,no" (const_string "no"))
382
d51f92df 383
25f905c2 384;; The number of machine instructions this pattern expands to.
385;; Used for Thumb-2 conditional execution.
386(define_attr "ce_count" "" (const_int 1))
387
d51f92df 388;;---------------------------------------------------------------------------
fd781bb2 389;; Mode iterators
d51f92df 390
391; A list of modes that are exactly 64 bits in size. We use this to expand
392; some splits that are the same for all modes when operating on ARM
393; registers.
fd781bb2 394(define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
d51f92df 395
396;;---------------------------------------------------------------------------
397;; Predicates
398
9c9db025 399(include "predicates.md")
234f6557 400(include "constraints.md")
9c9db025 401
a2cd141b 402;;---------------------------------------------------------------------------
403;; Pipeline descriptions
215b30b3 404
06469f9e 405;; Processor type. This is created automatically from arm-cores.def.
406(include "arm-tune.md")
331beb1a 407
e3879fd0 408(define_attr "tune_cortexr4" "yes,no"
409 (const (if_then_else
410 (eq_attr "tune" "cortexr4,cortexr4f")
411 (const_string "yes")
412 (const_string "no"))))
413
a2cd141b 414;; True if the generic scheduling description should be used.
415
416(define_attr "generic_sched" "yes,no"
4d5cb40d 417 (const (if_then_else
036068af 418 (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
e3879fd0 419 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 420 (const_string "no")
421 (const_string "yes"))))
422
c0e1af52 423(define_attr "generic_vfp" "yes,no"
424 (const (if_then_else
425 (and (eq_attr "fpu" "vfp")
036068af 426 (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
e3879fd0 427 (eq_attr "tune_cortexr4" "no"))
c0e1af52 428 (const_string "yes")
429 (const_string "no"))))
430
a2cd141b 431(include "arm-generic.md")
432(include "arm926ejs.md")
c0e1af52 433(include "arm1020e.md")
a2cd141b 434(include "arm1026ejs.md")
435(include "arm1136jfs.md")
bcaec148 436(include "cortex-a8.md")
036068af 437(include "cortex-a9.md")
934a1e72 438(include "cortex-r4.md")
e3879fd0 439(include "cortex-r4f.md")
55e3ada8 440(include "vfp11.md")
3586df96 441
9c08d1fa 442\f
215b30b3 443;;---------------------------------------------------------------------------
e1159bbe 444;; Insn patterns
445;;
a0f94409 446;; Addition insns.
215b30b3 447
9c08d1fa 448;; Note: For DImode insns, there is normally no reason why operands should
449;; not be in the same register, what we don't want is for something being
450;; written to partially overlap something that is an input.
7d57ec45 451;; Cirrus 64bit additions should not be split because we have a native
452;; 64bit addition instructions.
9c08d1fa 453
cffb2a26 454(define_expand "adddi3"
455 [(parallel
215b30b3 456 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 457 (plus:DI (match_operand:DI 1 "s_register_operand" "")
458 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 459 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 460 "TARGET_EITHER"
461 "
a2cd141b 462 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 463 {
464 if (!cirrus_fp_register (operands[0], DImode))
465 operands[0] = force_reg (DImode, operands[0]);
466 if (!cirrus_fp_register (operands[1], DImode))
467 operands[1] = force_reg (DImode, operands[1]);
468 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
469 DONE;
470 }
471
25f905c2 472 if (TARGET_THUMB1)
cffb2a26 473 {
474 if (GET_CODE (operands[1]) != REG)
bc5a93af 475 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 476 if (GET_CODE (operands[2]) != REG)
bc5a93af 477 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 478 }
479 "
480)
481
25f905c2 482(define_insn "*thumb1_adddi3"
cffb2a26 483 [(set (match_operand:DI 0 "register_operand" "=l")
484 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 485 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 486 (clobber (reg:CC CC_REGNUM))
cffb2a26 487 ]
25f905c2 488 "TARGET_THUMB1"
cffb2a26 489 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
490 [(set_attr "length" "4")]
491)
492
a0f94409 493(define_insn_and_split "*arm_adddi3"
cffb2a26 494 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 495 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
496 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 497 (clobber (reg:CC CC_REGNUM))]
25f905c2 498 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 499 "#"
25f905c2 500 "TARGET_32BIT && reload_completed"
a0f94409 501 [(parallel [(set (reg:CC_C CC_REGNUM)
502 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
503 (match_dup 1)))
504 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
505 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
506 (plus:SI (match_dup 4) (match_dup 5))))]
507 "
508 {
509 operands[3] = gen_highpart (SImode, operands[0]);
510 operands[0] = gen_lowpart (SImode, operands[0]);
511 operands[4] = gen_highpart (SImode, operands[1]);
512 operands[1] = gen_lowpart (SImode, operands[1]);
513 operands[5] = gen_highpart (SImode, operands[2]);
514 operands[2] = gen_lowpart (SImode, operands[2]);
515 }"
cffb2a26 516 [(set_attr "conds" "clob")
517 (set_attr "length" "8")]
518)
9c08d1fa 519
a0f94409 520(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 521 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
522 (plus:DI (sign_extend:DI
97499065 523 (match_operand:SI 2 "s_register_operand" "r,r"))
524 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 525 (clobber (reg:CC CC_REGNUM))]
25f905c2 526 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 527 "#"
25f905c2 528 "TARGET_32BIT && reload_completed"
a0f94409 529 [(parallel [(set (reg:CC_C CC_REGNUM)
530 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
531 (match_dup 1)))
532 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
533 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
534 (plus:SI (ashiftrt:SI (match_dup 2)
535 (const_int 31))
536 (match_dup 4))))]
537 "
538 {
539 operands[3] = gen_highpart (SImode, operands[0]);
540 operands[0] = gen_lowpart (SImode, operands[0]);
541 operands[4] = gen_highpart (SImode, operands[1]);
542 operands[1] = gen_lowpart (SImode, operands[1]);
543 operands[2] = gen_lowpart (SImode, operands[2]);
544 }"
215b30b3 545 [(set_attr "conds" "clob")
546 (set_attr "length" "8")]
547)
9c08d1fa 548
a0f94409 549(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 550 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
551 (plus:DI (zero_extend:DI
97499065 552 (match_operand:SI 2 "s_register_operand" "r,r"))
553 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 554 (clobber (reg:CC CC_REGNUM))]
25f905c2 555 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 556 "#"
25f905c2 557 "TARGET_32BIT && reload_completed"
a0f94409 558 [(parallel [(set (reg:CC_C CC_REGNUM)
559 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
560 (match_dup 1)))
561 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
562 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
563 (plus:SI (match_dup 4) (const_int 0))))]
564 "
565 {
566 operands[3] = gen_highpart (SImode, operands[0]);
567 operands[0] = gen_lowpart (SImode, operands[0]);
568 operands[4] = gen_highpart (SImode, operands[1]);
569 operands[1] = gen_lowpart (SImode, operands[1]);
570 operands[2] = gen_lowpart (SImode, operands[2]);
571 }"
cffb2a26 572 [(set_attr "conds" "clob")
573 (set_attr "length" "8")]
574)
b11cae9e 575
87b22bf7 576(define_expand "addsi3"
cffb2a26 577 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 578 (plus:SI (match_operand:SI 1 "s_register_operand" "")
579 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 580 "TARGET_EITHER"
87b22bf7 581 "
25f905c2 582 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 583 {
96f57e36 584 arm_split_constant (PLUS, SImode, NULL_RTX,
585 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 586 optimize && can_create_pseudo_p ());
87b22bf7 587 DONE;
588 }
cffb2a26 589 "
590)
87b22bf7 591
5bd751ff 592; If there is a scratch available, this will be faster than synthesizing the
a0f94409 593; addition.
594(define_peephole2
595 [(match_scratch:SI 3 "r")
372575c7 596 (set (match_operand:SI 0 "arm_general_register_operand" "")
597 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 598 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 599 "TARGET_32BIT &&
a0f94409 600 !(const_ok_for_arm (INTVAL (operands[2]))
601 || const_ok_for_arm (-INTVAL (operands[2])))
602 && const_ok_for_arm (~INTVAL (operands[2]))"
603 [(set (match_dup 3) (match_dup 2))
604 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
605 ""
606)
87b22bf7 607
2f02c19f 608;; The r/r/k alternative is required when reloading the address
609;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
610;; put the duplicated register first, and not try the commutative version.
a0f94409 611(define_insn_and_split "*arm_addsi3"
2f02c19f 612 [(set (match_operand:SI 0 "s_register_operand" "=r, !k, r,r, !k,r")
613 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
614 (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
25f905c2 615 "TARGET_32BIT"
5565501b 616 "@
617 add%?\\t%0, %1, %2
aaa37ad6 618 add%?\\t%0, %1, %2
2f02c19f 619 add%?\\t%0, %2, %1
aaa37ad6 620 sub%?\\t%0, %1, #%n2
87b22bf7 621 sub%?\\t%0, %1, #%n2
622 #"
a3ffc315 623 "TARGET_32BIT
624 && GET_CODE (operands[2]) == CONST_INT
a0f94409 625 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 626 || const_ok_for_arm (-INTVAL (operands[2])))
627 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 628 [(clobber (const_int 0))]
629 "
96f57e36 630 arm_split_constant (PLUS, SImode, curr_insn,
631 INTVAL (operands[2]), operands[0],
a0f94409 632 operands[1], 0);
633 DONE;
634 "
2f02c19f 635 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 636 (set_attr "predicable" "yes")]
cffb2a26 637)
638
639;; Register group 'k' is a single register group containing only the stack
640;; register. Trying to reload it will always fail catastrophically,
641;; so never allow those alternatives to match if reloading is needed.
642
0bdb6455 643(define_insn_and_split "*thumb1_addsi3"
644 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
645 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
646 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
25f905c2 647 "TARGET_THUMB1"
cffb2a26 648 "*
0d66636f 649 static const char * const asms[] =
cffb2a26 650 {
651 \"add\\t%0, %0, %2\",
652 \"sub\\t%0, %0, #%n2\",
653 \"add\\t%0, %1, %2\",
654 \"add\\t%0, %0, %2\",
655 \"add\\t%0, %0, %2\",
656 \"add\\t%0, %1, %2\",
0bdb6455 657 \"add\\t%0, %1, %2\",
658 \"#\",
659 \"#\"
cffb2a26 660 };
661 if ((which_alternative == 2 || which_alternative == 6)
662 && GET_CODE (operands[2]) == CONST_INT
663 && INTVAL (operands[2]) < 0)
664 return \"sub\\t%0, %1, #%n2\";
665 return asms[which_alternative];
666 "
0bdb6455 667 "&& reload_completed && CONST_INT_P (operands[2])
668 && operands[1] != stack_pointer_rtx
669 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
670 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
671 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
672 {
673 HOST_WIDE_INT offset = INTVAL (operands[2]);
674 if (offset > 255)
675 offset = 255;
676 else if (offset < -255)
677 offset = -255;
678
679 operands[3] = GEN_INT (offset);
680 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
681 }
682 [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
cffb2a26 683)
684
685;; Reloading and elimination of the frame pointer can
686;; sometimes cause this optimization to be missed.
a0f94409 687(define_peephole2
372575c7 688 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 689 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 690 (set (match_dup 0)
372575c7 691 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 692 "TARGET_THUMB1
cffb2a26 693 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
694 && (INTVAL (operands[1]) & 3) == 0"
372575c7 695 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 696 ""
cffb2a26 697)
b11cae9e 698
25f905c2 699;; ??? Make Thumb-2 variants which prefer low regs
f7fbdd4a 700(define_insn "*addsi3_compare0"
bd5b4116 701 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 702 (compare:CC_NOOV
215b30b3 703 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
704 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 705 (const_int 0)))
706 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 707 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 708 "TARGET_32BIT"
5565501b 709 "@
25f905c2 710 add%.\\t%0, %1, %2
711 sub%.\\t%0, %1, #%n2"
cffb2a26 712 [(set_attr "conds" "set")]
713)
9c08d1fa 714
aea4c774 715(define_insn "*addsi3_compare0_scratch"
bd5b4116 716 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 717 (compare:CC_NOOV
215b30b3 718 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
719 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 720 (const_int 0)))]
25f905c2 721 "TARGET_32BIT"
cffb2a26 722 "@
723 cmn%?\\t%0, %1
724 cmp%?\\t%0, #%n1"
0d66636f 725 [(set_attr "conds" "set")]
726)
cffb2a26 727
aed179ae 728(define_insn "*compare_negsi_si"
729 [(set (reg:CC_Z CC_REGNUM)
730 (compare:CC_Z
731 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
732 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 733 "TARGET_32BIT"
aed179ae 734 "cmn%?\\t%1, %0"
0d66636f 735 [(set_attr "conds" "set")]
736)
aea4c774 737
203c488f 738;; This is the canonicalization of addsi3_compare0_for_combiner when the
739;; addend is a constant.
740(define_insn "*cmpsi2_addneg"
741 [(set (reg:CC CC_REGNUM)
742 (compare:CC
743 (match_operand:SI 1 "s_register_operand" "r,r")
744 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
745 (set (match_operand:SI 0 "s_register_operand" "=r,r")
746 (plus:SI (match_dup 1)
747 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
25f905c2 748 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 749 "@
25f905c2 750 sub%.\\t%0, %1, %2
751 add%.\\t%0, %1, #%n2"
203c488f 752 [(set_attr "conds" "set")]
753)
754
755;; Convert the sequence
756;; sub rd, rn, #1
757;; cmn rd, #1 (equivalent to cmp rd, #-1)
758;; bne dest
759;; into
760;; subs rd, rn, #1
761;; bcs dest ((unsigned)rn >= 1)
762;; similarly for the beq variant using bcc.
763;; This is a common looping idiom (while (n--))
764(define_peephole2
372575c7 765 [(set (match_operand:SI 0 "arm_general_register_operand" "")
766 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 767 (const_int -1)))
768 (set (match_operand 2 "cc_register" "")
769 (compare (match_dup 0) (const_int -1)))
770 (set (pc)
771 (if_then_else (match_operator 3 "equality_operator"
772 [(match_dup 2) (const_int 0)])
773 (match_operand 4 "" "")
774 (match_operand 5 "" "")))]
25f905c2 775 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 776 [(parallel[
777 (set (match_dup 2)
778 (compare:CC
779 (match_dup 1) (const_int 1)))
780 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
781 (set (pc)
782 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
783 (match_dup 4)
784 (match_dup 5)))]
785 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
786 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
787 ? GEU : LTU),
788 VOIDmode,
789 operands[2], const0_rtx);"
790)
791
ebcc79bc 792;; The next four insns work because they compare the result with one of
793;; the operands, and we know that the use of the condition code is
794;; either GEU or LTU, so we can use the carry flag from the addition
795;; instead of doing the compare a second time.
796(define_insn "*addsi3_compare_op1"
bd5b4116 797 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 798 (compare:CC_C
799 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
800 (match_operand:SI 2 "arm_add_operand" "rI,L"))
801 (match_dup 1)))
802 (set (match_operand:SI 0 "s_register_operand" "=r,r")
803 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 804 "TARGET_32BIT"
ebcc79bc 805 "@
25f905c2 806 add%.\\t%0, %1, %2
807 sub%.\\t%0, %1, #%n2"
0d66636f 808 [(set_attr "conds" "set")]
809)
ebcc79bc 810
811(define_insn "*addsi3_compare_op2"
bd5b4116 812 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 813 (compare:CC_C
814 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
815 (match_operand:SI 2 "arm_add_operand" "rI,L"))
816 (match_dup 2)))
5565501b 817 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 818 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 819 "TARGET_32BIT"
5565501b 820 "@
25f905c2 821 add%.\\t%0, %1, %2
822 sub%.\\t%0, %1, #%n2"
0d66636f 823 [(set_attr "conds" "set")]
824)
9c08d1fa 825
ebcc79bc 826(define_insn "*compare_addsi2_op0"
bd5b4116 827 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 828 (compare:CC_C
829 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
830 (match_operand:SI 1 "arm_add_operand" "rI,L"))
831 (match_dup 0)))]
25f905c2 832 "TARGET_32BIT"
ebcc79bc 833 "@
834 cmn%?\\t%0, %1
835 cmp%?\\t%0, #%n1"
0d66636f 836 [(set_attr "conds" "set")]
837)
ebcc79bc 838
839(define_insn "*compare_addsi2_op1"
bd5b4116 840 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 841 (compare:CC_C
842 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
843 (match_operand:SI 1 "arm_add_operand" "rI,L"))
844 (match_dup 1)))]
25f905c2 845 "TARGET_32BIT"
ebcc79bc 846 "@
847 cmn%?\\t%0, %1
848 cmp%?\\t%0, #%n1"
0d66636f 849 [(set_attr "conds" "set")]
850)
ebcc79bc 851
852(define_insn "*addsi3_carryin"
853 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 854 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 855 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
856 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
25f905c2 857 "TARGET_32BIT"
ebcc79bc 858 "adc%?\\t%0, %1, %2"
cffb2a26 859 [(set_attr "conds" "use")]
860)
ebcc79bc 861
33782ec7 862(define_insn "*addsi3_carryin_shift"
7b63a8dd 863 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 864 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 865 (plus:SI
866 (match_operator:SI 2 "shift_operator"
7b63a8dd 867 [(match_operand:SI 3 "s_register_operand" "r")
868 (match_operand:SI 4 "reg_or_int_operand" "rM")])
869 (match_operand:SI 1 "s_register_operand" "r"))))]
25f905c2 870 "TARGET_32BIT"
33782ec7 871 "adc%?\\t%0, %1, %3%S2"
a2cd141b 872 [(set_attr "conds" "use")
873 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
874 (const_string "alu_shift")
875 (const_string "alu_shift_reg")))]
33782ec7 876)
877
ebcc79bc 878(define_insn "*addsi3_carryin_alt1"
879 [(set (match_operand:SI 0 "s_register_operand" "=r")
880 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
881 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 882 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
25f905c2 883 "TARGET_32BIT"
ebcc79bc 884 "adc%?\\t%0, %1, %2"
cffb2a26 885 [(set_attr "conds" "use")]
886)
ebcc79bc 887
888(define_insn "*addsi3_carryin_alt2"
889 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 890 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 891 (match_operand:SI 1 "s_register_operand" "r"))
892 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 893 "TARGET_32BIT"
ebcc79bc 894 "adc%?\\t%0, %1, %2"
0d66636f 895 [(set_attr "conds" "use")]
896)
ebcc79bc 897
898(define_insn "*addsi3_carryin_alt3"
899 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 900 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 901 (match_operand:SI 2 "arm_rhs_operand" "rI"))
902 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 903 "TARGET_32BIT"
ebcc79bc 904 "adc%?\\t%0, %1, %2"
cffb2a26 905 [(set_attr "conds" "use")]
906)
ebcc79bc 907
25f905c2 908(define_expand "incscc"
909 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
910 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
911 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
912 (match_operand:SI 1 "s_register_operand" "0,?r")))]
913 "TARGET_32BIT"
914 ""
915)
916
917(define_insn "*arm_incscc"
9c08d1fa 918 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 919 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 920 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 921 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 922 "TARGET_ARM"
5565501b 923 "@
924 add%d2\\t%0, %1, #1
925 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 926 [(set_attr "conds" "use")
215b30b3 927 (set_attr "length" "4,8")]
928)
9c08d1fa 929
d795fb69 930; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
931(define_split
932 [(set (match_operand:SI 0 "s_register_operand" "")
933 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
934 (match_operand:SI 2 "s_register_operand" ""))
935 (const_int -1)))
936 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 937 "TARGET_32BIT"
d795fb69 938 [(set (match_dup 3) (match_dup 1))
939 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
940 "
941 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
942")
943
604f3a0a 944(define_expand "addsf3"
945 [(set (match_operand:SF 0 "s_register_operand" "")
946 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 947 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 948 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 949 "
a2cd141b 950 if (TARGET_MAVERICK
604f3a0a 951 && !cirrus_fp_register (operands[2], SFmode))
952 operands[2] = force_reg (SFmode, operands[2]);
953")
954
604f3a0a 955(define_expand "adddf3"
956 [(set (match_operand:DF 0 "s_register_operand" "")
957 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 958 (match_operand:DF 2 "arm_float_add_operand" "")))]
25f905c2 959 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 960 "
a2cd141b 961 if (TARGET_MAVERICK
604f3a0a 962 && !cirrus_fp_register (operands[2], DFmode))
963 operands[2] = force_reg (DFmode, operands[2]);
964")
965
cffb2a26 966(define_expand "subdi3"
967 [(parallel
968 [(set (match_operand:DI 0 "s_register_operand" "")
969 (minus:DI (match_operand:DI 1 "s_register_operand" "")
970 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 971 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 972 "TARGET_EITHER"
973 "
a2cd141b 974 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 975 && TARGET_32BIT
7d57ec45 976 && cirrus_fp_register (operands[0], DImode)
977 && cirrus_fp_register (operands[1], DImode))
978 {
979 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
980 DONE;
981 }
982
25f905c2 983 if (TARGET_THUMB1)
cffb2a26 984 {
985 if (GET_CODE (operands[1]) != REG)
986 operands[1] = force_reg (SImode, operands[1]);
987 if (GET_CODE (operands[2]) != REG)
988 operands[2] = force_reg (SImode, operands[2]);
989 }
990 "
991)
992
993(define_insn "*arm_subdi3"
994 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 995 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
996 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 997 (clobber (reg:CC CC_REGNUM))]
25f905c2 998 "TARGET_32BIT"
97499065 999 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1000 [(set_attr "conds" "clob")
1001 (set_attr "length" "8")]
1002)
1003
1004(define_insn "*thumb_subdi3"
1005 [(set (match_operand:DI 0 "register_operand" "=l")
1006 (minus:DI (match_operand:DI 1 "register_operand" "0")
1007 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1008 (clobber (reg:CC CC_REGNUM))]
25f905c2 1009 "TARGET_THUMB1"
cffb2a26 1010 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1011 [(set_attr "length" "4")]
1012)
9c08d1fa 1013
f7fbdd4a 1014(define_insn "*subdi_di_zesidi"
cffb2a26 1015 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1016 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 1017 (zero_extend:DI
cffb2a26 1018 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1019 (clobber (reg:CC CC_REGNUM))]
25f905c2 1020 "TARGET_32BIT"
97499065 1021 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1022 [(set_attr "conds" "clob")
1023 (set_attr "length" "8")]
1024)
9c08d1fa 1025
f7fbdd4a 1026(define_insn "*subdi_di_sesidi"
cffb2a26 1027 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1028 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 1029 (sign_extend:DI
cffb2a26 1030 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1031 (clobber (reg:CC CC_REGNUM))]
25f905c2 1032 "TARGET_32BIT"
97499065 1033 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1034 [(set_attr "conds" "clob")
1035 (set_attr "length" "8")]
1036)
9c08d1fa 1037
f7fbdd4a 1038(define_insn "*subdi_zesidi_di"
cffb2a26 1039 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1040 (minus:DI (zero_extend:DI
cffb2a26 1041 (match_operand:SI 2 "s_register_operand" "r,r"))
1042 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 1043 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1044 "TARGET_ARM"
97499065 1045 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1046 [(set_attr "conds" "clob")
1047 (set_attr "length" "8")]
1048)
9c08d1fa 1049
f7fbdd4a 1050(define_insn "*subdi_sesidi_di"
cffb2a26 1051 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1052 (minus:DI (sign_extend:DI
cffb2a26 1053 (match_operand:SI 2 "s_register_operand" "r,r"))
1054 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 1055 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1056 "TARGET_ARM"
97499065 1057 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1058 [(set_attr "conds" "clob")
1059 (set_attr "length" "8")]
1060)
9c08d1fa 1061
f7fbdd4a 1062(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1063 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1064 (minus:DI (zero_extend:DI
cffb2a26 1065 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1066 (zero_extend:DI
cffb2a26 1067 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1068 (clobber (reg:CC CC_REGNUM))]
25f905c2 1069 "TARGET_32BIT"
1070 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1071 [(set_attr "conds" "clob")
1072 (set_attr "length" "8")]
1073)
b11cae9e 1074
87b22bf7 1075(define_expand "subsi3"
cffb2a26 1076 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1077 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1078 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1079 "TARGET_EITHER"
87b22bf7 1080 "
1081 if (GET_CODE (operands[1]) == CONST_INT)
1082 {
25f905c2 1083 if (TARGET_32BIT)
cffb2a26 1084 {
96f57e36 1085 arm_split_constant (MINUS, SImode, NULL_RTX,
1086 INTVAL (operands[1]), operands[0],
e1ba4a27 1087 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1088 DONE;
1089 }
25f905c2 1090 else /* TARGET_THUMB1 */
cffb2a26 1091 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1092 }
cffb2a26 1093 "
1094)
87b22bf7 1095
25f905c2 1096(define_insn "*thumb1_subsi3_insn"
cffb2a26 1097 [(set (match_operand:SI 0 "register_operand" "=l")
1098 (minus:SI (match_operand:SI 1 "register_operand" "l")
1099 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1100 "TARGET_THUMB1"
cffb2a26 1101 "sub\\t%0, %1, %2"
1102 [(set_attr "length" "2")]
1103)
1104
25f905c2 1105; ??? Check Thumb-2 split length
a0f94409 1106(define_insn_and_split "*arm_subsi3_insn"
aaa37ad6 1107 [(set (match_operand:SI 0 "s_register_operand" "=r,rk,r")
1108 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n")
1109 (match_operand:SI 2 "s_register_operand" "r, r, r")))]
25f905c2 1110 "TARGET_32BIT"
e2348bcb 1111 "@
87b22bf7 1112 rsb%?\\t%0, %2, %1
aaa37ad6 1113 sub%?\\t%0, %1, %2
87b22bf7 1114 #"
25f905c2 1115 "TARGET_32BIT
a0f94409 1116 && GET_CODE (operands[1]) == CONST_INT
1117 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 1118 [(clobber (const_int 0))]
1119 "
96f57e36 1120 arm_split_constant (MINUS, SImode, curr_insn,
1121 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1122 DONE;
cffb2a26 1123 "
aaa37ad6 1124 [(set_attr "length" "4,4,16")
a0f94409 1125 (set_attr "predicable" "yes")]
1126)
1127
1128(define_peephole2
1129 [(match_scratch:SI 3 "r")
372575c7 1130 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1131 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1132 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1133 "TARGET_32BIT
a0f94409 1134 && !const_ok_for_arm (INTVAL (operands[1]))
1135 && const_ok_for_arm (~INTVAL (operands[1]))"
1136 [(set (match_dup 3) (match_dup 1))
1137 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1138 ""
cffb2a26 1139)
b11cae9e 1140
f7fbdd4a 1141(define_insn "*subsi3_compare0"
bd5b4116 1142 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1143 (compare:CC_NOOV
1144 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1145 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1146 (const_int 0)))
9c08d1fa 1147 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1148 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1149 "TARGET_32BIT"
e2348bcb 1150 "@
25f905c2 1151 sub%.\\t%0, %1, %2
1152 rsb%.\\t%0, %2, %1"
cffb2a26 1153 [(set_attr "conds" "set")]
1154)
9c08d1fa 1155
25f905c2 1156(define_expand "decscc"
1157 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1158 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1159 (match_operator:SI 2 "arm_comparison_operator"
1160 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1161 "TARGET_32BIT"
1162 ""
1163)
1164
1165(define_insn "*arm_decscc"
cffb2a26 1166 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1167 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1168 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1169 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1170 "TARGET_ARM"
e2348bcb 1171 "@
215b30b3 1172 sub%d2\\t%0, %1, #1
1173 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1174 [(set_attr "conds" "use")
1175 (set_attr "length" "*,8")]
1176)
9c08d1fa 1177
604f3a0a 1178(define_expand "subsf3"
1179 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1180 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1181 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1182 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1183 "
a2cd141b 1184 if (TARGET_MAVERICK)
604f3a0a 1185 {
1186 if (!cirrus_fp_register (operands[1], SFmode))
1187 operands[1] = force_reg (SFmode, operands[1]);
1188 if (!cirrus_fp_register (operands[2], SFmode))
1189 operands[2] = force_reg (SFmode, operands[2]);
1190 }
1191")
1192
604f3a0a 1193(define_expand "subdf3"
1194 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1195 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1196 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1197 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1198 "
a2cd141b 1199 if (TARGET_MAVERICK)
604f3a0a 1200 {
1201 if (!cirrus_fp_register (operands[1], DFmode))
1202 operands[1] = force_reg (DFmode, operands[1]);
1203 if (!cirrus_fp_register (operands[2], DFmode))
1204 operands[2] = force_reg (DFmode, operands[2]);
1205 }
1206")
1207
b11cae9e 1208\f
1209;; Multiplication insns
1210
cffb2a26 1211(define_expand "mulsi3"
1212 [(set (match_operand:SI 0 "s_register_operand" "")
1213 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1214 (match_operand:SI 1 "s_register_operand" "")))]
1215 "TARGET_EITHER"
1216 ""
1217)
1218
9c08d1fa 1219;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1220(define_insn "*arm_mulsi3"
1221 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1222 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1223 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
58d7d654 1224 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1225 "mul%?\\t%0, %2, %1"
a2cd141b 1226 [(set_attr "insn" "mul")
0d66636f 1227 (set_attr "predicable" "yes")]
cffb2a26 1228)
1229
58d7d654 1230(define_insn "*arm_mulsi3_v6"
1231 [(set (match_operand:SI 0 "s_register_operand" "=r")
1232 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1233 (match_operand:SI 2 "s_register_operand" "r")))]
1234 "TARGET_32BIT && arm_arch6"
1235 "mul%?\\t%0, %1, %2"
1236 [(set_attr "insn" "mul")
1237 (set_attr "predicable" "yes")]
1238)
1239
215b30b3 1240; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1241; 1 and 2; are the same, because reload will make operand 0 match
1242; operand 1 without realizing that this conflicts with operand 2. We fix
1243; this by adding another alternative to match this case, and then `reload'
1244; it ourselves. This alternative must come first.
cffb2a26 1245(define_insn "*thumb_mulsi3"
1246 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1247 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1248 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1249 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1250 "*
1251 if (which_alternative < 2)
20c4e896 1252 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1253 else
20c4e896 1254 return \"mul\\t%0, %2\";
cffb2a26 1255 "
1256 [(set_attr "length" "4,4,2")
a2cd141b 1257 (set_attr "insn" "mul")]
cffb2a26 1258)
b11cae9e 1259
58d7d654 1260(define_insn "*thumb_mulsi3_v6"
1261 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1262 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1263 (match_operand:SI 2 "register_operand" "l,0,0")))]
1264 "TARGET_THUMB1 && arm_arch6"
1265 "@
1266 mul\\t%0, %2
1267 mul\\t%0, %1
1268 mul\\t%0, %1"
1269 [(set_attr "length" "2")
1270 (set_attr "insn" "mul")]
1271)
1272
f7fbdd4a 1273(define_insn "*mulsi3_compare0"
bd5b4116 1274 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1275 (compare:CC_NOOV (mult:SI
1276 (match_operand:SI 2 "s_register_operand" "r,r")
1277 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1278 (const_int 0)))
1279 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1280 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1281 "TARGET_ARM && !arm_arch6"
1282 "mul%.\\t%0, %2, %1"
1283 [(set_attr "conds" "set")
1284 (set_attr "insn" "muls")]
1285)
1286
1287(define_insn "*mulsi3_compare0_v6"
1288 [(set (reg:CC_NOOV CC_REGNUM)
1289 (compare:CC_NOOV (mult:SI
1290 (match_operand:SI 2 "s_register_operand" "r")
1291 (match_operand:SI 1 "s_register_operand" "r"))
1292 (const_int 0)))
1293 (set (match_operand:SI 0 "s_register_operand" "=r")
1294 (mult:SI (match_dup 2) (match_dup 1)))]
1295 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1296 "mul%.\\t%0, %2, %1"
cffb2a26 1297 [(set_attr "conds" "set")
a2cd141b 1298 (set_attr "insn" "muls")]
cffb2a26 1299)
9c08d1fa 1300
f7fbdd4a 1301(define_insn "*mulsi_compare0_scratch"
bd5b4116 1302 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1303 (compare:CC_NOOV (mult:SI
1304 (match_operand:SI 2 "s_register_operand" "r,r")
1305 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1306 (const_int 0)))
1307 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1308 "TARGET_ARM && !arm_arch6"
1309 "mul%.\\t%0, %2, %1"
1310 [(set_attr "conds" "set")
1311 (set_attr "insn" "muls")]
1312)
1313
1314(define_insn "*mulsi_compare0_scratch_v6"
1315 [(set (reg:CC_NOOV CC_REGNUM)
1316 (compare:CC_NOOV (mult:SI
1317 (match_operand:SI 2 "s_register_operand" "r")
1318 (match_operand:SI 1 "s_register_operand" "r"))
1319 (const_int 0)))
1320 (clobber (match_scratch:SI 0 "=r"))]
1321 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1322 "mul%.\\t%0, %2, %1"
cffb2a26 1323 [(set_attr "conds" "set")
a2cd141b 1324 (set_attr "insn" "muls")]
cffb2a26 1325)
9c08d1fa 1326
b11cae9e 1327;; Unnamed templates to match MLA instruction.
1328
f7fbdd4a 1329(define_insn "*mulsi3addsi"
9c08d1fa 1330 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1331 (plus:SI
9c08d1fa 1332 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1333 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1334 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
58d7d654 1335 "TARGET_32BIT && !arm_arch6"
1336 "mla%?\\t%0, %2, %1, %3"
1337 [(set_attr "insn" "mla")
1338 (set_attr "predicable" "yes")]
1339)
1340
1341(define_insn "*mulsi3addsi_v6"
1342 [(set (match_operand:SI 0 "s_register_operand" "=r")
1343 (plus:SI
1344 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1345 (match_operand:SI 1 "s_register_operand" "r"))
1346 (match_operand:SI 3 "s_register_operand" "r")))]
1347 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1348 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1349 [(set_attr "insn" "mla")
0d66636f 1350 (set_attr "predicable" "yes")]
1351)
b11cae9e 1352
f7fbdd4a 1353(define_insn "*mulsi3addsi_compare0"
bd5b4116 1354 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1355 (compare:CC_NOOV
1356 (plus:SI (mult:SI
1357 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1358 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1359 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1360 (const_int 0)))
9c08d1fa 1361 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1362 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1363 (match_dup 3)))]
58d7d654 1364 "TARGET_ARM && arm_arch6"
1365 "mla%.\\t%0, %2, %1, %3"
1366 [(set_attr "conds" "set")
1367 (set_attr "insn" "mlas")]
1368)
1369
1370(define_insn "*mulsi3addsi_compare0_v6"
1371 [(set (reg:CC_NOOV CC_REGNUM)
1372 (compare:CC_NOOV
1373 (plus:SI (mult:SI
1374 (match_operand:SI 2 "s_register_operand" "r")
1375 (match_operand:SI 1 "s_register_operand" "r"))
1376 (match_operand:SI 3 "s_register_operand" "r"))
1377 (const_int 0)))
1378 (set (match_operand:SI 0 "s_register_operand" "=r")
1379 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1380 (match_dup 3)))]
1381 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1382 "mla%.\\t%0, %2, %1, %3"
0d66636f 1383 [(set_attr "conds" "set")
a2cd141b 1384 (set_attr "insn" "mlas")]
0d66636f 1385)
9c08d1fa 1386
f7fbdd4a 1387(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1388 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1389 (compare:CC_NOOV
1390 (plus:SI (mult:SI
1391 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1392 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1393 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1394 (const_int 0)))
9c08d1fa 1395 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1396 "TARGET_ARM && !arm_arch6"
1397 "mla%.\\t%0, %2, %1, %3"
1398 [(set_attr "conds" "set")
1399 (set_attr "insn" "mlas")]
1400)
1401
1402(define_insn "*mulsi3addsi_compare0_scratch_v6"
1403 [(set (reg:CC_NOOV CC_REGNUM)
1404 (compare:CC_NOOV
1405 (plus:SI (mult:SI
1406 (match_operand:SI 2 "s_register_operand" "r")
1407 (match_operand:SI 1 "s_register_operand" "r"))
1408 (match_operand:SI 3 "s_register_operand" "r"))
1409 (const_int 0)))
1410 (clobber (match_scratch:SI 0 "=r"))]
1411 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1412 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1413 [(set_attr "conds" "set")
a2cd141b 1414 (set_attr "insn" "mlas")]
cffb2a26 1415)
f7fbdd4a 1416
89545238 1417(define_insn "*mulsi3subsi"
1418 [(set (match_operand:SI 0 "s_register_operand" "=r")
1419 (minus:SI
1420 (match_operand:SI 3 "s_register_operand" "r")
1421 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1422 (match_operand:SI 1 "s_register_operand" "r"))))]
1423 "TARGET_32BIT && arm_arch_thumb2"
1424 "mls%?\\t%0, %2, %1, %3"
1425 [(set_attr "insn" "mla")
1426 (set_attr "predicable" "yes")]
1427)
1428
efee20da 1429;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1430
1431(define_insn "*mulsidi3adddi"
fe8dbf85 1432 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1433 (plus:DI
215b30b3 1434 (mult:DI
fe8dbf85 1435 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1436 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1437 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1438 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1439 "smlal%?\\t%Q0, %R0, %3, %2"
1440 [(set_attr "insn" "smlal")
1441 (set_attr "predicable" "yes")]
1442)
1443
1444(define_insn "*mulsidi3adddi_v6"
1445 [(set (match_operand:DI 0 "s_register_operand" "=r")
1446 (plus:DI
1447 (mult:DI
1448 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1449 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1450 (match_operand:DI 1 "s_register_operand" "0")))]
1451 "TARGET_32BIT && arm_arch6"
fe8dbf85 1452 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1453 [(set_attr "insn" "smlal")
0d66636f 1454 (set_attr "predicable" "yes")]
1455)
82b85d08 1456
957788b0 1457;; 32x32->64 widening multiply.
1458;; As with mulsi3, the only difference between the v3-5 and v6+
1459;; versions of these patterns is the requirement that the output not
1460;; overlap the inputs, but that still means we have to have a named
1461;; expander and two different starred insns.
1462
1463(define_expand "mulsidi3"
1464 [(set (match_operand:DI 0 "s_register_operand" "")
1465 (mult:DI
1466 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1467 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1468 "TARGET_32BIT && arm_arch3m"
1469 ""
1470)
1471
1472(define_insn "*mulsidi3_nov6"
f7fbdd4a 1473 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1474 (mult:DI
1475 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1476 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1477 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1478 "smull%?\\t%Q0, %R0, %1, %2"
1479 [(set_attr "insn" "smull")
1480 (set_attr "predicable" "yes")]
1481)
1482
957788b0 1483(define_insn "*mulsidi3_v6"
58d7d654 1484 [(set (match_operand:DI 0 "s_register_operand" "=r")
1485 (mult:DI
1486 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1487 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1488 "TARGET_32BIT && arm_arch6"
97499065 1489 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1490 [(set_attr "insn" "smull")
0d66636f 1491 (set_attr "predicable" "yes")]
1492)
f7fbdd4a 1493
957788b0 1494(define_expand "umulsidi3"
1495 [(set (match_operand:DI 0 "s_register_operand" "")
1496 (mult:DI
1497 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1498 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1499 "TARGET_32BIT && arm_arch3m"
1500 ""
1501)
1502
1503(define_insn "*umulsidi3_nov6"
f7fbdd4a 1504 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1505 (mult:DI
1506 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1507 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1508 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1509 "umull%?\\t%Q0, %R0, %1, %2"
1510 [(set_attr "insn" "umull")
1511 (set_attr "predicable" "yes")]
1512)
1513
957788b0 1514(define_insn "*umulsidi3_v6"
58d7d654 1515 [(set (match_operand:DI 0 "s_register_operand" "=r")
1516 (mult:DI
1517 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1518 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1519 "TARGET_32BIT && arm_arch6"
97499065 1520 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1521 [(set_attr "insn" "umull")
0d66636f 1522 (set_attr "predicable" "yes")]
1523)
b11cae9e 1524
efee20da 1525;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1526
1527(define_insn "*umulsidi3adddi"
8ead09f9 1528 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1529 (plus:DI
215b30b3 1530 (mult:DI
fe8dbf85 1531 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1532 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1533 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1534 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1535 "umlal%?\\t%Q0, %R0, %3, %2"
1536 [(set_attr "insn" "umlal")
1537 (set_attr "predicable" "yes")]
1538)
1539
1540(define_insn "*umulsidi3adddi_v6"
1541 [(set (match_operand:DI 0 "s_register_operand" "=r")
1542 (plus:DI
1543 (mult:DI
1544 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1545 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1546 (match_operand:DI 1 "s_register_operand" "0")))]
1547 "TARGET_32BIT && arm_arch6"
fe8dbf85 1548 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1549 [(set_attr "insn" "umlal")
0d66636f 1550 (set_attr "predicable" "yes")]
1551)
82b85d08 1552
957788b0 1553(define_expand "smulsi3_highpart"
1554 [(parallel
1555 [(set (match_operand:SI 0 "s_register_operand" "")
1556 (truncate:SI
1557 (lshiftrt:DI
1558 (mult:DI
1559 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1560 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1561 (const_int 32))))
1562 (clobber (match_scratch:SI 3 ""))])]
1563 "TARGET_32BIT && arm_arch3m"
1564 ""
1565)
1566
1567(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1568 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1569 (truncate:SI
1570 (lshiftrt:DI
215b30b3 1571 (mult:DI
1572 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1573 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1574 (const_int 32))))
1575 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1576 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1577 "smull%?\\t%3, %0, %2, %1"
1578 [(set_attr "insn" "smull")
1579 (set_attr "predicable" "yes")]
1580)
1581
957788b0 1582(define_insn "*smulsi3_highpart_v6"
58d7d654 1583 [(set (match_operand:SI 0 "s_register_operand" "=r")
1584 (truncate:SI
1585 (lshiftrt:DI
1586 (mult:DI
1587 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1588 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1589 (const_int 32))))
1590 (clobber (match_scratch:SI 3 "=r"))]
1591 "TARGET_32BIT && arm_arch6"
f082f1c4 1592 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1593 [(set_attr "insn" "smull")
0d66636f 1594 (set_attr "predicable" "yes")]
cffb2a26 1595)
f082f1c4 1596
957788b0 1597(define_expand "umulsi3_highpart"
1598 [(parallel
1599 [(set (match_operand:SI 0 "s_register_operand" "")
1600 (truncate:SI
1601 (lshiftrt:DI
1602 (mult:DI
1603 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1604 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1605 (const_int 32))))
1606 (clobber (match_scratch:SI 3 ""))])]
1607 "TARGET_32BIT && arm_arch3m"
1608 ""
1609)
1610
1611(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1612 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1613 (truncate:SI
1614 (lshiftrt:DI
215b30b3 1615 (mult:DI
1616 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1617 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1618 (const_int 32))))
1619 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1620 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1621 "umull%?\\t%3, %0, %2, %1"
1622 [(set_attr "insn" "umull")
1623 (set_attr "predicable" "yes")]
1624)
1625
957788b0 1626(define_insn "*umulsi3_highpart_v6"
58d7d654 1627 [(set (match_operand:SI 0 "s_register_operand" "=r")
1628 (truncate:SI
1629 (lshiftrt:DI
1630 (mult:DI
1631 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1632 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1633 (const_int 32))))
1634 (clobber (match_scratch:SI 3 "=r"))]
1635 "TARGET_32BIT && arm_arch6"
f082f1c4 1636 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1637 [(set_attr "insn" "umull")
0d66636f 1638 (set_attr "predicable" "yes")]
cffb2a26 1639)
f082f1c4 1640
331beb1a 1641(define_insn "mulhisi3"
1642 [(set (match_operand:SI 0 "s_register_operand" "=r")
1643 (mult:SI (sign_extend:SI
1644 (match_operand:HI 1 "s_register_operand" "%r"))
1645 (sign_extend:SI
1646 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1647 "TARGET_DSP_MULTIPLY"
61a2d04c 1648 "smulbb%?\\t%0, %1, %2"
a2cd141b 1649 [(set_attr "insn" "smulxy")
fec538d9 1650 (set_attr "predicable" "yes")]
1651)
1652
1653(define_insn "*mulhisi3tb"
1654 [(set (match_operand:SI 0 "s_register_operand" "=r")
1655 (mult:SI (ashiftrt:SI
1656 (match_operand:SI 1 "s_register_operand" "r")
1657 (const_int 16))
1658 (sign_extend:SI
1659 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1660 "TARGET_DSP_MULTIPLY"
fec538d9 1661 "smultb%?\\t%0, %1, %2"
a2cd141b 1662 [(set_attr "insn" "smulxy")
fec538d9 1663 (set_attr "predicable" "yes")]
1664)
1665
1666(define_insn "*mulhisi3bt"
1667 [(set (match_operand:SI 0 "s_register_operand" "=r")
1668 (mult:SI (sign_extend:SI
1669 (match_operand:HI 1 "s_register_operand" "r"))
1670 (ashiftrt:SI
1671 (match_operand:SI 2 "s_register_operand" "r")
1672 (const_int 16))))]
25f905c2 1673 "TARGET_DSP_MULTIPLY"
fec538d9 1674 "smulbt%?\\t%0, %1, %2"
a2cd141b 1675 [(set_attr "insn" "smulxy")
fec538d9 1676 (set_attr "predicable" "yes")]
1677)
1678
1679(define_insn "*mulhisi3tt"
1680 [(set (match_operand:SI 0 "s_register_operand" "=r")
1681 (mult:SI (ashiftrt:SI
1682 (match_operand:SI 1 "s_register_operand" "r")
1683 (const_int 16))
1684 (ashiftrt:SI
1685 (match_operand:SI 2 "s_register_operand" "r")
1686 (const_int 16))))]
25f905c2 1687 "TARGET_DSP_MULTIPLY"
fec538d9 1688 "smultt%?\\t%0, %1, %2"
a2cd141b 1689 [(set_attr "insn" "smulxy")
fec538d9 1690 (set_attr "predicable" "yes")]
331beb1a 1691)
1692
1693(define_insn "*mulhisi3addsi"
1694 [(set (match_operand:SI 0 "s_register_operand" "=r")
1695 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1696 (mult:SI (sign_extend:SI
1697 (match_operand:HI 2 "s_register_operand" "%r"))
1698 (sign_extend:SI
1699 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1700 "TARGET_DSP_MULTIPLY"
61a2d04c 1701 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1702 [(set_attr "insn" "smlaxy")
fec538d9 1703 (set_attr "predicable" "yes")]
331beb1a 1704)
1705
1706(define_insn "*mulhidi3adddi"
1707 [(set (match_operand:DI 0 "s_register_operand" "=r")
1708 (plus:DI
1709 (match_operand:DI 1 "s_register_operand" "0")
1710 (mult:DI (sign_extend:DI
1711 (match_operand:HI 2 "s_register_operand" "%r"))
1712 (sign_extend:DI
1713 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1714 "TARGET_DSP_MULTIPLY"
331beb1a 1715 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1716 [(set_attr "insn" "smlalxy")
fec538d9 1717 (set_attr "predicable" "yes")])
331beb1a 1718
604f3a0a 1719(define_expand "mulsf3"
1720 [(set (match_operand:SF 0 "s_register_operand" "")
1721 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1722 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1723 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1724 "
a2cd141b 1725 if (TARGET_MAVERICK
604f3a0a 1726 && !cirrus_fp_register (operands[2], SFmode))
1727 operands[2] = force_reg (SFmode, operands[2]);
1728")
1729
604f3a0a 1730(define_expand "muldf3"
1731 [(set (match_operand:DF 0 "s_register_operand" "")
1732 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1733 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1734 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1735 "
a2cd141b 1736 if (TARGET_MAVERICK
604f3a0a 1737 && !cirrus_fp_register (operands[2], DFmode))
1738 operands[2] = force_reg (DFmode, operands[2]);
1739")
b11cae9e 1740\f
1741;; Division insns
1742
7db9af5d 1743(define_expand "divsf3"
1744 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1745 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1746 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1747 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1748 "")
9c08d1fa 1749
7db9af5d 1750(define_expand "divdf3"
1751 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1752 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1753 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1754 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1755 "")
b11cae9e 1756\f
1757;; Modulo insns
1758
7db9af5d 1759(define_expand "modsf3"
1760 [(set (match_operand:SF 0 "s_register_operand" "")
1761 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1762 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1763 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1764 "")
9c08d1fa 1765
7db9af5d 1766(define_expand "moddf3"
1767 [(set (match_operand:DF 0 "s_register_operand" "")
1768 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1769 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1770 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1771 "")
b11cae9e 1772\f
1773;; Boolean and,ior,xor insns
1774
f6ebffac 1775;; Split up double word logical operations
1776
1777;; Split up simple DImode logical operations. Simply perform the logical
1778;; operation on the upper and lower halves of the registers.
1779(define_split
1780 [(set (match_operand:DI 0 "s_register_operand" "")
1781 (match_operator:DI 6 "logical_binary_operator"
1782 [(match_operand:DI 1 "s_register_operand" "")
1783 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1784 "TARGET_32BIT && reload_completed
1785 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1786 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1787 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1788 "
215b30b3 1789 {
1790 operands[3] = gen_highpart (SImode, operands[0]);
1791 operands[0] = gen_lowpart (SImode, operands[0]);
1792 operands[4] = gen_highpart (SImode, operands[1]);
1793 operands[1] = gen_lowpart (SImode, operands[1]);
1794 operands[5] = gen_highpart (SImode, operands[2]);
1795 operands[2] = gen_lowpart (SImode, operands[2]);
1796 }"
1797)
f6ebffac 1798
f6ebffac 1799(define_split
1800 [(set (match_operand:DI 0 "s_register_operand" "")
1801 (match_operator:DI 6 "logical_binary_operator"
1802 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1803 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1804 "TARGET_32BIT && reload_completed"
f6ebffac 1805 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1806 (set (match_dup 3) (match_op_dup:SI 6
1807 [(ashiftrt:SI (match_dup 2) (const_int 31))
1808 (match_dup 4)]))]
1809 "
215b30b3 1810 {
1811 operands[3] = gen_highpart (SImode, operands[0]);
1812 operands[0] = gen_lowpart (SImode, operands[0]);
1813 operands[4] = gen_highpart (SImode, operands[1]);
1814 operands[1] = gen_lowpart (SImode, operands[1]);
1815 operands[5] = gen_highpart (SImode, operands[2]);
1816 operands[2] = gen_lowpart (SImode, operands[2]);
1817 }"
1818)
f6ebffac 1819
f6ebffac 1820;; The zero extend of operand 2 means we can just copy the high part of
1821;; operand1 into operand0.
1822(define_split
1823 [(set (match_operand:DI 0 "s_register_operand" "")
1824 (ior:DI
1825 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1826 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1827 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1828 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1829 (set (match_dup 3) (match_dup 4))]
1830 "
215b30b3 1831 {
1832 operands[4] = gen_highpart (SImode, operands[1]);
1833 operands[3] = gen_highpart (SImode, operands[0]);
1834 operands[0] = gen_lowpart (SImode, operands[0]);
1835 operands[1] = gen_lowpart (SImode, operands[1]);
1836 }"
1837)
f6ebffac 1838
1839;; The zero extend of operand 2 means we can just copy the high part of
1840;; operand1 into operand0.
1841(define_split
1842 [(set (match_operand:DI 0 "s_register_operand" "")
1843 (xor:DI
1844 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1845 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1846 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1847 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1848 (set (match_dup 3) (match_dup 4))]
1849 "
215b30b3 1850 {
1851 operands[4] = gen_highpart (SImode, operands[1]);
1852 operands[3] = gen_highpart (SImode, operands[0]);
1853 operands[0] = gen_lowpart (SImode, operands[0]);
1854 operands[1] = gen_lowpart (SImode, operands[1]);
1855 }"
1856)
f6ebffac 1857
b11cae9e 1858(define_insn "anddi3"
cffb2a26 1859 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1860 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1861 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 1862 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 1863 "#"
215b30b3 1864 [(set_attr "length" "8")]
1865)
b11cae9e 1866
a0f94409 1867(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1868 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1869 (and:DI (zero_extend:DI
1870 (match_operand:SI 2 "s_register_operand" "r,r"))
1871 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1872 "TARGET_32BIT"
f6ebffac 1873 "#"
25f905c2 1874 "TARGET_32BIT && reload_completed"
a0f94409 1875 ; The zero extend of operand 2 clears the high word of the output
1876 ; operand.
1877 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1878 (set (match_dup 3) (const_int 0))]
1879 "
1880 {
1881 operands[3] = gen_highpart (SImode, operands[0]);
1882 operands[0] = gen_lowpart (SImode, operands[0]);
1883 operands[1] = gen_lowpart (SImode, operands[1]);
1884 }"
215b30b3 1885 [(set_attr "length" "8")]
1886)
b11cae9e 1887
f7fbdd4a 1888(define_insn "*anddi_sesdi_di"
cffb2a26 1889 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1890 (and:DI (sign_extend:DI
1891 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1892 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1893 "TARGET_32BIT"
f6ebffac 1894 "#"
cffb2a26 1895 [(set_attr "length" "8")]
1896)
b11cae9e 1897
87b22bf7 1898(define_expand "andsi3"
cffb2a26 1899 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1900 (and:SI (match_operand:SI 1 "s_register_operand" "")
1901 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1902 "TARGET_EITHER"
87b22bf7 1903 "
25f905c2 1904 if (TARGET_32BIT)
87b22bf7 1905 {
cffb2a26 1906 if (GET_CODE (operands[2]) == CONST_INT)
1907 {
96f57e36 1908 arm_split_constant (AND, SImode, NULL_RTX,
1909 INTVAL (operands[2]), operands[0],
e1ba4a27 1910 operands[1], optimize && can_create_pseudo_p ());
615caa51 1911
cffb2a26 1912 DONE;
1913 }
87b22bf7 1914 }
25f905c2 1915 else /* TARGET_THUMB1 */
cffb2a26 1916 {
1917 if (GET_CODE (operands[2]) != CONST_INT)
1918 operands[2] = force_reg (SImode, operands[2]);
1919 else
1920 {
1921 int i;
1922
215b30b3 1923 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1924 {
215b30b3 1925 operands[2] = force_reg (SImode,
1926 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1927
1928 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1929
1930 DONE;
1931 }
87b22bf7 1932
cffb2a26 1933 for (i = 9; i <= 31; i++)
1934 {
1935 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1936 {
1937 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1938 const0_rtx));
1939 DONE;
1940 }
215b30b3 1941 else if ((((HOST_WIDE_INT) 1) << i) - 1
1942 == ~INTVAL (operands[2]))
cffb2a26 1943 {
1944 rtx shift = GEN_INT (i);
1945 rtx reg = gen_reg_rtx (SImode);
1946
1947 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1948 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1949
1950 DONE;
1951 }
1952 }
1953
1954 operands[2] = force_reg (SImode, operands[2]);
1955 }
215b30b3 1956 }
1957 "
cffb2a26 1958)
1959
25f905c2 1960; ??? Check split length for Thumb-2
a0f94409 1961(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1962 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1963 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1964 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 1965 "TARGET_32BIT"
5565501b 1966 "@
1967 and%?\\t%0, %1, %2
87b22bf7 1968 bic%?\\t%0, %1, #%B2
1969 #"
25f905c2 1970 "TARGET_32BIT
a0f94409 1971 && GET_CODE (operands[2]) == CONST_INT
1972 && !(const_ok_for_arm (INTVAL (operands[2]))
1973 || const_ok_for_arm (~INTVAL (operands[2])))"
1974 [(clobber (const_int 0))]
1975 "
96f57e36 1976 arm_split_constant (AND, SImode, curr_insn,
1977 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1978 DONE;
1979 "
0d66636f 1980 [(set_attr "length" "4,4,16")
1981 (set_attr "predicable" "yes")]
cffb2a26 1982)
1983
25f905c2 1984(define_insn "*thumb1_andsi3_insn"
cffb2a26 1985 [(set (match_operand:SI 0 "register_operand" "=l")
1986 (and:SI (match_operand:SI 1 "register_operand" "%0")
1987 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1988 "TARGET_THUMB1"
cffb2a26 1989 "and\\t%0, %0, %2"
1990 [(set_attr "length" "2")]
1991)
87b22bf7 1992
f7fbdd4a 1993(define_insn "*andsi3_compare0"
bd5b4116 1994 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1995 (compare:CC_NOOV
1996 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1997 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1998 (const_int 0)))
cffb2a26 1999 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2000 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2001 "TARGET_32BIT"
5565501b 2002 "@
25f905c2 2003 and%.\\t%0, %1, %2
2004 bic%.\\t%0, %1, #%B2"
cffb2a26 2005 [(set_attr "conds" "set")]
2006)
9c08d1fa 2007
f7fbdd4a 2008(define_insn "*andsi3_compare0_scratch"
bd5b4116 2009 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2010 (compare:CC_NOOV
2011 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2012 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2013 (const_int 0)))
dd193d7c 2014 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2015 "TARGET_32BIT"
5565501b 2016 "@
2017 tst%?\\t%0, %1
25f905c2 2018 bic%.\\t%2, %0, #%B1"
0d66636f 2019 [(set_attr "conds" "set")]
2020)
9c08d1fa 2021
f7fbdd4a 2022(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2023 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2024 (compare:CC_NOOV (zero_extract:SI
2025 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2026 (match_operand 1 "const_int_operand" "n")
2027 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2028 (const_int 0)))]
25f905c2 2029 "TARGET_32BIT
cffb2a26 2030 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2031 && INTVAL (operands[1]) > 0
2032 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2033 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2034 "*
5c49a439 2035 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2036 << INTVAL (operands[2]));
40dbec34 2037 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2038 return \"\";
0d66636f 2039 "
2040 [(set_attr "conds" "set")]
2041)
9c08d1fa 2042
f4462328 2043(define_insn_and_split "*ne_zeroextractsi"
c4034607 2044 [(set (match_operand:SI 0 "s_register_operand" "=r")
2045 (ne:SI (zero_extract:SI
2046 (match_operand:SI 1 "s_register_operand" "r")
2047 (match_operand:SI 2 "const_int_operand" "n")
2048 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2049 (const_int 0)))
2050 (clobber (reg:CC CC_REGNUM))]
25f905c2 2051 "TARGET_32BIT
cffb2a26 2052 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2053 && INTVAL (operands[2]) > 0
2054 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2055 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2056 "#"
25f905c2 2057 "TARGET_32BIT
f4462328 2058 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2059 && INTVAL (operands[2]) > 0
2060 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2061 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2062 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2063 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2064 (const_int 0)))
2065 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2066 (set (match_dup 0)
2067 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2068 (match_dup 0) (const_int 1)))]
2069 "
2070 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2071 << INTVAL (operands[3]));
2072 "
2073 [(set_attr "conds" "clob")
25f905c2 2074 (set (attr "length")
2075 (if_then_else (eq_attr "is_thumb" "yes")
2076 (const_int 12)
2077 (const_int 8)))]
f4462328 2078)
2079
2080(define_insn_and_split "*ne_zeroextractsi_shifted"
2081 [(set (match_operand:SI 0 "s_register_operand" "=r")
2082 (ne:SI (zero_extract:SI
2083 (match_operand:SI 1 "s_register_operand" "r")
2084 (match_operand:SI 2 "const_int_operand" "n")
2085 (const_int 0))
2086 (const_int 0)))
2087 (clobber (reg:CC CC_REGNUM))]
2088 "TARGET_ARM"
2089 "#"
2090 "TARGET_ARM"
2091 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2092 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2093 (const_int 0)))
2094 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2095 (set (match_dup 0)
2096 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2097 (match_dup 0) (const_int 1)))]
2098 "
2099 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2100 "
2101 [(set_attr "conds" "clob")
2102 (set_attr "length" "8")]
2103)
2104
2105(define_insn_and_split "*ite_ne_zeroextractsi"
2106 [(set (match_operand:SI 0 "s_register_operand" "=r")
2107 (if_then_else:SI (ne (zero_extract:SI
2108 (match_operand:SI 1 "s_register_operand" "r")
2109 (match_operand:SI 2 "const_int_operand" "n")
2110 (match_operand:SI 3 "const_int_operand" "n"))
2111 (const_int 0))
2112 (match_operand:SI 4 "arm_not_operand" "rIK")
2113 (const_int 0)))
2114 (clobber (reg:CC CC_REGNUM))]
2115 "TARGET_ARM
2116 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2117 && INTVAL (operands[2]) > 0
2118 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2119 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2120 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2121 "#"
2122 "TARGET_ARM
2123 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2124 && INTVAL (operands[2]) > 0
2125 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2126 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2127 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2128 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2129 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2130 (const_int 0)))
2131 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2132 (set (match_dup 0)
2133 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2134 (match_dup 0) (match_dup 4)))]
2135 "
c4034607 2136 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2137 << INTVAL (operands[3]));
2138 "
2139 [(set_attr "conds" "clob")
2140 (set_attr "length" "8")]
2141)
2142
2143(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2144 [(set (match_operand:SI 0 "s_register_operand" "=r")
2145 (if_then_else:SI (ne (zero_extract:SI
2146 (match_operand:SI 1 "s_register_operand" "r")
2147 (match_operand:SI 2 "const_int_operand" "n")
2148 (const_int 0))
2149 (const_int 0))
2150 (match_operand:SI 3 "arm_not_operand" "rIK")
2151 (const_int 0)))
2152 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2153 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2154 "#"
f8d7bf2f 2155 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2156 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2157 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2158 (const_int 0)))
2159 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2160 (set (match_dup 0)
2161 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2162 (match_dup 0) (match_dup 3)))]
2163 "
2164 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2165 "
2166 [(set_attr "conds" "clob")
215b30b3 2167 (set_attr "length" "8")]
2168)
9c08d1fa 2169
58d6528b 2170(define_split
2171 [(set (match_operand:SI 0 "s_register_operand" "")
2172 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2173 (match_operand:SI 2 "const_int_operand" "")
2174 (match_operand:SI 3 "const_int_operand" "")))
2175 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2176 "TARGET_THUMB1"
58d6528b 2177 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2178 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2179 "{
2180 HOST_WIDE_INT temp = INTVAL (operands[2]);
2181
2182 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2183 operands[3] = GEN_INT (32 - temp);
2184 }"
2185)
2186
25f905c2 2187;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2188(define_split
2189 [(set (match_operand:SI 0 "s_register_operand" "")
2190 (match_operator:SI 1 "shiftable_operator"
2191 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2192 (match_operand:SI 3 "const_int_operand" "")
2193 (match_operand:SI 4 "const_int_operand" ""))
2194 (match_operand:SI 5 "s_register_operand" "")]))
2195 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2196 "TARGET_ARM"
2197 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2198 (set (match_dup 0)
2199 (match_op_dup 1
2200 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2201 (match_dup 5)]))]
2202 "{
2203 HOST_WIDE_INT temp = INTVAL (operands[3]);
2204
2205 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2206 operands[4] = GEN_INT (32 - temp);
2207 }"
2208)
2209
58d6528b 2210(define_split
2211 [(set (match_operand:SI 0 "s_register_operand" "")
2212 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2213 (match_operand:SI 2 "const_int_operand" "")
2214 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2215 "TARGET_THUMB1"
58d6528b 2216 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2217 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2218 "{
2219 HOST_WIDE_INT temp = INTVAL (operands[2]);
2220
2221 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2222 operands[3] = GEN_INT (32 - temp);
2223 }"
2224)
2225
d7863cfe 2226(define_split
2227 [(set (match_operand:SI 0 "s_register_operand" "")
2228 (match_operator:SI 1 "shiftable_operator"
2229 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2230 (match_operand:SI 3 "const_int_operand" "")
2231 (match_operand:SI 4 "const_int_operand" ""))
2232 (match_operand:SI 5 "s_register_operand" "")]))
2233 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2234 "TARGET_ARM"
2235 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2236 (set (match_dup 0)
2237 (match_op_dup 1
2238 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2239 (match_dup 5)]))]
2240 "{
2241 HOST_WIDE_INT temp = INTVAL (operands[3]);
2242
2243 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2244 operands[4] = GEN_INT (32 - temp);
2245 }"
2246)
2247
a42059fd 2248;;; ??? This pattern is bogus. If operand3 has bits outside the range
2249;;; represented by the bitfield, then this will produce incorrect results.
2250;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2251;;; which have a real bit-field insert instruction, the truncation happens
2252;;; in the bit-field insert instruction itself. Since arm does not have a
2253;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2254;;; the value before we insert. This loses some of the advantage of having
2255;;; this insv pattern, so this pattern needs to be reevalutated.
2256
8a18b90c 2257(define_expand "insv"
2258 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2259 (match_operand:SI 1 "general_operand" "")
2260 (match_operand:SI 2 "general_operand" ""))
19335226 2261 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2262 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2263 "
215b30b3 2264 {
2265 int start_bit = INTVAL (operands[2]);
2266 int width = INTVAL (operands[1]);
2267 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2268 rtx target, subtarget;
2269
8b054d5a 2270 if (arm_arch_thumb2)
2271 {
2272 bool use_bfi = TRUE;
2273
2274 if (GET_CODE (operands[3]) == CONST_INT)
2275 {
2276 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2277
2278 if (val == 0)
2279 {
2280 emit_insn (gen_insv_zero (operands[0], operands[1],
2281 operands[2]));
2282 DONE;
2283 }
2284
2285 /* See if the set can be done with a single orr instruction. */
2286 if (val == mask && const_ok_for_arm (val << start_bit))
2287 use_bfi = FALSE;
2288 }
2289
2290 if (use_bfi)
2291 {
2292 if (GET_CODE (operands[3]) != REG)
2293 operands[3] = force_reg (SImode, operands[3]);
2294
2295 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2296 operands[3]));
2297 DONE;
2298 }
2299 }
2300
3f8fde42 2301 target = copy_rtx (operands[0]);
215b30b3 2302 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2303 subreg as the final target. */
2304 if (GET_CODE (target) == SUBREG)
2305 {
2306 subtarget = gen_reg_rtx (SImode);
2307 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2308 < GET_MODE_SIZE (SImode))
2309 target = SUBREG_REG (target);
2310 }
2311 else
2312 subtarget = target;
8a18b90c 2313
215b30b3 2314 if (GET_CODE (operands[3]) == CONST_INT)
2315 {
2316 /* Since we are inserting a known constant, we may be able to
2317 reduce the number of bits that we have to clear so that
2318 the mask becomes simple. */
2319 /* ??? This code does not check to see if the new mask is actually
2320 simpler. It may not be. */
2321 rtx op1 = gen_reg_rtx (SImode);
2322 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2323 start of this pattern. */
2324 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2325 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2326
c5b3a71b 2327 emit_insn (gen_andsi3 (op1, operands[0],
2328 gen_int_mode (~mask2, SImode)));
215b30b3 2329 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2330 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2331 }
2332 else if (start_bit == 0
2333 && !(const_ok_for_arm (mask)
2334 || const_ok_for_arm (~mask)))
2335 {
2336 /* A Trick, since we are setting the bottom bits in the word,
2337 we can shift operand[3] up, operand[0] down, OR them together
2338 and rotate the result back again. This takes 3 insns, and
5910bb95 2339 the third might be mergeable into another op. */
215b30b3 2340 /* The shift up copes with the possibility that operand[3] is
2341 wider than the bitfield. */
2342 rtx op0 = gen_reg_rtx (SImode);
2343 rtx op1 = gen_reg_rtx (SImode);
2344
2345 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2346 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2347 emit_insn (gen_iorsi3 (op1, op1, op0));
2348 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2349 }
2350 else if ((width + start_bit == 32)
2351 && !(const_ok_for_arm (mask)
2352 || const_ok_for_arm (~mask)))
2353 {
2354 /* Similar trick, but slightly less efficient. */
8a18b90c 2355
215b30b3 2356 rtx op0 = gen_reg_rtx (SImode);
2357 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2358
215b30b3 2359 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2360 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2361 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2362 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2363 }
2364 else
2365 {
c5b3a71b 2366 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2367 rtx op1 = gen_reg_rtx (SImode);
2368 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2369
215b30b3 2370 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2371 {
2372 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2373
215b30b3 2374 emit_insn (gen_movsi (tmp, op0));
2375 op0 = tmp;
2376 }
8a18b90c 2377
215b30b3 2378 /* Mask out any bits in operand[3] that are not needed. */
2379 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2380
215b30b3 2381 if (GET_CODE (op0) == CONST_INT
2382 && (const_ok_for_arm (mask << start_bit)
2383 || const_ok_for_arm (~(mask << start_bit))))
2384 {
c5b3a71b 2385 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2386 emit_insn (gen_andsi3 (op2, operands[0], op0));
2387 }
2388 else
2389 {
2390 if (GET_CODE (op0) == CONST_INT)
2391 {
2392 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2393
215b30b3 2394 emit_insn (gen_movsi (tmp, op0));
2395 op0 = tmp;
2396 }
2397
2398 if (start_bit != 0)
2399 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2400
215b30b3 2401 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2402 }
8a18b90c 2403
215b30b3 2404 if (start_bit != 0)
2405 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2406
215b30b3 2407 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2408 }
f082f1c4 2409
215b30b3 2410 if (subtarget != target)
2411 {
2412 /* If TARGET is still a SUBREG, then it must be wider than a word,
2413 so we must be careful only to set the subword we were asked to. */
2414 if (GET_CODE (target) == SUBREG)
2415 emit_move_insn (target, subtarget);
2416 else
2417 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2418 }
8a18b90c 2419
215b30b3 2420 DONE;
2421 }"
2422)
8a18b90c 2423
8b054d5a 2424(define_insn "insv_zero"
2425 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2426 (match_operand:SI 1 "const_int_operand" "M")
2427 (match_operand:SI 2 "const_int_operand" "M"))
2428 (const_int 0))]
2429 "arm_arch_thumb2"
2430 "bfc%?\t%0, %2, %1"
2431 [(set_attr "length" "4")
2432 (set_attr "predicable" "yes")]
2433)
2434
2435(define_insn "insv_t2"
2436 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2437 (match_operand:SI 1 "const_int_operand" "M")
2438 (match_operand:SI 2 "const_int_operand" "M"))
2439 (match_operand:SI 3 "s_register_operand" "r"))]
2440 "arm_arch_thumb2"
2441 "bfi%?\t%0, %3, %2, %1"
2442 [(set_attr "length" "4")
2443 (set_attr "predicable" "yes")]
2444)
2445
215b30b3 2446; constants for op 2 will never be given to these patterns.
a0f94409 2447(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2448 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 2449 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2450 (match_operand:DI 2 "s_register_operand" "0,r")))]
25f905c2 2451 "TARGET_32BIT"
f6ebffac 2452 "#"
25f905c2 2453 "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2454 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2455 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2456 "
2457 {
2458 operands[3] = gen_highpart (SImode, operands[0]);
2459 operands[0] = gen_lowpart (SImode, operands[0]);
2460 operands[4] = gen_highpart (SImode, operands[1]);
2461 operands[1] = gen_lowpart (SImode, operands[1]);
2462 operands[5] = gen_highpart (SImode, operands[2]);
2463 operands[2] = gen_lowpart (SImode, operands[2]);
2464 }"
0d66636f 2465 [(set_attr "length" "8")
2466 (set_attr "predicable" "yes")]
2467)
9c08d1fa 2468
a0f94409 2469(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2470 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2471 (and:DI (not:DI (zero_extend:DI
2472 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2473 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2474 "TARGET_32BIT"
e2348bcb 2475 "@
97499065 2476 bic%?\\t%Q0, %Q1, %2
f6ebffac 2477 #"
a0f94409 2478 ; (not (zero_extend ...)) allows us to just copy the high word from
2479 ; operand1 to operand0.
25f905c2 2480 "TARGET_32BIT
a0f94409 2481 && reload_completed
2482 && operands[0] != operands[1]"
5a097f7d 2483 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2484 (set (match_dup 3) (match_dup 4))]
2485 "
2486 {
2487 operands[3] = gen_highpart (SImode, operands[0]);
2488 operands[0] = gen_lowpart (SImode, operands[0]);
2489 operands[4] = gen_highpart (SImode, operands[1]);
2490 operands[1] = gen_lowpart (SImode, operands[1]);
2491 }"
0d66636f 2492 [(set_attr "length" "4,8")
2493 (set_attr "predicable" "yes")]
2494)
9c08d1fa 2495
a0f94409 2496(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2497 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2498 (and:DI (not:DI (sign_extend:DI
2499 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2500 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2501 "TARGET_32BIT"
f6ebffac 2502 "#"
25f905c2 2503 "TARGET_32BIT && reload_completed"
5a097f7d 2504 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2505 (set (match_dup 3) (and:SI (not:SI
2506 (ashiftrt:SI (match_dup 2) (const_int 31)))
2507 (match_dup 4)))]
2508 "
2509 {
2510 operands[3] = gen_highpart (SImode, operands[0]);
2511 operands[0] = gen_lowpart (SImode, operands[0]);
2512 operands[4] = gen_highpart (SImode, operands[1]);
2513 operands[1] = gen_lowpart (SImode, operands[1]);
2514 }"
0d66636f 2515 [(set_attr "length" "8")
2516 (set_attr "predicable" "yes")]
2517)
9c08d1fa 2518
8a18b90c 2519(define_insn "andsi_notsi_si"
9c08d1fa 2520 [(set (match_operand:SI 0 "s_register_operand" "=r")
2521 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2522 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2523 "TARGET_32BIT"
0d66636f 2524 "bic%?\\t%0, %1, %2"
2525 [(set_attr "predicable" "yes")]
2526)
b11cae9e 2527
cffb2a26 2528(define_insn "bicsi3"
2529 [(set (match_operand:SI 0 "register_operand" "=l")
2530 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2531 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2532 "TARGET_THUMB1"
cffb2a26 2533 "bic\\t%0, %0, %1"
2534 [(set_attr "length" "2")]
2535)
2536
8a18b90c 2537(define_insn "andsi_not_shiftsi_si"
a2cd141b 2538 [(set (match_operand:SI 0 "s_register_operand" "=r")
2539 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2540 [(match_operand:SI 2 "s_register_operand" "r")
2541 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2542 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2543 "TARGET_ARM"
6c4c2133 2544 "bic%?\\t%0, %1, %2%S4"
344495ea 2545 [(set_attr "predicable" "yes")
331beb1a 2546 (set_attr "shift" "2")
a2cd141b 2547 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2548 (const_string "alu_shift")
2549 (const_string "alu_shift_reg")))]
6c4c2133 2550)
8a18b90c 2551
f7fbdd4a 2552(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2553 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2554 (compare:CC_NOOV
2555 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2556 (match_operand:SI 1 "s_register_operand" "r"))
2557 (const_int 0)))
9c08d1fa 2558 (set (match_operand:SI 0 "s_register_operand" "=r")
2559 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2560 "TARGET_32BIT"
2561 "bic%.\\t%0, %1, %2"
0d66636f 2562 [(set_attr "conds" "set")]
2563)
9c08d1fa 2564
f7fbdd4a 2565(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2566 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2567 (compare:CC_NOOV
2568 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2569 (match_operand:SI 1 "s_register_operand" "r"))
2570 (const_int 0)))
9c08d1fa 2571 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2572 "TARGET_32BIT"
2573 "bic%.\\t%0, %1, %2"
0d66636f 2574 [(set_attr "conds" "set")]
2575)
9c08d1fa 2576
2577(define_insn "iordi3"
cffb2a26 2578 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2579 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2580 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2581 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 2582 "#"
0d66636f 2583 [(set_attr "length" "8")
2584 (set_attr "predicable" "yes")]
cffb2a26 2585)
9c08d1fa 2586
f7fbdd4a 2587(define_insn "*iordi_zesidi_di"
9c08d1fa 2588 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2589 (ior:DI (zero_extend:DI
2590 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2591 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2592 "TARGET_32BIT"
e2348bcb 2593 "@
97499065 2594 orr%?\\t%Q0, %Q1, %2
f6ebffac 2595 #"
0d66636f 2596 [(set_attr "length" "4,8")
2597 (set_attr "predicable" "yes")]
cffb2a26 2598)
9c08d1fa 2599
f7fbdd4a 2600(define_insn "*iordi_sesidi_di"
9c08d1fa 2601 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2602 (ior:DI (sign_extend:DI
2603 (match_operand:SI 2 "s_register_operand" "r,r"))
2604 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2605 "TARGET_32BIT"
f6ebffac 2606 "#"
0d66636f 2607 [(set_attr "length" "8")
2608 (set_attr "predicable" "yes")]
cffb2a26 2609)
9c08d1fa 2610
87b22bf7 2611(define_expand "iorsi3"
cffb2a26 2612 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2613 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2614 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2615 "TARGET_EITHER"
87b22bf7 2616 "
2617 if (GET_CODE (operands[2]) == CONST_INT)
2618 {
25f905c2 2619 if (TARGET_32BIT)
cffb2a26 2620 {
96f57e36 2621 arm_split_constant (IOR, SImode, NULL_RTX,
2622 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2623 optimize && can_create_pseudo_p ());
cffb2a26 2624 DONE;
2625 }
25f905c2 2626 else /* TARGET_THUMB1 */
cffb2a26 2627 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2628 }
cffb2a26 2629 "
2630)
87b22bf7 2631
a0f94409 2632(define_insn_and_split "*arm_iorsi3"
cffb2a26 2633 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2634 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2635 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
90560cad 2636 "TARGET_ARM"
87b22bf7 2637 "@
2638 orr%?\\t%0, %1, %2
2639 #"
90560cad 2640 "TARGET_ARM
a0f94409 2641 && GET_CODE (operands[2]) == CONST_INT
2642 && !const_ok_for_arm (INTVAL (operands[2]))"
2643 [(clobber (const_int 0))]
2644 "
96f57e36 2645 arm_split_constant (IOR, SImode, curr_insn,
2646 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2647 DONE;
2648 "
0d66636f 2649 [(set_attr "length" "4,16")
2650 (set_attr "predicable" "yes")]
cffb2a26 2651)
2652
25f905c2 2653(define_insn "*thumb1_iorsi3"
cffb2a26 2654 [(set (match_operand:SI 0 "register_operand" "=l")
2655 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2656 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2657 "TARGET_THUMB1"
cffb2a26 2658 "orr\\t%0, %0, %2"
2659 [(set_attr "length" "2")]
2660)
9c08d1fa 2661
a0f94409 2662(define_peephole2
2663 [(match_scratch:SI 3 "r")
372575c7 2664 (set (match_operand:SI 0 "arm_general_register_operand" "")
2665 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2666 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2667 "TARGET_ARM
a0f94409 2668 && !const_ok_for_arm (INTVAL (operands[2]))
2669 && const_ok_for_arm (~INTVAL (operands[2]))"
2670 [(set (match_dup 3) (match_dup 2))
2671 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2672 ""
215b30b3 2673)
a0f94409 2674
f7fbdd4a 2675(define_insn "*iorsi3_compare0"
bd5b4116 2676 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2677 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2678 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2679 (const_int 0)))
2680 (set (match_operand:SI 0 "s_register_operand" "=r")
2681 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2682 "TARGET_32BIT"
2683 "orr%.\\t%0, %1, %2"
cffb2a26 2684 [(set_attr "conds" "set")]
2685)
9c08d1fa 2686
f7fbdd4a 2687(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2688 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2689 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2690 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2691 (const_int 0)))
2692 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2693 "TARGET_32BIT"
2694 "orr%.\\t%0, %1, %2"
0d66636f 2695 [(set_attr "conds" "set")]
2696)
9c08d1fa 2697
2698(define_insn "xordi3"
cffb2a26 2699 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2700 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2701 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2702 "TARGET_32BIT && !TARGET_IWMMXT"
f6ebffac 2703 "#"
0d66636f 2704 [(set_attr "length" "8")
2705 (set_attr "predicable" "yes")]
cffb2a26 2706)
9c08d1fa 2707
f7fbdd4a 2708(define_insn "*xordi_zesidi_di"
9c08d1fa 2709 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2710 (xor:DI (zero_extend:DI
2711 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2712 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2713 "TARGET_32BIT"
e2348bcb 2714 "@
97499065 2715 eor%?\\t%Q0, %Q1, %2
f6ebffac 2716 #"
0d66636f 2717 [(set_attr "length" "4,8")
2718 (set_attr "predicable" "yes")]
cffb2a26 2719)
9c08d1fa 2720
f7fbdd4a 2721(define_insn "*xordi_sesidi_di"
9c08d1fa 2722 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2723 (xor:DI (sign_extend:DI
2724 (match_operand:SI 2 "s_register_operand" "r,r"))
2725 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2726 "TARGET_32BIT"
f6ebffac 2727 "#"
0d66636f 2728 [(set_attr "length" "8")
2729 (set_attr "predicable" "yes")]
cffb2a26 2730)
9c08d1fa 2731
cffb2a26 2732(define_expand "xorsi3"
2733 [(set (match_operand:SI 0 "s_register_operand" "")
2734 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2735 (match_operand:SI 2 "arm_rhs_operand" "")))]
2736 "TARGET_EITHER"
25f905c2 2737 "if (TARGET_THUMB1)
cffb2a26 2738 if (GET_CODE (operands[2]) == CONST_INT)
2739 operands[2] = force_reg (SImode, operands[2]);
2740 "
2741)
2742
2743(define_insn "*arm_xorsi3"
2744 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2745 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2746 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2747 "TARGET_32BIT"
cffb2a26 2748 "eor%?\\t%0, %1, %2"
0d66636f 2749 [(set_attr "predicable" "yes")]
cffb2a26 2750)
2751
25f905c2 2752(define_insn "*thumb1_xorsi3"
cffb2a26 2753 [(set (match_operand:SI 0 "register_operand" "=l")
2754 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2755 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2756 "TARGET_THUMB1"
cffb2a26 2757 "eor\\t%0, %0, %2"
2758 [(set_attr "length" "2")]
2759)
9c08d1fa 2760
f7fbdd4a 2761(define_insn "*xorsi3_compare0"
bd5b4116 2762 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2763 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2764 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2765 (const_int 0)))
2766 (set (match_operand:SI 0 "s_register_operand" "=r")
2767 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2768 "TARGET_32BIT"
2769 "eor%.\\t%0, %1, %2"
0d66636f 2770 [(set_attr "conds" "set")]
2771)
9c08d1fa 2772
f7fbdd4a 2773(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2774 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2775 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2776 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2777 (const_int 0)))]
25f905c2 2778 "TARGET_32BIT"
40dbec34 2779 "teq%?\\t%0, %1"
cffb2a26 2780 [(set_attr "conds" "set")]
2781)
9c08d1fa 2782
215b30b3 2783; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2784; (NOT D) we can sometimes merge the final NOT into one of the following
2785; insns.
9c08d1fa 2786
2787(define_split
a058e94a 2788 [(set (match_operand:SI 0 "s_register_operand" "")
2789 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2790 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2791 (match_operand:SI 3 "arm_rhs_operand" "")))
2792 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2793 "TARGET_32BIT"
9c08d1fa 2794 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2795 (not:SI (match_dup 3))))
2796 (set (match_dup 0) (not:SI (match_dup 4)))]
2797 ""
2798)
2799
f7fbdd4a 2800(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2801 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2802 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2803 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2804 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2805 "TARGET_32BIT"
40dbec34 2806 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2807 [(set_attr "length" "8")
25f905c2 2808 (set_attr "ce_count" "2")
0d66636f 2809 (set_attr "predicable" "yes")]
cffb2a26 2810)
9c08d1fa 2811
25f905c2 2812; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2813; insns are available?
d7863cfe 2814(define_split
2815 [(set (match_operand:SI 0 "s_register_operand" "")
2816 (match_operator:SI 1 "logical_binary_operator"
2817 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2818 (match_operand:SI 3 "const_int_operand" "")
2819 (match_operand:SI 4 "const_int_operand" ""))
2820 (match_operator:SI 9 "logical_binary_operator"
2821 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2822 (match_operand:SI 6 "const_int_operand" ""))
2823 (match_operand:SI 7 "s_register_operand" "")])]))
2824 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2825 "TARGET_32BIT
d7863cfe 2826 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2827 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2828 [(set (match_dup 8)
2829 (match_op_dup 1
2830 [(ashift:SI (match_dup 2) (match_dup 4))
2831 (match_dup 5)]))
2832 (set (match_dup 0)
2833 (match_op_dup 1
2834 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2835 (match_dup 7)]))]
2836 "
2837 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2838")
2839
2840(define_split
2841 [(set (match_operand:SI 0 "s_register_operand" "")
2842 (match_operator:SI 1 "logical_binary_operator"
2843 [(match_operator:SI 9 "logical_binary_operator"
2844 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2845 (match_operand:SI 6 "const_int_operand" ""))
2846 (match_operand:SI 7 "s_register_operand" "")])
2847 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2848 (match_operand:SI 3 "const_int_operand" "")
2849 (match_operand:SI 4 "const_int_operand" ""))]))
2850 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2851 "TARGET_32BIT
d7863cfe 2852 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2853 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2854 [(set (match_dup 8)
2855 (match_op_dup 1
2856 [(ashift:SI (match_dup 2) (match_dup 4))
2857 (match_dup 5)]))
2858 (set (match_dup 0)
2859 (match_op_dup 1
2860 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2861 (match_dup 7)]))]
2862 "
2863 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2864")
2865
2866(define_split
2867 [(set (match_operand:SI 0 "s_register_operand" "")
2868 (match_operator:SI 1 "logical_binary_operator"
2869 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2870 (match_operand:SI 3 "const_int_operand" "")
2871 (match_operand:SI 4 "const_int_operand" ""))
2872 (match_operator:SI 9 "logical_binary_operator"
2873 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2874 (match_operand:SI 6 "const_int_operand" ""))
2875 (match_operand:SI 7 "s_register_operand" "")])]))
2876 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2877 "TARGET_32BIT
d7863cfe 2878 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2879 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2880 [(set (match_dup 8)
2881 (match_op_dup 1
2882 [(ashift:SI (match_dup 2) (match_dup 4))
2883 (match_dup 5)]))
2884 (set (match_dup 0)
2885 (match_op_dup 1
2886 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2887 (match_dup 7)]))]
2888 "
2889 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2890")
2891
2892(define_split
2893 [(set (match_operand:SI 0 "s_register_operand" "")
2894 (match_operator:SI 1 "logical_binary_operator"
2895 [(match_operator:SI 9 "logical_binary_operator"
2896 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2897 (match_operand:SI 6 "const_int_operand" ""))
2898 (match_operand:SI 7 "s_register_operand" "")])
2899 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2900 (match_operand:SI 3 "const_int_operand" "")
2901 (match_operand:SI 4 "const_int_operand" ""))]))
2902 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2903 "TARGET_32BIT
d7863cfe 2904 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2905 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2906 [(set (match_dup 8)
2907 (match_op_dup 1
2908 [(ashift:SI (match_dup 2) (match_dup 4))
2909 (match_dup 5)]))
2910 (set (match_dup 0)
2911 (match_op_dup 1
2912 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2913 (match_dup 7)]))]
2914 "
2915 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2916")
9c08d1fa 2917\f
2918
2919;; Minimum and maximum insns
2920
8b9dc177 2921(define_expand "smaxsi3"
2922 [(parallel [
2923 (set (match_operand:SI 0 "s_register_operand" "")
2924 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2925 (match_operand:SI 2 "arm_rhs_operand" "")))
2926 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2927 "TARGET_32BIT"
8b9dc177 2928 "
8774928b 2929 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 2930 {
2931 /* No need for a clobber of the condition code register here. */
2932 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2933 gen_rtx_SMAX (SImode, operands[1],
2934 operands[2])));
2935 DONE;
2936 }
2937")
2938
2939(define_insn "*smax_0"
2940 [(set (match_operand:SI 0 "s_register_operand" "=r")
2941 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2942 (const_int 0)))]
25f905c2 2943 "TARGET_32BIT"
8b9dc177 2944 "bic%?\\t%0, %1, %1, asr #31"
2945 [(set_attr "predicable" "yes")]
2946)
2947
8774928b 2948(define_insn "*smax_m1"
2949 [(set (match_operand:SI 0 "s_register_operand" "=r")
2950 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2951 (const_int -1)))]
25f905c2 2952 "TARGET_32BIT"
8774928b 2953 "orr%?\\t%0, %1, %1, asr #31"
2954 [(set_attr "predicable" "yes")]
2955)
2956
25f905c2 2957(define_insn "*arm_smax_insn"
8b9dc177 2958 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2959 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2960 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 2961 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2962 "TARGET_ARM"
e2348bcb 2963 "@
2964 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 2965 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2966 [(set_attr "conds" "clob")
8b9dc177 2967 (set_attr "length" "8,12")]
cffb2a26 2968)
9c08d1fa 2969
8b9dc177 2970(define_expand "sminsi3"
2971 [(parallel [
2972 (set (match_operand:SI 0 "s_register_operand" "")
2973 (smin:SI (match_operand:SI 1 "s_register_operand" "")
2974 (match_operand:SI 2 "arm_rhs_operand" "")))
2975 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2976 "TARGET_32BIT"
8b9dc177 2977 "
2978 if (operands[2] == const0_rtx)
2979 {
2980 /* No need for a clobber of the condition code register here. */
2981 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2982 gen_rtx_SMIN (SImode, operands[1],
2983 operands[2])));
2984 DONE;
2985 }
2986")
2987
2988(define_insn "*smin_0"
2989 [(set (match_operand:SI 0 "s_register_operand" "=r")
2990 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2991 (const_int 0)))]
25f905c2 2992 "TARGET_32BIT"
8b9dc177 2993 "and%?\\t%0, %1, %1, asr #31"
2994 [(set_attr "predicable" "yes")]
2995)
2996
25f905c2 2997(define_insn "*arm_smin_insn"
8b9dc177 2998 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2999 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3000 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3001 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3002 "TARGET_ARM"
e2348bcb 3003 "@
3004 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3005 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3006 [(set_attr "conds" "clob")
8b9dc177 3007 (set_attr "length" "8,12")]
0d66636f 3008)
9c08d1fa 3009
25f905c2 3010(define_expand "umaxsi3"
3011 [(parallel [
3012 (set (match_operand:SI 0 "s_register_operand" "")
3013 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3014 (match_operand:SI 2 "arm_rhs_operand" "")))
3015 (clobber (reg:CC CC_REGNUM))])]
3016 "TARGET_32BIT"
3017 ""
3018)
3019
3020(define_insn "*arm_umaxsi3"
9c08d1fa 3021 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3022 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3023 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3024 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3025 "TARGET_ARM"
e2348bcb 3026 "@
3027 cmp\\t%1, %2\;movcc\\t%0, %2
3028 cmp\\t%1, %2\;movcs\\t%0, %1
3029 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3030 [(set_attr "conds" "clob")
3031 (set_attr "length" "8,8,12")]
3032)
9c08d1fa 3033
25f905c2 3034(define_expand "uminsi3"
3035 [(parallel [
3036 (set (match_operand:SI 0 "s_register_operand" "")
3037 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3038 (match_operand:SI 2 "arm_rhs_operand" "")))
3039 (clobber (reg:CC CC_REGNUM))])]
3040 "TARGET_32BIT"
3041 ""
3042)
3043
3044(define_insn "*arm_uminsi3"
9c08d1fa 3045 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3046 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3047 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3048 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3049 "TARGET_ARM"
e2348bcb 3050 "@
3051 cmp\\t%1, %2\;movcs\\t%0, %2
3052 cmp\\t%1, %2\;movcc\\t%0, %1
3053 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3054 [(set_attr "conds" "clob")
3055 (set_attr "length" "8,8,12")]
3056)
9c08d1fa 3057
8a18b90c 3058(define_insn "*store_minmaxsi"
9c08d1fa 3059 [(set (match_operand:SI 0 "memory_operand" "=m")
3060 (match_operator:SI 3 "minmax_operator"
3061 [(match_operand:SI 1 "s_register_operand" "r")
3062 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3063 (clobber (reg:CC CC_REGNUM))]
25f905c2 3064 "TARGET_32BIT"
9c08d1fa 3065 "*
dc55b8a9 3066 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3067 operands[1], operands[2]);
e2348bcb 3068 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3069 if (TARGET_THUMB2)
3070 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3071 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3072 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3073 return \"\";
0d66636f 3074 "
3075 [(set_attr "conds" "clob")
25f905c2 3076 (set (attr "length")
3077 (if_then_else (eq_attr "is_thumb" "yes")
3078 (const_int 14)
3079 (const_int 12)))
0d66636f 3080 (set_attr "type" "store1")]
3081)
9c08d1fa 3082
8a18b90c 3083; Reject the frame pointer in operand[1], since reloading this after
3084; it has been eliminated can cause carnage.
f7fbdd4a 3085(define_insn "*minmax_arithsi"
9c08d1fa 3086 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3087 (match_operator:SI 4 "shiftable_operator"
3088 [(match_operator:SI 5 "minmax_operator"
3089 [(match_operand:SI 2 "s_register_operand" "r,r")
3090 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3091 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3092 (clobber (reg:CC CC_REGNUM))]
25f905c2 3093 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3094 "*
0d66636f 3095 {
3096 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3097 bool need_else;
3098
3099 if (which_alternative != 0 || operands[3] != const0_rtx
3100 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3101 need_else = true;
3102 else
3103 need_else = false;
0d66636f 3104
dc55b8a9 3105 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3106 operands[2], operands[3]);
0d66636f 3107 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3108 if (TARGET_THUMB2)
3109 {
3110 if (need_else)
3111 output_asm_insn (\"ite\\t%d5\", operands);
3112 else
3113 output_asm_insn (\"it\\t%d5\", operands);
3114 }
0d66636f 3115 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3116 if (need_else)
0d66636f 3117 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3118 return \"\";
215b30b3 3119 }"
0d66636f 3120 [(set_attr "conds" "clob")
25f905c2 3121 (set (attr "length")
3122 (if_then_else (eq_attr "is_thumb" "yes")
3123 (const_int 14)
3124 (const_int 12)))]
0d66636f 3125)
9c08d1fa 3126
b11cae9e 3127\f
3128;; Shift and rotation insns
3129
a2cd141b 3130(define_expand "ashldi3"
3131 [(set (match_operand:DI 0 "s_register_operand" "")
3132 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3133 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3134 "TARGET_32BIT"
a2cd141b 3135 "
3136 if (GET_CODE (operands[2]) == CONST_INT)
3137 {
3138 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3139 {
3140 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3141 DONE;
3142 }
3143 /* Ideally we shouldn't fail here if we could know that operands[1]
3144 ends up already living in an iwmmxt register. Otherwise it's
3145 cheaper to have the alternate code being generated than moving
1d60d981 3146 values to iwmmxt regs and back. */
a2cd141b 3147 FAIL;
3148 }
3149 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3150 FAIL;
3151 "
3152)
3153
3154(define_insn "arm_ashldi3_1bit"
3155 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3156 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3157 (const_int 1)))
3158 (clobber (reg:CC CC_REGNUM))]
25f905c2 3159 "TARGET_32BIT"
a2cd141b 3160 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3161 [(set_attr "conds" "clob")
3162 (set_attr "length" "8")]
3163)
3164
87b22bf7 3165(define_expand "ashlsi3"
cffb2a26 3166 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3167 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3168 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3169 "TARGET_EITHER"
87b22bf7 3170 "
3171 if (GET_CODE (operands[2]) == CONST_INT
3172 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3173 {
3174 emit_insn (gen_movsi (operands[0], const0_rtx));
3175 DONE;
3176 }
cffb2a26 3177 "
3178)
3179
25f905c2 3180(define_insn "*thumb1_ashlsi3"
cffb2a26 3181 [(set (match_operand:SI 0 "register_operand" "=l,l")
3182 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3183 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3184 "TARGET_THUMB1"
cffb2a26 3185 "lsl\\t%0, %1, %2"
3186 [(set_attr "length" "2")]
3187)
b11cae9e 3188
a2cd141b 3189(define_expand "ashrdi3"
3190 [(set (match_operand:DI 0 "s_register_operand" "")
3191 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3192 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3193 "TARGET_32BIT"
a2cd141b 3194 "
3195 if (GET_CODE (operands[2]) == CONST_INT)
3196 {
3197 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3198 {
3199 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3200 DONE;
3201 }
3202 /* Ideally we shouldn't fail here if we could know that operands[1]
3203 ends up already living in an iwmmxt register. Otherwise it's
3204 cheaper to have the alternate code being generated than moving
1d60d981 3205 values to iwmmxt regs and back. */
a2cd141b 3206 FAIL;
3207 }
3208 else if (!TARGET_REALLY_IWMMXT)
3209 FAIL;
3210 "
3211)
3212
3213(define_insn "arm_ashrdi3_1bit"
3214 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3215 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3216 (const_int 1)))
3217 (clobber (reg:CC CC_REGNUM))]
25f905c2 3218 "TARGET_32BIT"
a2cd141b 3219 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3220 [(set_attr "conds" "clob")
3221 (set_attr "length" "8")]
3222)
3223
87b22bf7 3224(define_expand "ashrsi3"
cffb2a26 3225 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3226 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3227 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3228 "TARGET_EITHER"
87b22bf7 3229 "
3230 if (GET_CODE (operands[2]) == CONST_INT
3231 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3232 operands[2] = GEN_INT (31);
cffb2a26 3233 "
3234)
3235
25f905c2 3236(define_insn "*thumb1_ashrsi3"
cffb2a26 3237 [(set (match_operand:SI 0 "register_operand" "=l,l")
3238 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3239 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3240 "TARGET_THUMB1"
cffb2a26 3241 "asr\\t%0, %1, %2"
3242 [(set_attr "length" "2")]
3243)
b11cae9e 3244
a2cd141b 3245(define_expand "lshrdi3"
3246 [(set (match_operand:DI 0 "s_register_operand" "")
3247 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3248 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3249 "TARGET_32BIT"
a2cd141b 3250 "
3251 if (GET_CODE (operands[2]) == CONST_INT)
3252 {
3253 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3254 {
3255 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3256 DONE;
3257 }
3258 /* Ideally we shouldn't fail here if we could know that operands[1]
3259 ends up already living in an iwmmxt register. Otherwise it's
3260 cheaper to have the alternate code being generated than moving
1d60d981 3261 values to iwmmxt regs and back. */
a2cd141b 3262 FAIL;
3263 }
3264 else if (!TARGET_REALLY_IWMMXT)
3265 FAIL;
3266 "
3267)
3268
3269(define_insn "arm_lshrdi3_1bit"
3270 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3271 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3272 (const_int 1)))
3273 (clobber (reg:CC CC_REGNUM))]
25f905c2 3274 "TARGET_32BIT"
a2cd141b 3275 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3276 [(set_attr "conds" "clob")
3277 (set_attr "length" "8")]
3278)
3279
87b22bf7 3280(define_expand "lshrsi3"
cffb2a26 3281 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3282 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3283 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3284 "TARGET_EITHER"
87b22bf7 3285 "
3286 if (GET_CODE (operands[2]) == CONST_INT
3287 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3288 {
3289 emit_insn (gen_movsi (operands[0], const0_rtx));
3290 DONE;
3291 }
cffb2a26 3292 "
3293)
3294
25f905c2 3295(define_insn "*thumb1_lshrsi3"
cffb2a26 3296 [(set (match_operand:SI 0 "register_operand" "=l,l")
3297 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3298 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3299 "TARGET_THUMB1"
cffb2a26 3300 "lsr\\t%0, %1, %2"
3301 [(set_attr "length" "2")]
3302)
b11cae9e 3303
87b22bf7 3304(define_expand "rotlsi3"
cffb2a26 3305 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3306 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3307 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3308 "TARGET_32BIT"
87b22bf7 3309 "
3310 if (GET_CODE (operands[2]) == CONST_INT)
3311 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3312 else
b11cae9e 3313 {
87b22bf7 3314 rtx reg = gen_reg_rtx (SImode);
3315 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3316 operands[2] = reg;
b11cae9e 3317 }
cffb2a26 3318 "
3319)
9c08d1fa 3320
87b22bf7 3321(define_expand "rotrsi3"
cffb2a26 3322 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3323 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3324 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3325 "TARGET_EITHER"
87b22bf7 3326 "
25f905c2 3327 if (TARGET_32BIT)
cffb2a26 3328 {
3329 if (GET_CODE (operands[2]) == CONST_INT
3330 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3331 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3332 }
25f905c2 3333 else /* TARGET_THUMB1 */
cffb2a26 3334 {
3335 if (GET_CODE (operands [2]) == CONST_INT)
3336 operands [2] = force_reg (SImode, operands[2]);
3337 }
3338 "
3339)
87b22bf7 3340
25f905c2 3341(define_insn "*thumb1_rotrsi3"
cffb2a26 3342 [(set (match_operand:SI 0 "register_operand" "=l")
3343 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3344 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3345 "TARGET_THUMB1"
cffb2a26 3346 "ror\\t%0, %0, %2"
3347 [(set_attr "length" "2")]
3348)
3349
3350(define_insn "*arm_shiftsi3"
3351 [(set (match_operand:SI 0 "s_register_operand" "=r")
3352 (match_operator:SI 3 "shift_operator"
3353 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3354 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3355 "TARGET_32BIT"
3356 "* return arm_output_shift(operands, 0);"
344495ea 3357 [(set_attr "predicable" "yes")
331beb1a 3358 (set_attr "shift" "1")
a2cd141b 3359 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3360 (const_string "alu_shift")
3361 (const_string "alu_shift_reg")))]
6c4c2133 3362)
87b22bf7 3363
f7fbdd4a 3364(define_insn "*shiftsi3_compare0"
bd5b4116 3365 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3366 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3367 [(match_operand:SI 1 "s_register_operand" "r")
3368 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3369 (const_int 0)))
3370 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3371 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3372 "TARGET_32BIT"
3373 "* return arm_output_shift(operands, 1);"
344495ea 3374 [(set_attr "conds" "set")
331beb1a 3375 (set_attr "shift" "1")
a2cd141b 3376 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3377 (const_string "alu_shift")
3378 (const_string "alu_shift_reg")))]
0d66636f 3379)
9c08d1fa 3380
f7fbdd4a 3381(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3382 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3383 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3384 [(match_operand:SI 1 "s_register_operand" "r")
3385 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3386 (const_int 0)))
3387 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3388 "TARGET_32BIT"
3389 "* return arm_output_shift(operands, 1);"
344495ea 3390 [(set_attr "conds" "set")
a2cd141b 3391 (set_attr "shift" "1")]
0d66636f 3392)
9c08d1fa 3393
25f905c2 3394(define_insn "*arm_notsi_shiftsi"
9c08d1fa 3395 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3396 (not:SI (match_operator:SI 3 "shift_operator"
3397 [(match_operand:SI 1 "s_register_operand" "r")
3398 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 3399 "TARGET_ARM"
6c4c2133 3400 "mvn%?\\t%0, %1%S3"
344495ea 3401 [(set_attr "predicable" "yes")
331beb1a 3402 (set_attr "shift" "1")
a2cd141b 3403 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3404 (const_string "alu_shift")
3405 (const_string "alu_shift_reg")))]
0d66636f 3406)
9c08d1fa 3407
25f905c2 3408(define_insn "*arm_notsi_shiftsi_compare0"
bd5b4116 3409 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3410 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3411 [(match_operand:SI 1 "s_register_operand" "r")
3412 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3413 (const_int 0)))
3414 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3415 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 3416 "TARGET_ARM"
25f905c2 3417 "mvn%.\\t%0, %1%S3"
344495ea 3418 [(set_attr "conds" "set")
331beb1a 3419 (set_attr "shift" "1")
a2cd141b 3420 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3421 (const_string "alu_shift")
3422 (const_string "alu_shift_reg")))]
0d66636f 3423)
9c08d1fa 3424
25f905c2 3425(define_insn "*arm_not_shiftsi_compare0_scratch"
bd5b4116 3426 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3427 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3428 [(match_operand:SI 1 "s_register_operand" "r")
3429 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3430 (const_int 0)))
3431 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3432 "TARGET_ARM"
25f905c2 3433 "mvn%.\\t%0, %1%S3"
344495ea 3434 [(set_attr "conds" "set")
331beb1a 3435 (set_attr "shift" "1")
a2cd141b 3436 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3437 (const_string "alu_shift")
3438 (const_string "alu_shift_reg")))]
0d66636f 3439)
9c08d1fa 3440
cffb2a26 3441;; We don't really have extzv, but defining this using shifts helps
3442;; to reduce register pressure later on.
3443
3444(define_expand "extzv"
3445 [(set (match_dup 4)
3446 (ashift:SI (match_operand:SI 1 "register_operand" "")
3447 (match_operand:SI 2 "const_int_operand" "")))
3448 (set (match_operand:SI 0 "register_operand" "")
3449 (lshiftrt:SI (match_dup 4)
215b30b3 3450 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3451 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3452 "
3453 {
3454 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3455 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3456
8b054d5a 3457 if (arm_arch_thumb2)
3458 {
3459 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3460 operands[3]));
3461 DONE;
3462 }
3463
cffb2a26 3464 operands[3] = GEN_INT (rshift);
3465
3466 if (lshift == 0)
3467 {
3468 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3469 DONE;
3470 }
3471
3472 operands[2] = GEN_INT (lshift);
3473 operands[4] = gen_reg_rtx (SImode);
215b30b3 3474 }"
cffb2a26 3475)
3476
8b054d5a 3477(define_insn "extv"
3478 [(set (match_operand:SI 0 "s_register_operand" "=r")
3479 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3480 (match_operand:SI 2 "const_int_operand" "M")
3481 (match_operand:SI 3 "const_int_operand" "M")))]
3482 "arm_arch_thumb2"
3483 "sbfx%?\t%0, %1, %3, %2"
3484 [(set_attr "length" "4")
3485 (set_attr "predicable" "yes")]
3486)
3487
3488(define_insn "extzv_t2"
3489 [(set (match_operand:SI 0 "s_register_operand" "=r")
3490 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3491 (match_operand:SI 2 "const_int_operand" "M")
3492 (match_operand:SI 3 "const_int_operand" "M")))]
3493 "arm_arch_thumb2"
3494 "ubfx%?\t%0, %1, %3, %2"
3495 [(set_attr "length" "4")
3496 (set_attr "predicable" "yes")]
3497)
3498
b11cae9e 3499\f
3500;; Unary arithmetic insns
3501
cffb2a26 3502(define_expand "negdi2"
3503 [(parallel
3504 [(set (match_operand:DI 0 "s_register_operand" "")
3505 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3506 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3507 "TARGET_EITHER"
3508 "
25f905c2 3509 if (TARGET_THUMB1)
cffb2a26 3510 {
3511 if (GET_CODE (operands[1]) != REG)
3512 operands[1] = force_reg (SImode, operands[1]);
3513 }
215b30b3 3514 "
cffb2a26 3515)
3516
3517;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3518;; The second alternative is to allow the common case of a *full* overlap.
3519(define_insn "*arm_negdi2"
3520 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3521 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 3522 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3523 "TARGET_ARM"
97499065 3524 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3525 [(set_attr "conds" "clob")
3526 (set_attr "length" "8")]
3527)
b11cae9e 3528
25f905c2 3529(define_insn "*thumb1_negdi2"
cffb2a26 3530 [(set (match_operand:DI 0 "register_operand" "=&l")
3531 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3532 (clobber (reg:CC CC_REGNUM))]
25f905c2 3533 "TARGET_THUMB1"
cffb2a26 3534 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3535 [(set_attr "length" "6")]
3536)
3537
3538(define_expand "negsi2"
3539 [(set (match_operand:SI 0 "s_register_operand" "")
3540 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3541 "TARGET_EITHER"
b11cae9e 3542 ""
cffb2a26 3543)
3544
3545(define_insn "*arm_negsi2"
3546 [(set (match_operand:SI 0 "s_register_operand" "=r")
3547 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3548 "TARGET_32BIT"
cffb2a26 3549 "rsb%?\\t%0, %1, #0"
0d66636f 3550 [(set_attr "predicable" "yes")]
cffb2a26 3551)
3552
25f905c2 3553(define_insn "*thumb1_negsi2"
cffb2a26 3554 [(set (match_operand:SI 0 "register_operand" "=l")
3555 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3556 "TARGET_THUMB1"
cffb2a26 3557 "neg\\t%0, %1"
3558 [(set_attr "length" "2")]
3559)
b11cae9e 3560
604f3a0a 3561(define_expand "negsf2"
3562 [(set (match_operand:SF 0 "s_register_operand" "")
3563 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3564 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3565 ""
3566)
3567
3568(define_expand "negdf2"
3569 [(set (match_operand:DF 0 "s_register_operand" "")
3570 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3571 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3572 "")
3573
9c08d1fa 3574;; abssi2 doesn't really clobber the condition codes if a different register
3575;; is being set. To keep things simple, assume during rtl manipulations that
3576;; it does, but tell the final scan operator the truth. Similarly for
3577;; (neg (abs...))
3578
604f3a0a 3579(define_expand "abssi2"
3580 [(parallel
3581 [(set (match_operand:SI 0 "s_register_operand" "")
3582 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3583 (clobber (match_dup 2))])]
3584 "TARGET_EITHER"
3585 "
25f905c2 3586 if (TARGET_THUMB1)
ba156559 3587 operands[2] = gen_rtx_SCRATCH (SImode);
3588 else
3589 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3590")
604f3a0a 3591
7d57ec45 3592(define_insn "*arm_abssi2"
ba156559 3593 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3594 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3595 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3596 "TARGET_ARM"
e2348bcb 3597 "@
3598 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3599 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3600 [(set_attr "conds" "clob,*")
331beb1a 3601 (set_attr "shift" "1")
0d66636f 3602 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3603 (set_attr "length" "8")]
3604)
9c08d1fa 3605
25f905c2 3606(define_insn_and_split "*thumb1_abssi2"
ba156559 3607 [(set (match_operand:SI 0 "s_register_operand" "=l")
3608 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3609 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3610 "TARGET_THUMB1"
ba156559 3611 "#"
25f905c2 3612 "TARGET_THUMB1 && reload_completed"
ba156559 3613 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3614 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3615 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3616 ""
3617 [(set_attr "length" "6")]
3618)
3619
3620(define_insn "*arm_neg_abssi2"
9c08d1fa 3621 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3622 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3623 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3624 "TARGET_ARM"
e2348bcb 3625 "@
3626 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3627 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3628 [(set_attr "conds" "clob,*")
331beb1a 3629 (set_attr "shift" "1")
0d66636f 3630 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3631 (set_attr "length" "8")]
3632)
b11cae9e 3633
25f905c2 3634(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3635 [(set (match_operand:SI 0 "s_register_operand" "=l")
3636 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3637 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3638 "TARGET_THUMB1"
ba156559 3639 "#"
25f905c2 3640 "TARGET_THUMB1 && reload_completed"
ba156559 3641 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3642 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3643 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3644 ""
3645 [(set_attr "length" "6")]
3646)
3647
604f3a0a 3648(define_expand "abssf2"
3649 [(set (match_operand:SF 0 "s_register_operand" "")
3650 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3651 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3652 "")
3653
604f3a0a 3654(define_expand "absdf2"
3655 [(set (match_operand:DF 0 "s_register_operand" "")
3656 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3657 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3658 "")
3659
7db9af5d 3660(define_expand "sqrtsf2"
3661 [(set (match_operand:SF 0 "s_register_operand" "")
3662 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3663 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3664 "")
9c08d1fa 3665
7db9af5d 3666(define_expand "sqrtdf2"
3667 [(set (match_operand:DF 0 "s_register_operand" "")
3668 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3669 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3670 "")
9c08d1fa 3671
a0f94409 3672(define_insn_and_split "one_cmpldi2"
9c08d1fa 3673 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3674 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 3675 "TARGET_32BIT"
f6ebffac 3676 "#"
25f905c2 3677 "TARGET_32BIT && reload_completed"
a0f94409 3678 [(set (match_dup 0) (not:SI (match_dup 1)))
3679 (set (match_dup 2) (not:SI (match_dup 3)))]
3680 "
3681 {
3682 operands[2] = gen_highpart (SImode, operands[0]);
3683 operands[0] = gen_lowpart (SImode, operands[0]);
3684 operands[3] = gen_highpart (SImode, operands[1]);
3685 operands[1] = gen_lowpart (SImode, operands[1]);
3686 }"
0d66636f 3687 [(set_attr "length" "8")
3688 (set_attr "predicable" "yes")]
cffb2a26 3689)
b11cae9e 3690
cffb2a26 3691(define_expand "one_cmplsi2"
3692 [(set (match_operand:SI 0 "s_register_operand" "")
3693 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3694 "TARGET_EITHER"
b11cae9e 3695 ""
cffb2a26 3696)
3697
3698(define_insn "*arm_one_cmplsi2"
3699 [(set (match_operand:SI 0 "s_register_operand" "=r")
3700 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3701 "TARGET_32BIT"
cffb2a26 3702 "mvn%?\\t%0, %1"
0d66636f 3703 [(set_attr "predicable" "yes")]
cffb2a26 3704)
3705
25f905c2 3706(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3707 [(set (match_operand:SI 0 "register_operand" "=l")
3708 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3709 "TARGET_THUMB1"
cffb2a26 3710 "mvn\\t%0, %1"
3711 [(set_attr "length" "2")]
3712)
9c08d1fa 3713
f7fbdd4a 3714(define_insn "*notsi_compare0"
bd5b4116 3715 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3716 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3717 (const_int 0)))
3718 (set (match_operand:SI 0 "s_register_operand" "=r")
3719 (not:SI (match_dup 1)))]
25f905c2 3720 "TARGET_32BIT"
3721 "mvn%.\\t%0, %1"
cffb2a26 3722 [(set_attr "conds" "set")]
3723)
9c08d1fa 3724
f7fbdd4a 3725(define_insn "*notsi_compare0_scratch"
bd5b4116 3726 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3727 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3728 (const_int 0)))
3729 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3730 "TARGET_32BIT"
3731 "mvn%.\\t%0, %1"
cffb2a26 3732 [(set_attr "conds" "set")]
3733)
b11cae9e 3734\f
3735;; Fixed <--> Floating conversion insns
3736
604f3a0a 3737(define_expand "floatsisf2"
3738 [(set (match_operand:SF 0 "s_register_operand" "")
3739 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3740 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3741 "
a2cd141b 3742 if (TARGET_MAVERICK)
604f3a0a 3743 {
3744 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3745 DONE;
3746 }
3747")
3748
604f3a0a 3749(define_expand "floatsidf2"
3750 [(set (match_operand:DF 0 "s_register_operand" "")
3751 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3752 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3753 "
a2cd141b 3754 if (TARGET_MAVERICK)
604f3a0a 3755 {
3756 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3757 DONE;
3758 }
3759")
3760
604f3a0a 3761(define_expand "fix_truncsfsi2"
3762 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3763 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3764 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3765 "
a2cd141b 3766 if (TARGET_MAVERICK)
604f3a0a 3767 {
3768 if (!cirrus_fp_register (operands[0], SImode))
3769 operands[0] = force_reg (SImode, operands[0]);
3770 if (!cirrus_fp_register (operands[1], SFmode))
3771 operands[1] = force_reg (SFmode, operands[0]);
3772 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3773 DONE;
3774 }
3775")
3776
604f3a0a 3777(define_expand "fix_truncdfsi2"
3778 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3779 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
25f905c2 3780 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3781 "
a2cd141b 3782 if (TARGET_MAVERICK)
604f3a0a 3783 {
3784 if (!cirrus_fp_register (operands[1], DFmode))
3785 operands[1] = force_reg (DFmode, operands[0]);
3786 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3787 DONE;
3788 }
3789")
3790
f544c6d2 3791;; Truncation insns
b11cae9e 3792
604f3a0a 3793(define_expand "truncdfsf2"
3794 [(set (match_operand:SF 0 "s_register_operand" "")
3795 (float_truncate:SF
3796 (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3797 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3798 ""
3799)
b11cae9e 3800\f
9c08d1fa 3801;; Zero and sign extension instructions.
b11cae9e 3802
25f905c2 3803(define_expand "zero_extendsidi2"
3804 [(set (match_operand:DI 0 "s_register_operand" "")
3805 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3806 "TARGET_32BIT"
3807 ""
3808)
3809
3810(define_insn "*arm_zero_extendsidi2"
9c08d1fa 3811 [(set (match_operand:DI 0 "s_register_operand" "=r")
3812 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3813 "TARGET_ARM"
9c08d1fa 3814 "*
0d66636f 3815 if (REGNO (operands[1])
3816 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3817 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3818 return \"mov%?\\t%R0, #0\";
3819 "
3820 [(set_attr "length" "8")
3821 (set_attr "predicable" "yes")]
3822)
9c08d1fa 3823
25f905c2 3824(define_expand "zero_extendqidi2"
3825 [(set (match_operand:DI 0 "s_register_operand" "")
3826 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3827 "TARGET_32BIT"
3828 ""
3829)
3830
3831(define_insn "*arm_zero_extendqidi2"
cffb2a26 3832 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3833 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3834 "TARGET_ARM"
e2348bcb 3835 "@
97499065 3836 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
25f905c2 3837 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3838 [(set_attr "length" "8")
0d66636f 3839 (set_attr "predicable" "yes")
a2cd141b 3840 (set_attr "type" "*,load_byte")
cffb2a26 3841 (set_attr "pool_range" "*,4092")
3842 (set_attr "neg_pool_range" "*,4084")]
3843)
9c08d1fa 3844
25f905c2 3845(define_expand "extendsidi2"
3846 [(set (match_operand:DI 0 "s_register_operand" "")
3847 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3848 "TARGET_32BIT"
3849 ""
3850)
3851
3852(define_insn "*arm_extendsidi2"
9c08d1fa 3853 [(set (match_operand:DI 0 "s_register_operand" "=r")
3854 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3855 "TARGET_ARM"
9c08d1fa 3856 "*
0d66636f 3857 if (REGNO (operands[1])
3858 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3859 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3860 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3861 "
3862 [(set_attr "length" "8")
331beb1a 3863 (set_attr "shift" "1")
0d66636f 3864 (set_attr "predicable" "yes")]
3865)
9c08d1fa 3866
3867(define_expand "zero_extendhisi2"
cffb2a26 3868 [(set (match_dup 2)
0d66636f 3869 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3870 (const_int 16)))
9c08d1fa 3871 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3872 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3873 "TARGET_EITHER"
9c08d1fa 3874 "
cffb2a26 3875 {
25f905c2 3876 if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3877 {
a2cd141b 3878 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3879 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3880 DONE;
cffb2a26 3881 }
cffb2a26 3882
c1a66faf 3883 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3884 {
3885 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3886 DONE;
3887 }
cffb2a26 3888
a2cd141b 3889 if (!s_register_operand (operands[1], HImode))
3890 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3891
a2cd141b 3892 if (arm_arch6)
3893 {
3894 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3895 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3896 DONE;
cffb2a26 3897 }
a2cd141b 3898
3899 operands[1] = gen_lowpart (SImode, operands[1]);
3900 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3901 }"
3902)
3903
25f905c2 3904(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 3905 [(set (match_operand:SI 0 "register_operand" "=l")
3906 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
25f905c2 3907 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 3908 "*
3909 rtx mem = XEXP (operands[1], 0);
3910
3911 if (GET_CODE (mem) == CONST)
3912 mem = XEXP (mem, 0);
3913
3914 if (GET_CODE (mem) == LABEL_REF)
3915 return \"ldr\\t%0, %1\";
3916
3917 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3918 {
cffb2a26 3919 rtx a = XEXP (mem, 0);
3920 rtx b = XEXP (mem, 1);
3921
3922 /* This can happen due to bugs in reload. */
3923 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3924 {
3925 rtx ops[2];
3926 ops[0] = operands[0];
3927 ops[1] = a;
3928
3929 output_asm_insn (\"mov %0, %1\", ops);
3930
3931 XEXP (mem, 0) = operands[0];
3932 }
3933
3934 else if ( GET_CODE (a) == LABEL_REF
3935 && GET_CODE (b) == CONST_INT)
3936 return \"ldr\\t%0, %1\";
25f7a26e 3937 }
cffb2a26 3938
3939 return \"ldrh\\t%0, %1\";
3940 "
3941 [(set_attr "length" "4")
a2cd141b 3942 (set_attr "type" "load_byte")
cffb2a26 3943 (set_attr "pool_range" "60")]
3944)
9c08d1fa 3945
25f905c2 3946(define_insn "*thumb1_zero_extendhisi2_v6"
a2cd141b 3947 [(set (match_operand:SI 0 "register_operand" "=l,l")
3948 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
25f905c2 3949 "TARGET_THUMB1 && arm_arch6"
a2cd141b 3950 "*
3951 rtx mem;
3952
3953 if (which_alternative == 0)
3954 return \"uxth\\t%0, %1\";
3955
3956 mem = XEXP (operands[1], 0);
3957
3958 if (GET_CODE (mem) == CONST)
3959 mem = XEXP (mem, 0);
3960
3961 if (GET_CODE (mem) == LABEL_REF)
3962 return \"ldr\\t%0, %1\";
3963
3964 if (GET_CODE (mem) == PLUS)
3965 {
3966 rtx a = XEXP (mem, 0);
3967 rtx b = XEXP (mem, 1);
3968
3969 /* This can happen due to bugs in reload. */
3970 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3971 {
3972 rtx ops[2];
3973 ops[0] = operands[0];
3974 ops[1] = a;
3975
3976 output_asm_insn (\"mov %0, %1\", ops);
3977
3978 XEXP (mem, 0) = operands[0];
3979 }
3980
3981 else if ( GET_CODE (a) == LABEL_REF
3982 && GET_CODE (b) == CONST_INT)
3983 return \"ldr\\t%0, %1\";
3984 }
3985
3986 return \"ldrh\\t%0, %1\";
3987 "
3988 [(set_attr "length" "2,4")
3989 (set_attr "type" "alu_shift,load_byte")
3990 (set_attr "pool_range" "*,60")]
3991)
3992
cffb2a26 3993(define_insn "*arm_zero_extendhisi2"
a2cd141b 3994 [(set (match_operand:SI 0 "s_register_operand" "=r")
3995 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3996 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 3997 "ldr%(h%)\\t%0, %1"
a2cd141b 3998 [(set_attr "type" "load_byte")
0d66636f 3999 (set_attr "predicable" "yes")
cffb2a26 4000 (set_attr "pool_range" "256")
4001 (set_attr "neg_pool_range" "244")]
4002)
f7fbdd4a 4003
a2cd141b 4004(define_insn "*arm_zero_extendhisi2_v6"
4005 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4006 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4007 "TARGET_ARM && arm_arch6"
4008 "@
4009 uxth%?\\t%0, %1
25f905c2 4010 ldr%(h%)\\t%0, %1"
a2cd141b 4011 [(set_attr "type" "alu_shift,load_byte")
4012 (set_attr "predicable" "yes")
4013 (set_attr "pool_range" "*,256")
4014 (set_attr "neg_pool_range" "*,244")]
4015)
4016
4017(define_insn "*arm_zero_extendhisi2addsi"
4018 [(set (match_operand:SI 0 "s_register_operand" "=r")
4019 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4020 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4021 "TARGET_INT_SIMD"
a2cd141b 4022 "uxtah%?\\t%0, %2, %1"
4023 [(set_attr "type" "alu_shift")
4024 (set_attr "predicable" "yes")]
4025)
4026
87b22bf7 4027(define_expand "zero_extendqisi2"
cffb2a26 4028 [(set (match_operand:SI 0 "s_register_operand" "")
4029 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4030 "TARGET_EITHER"
87b22bf7 4031 "
a2cd141b 4032 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4033 {
cffb2a26 4034 if (TARGET_ARM)
4035 {
215b30b3 4036 emit_insn (gen_andsi3 (operands[0],
4037 gen_lowpart (SImode, operands[1]),
cffb2a26 4038 GEN_INT (255)));
4039 }
4040 else /* TARGET_THUMB */
4041 {
4042 rtx temp = gen_reg_rtx (SImode);
4043 rtx ops[3];
4044
4045 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4046 operands[1] = gen_lowpart (SImode, operands[1]);
4047
4048 ops[0] = temp;
4049 ops[1] = operands[1];
4050 ops[2] = GEN_INT (24);
4051
215b30b3 4052 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4053 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 4054
4055 ops[0] = operands[0];
4056 ops[1] = temp;
4057 ops[2] = GEN_INT (24);
4058
215b30b3 4059 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4060 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 4061 }
87b22bf7 4062 DONE;
4063 }
215b30b3 4064 "
4065)
9c08d1fa 4066
25f905c2 4067(define_insn "*thumb1_zero_extendqisi2"
a2cd141b 4068 [(set (match_operand:SI 0 "register_operand" "=l")
4069 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
25f905c2 4070 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4071 "ldrb\\t%0, %1"
4072 [(set_attr "length" "2")
a2cd141b 4073 (set_attr "type" "load_byte")
cffb2a26 4074 (set_attr "pool_range" "32")]
4075)
4076
25f905c2 4077(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4078 [(set (match_operand:SI 0 "register_operand" "=l,l")
4079 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4080 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4081 "@
4082 uxtb\\t%0, %1
4083 ldrb\\t%0, %1"
4084 [(set_attr "length" "2,2")
4085 (set_attr "type" "alu_shift,load_byte")
4086 (set_attr "pool_range" "*,32")]
4087)
4088
cffb2a26 4089(define_insn "*arm_zero_extendqisi2"
a2cd141b 4090 [(set (match_operand:SI 0 "s_register_operand" "=r")
4091 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4092 "TARGET_ARM && !arm_arch6"
25f905c2 4093 "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4094 [(set_attr "type" "load_byte")
0d66636f 4095 (set_attr "predicable" "yes")
cffb2a26 4096 (set_attr "pool_range" "4096")
4097 (set_attr "neg_pool_range" "4084")]
4098)
87b22bf7 4099
a2cd141b 4100(define_insn "*arm_zero_extendqisi2_v6"
4101 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4102 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4103 "TARGET_ARM && arm_arch6"
4104 "@
25f905c2 4105 uxtb%(%)\\t%0, %1
4106 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4107 [(set_attr "type" "alu_shift,load_byte")
4108 (set_attr "predicable" "yes")
4109 (set_attr "pool_range" "*,4096")
4110 (set_attr "neg_pool_range" "*,4084")]
4111)
4112
4113(define_insn "*arm_zero_extendqisi2addsi"
4114 [(set (match_operand:SI 0 "s_register_operand" "=r")
4115 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4116 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4117 "TARGET_INT_SIMD"
a2cd141b 4118 "uxtab%?\\t%0, %2, %1"
4119 [(set_attr "predicable" "yes")
bcaec148 4120 (set_attr "insn" "xtab")
a2cd141b 4121 (set_attr "type" "alu_shift")]
4122)
4123
87b22bf7 4124(define_split
4125 [(set (match_operand:SI 0 "s_register_operand" "")
4126 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4127 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4128 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4129 [(set (match_dup 2) (match_dup 1))
4130 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4131 ""
4132)
9c08d1fa 4133
8a4d25d6 4134(define_split
4135 [(set (match_operand:SI 0 "s_register_operand" "")
4136 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4137 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4138 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4139 [(set (match_dup 2) (match_dup 1))
4140 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4141 ""
4142)
4143
f7fbdd4a 4144(define_insn "*compareqi_eq0"
bd5b4116 4145 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4146 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4147 (const_int 0)))]
25f905c2 4148 "TARGET_32BIT"
87b22bf7 4149 "tst\\t%0, #255"
cffb2a26 4150 [(set_attr "conds" "set")]
4151)
b11cae9e 4152
b11cae9e 4153(define_expand "extendhisi2"
c8f69309 4154 [(set (match_dup 2)
25f7a26e 4155 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 4156 (const_int 16)))
9c08d1fa 4157 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4158 (ashiftrt:SI (match_dup 2)
4159 (const_int 16)))]
cffb2a26 4160 "TARGET_EITHER"
b11cae9e 4161 "
cffb2a26 4162 {
a2cd141b 4163 if (GET_CODE (operands[1]) == MEM)
cffb2a26 4164 {
25f905c2 4165 if (TARGET_THUMB1)
a2cd141b 4166 {
25f905c2 4167 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4168 DONE;
4169 }
4170 else if (arm_arch4)
4171 {
a2cd141b 4172 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4173 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4174 DONE;
4175 }
cffb2a26 4176 }
7bd8ccc9 4177
c1a66faf 4178 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 4179 {
4180 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4181 DONE;
4182 }
a2cd141b 4183
215b30b3 4184 if (!s_register_operand (operands[1], HImode))
cffb2a26 4185 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 4186
a2cd141b 4187 if (arm_arch6)
cffb2a26 4188 {
25f905c2 4189 if (TARGET_THUMB1)
4190 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4191 else
4192 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4193 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4194
cffb2a26 4195 DONE;
4196 }
a2cd141b 4197
4198 operands[1] = gen_lowpart (SImode, operands[1]);
4199 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4200 }"
4201)
4202
25f905c2 4203(define_insn "thumb1_extendhisi2"
a2cd141b 4204 [(set (match_operand:SI 0 "register_operand" "=l")
4205 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4206 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4207 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4208 "*
4209 {
4210 rtx ops[4];
4211 rtx mem = XEXP (operands[1], 0);
4212
4213 /* This code used to try to use 'V', and fix the address only if it was
4214 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4215 range of QImode offsets, and offsettable_address_p does a QImode
4216 address check. */
4217
4218 if (GET_CODE (mem) == CONST)
4219 mem = XEXP (mem, 0);
4220
4221 if (GET_CODE (mem) == LABEL_REF)
4222 return \"ldr\\t%0, %1\";
4223
4224 if (GET_CODE (mem) == PLUS)
4225 {
4226 rtx a = XEXP (mem, 0);
4227 rtx b = XEXP (mem, 1);
4228
4229 if (GET_CODE (a) == LABEL_REF
4230 && GET_CODE (b) == CONST_INT)
4231 return \"ldr\\t%0, %1\";
4232
4233 if (GET_CODE (b) == REG)
4234 return \"ldrsh\\t%0, %1\";
4235
4236 ops[1] = a;
4237 ops[2] = b;
4238 }
4239 else
4240 {
4241 ops[1] = mem;
4242 ops[2] = const0_rtx;
4243 }
ed29c566 4244
4245 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 4246
4247 ops[0] = operands[0];
4248 ops[3] = operands[2];
4249 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4250 return \"\";
4251 }"
4252 [(set_attr "length" "4")
a2cd141b 4253 (set_attr "type" "load_byte")
cffb2a26 4254 (set_attr "pool_range" "1020")]
4255)
25f7a26e 4256
a2cd141b 4257;; We used to have an early-clobber on the scratch register here.
4258;; However, there's a bug somewhere in reload which means that this
4259;; can be partially ignored during spill allocation if the memory
ed29c566 4260;; address also needs reloading; this causes us to die later on when
a2cd141b 4261;; we try to verify the operands. Fortunately, we don't really need
4262;; the early-clobber: we can always use operand 0 if operand 2
4263;; overlaps the address.
25f905c2 4264(define_insn "*thumb1_extendhisi2_insn_v6"
a2cd141b 4265 [(set (match_operand:SI 0 "register_operand" "=l,l")
4266 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4267 (clobber (match_scratch:SI 2 "=X,l"))]
25f905c2 4268 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4269 "*
4270 {
4271 rtx ops[4];
4272 rtx mem;
4273
4274 if (which_alternative == 0)
4275 return \"sxth\\t%0, %1\";
4276
4277 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 }
4310
ed29c566 4311 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4312
4313 ops[0] = operands[0];
4314 if (reg_mentioned_p (operands[2], ops[1]))
4315 ops[3] = ops[0];
4316 else
4317 ops[3] = operands[2];
4318 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4319 return \"\";
4320 }"
4321 [(set_attr "length" "2,4")
4322 (set_attr "type" "alu_shift,load_byte")
4323 (set_attr "pool_range" "*,1020")]
4324)
4325
25f905c2 4326;; This pattern will only be used when ldsh is not available
25f7a26e 4327(define_expand "extendhisi2_mem"
eab14235 4328 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4329 (set (match_dup 3)
eab14235 4330 (zero_extend:SI (match_dup 7)))
25f7a26e 4331 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4332 (set (match_operand:SI 0 "" "")
4333 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4334 "TARGET_ARM"
25f7a26e 4335 "
215b30b3 4336 {
4337 rtx mem1, mem2;
4338 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4339
788fcce0 4340 mem1 = change_address (operands[1], QImode, addr);
4341 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4342 operands[0] = gen_lowpart (SImode, operands[0]);
4343 operands[1] = mem1;
4344 operands[2] = gen_reg_rtx (SImode);
4345 operands[3] = gen_reg_rtx (SImode);
4346 operands[6] = gen_reg_rtx (SImode);
4347 operands[7] = mem2;
25f7a26e 4348
215b30b3 4349 if (BYTES_BIG_ENDIAN)
4350 {
4351 operands[4] = operands[2];
4352 operands[5] = operands[3];
4353 }
4354 else
4355 {
4356 operands[4] = operands[3];
4357 operands[5] = operands[2];
4358 }
4359 }"
4360)
b11cae9e 4361
a2cd141b 4362(define_insn "*arm_extendhisi2"
4363 [(set (match_operand:SI 0 "s_register_operand" "=r")
4364 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4365 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4366 "ldr%(sh%)\\t%0, %1"
a2cd141b 4367 [(set_attr "type" "load_byte")
0d66636f 4368 (set_attr "predicable" "yes")
cffb2a26 4369 (set_attr "pool_range" "256")
4370 (set_attr "neg_pool_range" "244")]
4371)
f7fbdd4a 4372
25f905c2 4373;; ??? Check Thumb-2 pool range
a2cd141b 4374(define_insn "*arm_extendhisi2_v6"
4375 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4376 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4377 "TARGET_32BIT && arm_arch6"
a2cd141b 4378 "@
4379 sxth%?\\t%0, %1
25f905c2 4380 ldr%(sh%)\\t%0, %1"
a2cd141b 4381 [(set_attr "type" "alu_shift,load_byte")
4382 (set_attr "predicable" "yes")
4383 (set_attr "pool_range" "*,256")
4384 (set_attr "neg_pool_range" "*,244")]
4385)
4386
4387(define_insn "*arm_extendhisi2addsi"
4388 [(set (match_operand:SI 0 "s_register_operand" "=r")
4389 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4390 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4391 "TARGET_INT_SIMD"
a2cd141b 4392 "sxtah%?\\t%0, %2, %1"
4393)
4394
c8f69309 4395(define_expand "extendqihi2"
4396 [(set (match_dup 2)
bed7d9a5 4397 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4398 (const_int 24)))
9c08d1fa 4399 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4400 (ashiftrt:SI (match_dup 2)
4401 (const_int 24)))]
cffb2a26 4402 "TARGET_ARM"
c8f69309 4403 "
215b30b3 4404 {
4405 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4406 {
4407 emit_insn (gen_rtx_SET (VOIDmode,
4408 operands[0],
4409 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4410 DONE;
4411 }
4412 if (!s_register_operand (operands[1], QImode))
4413 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4414 operands[0] = gen_lowpart (SImode, operands[0]);
4415 operands[1] = gen_lowpart (SImode, operands[1]);
4416 operands[2] = gen_reg_rtx (SImode);
4417 }"
4418)
f7fbdd4a 4419
25f905c2 4420(define_insn "*arm_extendqihi_insn"
b4e8a300 4421 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4422 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4423 "TARGET_ARM && arm_arch4"
25f905c2 4424 "ldr%(sb%)\\t%0, %1"
a2cd141b 4425 [(set_attr "type" "load_byte")
0d66636f 4426 (set_attr "predicable" "yes")
cffb2a26 4427 (set_attr "pool_range" "256")
4428 (set_attr "neg_pool_range" "244")]
4429)
3fc2009e 4430
b11cae9e 4431(define_expand "extendqisi2"
c8f69309 4432 [(set (match_dup 2)
bed7d9a5 4433 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
b11cae9e 4434 (const_int 24)))
9c08d1fa 4435 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4436 (ashiftrt:SI (match_dup 2)
4437 (const_int 24)))]
cffb2a26 4438 "TARGET_EITHER"
b11cae9e 4439 "
cffb2a26 4440 {
a2cd141b 4441 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 4442 {
a2cd141b 4443 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 4444 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4445 DONE;
4446 }
a2cd141b 4447
215b30b3 4448 if (!s_register_operand (operands[1], QImode))
cffb2a26 4449 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 4450
a2cd141b 4451 if (arm_arch6)
4452 {
4453 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4454 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4455 DONE;
cffb2a26 4456 }
a2cd141b 4457
4458 operands[1] = gen_lowpart (SImode, operands[1]);
4459 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4460 }"
4461)
f7fbdd4a 4462
a2cd141b 4463(define_insn "*arm_extendqisi"
4464 [(set (match_operand:SI 0 "s_register_operand" "=r")
bed7d9a5 4465 (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
a2cd141b 4466 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4467 "ldr%(sb%)\\t%0, %1"
a2cd141b 4468 [(set_attr "type" "load_byte")
0d66636f 4469 (set_attr "predicable" "yes")
cffb2a26 4470 (set_attr "pool_range" "256")
4471 (set_attr "neg_pool_range" "244")]
4472)
3fc2009e 4473
a2cd141b 4474(define_insn "*arm_extendqisi_v6"
4475 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4476 (sign_extend:SI
4477 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4478 "TARGET_ARM && arm_arch6"
b4e8a300 4479 "@
4480 sxtb%?\\t%0, %1
25f905c2 4481 ldr%(sb%)\\t%0, %1"
a2cd141b 4482 [(set_attr "type" "alu_shift,load_byte")
4483 (set_attr "predicable" "yes")
a2cd141b 4484 (set_attr "pool_range" "*,256")
4485 (set_attr "neg_pool_range" "*,244")]
4486)
4487
4488(define_insn "*arm_extendqisi2addsi"
4489 [(set (match_operand:SI 0 "s_register_operand" "=r")
4490 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4491 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4492 "TARGET_INT_SIMD"
a2cd141b 4493 "sxtab%?\\t%0, %2, %1"
4494 [(set_attr "type" "alu_shift")
bcaec148 4495 (set_attr "insn" "xtab")
a2cd141b 4496 (set_attr "predicable" "yes")]
4497)
4498
25f905c2 4499(define_insn "*thumb1_extendqisi2"
a2cd141b 4500 [(set (match_operand:SI 0 "register_operand" "=l,l")
4501 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
25f905c2 4502 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4503 "*
4504 {
4505 rtx ops[3];
4506 rtx mem = XEXP (operands[1], 0);
4507
4508 if (GET_CODE (mem) == CONST)
4509 mem = XEXP (mem, 0);
4510
4511 if (GET_CODE (mem) == LABEL_REF)
4512 return \"ldr\\t%0, %1\";
4513
4514 if (GET_CODE (mem) == PLUS
4515 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4516 return \"ldr\\t%0, %1\";
4517
4518 if (which_alternative == 0)
4519 return \"ldrsb\\t%0, %1\";
4520
4521 ops[0] = operands[0];
4522
4523 if (GET_CODE (mem) == PLUS)
4524 {
4525 rtx a = XEXP (mem, 0);
4526 rtx b = XEXP (mem, 1);
4527
4528 ops[1] = a;
4529 ops[2] = b;
4530
4531 if (GET_CODE (a) == REG)
4532 {
4533 if (GET_CODE (b) == REG)
4534 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4535 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 4536 {
4537 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4538 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4539 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4540 }
cffb2a26 4541 else
4542 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4543 }
cffb2a26 4544 else
4545 {
ed29c566 4546 gcc_assert (GET_CODE (b) == REG);
cffb2a26 4547 if (REGNO (b) == REGNO (ops[0]))
215b30b3 4548 {
4549 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4550 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4551 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4552 }
cffb2a26 4553 else
4554 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4555 }
4556 }
4557 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4558 {
215b30b3 4559 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4560 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4561 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 4562 }
4563 else
4564 {
4565 ops[1] = mem;
4566 ops[2] = const0_rtx;
4567
4568 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4569 }
4570 return \"\";
4571 }"
4572 [(set_attr "length" "2,6")
a2cd141b 4573 (set_attr "type" "load_byte,load_byte")
cffb2a26 4574 (set_attr "pool_range" "32,32")]
4575)
4576
25f905c2 4577(define_insn "*thumb1_extendqisi2_v6"
a2cd141b 4578 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4579 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
25f905c2 4580 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4581 "*
4582 {
4583 rtx ops[3];
4584 rtx mem;
4585
4586 if (which_alternative == 0)
4587 return \"sxtb\\t%0, %1\";
4588
4589 mem = XEXP (operands[1], 0);
4590
4591 if (GET_CODE (mem) == CONST)
4592 mem = XEXP (mem, 0);
4593
4594 if (GET_CODE (mem) == LABEL_REF)
4595 return \"ldr\\t%0, %1\";
4596
4597 if (GET_CODE (mem) == PLUS
4598 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4599 return \"ldr\\t%0, %1\";
4600
4601 if (which_alternative == 0)
4602 return \"ldrsb\\t%0, %1\";
4603
4604 ops[0] = operands[0];
4605
4606 if (GET_CODE (mem) == PLUS)
4607 {
4608 rtx a = XEXP (mem, 0);
4609 rtx b = XEXP (mem, 1);
4610
4611 ops[1] = a;
4612 ops[2] = b;
4613
4614 if (GET_CODE (a) == REG)
4615 {
4616 if (GET_CODE (b) == REG)
4617 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4618 else if (REGNO (a) == REGNO (ops[0]))
4619 {
4620 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4621 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4622 }
4623 else
4624 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4625 }
a2cd141b 4626 else
4627 {
ed29c566 4628 gcc_assert (GET_CODE (b) == REG);
a2cd141b 4629 if (REGNO (b) == REGNO (ops[0]))
4630 {
4631 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4632 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4633 }
4634 else
4635 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4636 }
4637 }
4638 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4639 {
4640 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4641 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4642 }
4643 else
4644 {
4645 ops[1] = mem;
4646 ops[2] = const0_rtx;
4647
4648 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4649 }
4650 return \"\";
4651 }"
4652 [(set_attr "length" "2,2,4")
4653 (set_attr "type" "alu_shift,load_byte,load_byte")
4654 (set_attr "pool_range" "*,32,32")]
4655)
4656
caedf871 4657(define_expand "extendsfdf2"
4658 [(set (match_operand:DF 0 "s_register_operand" "")
4659 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4660 "TARGET_32BIT && TARGET_HARD_FLOAT"
caedf871 4661 ""
4662)
b11cae9e 4663\f
4664;; Move insns (including loads and stores)
4665
4666;; XXX Just some ideas about movti.
9c08d1fa 4667;; I don't think these are a good idea on the arm, there just aren't enough
4668;; registers
b11cae9e 4669;;(define_expand "loadti"
9c08d1fa 4670;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4671;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4672;; "" "")
4673
4674;;(define_expand "storeti"
4675;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4676;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4677;; "" "")
4678
4679;;(define_expand "movti"
4680;; [(set (match_operand:TI 0 "general_operand" "")
4681;; (match_operand:TI 1 "general_operand" ""))]
4682;; ""
4683;; "
4684;;{
4685;; rtx insn;
4686;;
4687;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4688;; operands[1] = copy_to_reg (operands[1]);
4689;; if (GET_CODE (operands[0]) == MEM)
4690;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4691;; else if (GET_CODE (operands[1]) == MEM)
4692;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4693;; else
4694;; FAIL;
4695;;
4696;; emit_insn (insn);
4697;; DONE;
4698;;}")
4699
a2f10574 4700;; Recognize garbage generated above.
b11cae9e 4701
4702;;(define_insn ""
4703;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4704;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4705;; ""
4706;; "*
4707;; {
4708;; register mem = (which_alternative < 3);
0d66636f 4709;; register const char *template;
b11cae9e 4710;;
4711;; operands[mem] = XEXP (operands[mem], 0);
4712;; switch (which_alternative)
4713;; {
4714;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4715;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4716;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4717;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4718;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4719;; case 5: template = \"stmia\\t%0, %M1\"; break;
4720;; }
e2348bcb 4721;; output_asm_insn (template, operands);
4722;; return \"\";
b11cae9e 4723;; }")
4724
cffb2a26 4725(define_expand "movdi"
4726 [(set (match_operand:DI 0 "general_operand" "")
4727 (match_operand:DI 1 "general_operand" ""))]
4728 "TARGET_EITHER"
4729 "
e1ba4a27 4730 if (can_create_pseudo_p ())
cffb2a26 4731 {
b2778788 4732 if (GET_CODE (operands[0]) != REG)
4733 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4734 }
4735 "
4736)
b11cae9e 4737
cffb2a26 4738(define_insn "*arm_movdi"
d51f92df 4739 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4740 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4741 "TARGET_ARM
b2778788 4742 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4743 && !TARGET_IWMMXT
4744 && ( register_operand (operands[0], DImode)
4745 || register_operand (operands[1], DImode))"
b11cae9e 4746 "*
d51f92df 4747 switch (which_alternative)
4748 {
4749 case 0:
4750 case 1:
4751 case 2:
4752 return \"#\";
4753 default:
4754 return output_move_double (operands);
4755 }
cffb2a26 4756 "
359a6e9f 4757 [(set_attr "length" "8,12,16,8,8")
4758 (set_attr "type" "*,*,*,load2,store2")
4759 (set_attr "pool_range" "*,*,*,1020,*")
4760 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4761)
4762
d51f92df 4763(define_split
4764 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4765 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4766 "TARGET_32BIT
d51f92df 4767 && reload_completed
4768 && (arm_const_double_inline_cost (operands[1])
4769 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4770 [(const_int 0)]
4771 "
4772 arm_split_constant (SET, SImode, curr_insn,
4773 INTVAL (gen_lowpart (SImode, operands[1])),
4774 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4775 arm_split_constant (SET, SImode, curr_insn,
4776 INTVAL (gen_highpart_mode (SImode,
4777 GET_MODE (operands[0]),
4778 operands[1])),
4779 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4780 DONE;
4781 "
4782)
4783
e5ba9289 4784; If optimizing for size, or if we have load delay slots, then
4785; we want to split the constant into two separate operations.
4786; In both cases this may split a trivial part into a single data op
4787; leaving a single complex constant to load. We can also get longer
4788; offsets in a LDR which means we get better chances of sharing the pool
4789; entries. Finally, we can normally do a better job of scheduling
4790; LDR instructions than we can with LDM.
4791; This pattern will only match if the one above did not.
4792(define_split
4793 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4794 (match_operand:ANY64 1 "const_double_operand" ""))]
4795 "TARGET_ARM && reload_completed
4796 && arm_const_double_by_parts (operands[1])"
4797 [(set (match_dup 0) (match_dup 1))
4798 (set (match_dup 2) (match_dup 3))]
4799 "
4800 operands[2] = gen_highpart (SImode, operands[0]);
4801 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4802 operands[1]);
4803 operands[0] = gen_lowpart (SImode, operands[0]);
4804 operands[1] = gen_lowpart (SImode, operands[1]);
4805 "
4806)
4807
d51f92df 4808(define_split
4809 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4810 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4811 "TARGET_EITHER && reload_completed"
4812 [(set (match_dup 0) (match_dup 1))
4813 (set (match_dup 2) (match_dup 3))]
4814 "
4815 operands[2] = gen_highpart (SImode, operands[0]);
4816 operands[3] = gen_highpart (SImode, operands[1]);
4817 operands[0] = gen_lowpart (SImode, operands[0]);
4818 operands[1] = gen_lowpart (SImode, operands[1]);
4819
4820 /* Handle a partial overlap. */
4821 if (rtx_equal_p (operands[0], operands[3]))
4822 {
4823 rtx tmp0 = operands[0];
4824 rtx tmp1 = operands[1];
4825
4826 operands[0] = operands[2];
4827 operands[1] = operands[3];
4828 operands[2] = tmp0;
4829 operands[3] = tmp1;
4830 }
4831 "
4832)
4833
a8a3b539 4834;; We can't actually do base+index doubleword loads if the index and
4835;; destination overlap. Split here so that we at least have chance to
4836;; schedule.
4837(define_split
4838 [(set (match_operand:DI 0 "s_register_operand" "")
4839 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4840 (match_operand:SI 2 "s_register_operand" ""))))]
4841 "TARGET_LDRD
4842 && reg_overlap_mentioned_p (operands[0], operands[1])
4843 && reg_overlap_mentioned_p (operands[0], operands[2])"
4844 [(set (match_dup 4)
4845 (plus:SI (match_dup 1)
4846 (match_dup 2)))
4847 (set (match_dup 0)
4848 (mem:DI (match_dup 4)))]
4849 "
4850 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4851 "
4852)
4853
cffb2a26 4854;;; ??? This should have alternatives for constants.
4855;;; ??? This was originally identical to the movdf_insn pattern.
4856;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4857;;; thumb_reorg with a memory reference.
25f905c2 4858(define_insn "*thumb1_movdi_insn"
215b30b3 4859 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4860 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4861 "TARGET_THUMB1
a2cd141b 4862 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4863 && ( register_operand (operands[0], DImode)
4864 || register_operand (operands[1], DImode))"
4865 "*
4866 {
4867 switch (which_alternative)
4868 {
4869 default:
4870 case 0:
4871 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4872 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4873 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4874 case 1:
4875 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4876 case 2:
4877 operands[1] = GEN_INT (- INTVAL (operands[1]));
4878 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4879 case 3:
4880 return \"ldmia\\t%1, {%0, %H0}\";
4881 case 4:
4882 return \"stmia\\t%0, {%1, %H1}\";
4883 case 5:
4884 return thumb_load_double_from_address (operands);
4885 case 6:
1a83b3ff 4886 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4887 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4888 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4889 return \"\";
4890 case 7:
4891 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4892 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4893 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4894 }
4895 }"
4896 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4897 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4898 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4899)
b11cae9e 4900
9c08d1fa 4901(define_expand "movsi"
4902 [(set (match_operand:SI 0 "general_operand" "")
4903 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4904 "TARGET_EITHER"
9c08d1fa 4905 "
befb0bac 4906 {
e348ff3e 4907 rtx base, offset, tmp;
4908
25f905c2 4909 if (TARGET_32BIT)
9c08d1fa 4910 {
674a8f0b 4911 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4912 if (GET_CODE (operands[0]) == MEM)
4913 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4914 if (arm_general_register_operand (operands[0], SImode)
4915 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4916 && !(const_ok_for_arm (INTVAL (operands[1]))
4917 || const_ok_for_arm (~INTVAL (operands[1]))))
4918 {
96f57e36 4919 arm_split_constant (SET, SImode, NULL_RTX,
4920 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 4921 optimize && can_create_pseudo_p ());
cffb2a26 4922 DONE;
4923 }
d0e6a121 4924
4925 if (TARGET_USE_MOVT && !target_word_relocations
4926 && GET_CODE (operands[1]) == SYMBOL_REF
4927 && !flag_pic && !arm_tls_referenced_p (operands[1]))
4928 {
4929 arm_emit_movpair (operands[0], operands[1]);
4930 DONE;
4931 }
cffb2a26 4932 }
25f905c2 4933 else /* TARGET_THUMB1... */
cffb2a26 4934 {
e1ba4a27 4935 if (can_create_pseudo_p ())
cffb2a26 4936 {
4937 if (GET_CODE (operands[0]) != REG)
4938 operands[1] = force_reg (SImode, operands[1]);
4939 }
9c08d1fa 4940 }
f655717d 4941
e348ff3e 4942 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
4943 {
4944 split_const (operands[1], &base, &offset);
4945 if (GET_CODE (base) == SYMBOL_REF
4946 && !offset_within_block_p (base, INTVAL (offset)))
4947 {
b308ddcf 4948 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 4949 emit_move_insn (tmp, base);
4950 emit_insn (gen_addsi3 (operands[0], tmp, offset));
4951 DONE;
4952 }
4953 }
4954
f655717d 4955 /* Recognize the case where operand[1] is a reference to thread-local
4956 data and load its address to a register. */
4957 if (arm_tls_referenced_p (operands[1]))
4958 {
4959 rtx tmp = operands[1];
4960 rtx addend = NULL;
4961
4962 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4963 {
4964 addend = XEXP (XEXP (tmp, 0), 1);
4965 tmp = XEXP (XEXP (tmp, 0), 0);
4966 }
4967
4968 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4969 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4970
e1ba4a27 4971 tmp = legitimize_tls_address (tmp,
4972 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 4973 if (addend)
4974 {
4975 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4976 tmp = force_operand (tmp, operands[0]);
4977 }
4978 operands[1] = tmp;
4979 }
4980 else if (flag_pic
4981 && (CONSTANT_P (operands[1])
4982 || symbol_mentioned_p (operands[1])
4983 || label_mentioned_p (operands[1])))
4984 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 4985 (!can_create_pseudo_p ()
4986 ? operands[0]
4987 : 0));
befb0bac 4988 }
215b30b3 4989 "
4990)
9c08d1fa 4991
d0e6a121 4992;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
4993;; LO_SUM adds in the high bits. Fortunately these are opaque operations
4994;; so this does not matter.
4995(define_insn "*arm_movt"
4996 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
4997 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
4998 (match_operand:SI 2 "general_operand" "i")))]
4999 "TARGET_32BIT"
5000 "movt%?\t%0, #:upper16:%c2"
5001 [(set_attr "predicable" "yes")
5002 (set_attr "length" "4")]
5003)
5004
5005(define_insn "*arm_movw"
5006 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5007 (high:SI (match_operand:SI 1 "general_operand" "i")))]
5008 "TARGET_32BIT"
5009 "movw%?\t%0, #:lower16:%c1"
5010 [(set_attr "predicable" "yes")
5011 (set_attr "length" "4")]
5012)
5013
cffb2a26 5014(define_insn "*arm_movsi_insn"
aaa37ad6 5015 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5016 (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk"))]
755eb2b4 5017 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5018 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5019 && ( register_operand (operands[0], SImode)
5020 || register_operand (operands[1], SImode))"
f7fbdd4a 5021 "@
aaa37ad6 5022 mov%?\\t%0, %1
f7fbdd4a 5023 mov%?\\t%0, %1
5024 mvn%?\\t%0, #%B1
25f905c2 5025 movw%?\\t%0, %1
f7fbdd4a 5026 ldr%?\\t%0, %1
5027 str%?\\t%1, %0"
aaa37ad6 5028 [(set_attr "type" "*,*,*,*,load1,store1")
0d66636f 5029 (set_attr "predicable" "yes")
aaa37ad6 5030 (set_attr "pool_range" "*,*,*,*,4096,*")
5031 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5032)
87b22bf7 5033
5034(define_split
a2cd141b 5035 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5036 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5037 "TARGET_32BIT
215b30b3 5038 && (!(const_ok_for_arm (INTVAL (operands[1]))
5039 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5040 [(clobber (const_int 0))]
5041 "
96f57e36 5042 arm_split_constant (SET, SImode, NULL_RTX,
5043 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5044 DONE;
215b30b3 5045 "
5046)
9c08d1fa 5047
25f905c2 5048(define_insn "*thumb1_movsi_insn"
aaa37ad6 5049 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5050 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
25f905c2 5051 "TARGET_THUMB1
cffb2a26 5052 && ( register_operand (operands[0], SImode)
5053 || register_operand (operands[1], SImode))"
5054 "@
5055 mov %0, %1
5056 mov %0, %1
5057 #
5058 #
5059 ldmia\\t%1, {%0}
5060 stmia\\t%0, {%1}
5061 ldr\\t%0, %1
5062 str\\t%1, %0
5063 mov\\t%0, %1"
5064 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5065 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 5066 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5067)
5068
5069(define_split
5070 [(set (match_operand:SI 0 "register_operand" "")
5071 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5072 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
cffb2a26 5073 [(set (match_dup 0) (match_dup 1))
5074 (set (match_dup 0) (neg:SI (match_dup 0)))]
5075 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5076)
5077
5078(define_split
5079 [(set (match_operand:SI 0 "register_operand" "")
5080 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5081 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
cffb2a26 5082 [(set (match_dup 0) (match_dup 1))
5083 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5084 "
5085 {
5086 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
5087 unsigned HOST_WIDE_INT mask = 0xff;
5088 int i;
5089
5090 for (i = 0; i < 25; i++)
5091 if ((val & (mask << i)) == val)
5092 break;
5093
f5b3169c 5094 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 5095 if (i == 0)
5096 FAIL;
5097
5098 operands[1] = GEN_INT (val >> i);
5099 operands[2] = GEN_INT (i);
5100 }"
5101)
5102
67336bcf 5103;; When generating pic, we need to load the symbol offset into a register.
5104;; So that the optimizer does not confuse this with a normal symbol load
5105;; we use an unspec. The offset will be loaded from a constant pool entry,
5106;; since that is the only type of relocation we can use.
5107
5108;; The rather odd constraints on the following are to force reload to leave
5109;; the insn alone, and to force the minipool generation pass to then move
5110;; the GOT symbol to memory.
849170fd 5111
8c4d8060 5112(define_insn "pic_load_addr_arm"
849170fd 5113 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5114 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 5115 "TARGET_ARM && flag_pic"
67336bcf 5116 "ldr%?\\t%0, %1"
a2cd141b 5117 [(set_attr "type" "load1")
8c4d8060 5118 (set (attr "pool_range") (const_int 4096))
5119 (set (attr "neg_pool_range") (const_int 4084))]
5120)
5121
25f905c2 5122(define_insn "pic_load_addr_thumb1"
8c4d8060 5123 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5124 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5125 "TARGET_THUMB1 && flag_pic"
8c4d8060 5126 "ldr\\t%0, %1"
a2cd141b 5127 [(set_attr "type" "load1")
8c4d8060 5128 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5129)
849170fd 5130
cffb2a26 5131(define_insn "pic_add_dot_plus_four"
15d5d060 5132 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5133 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5134 (const_int 4)
beef0fb5 5135 (match_operand 2 "" "")]
5136 UNSPEC_PIC_BASE))]
25f905c2 5137 "TARGET_THUMB1"
cffb2a26 5138 "*
6cdcb15c 5139 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5140 INTVAL (operands[2]));
cffb2a26 5141 return \"add\\t%0, %|pc\";
5142 "
5143 [(set_attr "length" "2")]
5144)
849170fd 5145
5146(define_insn "pic_add_dot_plus_eight"
15d5d060 5147 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5148 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5149 (const_int 8)
beef0fb5 5150 (match_operand 2 "" "")]
5151 UNSPEC_PIC_BASE))]
f655717d 5152 "TARGET_ARM"
c4034607 5153 "*
6cdcb15c 5154 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5155 INTVAL (operands[2]));
15d5d060 5156 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5157 "
0d66636f 5158 [(set_attr "predicable" "yes")]
cffb2a26 5159)
849170fd 5160
f655717d 5161(define_insn "tls_load_dot_plus_eight"
5162 [(set (match_operand:SI 0 "register_operand" "+r")
c0c1fba5 5163 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5164 (const_int 8)
beef0fb5 5165 (match_operand 2 "" "")]
5166 UNSPEC_PIC_BASE)))]
f655717d 5167 "TARGET_ARM"
5168 "*
6cdcb15c 5169 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5170 INTVAL (operands[2]));
f655717d 5171 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5172 "
5173 [(set_attr "predicable" "yes")]
5174)
5175
5176;; PIC references to local variables can generate pic_add_dot_plus_eight
5177;; followed by a load. These sequences can be crunched down to
5178;; tls_load_dot_plus_eight by a peephole.
5179
5180(define_peephole2
c0c1fba5 5181 [(set (match_operand:SI 0 "register_operand" "")
5182 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5183 (const_int 8)
5184 (match_operand 1 "" "")]
5185 UNSPEC_PIC_BASE))
f655717d 5186 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5187 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5188 [(set (match_dup 2)
5189 (mem:SI (unspec:SI [(match_dup 3)
5190 (const_int 8)
5191 (match_dup 1)]
5192 UNSPEC_PIC_BASE)))]
f655717d 5193 ""
5194)
5195
bac7fc85 5196(define_insn "pic_offset_arm"
5197 [(set (match_operand:SI 0 "register_operand" "=r")
5198 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5199 (unspec:SI [(match_operand:SI 2 "" "X")]
5200 UNSPEC_PIC_OFFSET))))]
5201 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5202 "ldr%?\\t%0, [%1,%2]"
5203 [(set_attr "type" "load1")]
5204)
5205
95373f08 5206(define_expand "builtin_setjmp_receiver"
5207 [(label_ref (match_operand 0 "" ""))]
5208 "flag_pic"
5209 "
5210{
b935b306 5211 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5212 register. */
2cb7d577 5213 if (arm_pic_register != INVALID_REGNUM)
5214 arm_load_pic_register (1UL << 3);
95373f08 5215 DONE;
5216}")
5217
9c08d1fa 5218;; If copying one reg to another we can set the condition codes according to
5219;; its value. Such a move is common after a return from subroutine and the
5220;; result is being tested against zero.
5221
f7fbdd4a 5222(define_insn "*movsi_compare0"
bd5b4116 5223 [(set (reg:CC CC_REGNUM)
cffb2a26 5224 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5225 (const_int 0)))
5226 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5227 (match_dup 1))]
25f905c2 5228 "TARGET_32BIT"
e2348bcb 5229 "@
40dbec34 5230 cmp%?\\t%0, #0
25f905c2 5231 sub%.\\t%0, %1, #0"
cffb2a26 5232 [(set_attr "conds" "set")]
5233)
b11cae9e 5234
b11cae9e 5235;; Subroutine to store a half word from a register into memory.
5236;; Operand 0 is the source register (HImode)
c8f69309 5237;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5238
9c08d1fa 5239;; In both this routine and the next, we must be careful not to spill
01cc3b75 5240;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5241;; can generate unrecognizable rtl.
5242
b11cae9e 5243(define_expand "storehi"
c8f69309 5244 [;; store the low byte
f082f1c4 5245 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5246 ;; extract the high byte
c8f69309 5247 (set (match_dup 2)
5248 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5249 ;; store the high byte
787f8210 5250 (set (match_dup 4) (match_dup 5))]
cffb2a26 5251 "TARGET_ARM"
b11cae9e 5252 "
215b30b3 5253 {
537ffcfc 5254 rtx op1 = operands[1];
5255 rtx addr = XEXP (op1, 0);
215b30b3 5256 enum rtx_code code = GET_CODE (addr);
5257
5258 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5259 || code == MINUS)
537ffcfc 5260 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5261
537ffcfc 5262 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5263 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5264 operands[3] = gen_lowpart (QImode, operands[0]);
5265 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5266 operands[2] = gen_reg_rtx (SImode);
5267 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5268 }"
5269)
b11cae9e 5270
c7597b5d 5271(define_expand "storehi_bigend"
f082f1c4 5272 [(set (match_dup 4) (match_dup 3))
c7597b5d 5273 (set (match_dup 2)
5274 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5275 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5276 "TARGET_ARM"
b11cae9e 5277 "
215b30b3 5278 {
537ffcfc 5279 rtx op1 = operands[1];
5280 rtx addr = XEXP (op1, 0);
215b30b3 5281 enum rtx_code code = GET_CODE (addr);
5282
5283 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5284 || code == MINUS)
537ffcfc 5285 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5286
537ffcfc 5287 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5288 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5289 operands[3] = gen_lowpart (QImode, operands[0]);
5290 operands[0] = gen_lowpart (SImode, operands[0]);
5291 operands[2] = gen_reg_rtx (SImode);
787f8210 5292 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5293 }"
5294)
c7597b5d 5295
5296;; Subroutine to store a half word integer constant into memory.
5297(define_expand "storeinthi"
f082f1c4 5298 [(set (match_operand 0 "" "")
787f8210 5299 (match_operand 1 "" ""))
9e8503e6 5300 (set (match_dup 3) (match_dup 2))]
cffb2a26 5301 "TARGET_ARM"
c7597b5d 5302 "
215b30b3 5303 {
5304 HOST_WIDE_INT value = INTVAL (operands[1]);
5305 rtx addr = XEXP (operands[0], 0);
537ffcfc 5306 rtx op0 = operands[0];
215b30b3 5307 enum rtx_code code = GET_CODE (addr);
c7597b5d 5308
215b30b3 5309 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5310 || code == MINUS)
537ffcfc 5311 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5312
215b30b3 5313 operands[1] = gen_reg_rtx (SImode);
5314 if (BYTES_BIG_ENDIAN)
5315 {
5316 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5317 if ((value & 255) == ((value >> 8) & 255))
5318 operands[2] = operands[1];
5319 else
5320 {
5321 operands[2] = gen_reg_rtx (SImode);
5322 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5323 }
5324 }
5325 else
5326 {
5327 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5328 if ((value & 255) == ((value >> 8) & 255))
5329 operands[2] = operands[1];
5330 else
5331 {
5332 operands[2] = gen_reg_rtx (SImode);
5333 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5334 }
5335 }
c7597b5d 5336
537ffcfc 5337 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5338 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5339 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5340 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5341 }"
5342)
b11cae9e 5343
f7fbdd4a 5344(define_expand "storehi_single_op"
5345 [(set (match_operand:HI 0 "memory_operand" "")
5346 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5347 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5348 "
215b30b3 5349 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5350 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5351 "
5352)
f7fbdd4a 5353
b11cae9e 5354(define_expand "movhi"
5355 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5356 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5357 "TARGET_EITHER"
b11cae9e 5358 "
cffb2a26 5359 if (TARGET_ARM)
b11cae9e 5360 {
e1ba4a27 5361 if (can_create_pseudo_p ())
cffb2a26 5362 {
5363 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5364 {
cffb2a26 5365 if (arm_arch4)
5366 {
5367 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5368 DONE;
5369 }
5370 if (GET_CODE (operands[1]) == CONST_INT)
5371 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5372 else
cffb2a26 5373 {
5374 if (GET_CODE (operands[1]) == MEM)
5375 operands[1] = force_reg (HImode, operands[1]);
5376 if (BYTES_BIG_ENDIAN)
5377 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5378 else
5379 emit_insn (gen_storehi (operands[1], operands[0]));
5380 }
5381 DONE;
b11cae9e 5382 }
cffb2a26 5383 /* Sign extend a constant, and keep it in an SImode reg. */
5384 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5385 {
cffb2a26 5386 rtx reg = gen_reg_rtx (SImode);
5387 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5388
5389 /* If the constant is already valid, leave it alone. */
215b30b3 5390 if (!const_ok_for_arm (val))
cffb2a26 5391 {
5392 /* If setting all the top bits will make the constant
5393 loadable in a single instruction, then set them.
5394 Otherwise, sign extend the number. */
5395
215b30b3 5396 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5397 val |= ~0xffff;
5398 else if (val & 0x8000)
5399 val |= ~0xffff;
5400 }
5401
5402 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5403 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5404 }
e1ba4a27 5405 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5406 && GET_CODE (operands[1]) == MEM)
5407 {
5408 rtx reg = gen_reg_rtx (SImode);
5409
5410 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5411 operands[1] = gen_lowpart (HImode, reg);
5412 }
215b30b3 5413 else if (!arm_arch4)
f7fbdd4a 5414 {
cffb2a26 5415 if (GET_CODE (operands[1]) == MEM)
5416 {
c1a66faf 5417 rtx base;
5418 rtx offset = const0_rtx;
5419 rtx reg = gen_reg_rtx (SImode);
5420
5421 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5422 || (GET_CODE (base) == PLUS
5423 && (GET_CODE (offset = XEXP (base, 1))
5424 == CONST_INT)
5425 && ((INTVAL(offset) & 1) != 1)
5426 && GET_CODE (base = XEXP (base, 0)) == REG))
5427 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5428 {
8deb3959 5429 rtx new_rtx;
c1a66faf 5430
8deb3959 5431 new_rtx = widen_memory_access (operands[1], SImode,
5432 ((INTVAL (offset) & ~3)
5433 - INTVAL (offset)));
5434 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5435 if (((INTVAL (offset) & 2) != 0)
5436 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5437 {
5438 rtx reg2 = gen_reg_rtx (SImode);
5439
5440 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5441 reg = reg2;
5442 }
206ee9a2 5443 }
c1a66faf 5444 else
5445 emit_insn (gen_movhi_bytes (reg, operands[1]));
5446
5447 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5448 }
5449 }
5450 }
674a8f0b 5451 /* Handle loading a large integer during reload. */
cffb2a26 5452 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5453 && !const_ok_for_arm (INTVAL (operands[1]))
5454 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5455 {
5456 /* Writing a constant to memory needs a scratch, which should
5457 be handled with SECONDARY_RELOADs. */
ed29c566 5458 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5459
5460 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5461 emit_insn (gen_movsi (operands[0], operands[1]));
5462 DONE;
5463 }
5464 }
25f905c2 5465 else if (TARGET_THUMB2)
5466 {
5467 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5468 if (can_create_pseudo_p ())
25f905c2 5469 {
5470 if (GET_CODE (operands[0]) != REG)
5471 operands[1] = force_reg (HImode, operands[1]);
5472 /* Zero extend a constant, and keep it in an SImode reg. */
5473 else if (GET_CODE (operands[1]) == CONST_INT)
5474 {
5475 rtx reg = gen_reg_rtx (SImode);
5476 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5477
5478 emit_insn (gen_movsi (reg, GEN_INT (val)));
5479 operands[1] = gen_lowpart (HImode, reg);
5480 }
5481 }
5482 }
5483 else /* TARGET_THUMB1 */
cffb2a26 5484 {
e1ba4a27 5485 if (can_create_pseudo_p ())
cffb2a26 5486 {
6cffc037 5487 if (GET_CODE (operands[1]) == CONST_INT)
5488 {
5489 rtx reg = gen_reg_rtx (SImode);
5490
5491 emit_insn (gen_movsi (reg, operands[1]));
5492 operands[1] = gen_lowpart (HImode, reg);
5493 }
cffb2a26 5494
5495 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5496 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5497 virtual register (also rejected as illegitimate for HImode/QImode)
5498 relative address. */
cffb2a26 5499 /* ??? This should perhaps be fixed elsewhere, for instance, in
5500 fixup_stack_1, by checking for other kinds of invalid addresses,
5501 e.g. a bare reference to a virtual register. This may confuse the
5502 alpha though, which must handle this case differently. */
5503 if (GET_CODE (operands[0]) == MEM
215b30b3 5504 && !memory_address_p (GET_MODE (operands[0]),
5505 XEXP (operands[0], 0)))
537ffcfc 5506 operands[0]
5507 = replace_equiv_address (operands[0],
5508 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5509
5510 if (GET_CODE (operands[1]) == MEM
215b30b3 5511 && !memory_address_p (GET_MODE (operands[1]),
5512 XEXP (operands[1], 0)))
537ffcfc 5513 operands[1]
5514 = replace_equiv_address (operands[1],
5515 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5516
5517 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5518 {
5519 rtx reg = gen_reg_rtx (SImode);
5520
5521 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5522 operands[1] = gen_lowpart (HImode, reg);
5523 }
5524
5525 if (GET_CODE (operands[0]) == MEM)
5526 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5527 }
cffb2a26 5528 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5529 && !satisfies_constraint_I (operands[1]))
cffb2a26 5530 {
6cffc037 5531 /* Handle loading a large integer during reload. */
5532
cffb2a26 5533 /* Writing a constant to memory needs a scratch, which should
5534 be handled with SECONDARY_RELOADs. */
ed29c566 5535 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5536
1a83b3ff 5537 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5538 emit_insn (gen_movsi (operands[0], operands[1]));
5539 DONE;
5540 }
b11cae9e 5541 }
cffb2a26 5542 "
5543)
5544
25f905c2 5545(define_insn "*thumb1_movhi_insn"
a941568e 5546 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5547 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5548 "TARGET_THUMB1
cffb2a26 5549 && ( register_operand (operands[0], HImode)
5550 || register_operand (operands[1], HImode))"
5551 "*
5552 switch (which_alternative)
d79300ac 5553 {
cffb2a26 5554 case 0: return \"add %0, %1, #0\";
5555 case 2: return \"strh %1, %0\";
5556 case 3: return \"mov %0, %1\";
5557 case 4: return \"mov %0, %1\";
5558 case 5: return \"mov %0, %1\";
ed29c566 5559 default: gcc_unreachable ();
cffb2a26 5560 case 1:
5561 /* The stack pointer can end up being taken as an index register.
5562 Catch this case here and deal with it. */
5563 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5564 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5565 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5566 {
5567 rtx ops[2];
5568 ops[0] = operands[0];
5569 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5570
5571 output_asm_insn (\"mov %0, %1\", ops);
5572
5573 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5574
5575 }
5576 return \"ldrh %0, %1\";
5577 }"
5578 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 5579 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 5580)
d79300ac 5581
b11cae9e 5582
25f7a26e 5583(define_expand "movhi_bytes"
eab14235 5584 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5585 (set (match_dup 3)
eab14235 5586 (zero_extend:SI (match_dup 6)))
25f7a26e 5587 (set (match_operand:SI 0 "" "")
5588 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5589 "TARGET_ARM"
25f7a26e 5590 "
215b30b3 5591 {
5592 rtx mem1, mem2;
5593 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5594
788fcce0 5595 mem1 = change_address (operands[1], QImode, addr);
5596 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5597 operands[0] = gen_lowpart (SImode, operands[0]);
5598 operands[1] = mem1;
5599 operands[2] = gen_reg_rtx (SImode);
5600 operands[3] = gen_reg_rtx (SImode);
5601 operands[6] = mem2;
25f7a26e 5602
215b30b3 5603 if (BYTES_BIG_ENDIAN)
5604 {
5605 operands[4] = operands[2];
5606 operands[5] = operands[3];
5607 }
5608 else
5609 {
5610 operands[4] = operands[3];
5611 operands[5] = operands[2];
5612 }
5613 }"
5614)
25f7a26e 5615
c7597b5d 5616(define_expand "movhi_bigend"
5617 [(set (match_dup 2)
5618 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5619 (const_int 16)))
5620 (set (match_dup 3)
5621 (ashiftrt:SI (match_dup 2) (const_int 16)))
5622 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5623 (match_dup 4))]
cffb2a26 5624 "TARGET_ARM"
c7597b5d 5625 "
5626 operands[2] = gen_reg_rtx (SImode);
5627 operands[3] = gen_reg_rtx (SImode);
787f8210 5628 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5629 "
5630)
b11cae9e 5631
a2f10574 5632;; Pattern to recognize insn generated default case above
f7fbdd4a 5633(define_insn "*movhi_insn_arch4"
cffb2a26 5634 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5635 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5636 "TARGET_ARM
5637 && arm_arch4
f7fbdd4a 5638 && (GET_CODE (operands[1]) != CONST_INT
5639 || const_ok_for_arm (INTVAL (operands[1]))
5640 || const_ok_for_arm (~INTVAL (operands[1])))"
5641 "@
5642 mov%?\\t%0, %1\\t%@ movhi
5643 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5644 str%(h%)\\t%1, %0\\t%@ movhi
5645 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5646 [(set_attr "type" "*,*,store1,load1")
0d66636f 5647 (set_attr "predicable" "yes")
cffb2a26 5648 (set_attr "pool_range" "*,*,*,256")
5649 (set_attr "neg_pool_range" "*,*,*,244")]
5650)
f7fbdd4a 5651
f7fbdd4a 5652(define_insn "*movhi_bytes"
25f7a26e 5653 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5654 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5655 "TARGET_ARM"
25f7a26e 5656 "@
5657 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5658 mvn%?\\t%0, #%B1\\t%@ movhi"
5659 [(set_attr "predicable" "yes")]
5660)
25f7a26e 5661
f90b51f1 5662(define_expand "thumb_movhi_clobber"
5663 [(set (match_operand:HI 0 "memory_operand" "")
5664 (match_operand:HI 1 "register_operand" ""))
5665 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5666 "TARGET_THUMB1"
f90b51f1 5667 "
5668 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5669 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5670 {
5671 emit_insn (gen_movhi (operands[0], operands[1]));
5672 DONE;
5673 }
5674 /* XXX Fixme, need to handle other cases here as well. */
5675 gcc_unreachable ();
5676 "
cffb2a26 5677)
5678
bc5c7e08 5679;; We use a DImode scratch because we may occasionally need an additional
5680;; temporary if the address isn't offsettable -- push_reload doesn't seem
5681;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5682(define_expand "reload_outhi"
cffb2a26 5683 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5684 (match_operand:HI 1 "s_register_operand" "r")
5685 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5686 "TARGET_EITHER"
5687 "if (TARGET_ARM)
5688 arm_reload_out_hi (operands);
5689 else
5690 thumb_reload_out_hi (operands);
d3373b54 5691 DONE;
cffb2a26 5692 "
5693)
d3373b54 5694
25f7a26e 5695(define_expand "reload_inhi"
5696 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5697 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5698 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5699 "TARGET_EITHER"
25f7a26e 5700 "
cffb2a26 5701 if (TARGET_ARM)
5702 arm_reload_in_hi (operands);
5703 else
5704 thumb_reload_out_hi (operands);
25f7a26e 5705 DONE;
5706")
5707
9c08d1fa 5708(define_expand "movqi"
5709 [(set (match_operand:QI 0 "general_operand" "")
5710 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5711 "TARGET_EITHER"
9c08d1fa 5712 "
6cffc037 5713 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5714
e1ba4a27 5715 if (can_create_pseudo_p ())
cffb2a26 5716 {
6cffc037 5717 if (GET_CODE (operands[1]) == CONST_INT)
5718 {
5719 rtx reg = gen_reg_rtx (SImode);
5720
5721 emit_insn (gen_movsi (reg, operands[1]));
5722 operands[1] = gen_lowpart (QImode, reg);
5723 }
cffb2a26 5724
6cffc037 5725 if (TARGET_THUMB)
5726 {
cffb2a26 5727 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5728 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5729 virtual register (also rejected as illegitimate for HImode/QImode)
5730 relative address. */
cffb2a26 5731 /* ??? This should perhaps be fixed elsewhere, for instance, in
5732 fixup_stack_1, by checking for other kinds of invalid addresses,
5733 e.g. a bare reference to a virtual register. This may confuse the
5734 alpha though, which must handle this case differently. */
5735 if (GET_CODE (operands[0]) == MEM
215b30b3 5736 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5737 XEXP (operands[0], 0)))
537ffcfc 5738 operands[0]
5739 = replace_equiv_address (operands[0],
5740 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5741 if (GET_CODE (operands[1]) == MEM
5742 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5743 XEXP (operands[1], 0)))
537ffcfc 5744 operands[1]
5745 = replace_equiv_address (operands[1],
5746 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5747 }
5748
5749 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5750 {
5751 rtx reg = gen_reg_rtx (SImode);
5752
5753 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5754 operands[1] = gen_lowpart (QImode, reg);
5755 }
5756
5757 if (GET_CODE (operands[0]) == MEM)
5758 operands[1] = force_reg (QImode, operands[1]);
5759 }
5760 else if (TARGET_THUMB
5761 && GET_CODE (operands[1]) == CONST_INT
234f6557 5762 && !satisfies_constraint_I (operands[1]))
6cffc037 5763 {
674a8f0b 5764 /* Handle loading a large integer during reload. */
cffb2a26 5765
6cffc037 5766 /* Writing a constant to memory needs a scratch, which should
5767 be handled with SECONDARY_RELOADs. */
5768 gcc_assert (GET_CODE (operands[0]) == REG);
5769
5770 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5771 emit_insn (gen_movsi (operands[0], operands[1]));
5772 DONE;
cffb2a26 5773 }
5774 "
5775)
b11cae9e 5776
9c08d1fa 5777
cffb2a26 5778(define_insn "*arm_movqi_insn"
5779 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5780 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5781 "TARGET_32BIT
cffb2a26 5782 && ( register_operand (operands[0], QImode)
5783 || register_operand (operands[1], QImode))"
5565501b 5784 "@
5785 mov%?\\t%0, %1
5786 mvn%?\\t%0, #%B1
25f905c2 5787 ldr%(b%)\\t%0, %1
5788 str%(b%)\\t%1, %0"
a2cd141b 5789 [(set_attr "type" "*,*,load1,store1")
0d66636f 5790 (set_attr "predicable" "yes")]
cffb2a26 5791)
5792
25f905c2 5793(define_insn "*thumb1_movqi_insn"
cffb2a26 5794 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5795 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5796 "TARGET_THUMB1
cffb2a26 5797 && ( register_operand (operands[0], QImode)
5798 || register_operand (operands[1], QImode))"
5799 "@
5800 add\\t%0, %1, #0
5801 ldrb\\t%0, %1
5802 strb\\t%1, %0
5803 mov\\t%0, %1
5804 mov\\t%0, %1
5805 mov\\t%0, %1"
5806 [(set_attr "length" "2")
a2cd141b 5807 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5808 (set_attr "pool_range" "*,32,*,*,*,*")]
5809)
b11cae9e 5810
87b22bf7 5811(define_expand "movsf"
5812 [(set (match_operand:SF 0 "general_operand" "")
5813 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5814 "TARGET_EITHER"
87b22bf7 5815 "
25f905c2 5816 if (TARGET_32BIT)
cffb2a26 5817 {
5818 if (GET_CODE (operands[0]) == MEM)
5819 operands[1] = force_reg (SFmode, operands[1]);
5820 }
25f905c2 5821 else /* TARGET_THUMB1 */
cffb2a26 5822 {
e1ba4a27 5823 if (can_create_pseudo_p ())
cffb2a26 5824 {
5825 if (GET_CODE (operands[0]) != REG)
5826 operands[1] = force_reg (SFmode, operands[1]);
5827 }
5828 }
5829 "
5830)
5831
03d440a6 5832;; Transform a floating-point move of a constant into a core register into
5833;; an SImode operation.
cffb2a26 5834(define_split
03d440a6 5835 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 5836 (match_operand:SF 1 "immediate_operand" ""))]
25f905c2 5837 "TARGET_32BIT
cffb2a26 5838 && reload_completed
5839 && GET_CODE (operands[1]) == CONST_DOUBLE"
5840 [(set (match_dup 2) (match_dup 3))]
5841 "
5842 operands[2] = gen_lowpart (SImode, operands[0]);
5843 operands[3] = gen_lowpart (SImode, operands[1]);
5844 if (operands[2] == 0 || operands[3] == 0)
5845 FAIL;
215b30b3 5846 "
5847)
87b22bf7 5848
cffb2a26 5849(define_insn "*arm_movsf_soft_insn"
5850 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5851 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5852 "TARGET_ARM
5853 && TARGET_SOFT_FLOAT
215b30b3 5854 && (GET_CODE (operands[0]) != MEM
5855 || register_operand (operands[1], SFmode))"
9a1112d7 5856 "@
5857 mov%?\\t%0, %1
5858 ldr%?\\t%0, %1\\t%@ float
5859 str%?\\t%1, %0\\t%@ float"
cffb2a26 5860 [(set_attr "length" "4,4,4")
0d66636f 5861 (set_attr "predicable" "yes")
a2cd141b 5862 (set_attr "type" "*,load1,store1")
cffb2a26 5863 (set_attr "pool_range" "*,4096,*")
5864 (set_attr "neg_pool_range" "*,4084,*")]
5865)
5866
5867;;; ??? This should have alternatives for constants.
25f905c2 5868(define_insn "*thumb1_movsf_insn"
215b30b3 5869 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5870 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 5871 "TARGET_THUMB1
cffb2a26 5872 && ( register_operand (operands[0], SFmode)
5873 || register_operand (operands[1], SFmode))"
5874 "@
5875 add\\t%0, %1, #0
5876 ldmia\\t%1, {%0}
5877 stmia\\t%0, {%1}
5878 ldr\\t%0, %1
5879 str\\t%1, %0
5880 mov\\t%0, %1
5881 mov\\t%0, %1"
5882 [(set_attr "length" "2")
a2cd141b 5883 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 5884 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5885)
9a1112d7 5886
9c08d1fa 5887(define_expand "movdf"
87b22bf7 5888 [(set (match_operand:DF 0 "general_operand" "")
5889 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5890 "TARGET_EITHER"
9c08d1fa 5891 "
25f905c2 5892 if (TARGET_32BIT)
cffb2a26 5893 {
5894 if (GET_CODE (operands[0]) == MEM)
5895 operands[1] = force_reg (DFmode, operands[1]);
5896 }
5897 else /* TARGET_THUMB */
5898 {
e1ba4a27 5899 if (can_create_pseudo_p ())
cffb2a26 5900 {
5901 if (GET_CODE (operands[0]) != REG)
5902 operands[1] = force_reg (DFmode, operands[1]);
5903 }
5904 }
5905 "
5906)
b11cae9e 5907
9c08d1fa 5908;; Reloading a df mode value stored in integer regs to memory can require a
5909;; scratch reg.
5910(define_expand "reload_outdf"
cffb2a26 5911 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5912 (match_operand:DF 1 "s_register_operand" "r")
5913 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 5914 "TARGET_32BIT"
87b22bf7 5915 "
215b30b3 5916 {
5917 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5918
215b30b3 5919 if (code == REG)
5920 operands[2] = XEXP (operands[0], 0);
5921 else if (code == POST_INC || code == PRE_DEC)
5922 {
5923 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5924 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5925 emit_insn (gen_movdi (operands[0], operands[1]));
5926 DONE;
5927 }
5928 else if (code == PRE_INC)
5929 {
5930 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5931
215b30b3 5932 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5933 operands[2] = reg;
5934 }
5935 else if (code == POST_DEC)
5936 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5937 else
5938 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5939 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5940
788fcce0 5941 emit_insn (gen_rtx_SET (VOIDmode,
5942 replace_equiv_address (operands[0], operands[2]),
215b30b3 5943 operands[1]));
f7fbdd4a 5944
215b30b3 5945 if (code == POST_DEC)
5946 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5947
5948 DONE;
5949 }"
5950)
9c08d1fa 5951
9a1112d7 5952(define_insn "*movdf_soft_insn"
359a6e9f 5953 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5954 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 5955 "TARGET_ARM && TARGET_SOFT_FLOAT
b2778788 5956 && ( register_operand (operands[0], DFmode)
5957 || register_operand (operands[1], DFmode))"
d51f92df 5958 "*
5959 switch (which_alternative)
5960 {
5961 case 0:
5962 case 1:
5963 case 2:
5964 return \"#\";
5965 default:
5966 return output_move_double (operands);
5967 }
5968 "
359a6e9f 5969 [(set_attr "length" "8,12,16,8,8")
5970 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 5971 (set_attr "pool_range" "1020")
5972 (set_attr "neg_pool_range" "1008")]
cffb2a26 5973)
5974
5975;;; ??? This should have alternatives for constants.
5976;;; ??? This was originally identical to the movdi_insn pattern.
5977;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5978;;; thumb_reorg with a memory reference.
5979(define_insn "*thumb_movdf_insn"
215b30b3 5980 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5981 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 5982 "TARGET_THUMB1
cffb2a26 5983 && ( register_operand (operands[0], DFmode)
5984 || register_operand (operands[1], DFmode))"
5985 "*
5986 switch (which_alternative)
5987 {
5988 default:
5989 case 0:
5990 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5991 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5992 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5993 case 1:
5994 return \"ldmia\\t%1, {%0, %H0}\";
5995 case 2:
5996 return \"stmia\\t%0, {%1, %H1}\";
5997 case 3:
5998 return thumb_load_double_from_address (operands);
5999 case 4:
1a83b3ff 6000 operands[2] = gen_rtx_MEM (SImode,
6001 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6002 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6003 return \"\";
6004 case 5:
6005 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6006 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6007 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6008 }
6009 "
6010 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6011 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 6012 (set_attr "pool_range" "*,*,*,1020,*,*")]
6013)
755eb2b4 6014
ccd90aaa 6015(define_expand "movxf"
6016 [(set (match_operand:XF 0 "general_operand" "")
6017 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6018 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6019 "
6020 if (GET_CODE (operands[0]) == MEM)
6021 operands[1] = force_reg (XFmode, operands[1]);
6022 "
6023)
6024
b11cae9e 6025\f
b11cae9e 6026
9c08d1fa 6027;; load- and store-multiple insns
6028;; The arm can load/store any set of registers, provided that they are in
6029;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 6030
9c08d1fa 6031(define_expand "load_multiple"
6032 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6033 (match_operand:SI 1 "" ""))
6034 (use (match_operand:SI 2 "" ""))])]
25f905c2 6035 "TARGET_32BIT"
9580c25f 6036{
6037 HOST_WIDE_INT offset = 0;
6038
bd5b4116 6039 /* Support only fixed point registers. */
9c08d1fa 6040 if (GET_CODE (operands[2]) != CONST_INT
6041 || INTVAL (operands[2]) > 14
6042 || INTVAL (operands[2]) < 2
6043 || GET_CODE (operands[1]) != MEM
6044 || GET_CODE (operands[0]) != REG
bd5b4116 6045 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6046 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6047 FAIL;
6048
6049 operands[3]
f082f1c4 6050 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6051 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 6052 TRUE, FALSE, operands[1], &offset);
6053})
b11cae9e 6054
9c08d1fa 6055;; Load multiple with write-back
6056
2162064c 6057(define_insn "*ldmsi_postinc4"
9c08d1fa 6058 [(match_parallel 0 "load_multiple_operation"
13e9316a 6059 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6060 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6061 (const_int 16)))
6062 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6063 (mem:SI (match_dup 2)))
a0a72ac3 6064 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 6065 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6066 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6067 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6068 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6069 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6070 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6071 "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
a2cd141b 6072 [(set_attr "type" "load4")
2162064c 6073 (set_attr "predicable" "yes")]
6074)
b11cae9e 6075
25f905c2 6076(define_insn "*ldmsi_postinc4_thumb1"
ccd90aaa 6077 [(match_parallel 0 "load_multiple_operation"
6078 [(set (match_operand:SI 1 "s_register_operand" "=l")
6079 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6080 (const_int 16)))
6081 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6082 (mem:SI (match_dup 2)))
6083 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6084 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6085 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6086 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6087 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6088 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6089 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6090 "ldmia\\t%1!, {%3, %4, %5, %6}"
6091 [(set_attr "type" "load4")]
6092)
6093
2162064c 6094(define_insn "*ldmsi_postinc3"
6095 [(match_parallel 0 "load_multiple_operation"
13e9316a 6096 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6097 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6098 (const_int 12)))
6099 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6100 (mem:SI (match_dup 2)))
6101 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6102 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6103 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6104 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
25f905c2 6105 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6106 "ldm%(ia%)\\t%1!, {%3, %4, %5}"
a2cd141b 6107 [(set_attr "type" "load3")
2162064c 6108 (set_attr "predicable" "yes")]
6109)
b11cae9e 6110
2162064c 6111(define_insn "*ldmsi_postinc2"
6112 [(match_parallel 0 "load_multiple_operation"
13e9316a 6113 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6114 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6115 (const_int 8)))
6116 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6117 (mem:SI (match_dup 2)))
6118 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6119 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
25f905c2 6120 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6121 "ldm%(ia%)\\t%1!, {%3, %4}"
a2cd141b 6122 [(set_attr "type" "load2")
0d66636f 6123 (set_attr "predicable" "yes")]
6124)
b11cae9e 6125
9c08d1fa 6126;; Ordinary load multiple
b11cae9e 6127
2162064c 6128(define_insn "*ldmsi4"
9c08d1fa 6129 [(match_parallel 0 "load_multiple_operation"
2162064c 6130 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6131 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6132 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6133 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6134 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6135 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6136 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6137 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
25f905c2 6138 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6139 "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
a2cd141b 6140 [(set_attr "type" "load4")
2162064c 6141 (set_attr "predicable" "yes")]
6142)
9c08d1fa 6143
2162064c 6144(define_insn "*ldmsi3"
6145 [(match_parallel 0 "load_multiple_operation"
6146 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6147 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6148 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6149 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6150 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6151 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
25f905c2 6152 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6153 "ldm%(ia%)\\t%1, {%2, %3, %4}"
a2cd141b 6154 [(set_attr "type" "load3")
2162064c 6155 (set_attr "predicable" "yes")]
6156)
9c08d1fa 6157
2162064c 6158(define_insn "*ldmsi2"
6159 [(match_parallel 0 "load_multiple_operation"
6160 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6161 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6162 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6163 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
25f905c2 6164 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6165 "ldm%(ia%)\\t%1, {%2, %3}"
a2cd141b 6166 [(set_attr "type" "load2")
0d66636f 6167 (set_attr "predicable" "yes")]
6168)
9c08d1fa 6169
6170(define_expand "store_multiple"
6171 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6172 (match_operand:SI 1 "" ""))
6173 (use (match_operand:SI 2 "" ""))])]
25f905c2 6174 "TARGET_32BIT"
9580c25f 6175{
6176 HOST_WIDE_INT offset = 0;
6177
674a8f0b 6178 /* Support only fixed point registers. */
9c08d1fa 6179 if (GET_CODE (operands[2]) != CONST_INT
6180 || INTVAL (operands[2]) > 14
6181 || INTVAL (operands[2]) < 2
6182 || GET_CODE (operands[1]) != REG
6183 || GET_CODE (operands[0]) != MEM
bd5b4116 6184 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6185 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6186 FAIL;
6187
6188 operands[3]
f082f1c4 6189 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6190 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 6191 TRUE, FALSE, operands[0], &offset);
6192})
b11cae9e 6193
9c08d1fa 6194;; Store multiple with write-back
6195
2162064c 6196(define_insn "*stmsi_postinc4"
9c08d1fa 6197 [(match_parallel 0 "store_multiple_operation"
13e9316a 6198 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6199 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6200 (const_int 16)))
a0a72ac3 6201 (set (mem:SI (match_dup 2))
2162064c 6202 (match_operand:SI 3 "arm_hard_register_operand" ""))
6203 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6204 (match_operand:SI 4 "arm_hard_register_operand" ""))
6205 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6206 (match_operand:SI 5 "arm_hard_register_operand" ""))
6207 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6208 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6209 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6210 "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
2162064c 6211 [(set_attr "predicable" "yes")
6212 (set_attr "type" "store4")]
6213)
b11cae9e 6214
25f905c2 6215(define_insn "*stmsi_postinc4_thumb1"
ccd90aaa 6216 [(match_parallel 0 "store_multiple_operation"
6217 [(set (match_operand:SI 1 "s_register_operand" "=l")
6218 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6219 (const_int 16)))
6220 (set (mem:SI (match_dup 2))
6221 (match_operand:SI 3 "arm_hard_register_operand" ""))
6222 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6223 (match_operand:SI 4 "arm_hard_register_operand" ""))
6224 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6225 (match_operand:SI 5 "arm_hard_register_operand" ""))
6226 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6227 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6228 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6229 "stmia\\t%1!, {%3, %4, %5, %6}"
6230 [(set_attr "type" "store4")]
6231)
6232
2162064c 6233(define_insn "*stmsi_postinc3"
6234 [(match_parallel 0 "store_multiple_operation"
13e9316a 6235 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6236 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6237 (const_int 12)))
6238 (set (mem:SI (match_dup 2))
6239 (match_operand:SI 3 "arm_hard_register_operand" ""))
6240 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6241 (match_operand:SI 4 "arm_hard_register_operand" ""))
6242 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6243 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6244 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6245 "stm%(ia%)\\t%1!, {%3, %4, %5}"
2162064c 6246 [(set_attr "predicable" "yes")
6247 (set_attr "type" "store3")]
6248)
9c08d1fa 6249
2162064c 6250(define_insn "*stmsi_postinc2"
6251 [(match_parallel 0 "store_multiple_operation"
13e9316a 6252 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6253 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6254 (const_int 8)))
6255 (set (mem:SI (match_dup 2))
6256 (match_operand:SI 3 "arm_hard_register_operand" ""))
6257 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6258 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6259 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6260 "stm%(ia%)\\t%1!, {%3, %4}"
0d66636f 6261 [(set_attr "predicable" "yes")
2162064c 6262 (set_attr "type" "store2")]
cffb2a26 6263)
9c08d1fa 6264
6265;; Ordinary store multiple
6266
2162064c 6267(define_insn "*stmsi4"
9c08d1fa 6268 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 6269 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 6270 (match_operand:SI 2 "arm_hard_register_operand" ""))
6271 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6272 (match_operand:SI 3 "arm_hard_register_operand" ""))
6273 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6274 (match_operand:SI 4 "arm_hard_register_operand" ""))
6275 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6276 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6277 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6278 "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
2162064c 6279 [(set_attr "predicable" "yes")
6280 (set_attr "type" "store4")]
6281)
9c08d1fa 6282
2162064c 6283(define_insn "*stmsi3"
6284 [(match_parallel 0 "store_multiple_operation"
6285 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6286 (match_operand:SI 2 "arm_hard_register_operand" ""))
6287 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6288 (match_operand:SI 3 "arm_hard_register_operand" ""))
6289 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6290 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6291 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6292 "stm%(ia%)\\t%1, {%2, %3, %4}"
2162064c 6293 [(set_attr "predicable" "yes")
6294 (set_attr "type" "store3")]
6295)
9c08d1fa 6296
2162064c 6297(define_insn "*stmsi2"
6298 [(match_parallel 0 "store_multiple_operation"
6299 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6300 (match_operand:SI 2 "arm_hard_register_operand" ""))
6301 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6302 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
25f905c2 6303 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6304 "stm%(ia%)\\t%1, {%2, %3}"
0d66636f 6305 [(set_attr "predicable" "yes")
2162064c 6306 (set_attr "type" "store2")]
cffb2a26 6307)
9c08d1fa 6308
6309;; Move a block of memory if it is word aligned and MORE than 2 words long.
6310;; We could let this apply for blocks of less than this, but it clobbers so
6311;; many registers that there is then probably a better way.
6312
008c057d 6313(define_expand "movmemqi"
34191dd1 6314 [(match_operand:BLK 0 "general_operand" "")
6315 (match_operand:BLK 1 "general_operand" "")
6316 (match_operand:SI 2 "const_int_operand" "")
6317 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6318 "TARGET_EITHER"
9c08d1fa 6319 "
25f905c2 6320 if (TARGET_32BIT)
cffb2a26 6321 {
008c057d 6322 if (arm_gen_movmemqi (operands))
cffb2a26 6323 DONE;
6324 FAIL;
6325 }
25f905c2 6326 else /* TARGET_THUMB1 */
cffb2a26 6327 {
6328 if ( INTVAL (operands[3]) != 4
6329 || INTVAL (operands[2]) > 48)
6330 FAIL;
6331
008c057d 6332 thumb_expand_movmemqi (operands);
cffb2a26 6333 DONE;
6334 }
6335 "
6336)
6337
2162064c 6338;; Thumb block-move insns
cffb2a26 6339
6340(define_insn "movmem12b"
960f3acf 6341 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6342 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6343 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6344 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6345 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6346 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6347 (set (match_operand:SI 0 "register_operand" "=l")
6348 (plus:SI (match_dup 2) (const_int 12)))
6349 (set (match_operand:SI 1 "register_operand" "=l")
6350 (plus:SI (match_dup 3) (const_int 12)))
6351 (clobber (match_scratch:SI 4 "=&l"))
6352 (clobber (match_scratch:SI 5 "=&l"))
6353 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6354 "TARGET_THUMB1"
cffb2a26 6355 "* return thumb_output_move_mem_multiple (3, operands);"
6356 [(set_attr "length" "4")
215b30b3 6357 ; This isn't entirely accurate... It loads as well, but in terms of
6358 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6359 (set_attr "type" "store3")]
6360)
6361
6362(define_insn "movmem8b"
960f3acf 6363 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6364 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6365 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6366 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6367 (set (match_operand:SI 0 "register_operand" "=l")
6368 (plus:SI (match_dup 2) (const_int 8)))
6369 (set (match_operand:SI 1 "register_operand" "=l")
6370 (plus:SI (match_dup 3) (const_int 8)))
6371 (clobber (match_scratch:SI 4 "=&l"))
6372 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6373 "TARGET_THUMB1"
cffb2a26 6374 "* return thumb_output_move_mem_multiple (2, operands);"
6375 [(set_attr "length" "4")
215b30b3 6376 ; This isn't entirely accurate... It loads as well, but in terms of
6377 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6378 (set_attr "type" "store2")]
6379)
6380
9c08d1fa 6381\f
b11cae9e 6382
341940e8 6383;; Compare & branch insns
8d232dc7 6384;; The range calculations are based as follows:
341940e8 6385;; For forward branches, the address calculation returns the address of
6386;; the next instruction. This is 2 beyond the branch instruction.
6387;; For backward branches, the address calculation returns the address of
6388;; the first instruction in this pattern (cmp). This is 2 before the branch
6389;; instruction for the shortest sequence, and 4 before the branch instruction
6390;; if we have to jump around an unconditional branch.
6391;; To the basic branch range the PC offset must be added (this is +4).
6392;; So for forward branches we have
6393;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6394;; And for backward branches we have
6395;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6396;;
6397;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6398;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6399
aeac46d4 6400(define_expand "cbranchsi4"
6401 [(set (pc) (if_then_else
6402 (match_operator 0 "arm_comparison_operator"
6403 [(match_operand:SI 1 "s_register_operand" "")
6404 (match_operand:SI 2 "nonmemory_operand" "")])
6405 (label_ref (match_operand 3 "" ""))
6406 (pc)))]
74f4459c 6407 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6408 "
74f4459c 6409 if (!TARGET_THUMB1)
6410 {
6411 if (!arm_add_operand (operands[2], SImode))
6412 operands[2] = force_reg (SImode, operands[2]);
6413 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6414 operands[3]));
6415 DONE;
6416 }
25f905c2 6417 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6418 {
6419 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6420 operands[3], operands[0]));
6421 DONE;
6422 }
25f905c2 6423 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6424 operands[2] = force_reg (SImode, operands[2]);
6425 ")
6426
74f4459c 6427(define_expand "cbranchsf4"
6428 [(set (pc) (if_then_else
6429 (match_operator 0 "arm_comparison_operator"
6430 [(match_operand:SF 1 "s_register_operand" "")
6431 (match_operand:SF 2 "arm_float_compare_operand" "")])
6432 (label_ref (match_operand 3 "" ""))
6433 (pc)))]
6434 "TARGET_32BIT && TARGET_HARD_FLOAT"
6435 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6436 operands[3])); DONE;"
6437)
6438
6439(define_expand "cbranchdf4"
6440 [(set (pc) (if_then_else
6441 (match_operator 0 "arm_comparison_operator"
6442 [(match_operand:DF 1 "s_register_operand" "")
6443 (match_operand:DF 2 "arm_float_compare_operand" "")])
6444 (label_ref (match_operand 3 "" ""))
6445 (pc)))]
6446 "TARGET_32BIT && TARGET_HARD_FLOAT"
6447 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6448 operands[3])); DONE;"
6449)
6450
6451;; this uses the Cirrus DI compare instruction
6452(define_expand "cbranchdi4"
6453 [(set (pc) (if_then_else
6454 (match_operator 0 "arm_comparison_operator"
6455 [(match_operand:DI 1 "cirrus_fp_register" "")
6456 (match_operand:DI 2 "cirrus_fp_register" "")])
6457 (label_ref (match_operand 3 "" ""))
6458 (pc)))]
6459 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6460 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6461 operands[3])); DONE;"
6462)
6463
aeac46d4 6464(define_insn "*cbranchsi4_insn"
6465 [(set (pc) (if_then_else
6466 (match_operator 0 "arm_comparison_operator"
6467 [(match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 6468 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6469 (label_ref (match_operand 3 "" ""))
6470 (pc)))]
25f905c2 6471 "TARGET_THUMB1"
cffb2a26 6472 "*
6473 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 6474
cffb2a26 6475 switch (get_attr_length (insn))
6476 {
6477 case 4: return \"b%d0\\t%l3\";
6478 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6479 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6480 }
6481 "
6482 [(set (attr "far_jump")
6483 (if_then_else
6484 (eq_attr "length" "8")
6485 (const_string "yes")
6486 (const_string "no")))
6487 (set (attr "length")
6488 (if_then_else
6489 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6490 (le (minus (match_dup 3) (pc)) (const_int 256)))
6491 (const_int 4)
6492 (if_then_else
6493 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6494 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6495 (const_int 6)
6496 (const_int 8))))]
6497)
6498
aeac46d4 6499(define_insn "cbranchsi4_scratch"
6500 [(set (pc) (if_then_else
6501 (match_operator 4 "arm_comparison_operator"
6502 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6503 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6504 (label_ref (match_operand 3 "" ""))
6505 (pc)))
6506 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6507 "TARGET_THUMB1"
aeac46d4 6508 "*
6509 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6510
6511 switch (get_attr_length (insn))
6512 {
6513 case 4: return \"b%d4\\t%l3\";
6514 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6515 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6516 }
6517 "
6518 [(set (attr "far_jump")
6519 (if_then_else
6520 (eq_attr "length" "8")
6521 (const_string "yes")
6522 (const_string "no")))
6523 (set (attr "length")
6524 (if_then_else
6525 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6526 (le (minus (match_dup 3) (pc)) (const_int 256)))
6527 (const_int 4)
6528 (if_then_else
6529 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6530 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6531 (const_int 6)
6532 (const_int 8))))]
6533)
6534(define_insn "*movsi_cbranchsi4"
6535 [(set (pc)
6536 (if_then_else
6537 (match_operator 3 "arm_comparison_operator"
6538 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6539 (const_int 0)])
6540 (label_ref (match_operand 2 "" ""))
6541 (pc)))
6542 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6543 (match_dup 1))]
25f905c2 6544 "TARGET_THUMB1"
aeac46d4 6545 "*{
6546 if (which_alternative == 0)
6547 output_asm_insn (\"cmp\t%0, #0\", operands);
6548 else if (which_alternative == 1)
6549 output_asm_insn (\"sub\t%0, %1, #0\", operands);
6550 else
6551 {
6552 output_asm_insn (\"cmp\t%1, #0\", operands);
6553 if (which_alternative == 2)
6554 output_asm_insn (\"mov\t%0, %1\", operands);
6555 else
6556 output_asm_insn (\"str\t%1, %0\", operands);
6557 }
6558 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6559 {
6560 case 4: return \"b%d3\\t%l2\";
6561 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6562 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6563 }
6564 }"
6565 [(set (attr "far_jump")
6566 (if_then_else
6567 (ior (and (gt (symbol_ref ("which_alternative"))
6568 (const_int 1))
6569 (eq_attr "length" "8"))
6570 (eq_attr "length" "10"))
6571 (const_string "yes")
6572 (const_string "no")))
6573 (set (attr "length")
6574 (if_then_else
6575 (le (symbol_ref ("which_alternative"))
6576 (const_int 1))
6577 (if_then_else
6578 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6579 (le (minus (match_dup 2) (pc)) (const_int 256)))
6580 (const_int 4)
6581 (if_then_else
6582 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6583 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6584 (const_int 6)
6585 (const_int 8)))
6586 (if_then_else
6587 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6588 (le (minus (match_dup 2) (pc)) (const_int 256)))
6589 (const_int 6)
6590 (if_then_else
6591 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6592 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6593 (const_int 8)
6594 (const_int 10)))))]
6595)
6596
cffb2a26 6597(define_insn "*negated_cbranchsi4"
6598 [(set (pc)
6599 (if_then_else
aed179ae 6600 (match_operator 0 "equality_operator"
aeac46d4 6601 [(match_operand:SI 1 "s_register_operand" "l")
6602 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6603 (label_ref (match_operand 3 "" ""))
215b30b3 6604 (pc)))]
25f905c2 6605 "TARGET_THUMB1"
cffb2a26 6606 "*
6607 output_asm_insn (\"cmn\\t%1, %2\", operands);
6608 switch (get_attr_length (insn))
6609 {
6610 case 4: return \"b%d0\\t%l3\";
6611 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6612 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6613 }
6614 "
6615 [(set (attr "far_jump")
6616 (if_then_else
6617 (eq_attr "length" "8")
6618 (const_string "yes")
6619 (const_string "no")))
6620 (set (attr "length")
6621 (if_then_else
6622 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6623 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6624 (const_int 4)
6625 (if_then_else
341940e8 6626 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6627 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6628 (const_int 6)
6629 (const_int 8))))]
6630)
6631
58d6528b 6632(define_insn "*tbit_cbranch"
6633 [(set (pc)
6634 (if_then_else
6635 (match_operator 0 "equality_operator"
6636 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6637 (const_int 1)
6638 (match_operand:SI 2 "const_int_operand" "i"))
6639 (const_int 0)])
6640 (label_ref (match_operand 3 "" ""))
6641 (pc)))
6642 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6643 "TARGET_THUMB1"
58d6528b 6644 "*
6645 {
6646 rtx op[3];
6647 op[0] = operands[4];
6648 op[1] = operands[1];
6649 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6650
86efa74d 6651 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6652 switch (get_attr_length (insn))
6653 {
6654 case 4: return \"b%d0\\t%l3\";
6655 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6656 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6657 }
6658 }"
6659 [(set (attr "far_jump")
6660 (if_then_else
6661 (eq_attr "length" "8")
6662 (const_string "yes")
6663 (const_string "no")))
6664 (set (attr "length")
6665 (if_then_else
6666 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6667 (le (minus (match_dup 3) (pc)) (const_int 256)))
6668 (const_int 4)
6669 (if_then_else
6670 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6671 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6672 (const_int 6)
6673 (const_int 8))))]
6674)
6675
6676(define_insn "*tlobits_cbranch"
6677 [(set (pc)
6678 (if_then_else
6679 (match_operator 0 "equality_operator"
6680 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6681 (match_operand:SI 2 "const_int_operand" "i")
6682 (const_int 0))
6683 (const_int 0)])
6684 (label_ref (match_operand 3 "" ""))
6685 (pc)))
6686 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6687 "TARGET_THUMB1"
86efa74d 6688 "*
6689 {
6690 rtx op[3];
6691 op[0] = operands[4];
6692 op[1] = operands[1];
6693 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6694
58d6528b 6695 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6696 switch (get_attr_length (insn))
6697 {
6698 case 4: return \"b%d0\\t%l3\";
6699 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6700 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6701 }
6702 }"
6703 [(set (attr "far_jump")
6704 (if_then_else
6705 (eq_attr "length" "8")
6706 (const_string "yes")
6707 (const_string "no")))
6708 (set (attr "length")
6709 (if_then_else
6710 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6711 (le (minus (match_dup 3) (pc)) (const_int 256)))
6712 (const_int 4)
6713 (if_then_else
6714 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6715 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6716 (const_int 6)
6717 (const_int 8))))]
6718)
6719
aeac46d4 6720(define_insn "*tstsi3_cbranch"
58d6528b 6721 [(set (pc)
6722 (if_then_else
aeac46d4 6723 (match_operator 3 "equality_operator"
6724 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6725 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6726 (const_int 0)])
aeac46d4 6727 (label_ref (match_operand 2 "" ""))
6728 (pc)))]
25f905c2 6729 "TARGET_THUMB1"
58d6528b 6730 "*
6731 {
aeac46d4 6732 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6733 switch (get_attr_length (insn))
6734 {
aeac46d4 6735 case 4: return \"b%d3\\t%l2\";
6736 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6737 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6738 }
6739 }"
6740 [(set (attr "far_jump")
6741 (if_then_else
6742 (eq_attr "length" "8")
6743 (const_string "yes")
6744 (const_string "no")))
6745 (set (attr "length")
6746 (if_then_else
aeac46d4 6747 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6748 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6749 (const_int 4)
6750 (if_then_else
aeac46d4 6751 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6752 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6753 (const_int 6)
6754 (const_int 8))))]
6755)
6756
6757(define_insn "*andsi3_cbranch"
6758 [(set (pc)
6759 (if_then_else
6760 (match_operator 5 "equality_operator"
6761 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6762 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6763 (const_int 0)])
6764 (label_ref (match_operand 4 "" ""))
6765 (pc)))
aeac46d4 6766 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6767 (and:SI (match_dup 2) (match_dup 3)))
6768 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6769 "TARGET_THUMB1"
58d6528b 6770 "*
6771 {
6772 if (which_alternative == 0)
6773 output_asm_insn (\"and\\t%0, %3\", operands);
6774 else if (which_alternative == 1)
6775 {
6776 output_asm_insn (\"and\\t%1, %3\", operands);
6777 output_asm_insn (\"mov\\t%0, %1\", operands);
6778 }
6779 else
6780 {
6781 output_asm_insn (\"and\\t%1, %3\", operands);
6782 output_asm_insn (\"str\\t%1, %0\", operands);
6783 }
6784
6785 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6786 {
6787 case 4: return \"b%d5\\t%l4\";
6788 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6789 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6790 }
6791 }"
6792 [(set (attr "far_jump")
6793 (if_then_else
6794 (ior (and (eq (symbol_ref ("which_alternative"))
6795 (const_int 0))
6796 (eq_attr "length" "8"))
6797 (eq_attr "length" "10"))
6798 (const_string "yes")
6799 (const_string "no")))
6800 (set (attr "length")
6801 (if_then_else
6802 (eq (symbol_ref ("which_alternative"))
6803 (const_int 0))
6804 (if_then_else
6805 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6806 (le (minus (match_dup 4) (pc)) (const_int 256)))
6807 (const_int 4)
6808 (if_then_else
6809 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6810 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6811 (const_int 6)
6812 (const_int 8)))
6813 (if_then_else
6814 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6815 (le (minus (match_dup 4) (pc)) (const_int 256)))
6816 (const_int 6)
6817 (if_then_else
6818 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6819 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6820 (const_int 8)
6821 (const_int 10)))))]
6822)
6823
6824(define_insn "*orrsi3_cbranch_scratch"
6825 [(set (pc)
6826 (if_then_else
6827 (match_operator 4 "equality_operator"
6828 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6829 (match_operand:SI 2 "s_register_operand" "l"))
6830 (const_int 0)])
6831 (label_ref (match_operand 3 "" ""))
6832 (pc)))
6833 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 6834 "TARGET_THUMB1"
58d6528b 6835 "*
6836 {
6837 output_asm_insn (\"orr\\t%0, %2\", operands);
6838 switch (get_attr_length (insn))
6839 {
6840 case 4: return \"b%d4\\t%l3\";
6841 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6842 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6843 }
6844 }"
6845 [(set (attr "far_jump")
6846 (if_then_else
6847 (eq_attr "length" "8")
6848 (const_string "yes")
6849 (const_string "no")))
6850 (set (attr "length")
6851 (if_then_else
6852 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6853 (le (minus (match_dup 3) (pc)) (const_int 256)))
6854 (const_int 4)
6855 (if_then_else
6856 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6857 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6858 (const_int 6)
6859 (const_int 8))))]
6860)
6861
6862(define_insn "*orrsi3_cbranch"
6863 [(set (pc)
6864 (if_then_else
6865 (match_operator 5 "equality_operator"
6866 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6867 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6868 (const_int 0)])
6869 (label_ref (match_operand 4 "" ""))
6870 (pc)))
aeac46d4 6871 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6872 (ior:SI (match_dup 2) (match_dup 3)))
6873 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6874 "TARGET_THUMB1"
58d6528b 6875 "*
6876 {
6877 if (which_alternative == 0)
6878 output_asm_insn (\"orr\\t%0, %3\", operands);
6879 else if (which_alternative == 1)
6880 {
6881 output_asm_insn (\"orr\\t%1, %3\", operands);
6882 output_asm_insn (\"mov\\t%0, %1\", operands);
6883 }
6884 else
6885 {
6886 output_asm_insn (\"orr\\t%1, %3\", operands);
6887 output_asm_insn (\"str\\t%1, %0\", operands);
6888 }
6889
6890 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6891 {
6892 case 4: return \"b%d5\\t%l4\";
6893 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6894 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6895 }
6896 }"
6897 [(set (attr "far_jump")
6898 (if_then_else
6899 (ior (and (eq (symbol_ref ("which_alternative"))
6900 (const_int 0))
6901 (eq_attr "length" "8"))
6902 (eq_attr "length" "10"))
6903 (const_string "yes")
6904 (const_string "no")))
6905 (set (attr "length")
6906 (if_then_else
6907 (eq (symbol_ref ("which_alternative"))
6908 (const_int 0))
6909 (if_then_else
6910 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6911 (le (minus (match_dup 4) (pc)) (const_int 256)))
6912 (const_int 4)
6913 (if_then_else
6914 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6915 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6916 (const_int 6)
6917 (const_int 8)))
6918 (if_then_else
6919 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6920 (le (minus (match_dup 4) (pc)) (const_int 256)))
6921 (const_int 6)
6922 (if_then_else
6923 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6924 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6925 (const_int 8)
6926 (const_int 10)))))]
6927)
6928
6929(define_insn "*xorsi3_cbranch_scratch"
6930 [(set (pc)
6931 (if_then_else
6932 (match_operator 4 "equality_operator"
6933 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6934 (match_operand:SI 2 "s_register_operand" "l"))
6935 (const_int 0)])
6936 (label_ref (match_operand 3 "" ""))
6937 (pc)))
6938 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 6939 "TARGET_THUMB1"
58d6528b 6940 "*
6941 {
6942 output_asm_insn (\"eor\\t%0, %2\", operands);
6943 switch (get_attr_length (insn))
6944 {
6945 case 4: return \"b%d4\\t%l3\";
6946 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6947 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6948 }
6949 }"
6950 [(set (attr "far_jump")
6951 (if_then_else
6952 (eq_attr "length" "8")
6953 (const_string "yes")
6954 (const_string "no")))
6955 (set (attr "length")
6956 (if_then_else
6957 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6958 (le (minus (match_dup 3) (pc)) (const_int 256)))
6959 (const_int 4)
6960 (if_then_else
6961 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6962 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6963 (const_int 6)
6964 (const_int 8))))]
6965)
6966
6967(define_insn "*xorsi3_cbranch"
6968 [(set (pc)
6969 (if_then_else
6970 (match_operator 5 "equality_operator"
6971 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6972 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6973 (const_int 0)])
6974 (label_ref (match_operand 4 "" ""))
6975 (pc)))
aeac46d4 6976 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6977 (xor:SI (match_dup 2) (match_dup 3)))
6978 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6979 "TARGET_THUMB1"
58d6528b 6980 "*
6981 {
6982 if (which_alternative == 0)
6983 output_asm_insn (\"eor\\t%0, %3\", operands);
6984 else if (which_alternative == 1)
6985 {
6986 output_asm_insn (\"eor\\t%1, %3\", operands);
6987 output_asm_insn (\"mov\\t%0, %1\", operands);
6988 }
6989 else
6990 {
6991 output_asm_insn (\"eor\\t%1, %3\", operands);
6992 output_asm_insn (\"str\\t%1, %0\", operands);
6993 }
6994
6995 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6996 {
6997 case 4: return \"b%d5\\t%l4\";
6998 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6999 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7000 }
7001 }"
7002 [(set (attr "far_jump")
7003 (if_then_else
7004 (ior (and (eq (symbol_ref ("which_alternative"))
7005 (const_int 0))
7006 (eq_attr "length" "8"))
7007 (eq_attr "length" "10"))
7008 (const_string "yes")
7009 (const_string "no")))
7010 (set (attr "length")
7011 (if_then_else
7012 (eq (symbol_ref ("which_alternative"))
7013 (const_int 0))
7014 (if_then_else
7015 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7016 (le (minus (match_dup 4) (pc)) (const_int 256)))
7017 (const_int 4)
7018 (if_then_else
7019 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7020 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7021 (const_int 6)
7022 (const_int 8)))
7023 (if_then_else
7024 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7025 (le (minus (match_dup 4) (pc)) (const_int 256)))
7026 (const_int 6)
7027 (if_then_else
7028 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7029 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7030 (const_int 8)
7031 (const_int 10)))))]
7032)
7033
aeac46d4 7034(define_insn "*bicsi3_cbranch_scratch"
7035 [(set (pc)
7036 (if_then_else
7037 (match_operator 4 "equality_operator"
7038 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7039 (match_operand:SI 1 "s_register_operand" "0"))
7040 (const_int 0)])
7041 (label_ref (match_operand 3 "" ""))
7042 (pc)))
7043 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7044 "TARGET_THUMB1"
aeac46d4 7045 "*
7046 {
7047 output_asm_insn (\"bic\\t%0, %2\", operands);
7048 switch (get_attr_length (insn))
7049 {
7050 case 4: return \"b%d4\\t%l3\";
7051 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7052 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7053 }
7054 }"
7055 [(set (attr "far_jump")
7056 (if_then_else
7057 (eq_attr "length" "8")
7058 (const_string "yes")
7059 (const_string "no")))
7060 (set (attr "length")
7061 (if_then_else
7062 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7063 (le (minus (match_dup 3) (pc)) (const_int 256)))
7064 (const_int 4)
7065 (if_then_else
7066 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7067 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7068 (const_int 6)
7069 (const_int 8))))]
7070)
7071
7072(define_insn "*bicsi3_cbranch"
7073 [(set (pc)
7074 (if_then_else
7075 (match_operator 5 "equality_operator"
01145ae6 7076 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7077 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 7078 (const_int 0)])
7079 (label_ref (match_operand 4 "" ""))
7080 (pc)))
01145ae6 7081 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 7082 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 7083 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
25f905c2 7084 "TARGET_THUMB1"
aeac46d4 7085 "*
7086 {
7087 if (which_alternative == 0)
7088 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 7089 else if (which_alternative <= 2)
aeac46d4 7090 {
7091 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 7092 /* It's ok if OP0 is a lo-reg, even though the mov will set the
7093 conditions again, since we're only testing for equality. */
aeac46d4 7094 output_asm_insn (\"mov\\t%0, %1\", operands);
7095 }
7096 else
7097 {
7098 output_asm_insn (\"bic\\t%1, %3\", operands);
7099 output_asm_insn (\"str\\t%1, %0\", operands);
7100 }
7101
7102 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7103 {
7104 case 4: return \"b%d5\\t%l4\";
7105 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7106 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7107 }
7108 }"
7109 [(set (attr "far_jump")
7110 (if_then_else
7111 (ior (and (eq (symbol_ref ("which_alternative"))
7112 (const_int 0))
7113 (eq_attr "length" "8"))
7114 (eq_attr "length" "10"))
7115 (const_string "yes")
7116 (const_string "no")))
7117 (set (attr "length")
7118 (if_then_else
7119 (eq (symbol_ref ("which_alternative"))
7120 (const_int 0))
7121 (if_then_else
7122 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7123 (le (minus (match_dup 4) (pc)) (const_int 256)))
7124 (const_int 4)
7125 (if_then_else
7126 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7127 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7128 (const_int 6)
7129 (const_int 8)))
7130 (if_then_else
7131 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7132 (le (minus (match_dup 4) (pc)) (const_int 256)))
7133 (const_int 6)
7134 (if_then_else
7135 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7136 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7137 (const_int 8)
7138 (const_int 10)))))]
7139)
7140
203c488f 7141(define_insn "*cbranchne_decr1"
7142 [(set (pc)
7143 (if_then_else (match_operator 3 "equality_operator"
7144 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7145 (const_int 0)])
7146 (label_ref (match_operand 4 "" ""))
7147 (pc)))
aeac46d4 7148 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7149 (plus:SI (match_dup 2) (const_int -1)))
7150 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7151 "TARGET_THUMB1"
203c488f 7152 "*
7153 {
7154 rtx cond[2];
7155 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7156 ? GEU : LTU),
58d6528b 7157 VOIDmode, operands[2], const1_rtx);
203c488f 7158 cond[1] = operands[4];
7159
7160 if (which_alternative == 0)
7161 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7162 else if (which_alternative == 1)
7163 {
7164 /* We must provide an alternative for a hi reg because reload
7165 cannot handle output reloads on a jump instruction, but we
7166 can't subtract into that. Fortunately a mov from lo to hi
7167 does not clobber the condition codes. */
7168 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7169 output_asm_insn (\"mov\\t%0, %1\", operands);
7170 }
7171 else
7172 {
7173 /* Similarly, but the target is memory. */
7174 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7175 output_asm_insn (\"str\\t%1, %0\", operands);
7176 }
7177
7178 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7179 {
7180 case 4:
8aea555f 7181 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7182 return \"\";
7183 case 6:
8aea555f 7184 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7185 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7186 default:
8aea555f 7187 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7188 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7189 }
7190 }
7191 "
7192 [(set (attr "far_jump")
7193 (if_then_else
7194 (ior (and (eq (symbol_ref ("which_alternative"))
7195 (const_int 0))
7196 (eq_attr "length" "8"))
7197 (eq_attr "length" "10"))
7198 (const_string "yes")
7199 (const_string "no")))
7200 (set_attr_alternative "length"
7201 [
7202 ;; Alternative 0
7203 (if_then_else
7204 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7205 (le (minus (match_dup 4) (pc)) (const_int 256)))
7206 (const_int 4)
7207 (if_then_else
7208 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7209 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7210 (const_int 6)
7211 (const_int 8)))
7212 ;; Alternative 1
7213 (if_then_else
7214 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7215 (le (minus (match_dup 4) (pc)) (const_int 256)))
7216 (const_int 6)
7217 (if_then_else
7218 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7219 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7220 (const_int 8)
7221 (const_int 10)))
7222 ;; Alternative 2
7223 (if_then_else
7224 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7225 (le (minus (match_dup 4) (pc)) (const_int 256)))
7226 (const_int 6)
7227 (if_then_else
7228 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7229 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7230 (const_int 8)
7231 (const_int 10)))
7232 ;; Alternative 3
7233 (if_then_else
7234 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7235 (le (minus (match_dup 4) (pc)) (const_int 256)))
7236 (const_int 6)
7237 (if_then_else
7238 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7239 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7240 (const_int 8)
7241 (const_int 10)))])]
7242)
cffb2a26 7243
58d6528b 7244(define_insn "*addsi3_cbranch"
7245 [(set (pc)
7246 (if_then_else
7247 (match_operator 4 "comparison_operator"
7248 [(plus:SI
7249 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
7250 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
7251 (const_int 0)])
7252 (label_ref (match_operand 5 "" ""))
7253 (pc)))
aeac46d4 7254 (set
7255 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7256 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 7257 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
25f905c2 7258 "TARGET_THUMB1
58d6528b 7259 && (GET_CODE (operands[4]) == EQ
7260 || GET_CODE (operands[4]) == NE
7261 || GET_CODE (operands[4]) == GE
7262 || GET_CODE (operands[4]) == LT)"
7263 "*
7264 {
7265 rtx cond[3];
7266
7267
7268 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
7269 cond[1] = operands[2];
7270 cond[2] = operands[3];
7271
7272 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7273 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7274 else
7275 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7276
7277 if (which_alternative >= 3
7278 && which_alternative < 4)
7279 output_asm_insn (\"mov\\t%0, %1\", operands);
7280 else if (which_alternative >= 4)
7281 output_asm_insn (\"str\\t%1, %0\", operands);
7282
7283 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7284 {
7285 case 4:
7286 return \"b%d4\\t%l5\";
7287 case 6:
7288 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7289 default:
7290 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7291 }
7292 }
7293 "
7294 [(set (attr "far_jump")
7295 (if_then_else
7296 (ior (and (lt (symbol_ref ("which_alternative"))
7297 (const_int 3))
7298 (eq_attr "length" "8"))
7299 (eq_attr "length" "10"))
7300 (const_string "yes")
7301 (const_string "no")))
7302 (set (attr "length")
7303 (if_then_else
7304 (lt (symbol_ref ("which_alternative"))
7305 (const_int 3))
7306 (if_then_else
7307 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7308 (le (minus (match_dup 5) (pc)) (const_int 256)))
7309 (const_int 4)
7310 (if_then_else
7311 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7312 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7313 (const_int 6)
7314 (const_int 8)))
7315 (if_then_else
7316 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7317 (le (minus (match_dup 5) (pc)) (const_int 256)))
7318 (const_int 6)
7319 (if_then_else
7320 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7321 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7322 (const_int 8)
7323 (const_int 10)))))]
7324)
7325
7326(define_insn "*addsi3_cbranch_scratch"
7327 [(set (pc)
7328 (if_then_else
7329 (match_operator 3 "comparison_operator"
7330 [(plus:SI
7331 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7332 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7333 (const_int 0)])
7334 (label_ref (match_operand 4 "" ""))
7335 (pc)))
7336 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7337 "TARGET_THUMB1
58d6528b 7338 && (GET_CODE (operands[3]) == EQ
7339 || GET_CODE (operands[3]) == NE
7340 || GET_CODE (operands[3]) == GE
7341 || GET_CODE (operands[3]) == LT)"
7342 "*
7343 {
7344 switch (which_alternative)
7345 {
7346 case 0:
7347 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7348 break;
7349 case 1:
7350 output_asm_insn (\"cmn\t%1, %2\", operands);
7351 break;
0f5e9701 7352 case 2:
3a445a04 7353 if (INTVAL (operands[2]) < 0)
7354 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7355 else
7356 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7357 break;
0f5e9701 7358 case 3:
3a445a04 7359 if (INTVAL (operands[2]) < 0)
7360 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7361 else
7362 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7363 break;
7364 }
7365
7366 switch (get_attr_length (insn))
7367 {
7368 case 4:
7369 return \"b%d3\\t%l4\";
7370 case 6:
7371 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7372 default:
7373 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7374 }
7375 }
7376 "
7377 [(set (attr "far_jump")
7378 (if_then_else
7379 (eq_attr "length" "8")
7380 (const_string "yes")
7381 (const_string "no")))
7382 (set (attr "length")
7383 (if_then_else
7384 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7385 (le (minus (match_dup 4) (pc)) (const_int 256)))
7386 (const_int 4)
7387 (if_then_else
7388 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7389 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7390 (const_int 6)
7391 (const_int 8))))]
7392)
7393
7394(define_insn "*subsi3_cbranch"
7395 [(set (pc)
7396 (if_then_else
7397 (match_operator 4 "comparison_operator"
7398 [(minus:SI
7399 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7400 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7401 (const_int 0)])
7402 (label_ref (match_operand 5 "" ""))
7403 (pc)))
aeac46d4 7404 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7405 (minus:SI (match_dup 2) (match_dup 3)))
7406 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7407 "TARGET_THUMB1
58d6528b 7408 && (GET_CODE (operands[4]) == EQ
7409 || GET_CODE (operands[4]) == NE
7410 || GET_CODE (operands[4]) == GE
7411 || GET_CODE (operands[4]) == LT)"
7412 "*
7413 {
7414 if (which_alternative == 0)
7415 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7416 else if (which_alternative == 1)
7417 {
7418 /* We must provide an alternative for a hi reg because reload
7419 cannot handle output reloads on a jump instruction, but we
7420 can't subtract into that. Fortunately a mov from lo to hi
7421 does not clobber the condition codes. */
7422 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7423 output_asm_insn (\"mov\\t%0, %1\", operands);
7424 }
7425 else
7426 {
7427 /* Similarly, but the target is memory. */
7428 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7429 output_asm_insn (\"str\\t%1, %0\", operands);
7430 }
7431
7432 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7433 {
7434 case 4:
7435 return \"b%d4\\t%l5\";
7436 case 6:
7437 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7438 default:
7439 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7440 }
7441 }
7442 "
7443 [(set (attr "far_jump")
7444 (if_then_else
7445 (ior (and (eq (symbol_ref ("which_alternative"))
7446 (const_int 0))
7447 (eq_attr "length" "8"))
7448 (eq_attr "length" "10"))
7449 (const_string "yes")
7450 (const_string "no")))
7451 (set (attr "length")
7452 (if_then_else
7453 (eq (symbol_ref ("which_alternative"))
7454 (const_int 0))
7455 (if_then_else
7456 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7457 (le (minus (match_dup 5) (pc)) (const_int 256)))
7458 (const_int 4)
7459 (if_then_else
7460 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7461 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7462 (const_int 6)
7463 (const_int 8)))
7464 (if_then_else
7465 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7466 (le (minus (match_dup 5) (pc)) (const_int 256)))
7467 (const_int 6)
7468 (if_then_else
7469 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7470 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7471 (const_int 8)
7472 (const_int 10)))))]
7473)
7474
7475(define_insn "*subsi3_cbranch_scratch"
7476 [(set (pc)
7477 (if_then_else
7478 (match_operator 0 "arm_comparison_operator"
7479 [(minus:SI (match_operand:SI 1 "register_operand" "l")
7480 (match_operand:SI 2 "nonmemory_operand" "l"))
7481 (const_int 0)])
7482 (label_ref (match_operand 3 "" ""))
7483 (pc)))]
25f905c2 7484 "TARGET_THUMB1
58d6528b 7485 && (GET_CODE (operands[0]) == EQ
7486 || GET_CODE (operands[0]) == NE
7487 || GET_CODE (operands[0]) == GE
7488 || GET_CODE (operands[0]) == LT)"
7489 "*
7490 output_asm_insn (\"cmp\\t%1, %2\", operands);
7491 switch (get_attr_length (insn))
7492 {
7493 case 4: return \"b%d0\\t%l3\";
7494 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7495 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7496 }
7497 "
7498 [(set (attr "far_jump")
7499 (if_then_else
7500 (eq_attr "length" "8")
7501 (const_string "yes")
7502 (const_string "no")))
7503 (set (attr "length")
7504 (if_then_else
7505 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7506 (le (minus (match_dup 3) (pc)) (const_int 256)))
7507 (const_int 4)
7508 (if_then_else
7509 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7510 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7511 (const_int 6)
7512 (const_int 8))))]
7513)
7514
9c08d1fa 7515;; Comparison and test insns
7516
cffb2a26 7517(define_insn "*arm_cmpsi_insn"
bd5b4116 7518 [(set (reg:CC CC_REGNUM)
aea4c774 7519 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7520 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7521 "TARGET_32BIT"
5565501b 7522 "@
aea4c774 7523 cmp%?\\t%0, %1
7524 cmn%?\\t%0, #%n1"
cffb2a26 7525 [(set_attr "conds" "set")]
7526)
b11cae9e 7527
25f905c2 7528(define_insn "*arm_cmpsi_shiftsi"
bd5b4116 7529 [(set (reg:CC CC_REGNUM)
cffb2a26 7530 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
7531 (match_operator:SI 3 "shift_operator"
aea4c774 7532 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 7533 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
7534 "TARGET_ARM"
aea4c774 7535 "cmp%?\\t%0, %1%S3"
344495ea 7536 [(set_attr "conds" "set")
331beb1a 7537 (set_attr "shift" "1")
a2cd141b 7538 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7539 (const_string "alu_shift")
7540 (const_string "alu_shift_reg")))]
0d66636f 7541)
b11cae9e 7542
25f905c2 7543(define_insn "*arm_cmpsi_shiftsi_swp"
bd5b4116 7544 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7545 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7546 [(match_operand:SI 1 "s_register_operand" "r")
7547 (match_operand:SI 2 "reg_or_int_operand" "rM")])
7548 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7549 "TARGET_ARM"
aea4c774 7550 "cmp%?\\t%0, %1%S3"
344495ea 7551 [(set_attr "conds" "set")
331beb1a 7552 (set_attr "shift" "1")
a2cd141b 7553 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7554 (const_string "alu_shift")
7555 (const_string "alu_shift_reg")))]
0d66636f 7556)
b11cae9e 7557
25f905c2 7558(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7559 [(set (reg:CC_Z CC_REGNUM)
7560 (compare:CC_Z
7561 (neg:SI (match_operator:SI 1 "shift_operator"
7562 [(match_operand:SI 2 "s_register_operand" "r")
7563 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7564 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7565 "TARGET_ARM"
aed179ae 7566 "cmn%?\\t%0, %2%S1"
344495ea 7567 [(set_attr "conds" "set")
aed179ae 7568 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7569 (const_string "alu_shift")
7570 (const_string "alu_shift_reg")))]
0d66636f 7571)
b11cae9e 7572
7d57ec45 7573;; Cirrus SF compare instruction
7574(define_insn "*cirrus_cmpsf"
7575 [(set (reg:CCFP CC_REGNUM)
7576 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7577 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7578 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7579 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7580 [(set_attr "type" "mav_farith")
7d57ec45 7581 (set_attr "cirrus" "compare")]
7582)
7583
7584;; Cirrus DF compare instruction
7585(define_insn "*cirrus_cmpdf"
7586 [(set (reg:CCFP CC_REGNUM)
7587 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7588 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7589 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7590 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7591 [(set_attr "type" "mav_farith")
7d57ec45 7592 (set_attr "cirrus" "compare")]
7593)
7594
7d57ec45 7595(define_insn "*cirrus_cmpdi"
7596 [(set (reg:CC CC_REGNUM)
7597 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7598 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7599 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7600 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7601 [(set_attr "type" "mav_farith")
7d57ec45 7602 (set_attr "cirrus" "compare")]
7603)
7604
9c08d1fa 7605; This insn allows redundant compares to be removed by cse, nothing should
7606; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7607; is deleted later on. The match_dup will match the mode here, so that
7608; mode changes of the condition codes aren't lost by this even though we don't
7609; specify what they are.
7610
8a18b90c 7611(define_insn "*deleted_compare"
9c08d1fa 7612 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7613 "TARGET_32BIT"
40dbec34 7614 "\\t%@ deleted compare"
cffb2a26 7615 [(set_attr "conds" "set")
7616 (set_attr "length" "0")]
7617)
9c08d1fa 7618
7619\f
7620;; Conditional branch insns
7621
74f4459c 7622(define_expand "cbranch_cc"
9c08d1fa 7623 [(set (pc)
74f4459c 7624 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7625 (match_operand 2 "" "")])
7626 (label_ref (match_operand 3 "" ""))
9c08d1fa 7627 (pc)))]
25f905c2 7628 "TARGET_32BIT"
74f4459c 7629 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7630 operands[1], operands[2]);
7631 operands[2] = const0_rtx;"
8fa3ba89 7632)
7633
7634;;
7635;; Patterns to match conditional branch insns.
7636;;
7637
7638; Special pattern to match UNEQ.
7639(define_insn "*arm_buneq"
7640 [(set (pc)
7641 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7642 (label_ref (match_operand 0 "" ""))
7643 (pc)))]
25f905c2 7644 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7645 "*
ed29c566 7646 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7647
278b301d 7648 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7649 "
7650 [(set_attr "conds" "jump_clob")
7651 (set_attr "length" "8")]
7652)
7653
7654; Special pattern to match LTGT.
7655(define_insn "*arm_bltgt"
7656 [(set (pc)
7657 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7658 (label_ref (match_operand 0 "" ""))
7659 (pc)))]
25f905c2 7660 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7661 "*
ed29c566 7662 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7663
278b301d 7664 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7665 "
7666 [(set_attr "conds" "jump_clob")
7667 (set_attr "length" "8")]
7668)
9c08d1fa 7669
cffb2a26 7670(define_insn "*arm_cond_branch"
9c08d1fa 7671 [(set (pc)
8fa3ba89 7672 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7673 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7674 (label_ref (match_operand 0 "" ""))
7675 (pc)))]
25f905c2 7676 "TARGET_32BIT"
d75350ce 7677 "*
9c08d1fa 7678 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7679 {
7680 arm_ccfsm_state += 2;
7681 return \"\";
7682 }
e2348bcb 7683 return \"b%d1\\t%l0\";
cffb2a26 7684 "
a2cd141b 7685 [(set_attr "conds" "use")
7686 (set_attr "type" "branch")]
cffb2a26 7687)
d75350ce 7688
8fa3ba89 7689; Special pattern to match reversed UNEQ.
7690(define_insn "*arm_buneq_reversed"
7691 [(set (pc)
7692 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7693 (pc)
7694 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7695 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7696 "*
ed29c566 7697 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7698
278b301d 7699 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7700 "
7701 [(set_attr "conds" "jump_clob")
7702 (set_attr "length" "8")]
7703)
7704
7705; Special pattern to match reversed LTGT.
7706(define_insn "*arm_bltgt_reversed"
7707 [(set (pc)
7708 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7709 (pc)
7710 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7711 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7712 "*
ed29c566 7713 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7714
278b301d 7715 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7716 "
7717 [(set_attr "conds" "jump_clob")
7718 (set_attr "length" "8")]
7719)
7720
cffb2a26 7721(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7722 [(set (pc)
8fa3ba89 7723 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7724 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7725 (pc)
7726 (label_ref (match_operand 0 "" ""))))]
25f905c2 7727 "TARGET_32BIT"
d75350ce 7728 "*
9c08d1fa 7729 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7730 {
7731 arm_ccfsm_state += 2;
7732 return \"\";
7733 }
e2348bcb 7734 return \"b%D1\\t%l0\";
cffb2a26 7735 "
a2cd141b 7736 [(set_attr "conds" "use")
7737 (set_attr "type" "branch")]
cffb2a26 7738)
7739
b11cae9e 7740\f
9c08d1fa 7741
7742; scc insns
7743
74f4459c 7744(define_expand "cstore_cc"
7db9af5d 7745 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7746 (match_operator:SI 1 "" [(match_operand 2 "" "")
7747 (match_operand 3 "" "")]))]
25f905c2 7748 "TARGET_32BIT"
74f4459c 7749 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7750 operands[2], operands[3]);
7751 operands[3] = const0_rtx;"
8fa3ba89 7752)
7753
f7fbdd4a 7754(define_insn "*mov_scc"
9c08d1fa 7755 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7756 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7757 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7758 "TARGET_ARM"
4d61e570 7759 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7760 [(set_attr "conds" "use")
7761 (set_attr "length" "8")]
7762)
9c08d1fa 7763
f7fbdd4a 7764(define_insn "*mov_negscc"
9c08d1fa 7765 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7766 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7767 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7768 "TARGET_ARM"
4d61e570 7769 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7770 [(set_attr "conds" "use")
7771 (set_attr "length" "8")]
7772)
9c08d1fa 7773
f7fbdd4a 7774(define_insn "*mov_notscc"
9c08d1fa 7775 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7776 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7777 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7778 "TARGET_ARM"
4d61e570 7779 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7780 [(set_attr "conds" "use")
7781 (set_attr "length" "8")]
7782)
9c08d1fa 7783
595d88b5 7784(define_expand "cstoresi4"
7785 [(set (match_operand:SI 0 "s_register_operand" "")
7786 (match_operator:SI 1 "arm_comparison_operator"
7787 [(match_operand:SI 2 "s_register_operand" "")
7788 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7789 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7790 "{
7791 rtx op3, scratch, scratch2;
7792
74f4459c 7793 if (!TARGET_THUMB1)
7794 {
7795 if (!arm_add_operand (operands[3], SImode))
7796 operands[3] = force_reg (SImode, operands[3]);
7797 emit_insn (gen_cstore_cc (operands[0], operands[1],
7798 operands[2], operands[3]));
7799 DONE;
7800 }
7801
595d88b5 7802 if (operands[3] == const0_rtx)
7803 {
7804 switch (GET_CODE (operands[1]))
7805 {
7806 case EQ:
25f905c2 7807 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7808 break;
7809
7810 case NE:
25f905c2 7811 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7812 break;
7813
7814 case LE:
7815 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7816 NULL_RTX, 0, OPTAB_WIDEN);
7817 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7818 NULL_RTX, 0, OPTAB_WIDEN);
7819 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7820 operands[0], 1, OPTAB_WIDEN);
7821 break;
7822
7823 case GE:
7824 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7825 NULL_RTX, 1);
7826 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7827 NULL_RTX, 1, OPTAB_WIDEN);
7828 break;
7829
7830 case GT:
7831 scratch = expand_binop (SImode, ashr_optab, operands[2],
7832 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7833 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7834 NULL_RTX, 0, OPTAB_WIDEN);
7835 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7836 0, OPTAB_WIDEN);
7837 break;
7838
7839 /* LT is handled by generic code. No need for unsigned with 0. */
7840 default:
7841 FAIL;
7842 }
7843 DONE;
7844 }
7845
7846 switch (GET_CODE (operands[1]))
7847 {
7848 case EQ:
7849 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7850 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7851 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7852 break;
7853
7854 case NE:
7855 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7856 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7857 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7858 break;
7859
7860 case LE:
7861 op3 = force_reg (SImode, operands[3]);
7862
7863 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7864 NULL_RTX, 1, OPTAB_WIDEN);
7865 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7866 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7867 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7868 op3, operands[2]));
7869 break;
7870
7871 case GE:
7872 op3 = operands[3];
25f905c2 7873 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7874 op3 = force_reg (SImode, op3);
7875 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7876 NULL_RTX, 0, OPTAB_WIDEN);
7877 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7878 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7879 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7880 operands[2], op3));
7881 break;
7882
7883 case LEU:
7884 op3 = force_reg (SImode, operands[3]);
7885 scratch = force_reg (SImode, const0_rtx);
25f905c2 7886 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7887 op3, operands[2]));
7888 break;
7889
7890 case GEU:
7891 op3 = operands[3];
25f905c2 7892 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7893 op3 = force_reg (SImode, op3);
7894 scratch = force_reg (SImode, const0_rtx);
25f905c2 7895 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7896 operands[2], op3));
7897 break;
7898
7899 case LTU:
7900 op3 = operands[3];
25f905c2 7901 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7902 op3 = force_reg (SImode, op3);
7903 scratch = gen_reg_rtx (SImode);
25f905c2 7904 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
595d88b5 7905 emit_insn (gen_negsi2 (operands[0], scratch));
7906 break;
7907
7908 case GTU:
7909 op3 = force_reg (SImode, operands[3]);
7910 scratch = gen_reg_rtx (SImode);
25f905c2 7911 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
595d88b5 7912 emit_insn (gen_negsi2 (operands[0], scratch));
7913 break;
7914
7915 /* No good sequences for GT, LT. */
7916 default:
7917 FAIL;
7918 }
7919 DONE;
7920}")
7921
74f4459c 7922(define_expand "cstoresf4"
7923 [(set (match_operand:SI 0 "s_register_operand" "")
7924 (match_operator:SI 1 "arm_comparison_operator"
7925 [(match_operand:SF 2 "s_register_operand" "")
7926 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7927 "TARGET_32BIT && TARGET_HARD_FLOAT"
7928 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7929 operands[2], operands[3])); DONE;"
7930)
7931
7932(define_expand "cstoredf4"
7933 [(set (match_operand:SI 0 "s_register_operand" "")
7934 (match_operator:SI 1 "arm_comparison_operator"
7935 [(match_operand:DF 2 "s_register_operand" "")
7936 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
7937 "TARGET_32BIT && TARGET_HARD_FLOAT"
7938 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7939 operands[2], operands[3])); DONE;"
7940)
7941
7942;; this uses the Cirrus DI compare instruction
7943(define_expand "cstoredi4"
7944 [(set (match_operand:SI 0 "s_register_operand" "")
7945 (match_operator:SI 1 "arm_comparison_operator"
7946 [(match_operand:DI 2 "cirrus_fp_register" "")
7947 (match_operand:DI 3 "cirrus_fp_register" "")]))]
7948 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7949 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7950 operands[2], operands[3])); DONE;"
7951)
7952
7953
25f905c2 7954(define_expand "cstoresi_eq0_thumb1"
595d88b5 7955 [(parallel
7956 [(set (match_operand:SI 0 "s_register_operand" "")
7957 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7958 (const_int 0)))
7959 (clobber (match_dup:SI 2))])]
25f905c2 7960 "TARGET_THUMB1"
595d88b5 7961 "operands[2] = gen_reg_rtx (SImode);"
7962)
7963
25f905c2 7964(define_expand "cstoresi_ne0_thumb1"
595d88b5 7965 [(parallel
7966 [(set (match_operand:SI 0 "s_register_operand" "")
7967 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7968 (const_int 0)))
7969 (clobber (match_dup:SI 2))])]
25f905c2 7970 "TARGET_THUMB1"
595d88b5 7971 "operands[2] = gen_reg_rtx (SImode);"
7972)
7973
25f905c2 7974(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7975 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7976 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7977 (const_int 0)))
7978 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7979 "TARGET_THUMB1"
595d88b5 7980 "@
7981 neg\\t%0, %1\;adc\\t%0, %0, %1
7982 neg\\t%2, %1\;adc\\t%0, %1, %2"
7983 [(set_attr "length" "4")]
7984)
7985
25f905c2 7986(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7987 [(set (match_operand:SI 0 "s_register_operand" "=l")
7988 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7989 (const_int 0)))
7990 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7991 "TARGET_THUMB1"
595d88b5 7992 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7993 [(set_attr "length" "4")]
7994)
7995
25f905c2 7996(define_insn "cstoresi_nltu_thumb1"
595d88b5 7997 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7998 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7999 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8000 "TARGET_THUMB1"
595d88b5 8001 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8002 [(set_attr "length" "4")]
8003)
8004
8005;; Used as part of the expansion of thumb les sequence.
25f905c2 8006(define_insn "thumb1_addsi3_addgeu"
595d88b5 8007 [(set (match_operand:SI 0 "s_register_operand" "=l")
8008 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8009 (match_operand:SI 2 "s_register_operand" "l"))
8010 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8011 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8012 "TARGET_THUMB1"
595d88b5 8013 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8014 [(set_attr "length" "4")]
8015)
8016
9c08d1fa 8017\f
39b5e676 8018;; Conditional move insns
8019
8020(define_expand "movsicc"
8a18b90c 8021 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 8022 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 8023 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8024 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8025 "TARGET_32BIT"
39b5e676 8026 "
215b30b3 8027 {
8028 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8029 rtx ccreg;
8030
8031 if (code == UNEQ || code == LTGT)
8032 FAIL;
39b5e676 8033
74f4459c 8034 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8035 XEXP (operands[1], 1));
29bb088d 8036 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8037 }"
8038)
39b5e676 8039
8040(define_expand "movsfcc"
8a18b90c 8041 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 8042 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8043 (match_operand:SF 2 "s_register_operand" "")
8044 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 8045 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8046 "
215b30b3 8047 {
8048 enum rtx_code code = GET_CODE (operands[1]);
8049 rtx ccreg;
f082f1c4 8050
278b301d 8051 if (code == UNEQ || code == LTGT)
8052 FAIL;
8053
215b30b3 8054 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 8055 Otherwise, ensure it is a valid FP add operand */
8056 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8057 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 8058 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8059
74f4459c 8060 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8061 XEXP (operands[1], 1));
29bb088d 8062 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8063 }"
8064)
39b5e676 8065
8066(define_expand "movdfcc"
8a18b90c 8067 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 8068 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8069 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8070 (match_operand:DF 3 "arm_float_add_operand" "")))]
25f905c2 8071 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 8072 "
215b30b3 8073 {
8074 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8075 rtx ccreg;
39b5e676 8076
278b301d 8077 if (code == UNEQ || code == LTGT)
8078 FAIL;
8079
74f4459c 8080 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8081 XEXP (operands[1], 1));
29bb088d 8082 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8083 }"
8084)
39b5e676 8085
8086(define_insn "*movsicc_insn"
f082f1c4 8087 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8088 (if_then_else:SI
8fa3ba89 8089 (match_operator 3 "arm_comparison_operator"
8a18b90c 8090 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8091 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8092 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8093 "TARGET_ARM"
39b5e676 8094 "@
8a18b90c 8095 mov%D3\\t%0, %2
8096 mvn%D3\\t%0, #%B2
f082f1c4 8097 mov%d3\\t%0, %1
8098 mvn%d3\\t%0, #%B1
8a18b90c 8099 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8100 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8101 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8102 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8103 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 8104 (set_attr "conds" "use")]
8105)
39b5e676 8106
39b5e676 8107(define_insn "*movsfcc_soft_insn"
f082f1c4 8108 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8109 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8110 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8111 (match_operand:SF 1 "s_register_operand" "0,r")
8112 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8113 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8114 "@
8115 mov%D3\\t%0, %2
8116 mov%d3\\t%0, %1"
8fa3ba89 8117 [(set_attr "conds" "use")]
8118)
39b5e676 8119
39b5e676 8120\f
9c08d1fa 8121;; Jump and linkage insns
8122
cffb2a26 8123(define_expand "jump"
9c08d1fa 8124 [(set (pc)
8125 (label_ref (match_operand 0 "" "")))]
cffb2a26 8126 "TARGET_EITHER"
9c08d1fa 8127 ""
cffb2a26 8128)
8129
8130(define_insn "*arm_jump"
8131 [(set (pc)
8132 (label_ref (match_operand 0 "" "")))]
25f905c2 8133 "TARGET_32BIT"
9c08d1fa 8134 "*
0d66636f 8135 {
8136 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8137 {
8138 arm_ccfsm_state += 2;
8139 return \"\";
8140 }
8141 return \"b%?\\t%l0\";
8142 }
8143 "
8144 [(set_attr "predicable" "yes")]
8145)
9c08d1fa 8146
cffb2a26 8147(define_insn "*thumb_jump"
8148 [(set (pc)
8149 (label_ref (match_operand 0 "" "")))]
25f905c2 8150 "TARGET_THUMB1"
cffb2a26 8151 "*
8152 if (get_attr_length (insn) == 2)
8153 return \"b\\t%l0\";
8154 return \"bl\\t%l0\\t%@ far jump\";
8155 "
8156 [(set (attr "far_jump")
8157 (if_then_else
8158 (eq_attr "length" "4")
8159 (const_string "yes")
8160 (const_string "no")))
8161 (set (attr "length")
8162 (if_then_else
911ed8af 8163 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8164 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8165 (const_int 2)
8166 (const_int 4)))]
8167)
8168
d3373b54 8169(define_expand "call"
8170 [(parallel [(call (match_operand 0 "memory_operand" "")
8171 (match_operand 1 "general_operand" ""))
cffb2a26 8172 (use (match_operand 2 "" ""))
bd5b4116 8173 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8174 "TARGET_EITHER"
6c4c2133 8175 "
8176 {
bac7fc85 8177 rtx callee, pat;
bbe777ea 8178
bbe777ea 8179 /* In an untyped call, we can get NULL for operand 2. */
8180 if (operands[2] == NULL_RTX)
8181 operands[2] = const0_rtx;
8182
de55252a 8183 /* Decide if we should generate indirect calls by loading the
85c36fd1 8184 32-bit address of the callee into a register before performing the
de55252a 8185 branch and link. */
8186 callee = XEXP (operands[0], 0);
8187 if (GET_CODE (callee) == SYMBOL_REF
8188 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8189 : !REG_P (callee))
bbe777ea 8190 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8191
8192 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8193 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8194 DONE;
6c4c2133 8195 }"
8196)
d3373b54 8197
bac7fc85 8198(define_expand "call_internal"
8199 [(parallel [(call (match_operand 0 "memory_operand" "")
8200 (match_operand 1 "general_operand" ""))
8201 (use (match_operand 2 "" ""))
8202 (clobber (reg:SI LR_REGNUM))])])
8203
f1039640 8204(define_insn "*call_reg_armv5"
d3373b54 8205 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8206 (match_operand 1 "" ""))
8207 (use (match_operand 2 "" ""))
bd5b4116 8208 (clobber (reg:SI LR_REGNUM))]
f1039640 8209 "TARGET_ARM && arm_arch5"
8210 "blx%?\\t%0"
8211 [(set_attr "type" "call")]
8212)
8213
8214(define_insn "*call_reg_arm"
8215 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8216 (match_operand 1 "" ""))
8217 (use (match_operand 2 "" ""))
8218 (clobber (reg:SI LR_REGNUM))]
8219 "TARGET_ARM && !arm_arch5"
9c08d1fa 8220 "*
5565501b 8221 return output_call (operands);
cffb2a26 8222 "
8223 ;; length is worst case, normally it is only two
8224 [(set_attr "length" "12")
8225 (set_attr "type" "call")]
8226)
9c08d1fa 8227
f7fbdd4a 8228(define_insn "*call_mem"
a3c63a9d 8229 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8230 (match_operand 1 "" ""))
8231 (use (match_operand 2 "" ""))
bd5b4116 8232 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8233 "TARGET_ARM"
9c08d1fa 8234 "*
5565501b 8235 return output_call_mem (operands);
cffb2a26 8236 "
8237 [(set_attr "length" "12")
8238 (set_attr "type" "call")]
8239)
8240
25f905c2 8241(define_insn "*call_reg_thumb1_v5"
cffb2a26 8242 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8243 (match_operand 1 "" ""))
8244 (use (match_operand 2 "" ""))
bd5b4116 8245 (clobber (reg:SI LR_REGNUM))]
25f905c2 8246 "TARGET_THUMB1 && arm_arch5"
f1039640 8247 "blx\\t%0"
8248 [(set_attr "length" "2")
8249 (set_attr "type" "call")]
cffb2a26 8250)
8251
25f905c2 8252(define_insn "*call_reg_thumb1"
f1039640 8253 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8254 (match_operand 1 "" ""))
8255 (use (match_operand 2 "" ""))
bd5b4116 8256 (clobber (reg:SI LR_REGNUM))]
25f905c2 8257 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8258 "*
8259 {
150502c9 8260 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8261 return thumb_call_via_reg (operands[0]);
150502c9 8262 else if (operands[1] == const0_rtx)
f1039640 8263 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8264 else if (frame_pointer_needed)
8265 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8266 else
150502c9 8267 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8268 }"
8269 [(set_attr "type" "call")]
8270)
9c08d1fa 8271
d3373b54 8272(define_expand "call_value"
e0698af7 8273 [(parallel [(set (match_operand 0 "" "")
8274 (call (match_operand 1 "memory_operand" "")
8275 (match_operand 2 "general_operand" "")))
cffb2a26 8276 (use (match_operand 3 "" ""))
bd5b4116 8277 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8278 "TARGET_EITHER"
6c4c2133 8279 "
8280 {
bac7fc85 8281 rtx pat, callee;
bbe777ea 8282
8283 /* In an untyped call, we can get NULL for operand 2. */
8284 if (operands[3] == 0)
8285 operands[3] = const0_rtx;
8286
de55252a 8287 /* Decide if we should generate indirect calls by loading the
8288 32-bit address of the callee into a register before performing the
8289 branch and link. */
8290 callee = XEXP (operands[1], 0);
8291 if (GET_CODE (callee) == SYMBOL_REF
8292 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8293 : !REG_P (callee))
78fe751b 8294 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8295
8296 pat = gen_call_value_internal (operands[0], operands[1],
8297 operands[2], operands[3]);
8298 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8299 DONE;
6c4c2133 8300 }"
8301)
d3373b54 8302
bac7fc85 8303(define_expand "call_value_internal"
8304 [(parallel [(set (match_operand 0 "" "")
8305 (call (match_operand 1 "memory_operand" "")
8306 (match_operand 2 "general_operand" "")))
8307 (use (match_operand 3 "" ""))
8308 (clobber (reg:SI LR_REGNUM))])])
8309
f1039640 8310(define_insn "*call_value_reg_armv5"
27ed6835 8311 [(set (match_operand 0 "" "")
755eb2b4 8312 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8313 (match_operand 2 "" "")))
bbe777ea 8314 (use (match_operand 3 "" ""))
bd5b4116 8315 (clobber (reg:SI LR_REGNUM))]
f1039640 8316 "TARGET_ARM && arm_arch5"
8317 "blx%?\\t%1"
8318 [(set_attr "type" "call")]
8319)
8320
8321(define_insn "*call_value_reg_arm"
8322 [(set (match_operand 0 "" "")
8323 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8324 (match_operand 2 "" "")))
8325 (use (match_operand 3 "" ""))
8326 (clobber (reg:SI LR_REGNUM))]
8327 "TARGET_ARM && !arm_arch5"
9c08d1fa 8328 "*
215b30b3 8329 return output_call (&operands[1]);
cffb2a26 8330 "
8331 [(set_attr "length" "12")
8332 (set_attr "type" "call")]
8333)
9c08d1fa 8334
f7fbdd4a 8335(define_insn "*call_value_mem"
27ed6835 8336 [(set (match_operand 0 "" "")
a3c63a9d 8337 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8338 (match_operand 2 "" "")))
bbe777ea 8339 (use (match_operand 3 "" ""))
bd5b4116 8340 (clobber (reg:SI LR_REGNUM))]
215b30b3 8341 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8342 "*
215b30b3 8343 return output_call_mem (&operands[1]);
cffb2a26 8344 "
8345 [(set_attr "length" "12")
8346 (set_attr "type" "call")]
8347)
9c08d1fa 8348
25f905c2 8349(define_insn "*call_value_reg_thumb1_v5"
f1039640 8350 [(set (match_operand 0 "" "")
8351 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8352 (match_operand 2 "" "")))
8353 (use (match_operand 3 "" ""))
8354 (clobber (reg:SI LR_REGNUM))]
25f905c2 8355 "TARGET_THUMB1 && arm_arch5"
f1039640 8356 "blx\\t%1"
8357 [(set_attr "length" "2")
8358 (set_attr "type" "call")]
8359)
8360
25f905c2 8361(define_insn "*call_value_reg_thumb1"
f1039640 8362 [(set (match_operand 0 "" "")
8363 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8364 (match_operand 2 "" "")))
8365 (use (match_operand 3 "" ""))
8366 (clobber (reg:SI LR_REGNUM))]
25f905c2 8367 "TARGET_THUMB1 && !arm_arch5"
f1039640 8368 "*
8369 {
150502c9 8370 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8371 return thumb_call_via_reg (operands[1]);
150502c9 8372 else if (operands[2] == const0_rtx)
f1039640 8373 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8374 else if (frame_pointer_needed)
8375 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8376 else
150502c9 8377 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8378 }"
8379 [(set_attr "type" "call")]
8380)
8381
9c08d1fa 8382;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8383;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8384
f7fbdd4a 8385(define_insn "*call_symbol"
27ed6835 8386 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8387 (match_operand 1 "" ""))
bbe777ea 8388 (use (match_operand 2 "" ""))
bd5b4116 8389 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8390 "TARGET_ARM
8391 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8392 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8393 "*
8394 {
55c1e470 8395 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8396 }"
cffb2a26 8397 [(set_attr "type" "call")]
8398)
9c08d1fa 8399
f7fbdd4a 8400(define_insn "*call_value_symbol"
ccd90aaa 8401 [(set (match_operand 0 "" "")
27ed6835 8402 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8403 (match_operand:SI 2 "" "")))
bbe777ea 8404 (use (match_operand 3 "" ""))
bd5b4116 8405 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8406 "TARGET_ARM
8407 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8408 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8409 "*
8410 {
55c1e470 8411 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8412 }"
cffb2a26 8413 [(set_attr "type" "call")]
8414)
8415
8416(define_insn "*call_insn"
27ed6835 8417 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8418 (match_operand:SI 1 "" ""))
8419 (use (match_operand 2 "" ""))
bd5b4116 8420 (clobber (reg:SI LR_REGNUM))]
1c494086 8421 "TARGET_THUMB
1675c6e9 8422 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8423 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8424 "bl\\t%a0"
8425 [(set_attr "length" "4")
8426 (set_attr "type" "call")]
8427)
8428
8429(define_insn "*call_value_insn"
ccd90aaa 8430 [(set (match_operand 0 "" "")
27ed6835 8431 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8432 (match_operand 2 "" "")))
8433 (use (match_operand 3 "" ""))
bd5b4116 8434 (clobber (reg:SI LR_REGNUM))]
1c494086 8435 "TARGET_THUMB
1675c6e9 8436 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8437 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8438 "bl\\t%a1"
8439 [(set_attr "length" "4")
8440 (set_attr "type" "call")]
8441)
9c08d1fa 8442
1c494086 8443;; We may also be able to do sibcalls for Thumb, but it's much harder...
8444(define_expand "sibcall"
8445 [(parallel [(call (match_operand 0 "memory_operand" "")
8446 (match_operand 1 "general_operand" ""))
2ba80634 8447 (return)
8448 (use (match_operand 2 "" ""))])]
1c494086 8449 "TARGET_ARM"
8450 "
8451 {
8452 if (operands[2] == NULL_RTX)
8453 operands[2] = const0_rtx;
1c494086 8454 }"
8455)
8456
8457(define_expand "sibcall_value"
ccd90aaa 8458 [(parallel [(set (match_operand 0 "" "")
1c494086 8459 (call (match_operand 1 "memory_operand" "")
8460 (match_operand 2 "general_operand" "")))
2ba80634 8461 (return)
8462 (use (match_operand 3 "" ""))])]
1c494086 8463 "TARGET_ARM"
8464 "
8465 {
8466 if (operands[3] == NULL_RTX)
8467 operands[3] = const0_rtx;
1c494086 8468 }"
8469)
8470
8471(define_insn "*sibcall_insn"
8472 [(call (mem:SI (match_operand:SI 0 "" "X"))
8473 (match_operand 1 "" ""))
2ba80634 8474 (return)
8475 (use (match_operand 2 "" ""))]
1c494086 8476 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8477 "*
8478 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8479 "
8480 [(set_attr "type" "call")]
8481)
8482
8483(define_insn "*sibcall_value_insn"
ccd90aaa 8484 [(set (match_operand 0 "" "")
755eb2b4 8485 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8486 (match_operand 2 "" "")))
2ba80634 8487 (return)
8488 (use (match_operand 3 "" ""))]
1c494086 8489 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8490 "*
8491 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8492 "
8493 [(set_attr "type" "call")]
8494)
8495
9c08d1fa 8496;; Often the return insn will be the same as loading from memory, so set attr
8497(define_insn "return"
8498 [(return)]
cffb2a26 8499 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8500 "*
9c08d1fa 8501 {
cffb2a26 8502 if (arm_ccfsm_state == 2)
8503 {
8504 arm_ccfsm_state += 2;
8505 return \"\";
8506 }
5db468b7 8507 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8508 }"
a2cd141b 8509 [(set_attr "type" "load1")
755eb2b4 8510 (set_attr "length" "12")
0d66636f 8511 (set_attr "predicable" "yes")]
cffb2a26 8512)
9c08d1fa 8513
f7fbdd4a 8514(define_insn "*cond_return"
9c08d1fa 8515 [(set (pc)
8fa3ba89 8516 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8517 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8518 (return)
8519 (pc)))]
cffb2a26 8520 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8521 "*
8fa3ba89 8522 {
8523 if (arm_ccfsm_state == 2)
8524 {
8525 arm_ccfsm_state += 2;
8526 return \"\";
8527 }
8528 return output_return_instruction (operands[0], TRUE, FALSE);
8529 }"
8530 [(set_attr "conds" "use")
755eb2b4 8531 (set_attr "length" "12")
a2cd141b 8532 (set_attr "type" "load1")]
8fa3ba89 8533)
9c08d1fa 8534
f7fbdd4a 8535(define_insn "*cond_return_inverted"
9c08d1fa 8536 [(set (pc)
8fa3ba89 8537 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8538 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8539 (pc)
8540 (return)))]
cffb2a26 8541 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8542 "*
8fa3ba89 8543 {
8544 if (arm_ccfsm_state == 2)
8545 {
8546 arm_ccfsm_state += 2;
8547 return \"\";
8548 }
8549 return output_return_instruction (operands[0], TRUE, TRUE);
8550 }"
8551 [(set_attr "conds" "use")
37a1317b 8552 (set_attr "length" "12")
a2cd141b 8553 (set_attr "type" "load1")]
8fa3ba89 8554)
9c08d1fa 8555
68121397 8556;; Generate a sequence of instructions to determine if the processor is
8557;; in 26-bit or 32-bit mode, and return the appropriate return address
8558;; mask.
8559
8560(define_expand "return_addr_mask"
8561 [(set (match_dup 1)
8562 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8563 (const_int 0)))
8564 (set (match_operand:SI 0 "s_register_operand" "")
8565 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8566 (const_int -1)
8567 (const_int 67108860)))] ; 0x03fffffc
8568 "TARGET_ARM"
8569 "
62eddbd4 8570 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8571 ")
8572
8573(define_insn "*check_arch2"
8574 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8575 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8576 (const_int 0)))]
8577 "TARGET_ARM"
8578 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8579 [(set_attr "length" "8")
8580 (set_attr "conds" "set")]
8581)
8582
9c08d1fa 8583;; Call subroutine returning any type.
8584
8585(define_expand "untyped_call"
8586 [(parallel [(call (match_operand 0 "" "")
8587 (const_int 0))
8588 (match_operand 1 "" "")
8589 (match_operand 2 "" "")])]
ccd90aaa 8590 "TARGET_EITHER"
9c08d1fa 8591 "
215b30b3 8592 {
8593 int i;
ccd90aaa 8594 rtx par = gen_rtx_PARALLEL (VOIDmode,
8595 rtvec_alloc (XVECLEN (operands[2], 0)));
8596 rtx addr = gen_reg_rtx (Pmode);
8597 rtx mem;
8598 int size = 0;
9c08d1fa 8599
ccd90aaa 8600 emit_move_insn (addr, XEXP (operands[1], 0));
8601 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8602
215b30b3 8603 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8604 {
ccd90aaa 8605 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8606
ccd90aaa 8607 /* Default code only uses r0 as a return value, but we could
8608 be using anything up to 4 registers. */
8609 if (REGNO (src) == R0_REGNUM)
8610 src = gen_rtx_REG (TImode, R0_REGNUM);
8611
8612 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8613 GEN_INT (size));
8614 size += GET_MODE_SIZE (GET_MODE (src));
8615 }
8616
8617 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8618 const0_rtx));
8619
8620 size = 0;
8621
8622 for (i = 0; i < XVECLEN (par, 0); i++)
8623 {
8624 HOST_WIDE_INT offset = 0;
8625 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8626
8627 if (size != 0)
8628 emit_move_insn (addr, plus_constant (addr, size));
8629
8630 mem = change_address (mem, GET_MODE (reg), NULL);
8631 if (REGNO (reg) == R0_REGNUM)
8632 {
8633 /* On thumb we have to use a write-back instruction. */
8634 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8635 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8636 size = TARGET_ARM ? 16 : 0;
8637 }
8638 else
8639 {
8640 emit_move_insn (mem, reg);
8641 size = GET_MODE_SIZE (GET_MODE (reg));
8642 }
215b30b3 8643 }
9c08d1fa 8644
215b30b3 8645 /* The optimizer does not know that the call sets the function value
8646 registers we stored in the result block. We avoid problems by
8647 claiming that all hard registers are used and clobbered at this
8648 point. */
8649 emit_insn (gen_blockage ());
8650
8651 DONE;
8652 }"
8653)
9c08d1fa 8654
ccd90aaa 8655(define_expand "untyped_return"
8656 [(match_operand:BLK 0 "memory_operand" "")
8657 (match_operand 1 "" "")]
8658 "TARGET_EITHER"
8659 "
8660 {
8661 int i;
8662 rtx addr = gen_reg_rtx (Pmode);
8663 rtx mem;
8664 int size = 0;
8665
8666 emit_move_insn (addr, XEXP (operands[0], 0));
8667 mem = change_address (operands[0], BLKmode, addr);
8668
8669 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8670 {
8671 HOST_WIDE_INT offset = 0;
8672 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8673
8674 if (size != 0)
8675 emit_move_insn (addr, plus_constant (addr, size));
8676
8677 mem = change_address (mem, GET_MODE (reg), NULL);
8678 if (REGNO (reg) == R0_REGNUM)
8679 {
8680 /* On thumb we have to use a write-back instruction. */
8681 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8682 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8683 size = TARGET_ARM ? 16 : 0;
8684 }
8685 else
8686 {
8687 emit_move_insn (reg, mem);
8688 size = GET_MODE_SIZE (GET_MODE (reg));
8689 }
8690 }
8691
8692 /* Emit USE insns before the return. */
8693 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8694 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8695
8696 /* Construct the return. */
8697 expand_naked_return ();
8698
8699 DONE;
8700 }"
8701)
8702
9c08d1fa 8703;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8704;; all of memory. This blocks insns from being moved across this point.
8705
8706(define_insn "blockage"
e1159bbe 8707 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8708 "TARGET_EITHER"
9c08d1fa 8709 ""
cffb2a26 8710 [(set_attr "length" "0")
8711 (set_attr "type" "block")]
8712)
9c08d1fa 8713
f7fbdd4a 8714(define_expand "casesi"
8715 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8716 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8717 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8718 (match_operand:SI 3 "" "") ; table label
8719 (match_operand:SI 4 "" "")] ; Out of range label
25f905c2 8720 "TARGET_32BIT"
f7fbdd4a 8721 "
215b30b3 8722 {
8723 rtx reg;
8724 if (operands[1] != const0_rtx)
8725 {
8726 reg = gen_reg_rtx (SImode);
f7fbdd4a 8727
215b30b3 8728 emit_insn (gen_addsi3 (reg, operands[0],
8729 GEN_INT (-INTVAL (operands[1]))));
8730 operands[0] = reg;
8731 }
9c08d1fa 8732
215b30b3 8733 if (!const_ok_for_arm (INTVAL (operands[2])))
8734 operands[2] = force_reg (SImode, operands[2]);
8735
25f905c2 8736 if (TARGET_ARM)
8737 {
8738 emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
8739 operands[3], operands[4]));
8740 }
8741 else if (flag_pic)
8742 {
8743 emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
8744 operands[2], operands[3], operands[4]));
8745 }
8746 else
8747 {
8748 emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
8749 operands[3], operands[4]));
8750 }
215b30b3 8751 DONE;
8752 }"
8753)
f7fbdd4a 8754
f082f1c4 8755;; The USE in this pattern is needed to tell flow analysis that this is
8756;; a CASESI insn. It has no other purpose.
25f905c2 8757(define_insn "arm_casesi_internal"
f082f1c4 8758 [(parallel [(set (pc)
8759 (if_then_else
8760 (leu (match_operand:SI 0 "s_register_operand" "r")
8761 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8762 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8763 (label_ref (match_operand 2 "" ""))))
8764 (label_ref (match_operand 3 "" ""))))
bd5b4116 8765 (clobber (reg:CC CC_REGNUM))
f082f1c4 8766 (use (label_ref (match_dup 2)))])]
cffb2a26 8767 "TARGET_ARM"
f7fbdd4a 8768 "*
0d66636f 8769 if (flag_pic)
8770 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8771 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8772 "
8773 [(set_attr "conds" "clob")
8774 (set_attr "length" "12")]
8775)
9c08d1fa 8776
cffb2a26 8777(define_expand "indirect_jump"
9c08d1fa 8778 [(set (pc)
cffb2a26 8779 (match_operand:SI 0 "s_register_operand" ""))]
8780 "TARGET_EITHER"
25f905c2 8781 "
8782 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8783 address and use bx. */
8784 if (TARGET_THUMB2)
8785 {
8786 rtx tmp;
8787 tmp = gen_reg_rtx (SImode);
8788 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8789 operands[0] = tmp;
8790 }
8791 "
cffb2a26 8792)
8793
f1039640 8794;; NB Never uses BX.
cffb2a26 8795(define_insn "*arm_indirect_jump"
8796 [(set (pc)
8797 (match_operand:SI 0 "s_register_operand" "r"))]
8798 "TARGET_ARM"
8799 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8800 [(set_attr "predicable" "yes")]
cffb2a26 8801)
9c08d1fa 8802
f7fbdd4a 8803(define_insn "*load_indirect_jump"
9c08d1fa 8804 [(set (pc)
8805 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8806 "TARGET_ARM"
8807 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8808 [(set_attr "type" "load1")
61a2d04c 8809 (set_attr "pool_range" "4096")
8810 (set_attr "neg_pool_range" "4084")
0d66636f 8811 (set_attr "predicable" "yes")]
cffb2a26 8812)
8813
f1039640 8814;; NB Never uses BX.
25f905c2 8815(define_insn "*thumb1_indirect_jump"
cffb2a26 8816 [(set (pc)
8817 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8818 "TARGET_THUMB1"
cffb2a26 8819 "mov\\tpc, %0"
8820 [(set_attr "conds" "clob")
8821 (set_attr "length" "2")]
8822)
8823
9c08d1fa 8824\f
8825;; Misc insns
8826
8827(define_insn "nop"
8828 [(const_int 0)]
cffb2a26 8829 "TARGET_EITHER"
8830 "*
25f905c2 8831 if (TARGET_UNIFIED_ASM)
8832 return \"nop\";
cffb2a26 8833 if (TARGET_ARM)
8834 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8835 return \"mov\\tr8, r8\";
8836 "
8837 [(set (attr "length")
8838 (if_then_else (eq_attr "is_thumb" "yes")
8839 (const_int 2)
8840 (const_int 4)))]
8841)
8842
9c08d1fa 8843\f
8844;; Patterns to allow combination of arithmetic, cond code and shifts
8845
f7fbdd4a 8846(define_insn "*arith_shiftsi"
9c08d1fa 8847 [(set (match_operand:SI 0 "s_register_operand" "=r")
8848 (match_operator:SI 1 "shiftable_operator"
8849 [(match_operator:SI 3 "shift_operator"
8850 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8851 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8852 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 8853 "TARGET_ARM"
6c4c2133 8854 "%i1%?\\t%0, %2, %4%S3"
344495ea 8855 [(set_attr "predicable" "yes")
331beb1a 8856 (set_attr "shift" "4")
a2cd141b 8857 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8858 (const_string "alu_shift")
8859 (const_string "alu_shift_reg")))]
6c4c2133 8860)
9c08d1fa 8861
d7863cfe 8862(define_split
8863 [(set (match_operand:SI 0 "s_register_operand" "")
8864 (match_operator:SI 1 "shiftable_operator"
8865 [(match_operator:SI 2 "shiftable_operator"
8866 [(match_operator:SI 3 "shift_operator"
8867 [(match_operand:SI 4 "s_register_operand" "")
8868 (match_operand:SI 5 "reg_or_int_operand" "")])
8869 (match_operand:SI 6 "s_register_operand" "")])
8870 (match_operand:SI 7 "arm_rhs_operand" "")]))
8871 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8872 "TARGET_ARM"
8873 [(set (match_dup 8)
8874 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8875 (match_dup 6)]))
8876 (set (match_dup 0)
8877 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8878 "")
8879
f7fbdd4a 8880(define_insn "*arith_shiftsi_compare0"
bd5b4116 8881 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8882 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8883 [(match_operator:SI 3 "shift_operator"
8884 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8885 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8886 (match_operand:SI 2 "s_register_operand" "r")])
8887 (const_int 0)))
8888 (set (match_operand:SI 0 "s_register_operand" "=r")
8889 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8890 (match_dup 2)]))]
cffb2a26 8891 "TARGET_ARM"
25f905c2 8892 "%i1%.\\t%0, %2, %4%S3"
344495ea 8893 [(set_attr "conds" "set")
331beb1a 8894 (set_attr "shift" "4")
a2cd141b 8895 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8896 (const_string "alu_shift")
8897 (const_string "alu_shift_reg")))]
0d66636f 8898)
9c08d1fa 8899
f7fbdd4a 8900(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8901 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8902 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8903 [(match_operator:SI 3 "shift_operator"
8904 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8905 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8906 (match_operand:SI 2 "s_register_operand" "r")])
8907 (const_int 0)))
8908 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8909 "TARGET_ARM"
25f905c2 8910 "%i1%.\\t%0, %2, %4%S3"
344495ea 8911 [(set_attr "conds" "set")
331beb1a 8912 (set_attr "shift" "4")
a2cd141b 8913 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8914 (const_string "alu_shift")
8915 (const_string "alu_shift_reg")))]
0d66636f 8916)
9c08d1fa 8917
f7fbdd4a 8918(define_insn "*sub_shiftsi"
9c08d1fa 8919 [(set (match_operand:SI 0 "s_register_operand" "=r")
8920 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8921 (match_operator:SI 2 "shift_operator"
8922 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8923 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 8924 "TARGET_ARM"
6c4c2133 8925 "sub%?\\t%0, %1, %3%S2"
344495ea 8926 [(set_attr "predicable" "yes")
331beb1a 8927 (set_attr "shift" "3")
a2cd141b 8928 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8929 (const_string "alu_shift")
8930 (const_string "alu_shift_reg")))]
6c4c2133 8931)
9c08d1fa 8932
f7fbdd4a 8933(define_insn "*sub_shiftsi_compare0"
bd5b4116 8934 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8935 (compare:CC_NOOV
8936 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8937 (match_operator:SI 2 "shift_operator"
8938 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8939 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8940 (const_int 0)))
9c08d1fa 8941 (set (match_operand:SI 0 "s_register_operand" "=r")
8942 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8943 (match_dup 4)])))]
cffb2a26 8944 "TARGET_ARM"
25f905c2 8945 "sub%.\\t%0, %1, %3%S2"
344495ea 8946 [(set_attr "conds" "set")
a2cd141b 8947 (set_attr "shift" "3")
8948 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8949 (const_string "alu_shift")
8950 (const_string "alu_shift_reg")))]
0d66636f 8951)
9c08d1fa 8952
f7fbdd4a 8953(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8954 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8955 (compare:CC_NOOV
8956 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8957 (match_operator:SI 2 "shift_operator"
8958 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8959 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8960 (const_int 0)))
9c08d1fa 8961 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8962 "TARGET_ARM"
25f905c2 8963 "sub%.\\t%0, %1, %3%S2"
344495ea 8964 [(set_attr "conds" "set")
a2cd141b 8965 (set_attr "shift" "3")
8966 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8967 (const_string "alu_shift")
8968 (const_string "alu_shift_reg")))]
0d66636f 8969)
9c08d1fa 8970
9c08d1fa 8971\f
8972
f7fbdd4a 8973(define_insn "*and_scc"
9c08d1fa 8974 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8975 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8976 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8977 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8978 "TARGET_ARM"
e2348bcb 8979 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8980 [(set_attr "conds" "use")
8981 (set_attr "length" "8")]
8982)
9c08d1fa 8983
f7fbdd4a 8984(define_insn "*ior_scc"
9c08d1fa 8985 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8986 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8987 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8988 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8989 "TARGET_ARM"
e2348bcb 8990 "@
899850b0 8991 orr%d2\\t%0, %1, #1
8992 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8993 [(set_attr "conds" "use")
8994 (set_attr "length" "4,8")]
8995)
9c08d1fa 8996
f7fbdd4a 8997(define_insn "*compare_scc"
5565501b 8998 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8999 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9000 [(match_operand:SI 2 "s_register_operand" "r,r")
9001 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9002 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9003 "TARGET_ARM"
9c08d1fa 9004 "*
601f584c 9005 if (operands[3] == const0_rtx)
9006 {
9007 if (GET_CODE (operands[1]) == LT)
9008 return \"mov\\t%0, %2, lsr #31\";
9009
9010 if (GET_CODE (operands[1]) == GE)
9011 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 9012
601f584c 9013 if (GET_CODE (operands[1]) == EQ)
9014 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9015 }
e2348bcb 9016
8fa3ba89 9017 if (GET_CODE (operands[1]) == NE)
9018 {
9019 if (which_alternative == 1)
9020 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9021 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9022 }
9023 if (which_alternative == 1)
9024 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9025 else
9026 output_asm_insn (\"cmp\\t%2, %3\", operands);
9027 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9028 "
9029 [(set_attr "conds" "clob")
9030 (set_attr "length" "12")]
9031)
9c08d1fa 9032
f7fbdd4a 9033(define_insn "*cond_move"
9c08d1fa 9034 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9035 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9036 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9037 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9038 (const_int 0)])
9039 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9040 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9041 "TARGET_ARM"
9c08d1fa 9042 "*
8fa3ba89 9043 if (GET_CODE (operands[3]) == NE)
9044 {
9045 if (which_alternative != 1)
9046 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9047 if (which_alternative != 0)
9048 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9049 return \"\";
9050 }
9051 if (which_alternative != 0)
9052 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9053 if (which_alternative != 1)
9054 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9055 return \"\";
9056 "
9057 [(set_attr "conds" "use")
9058 (set_attr "length" "4,4,8")]
9059)
9c08d1fa 9060
f7fbdd4a 9061(define_insn "*cond_arith"
9c08d1fa 9062 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9063 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9064 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9065 [(match_operand:SI 2 "s_register_operand" "r,r")
9066 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9067 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9068 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9069 "TARGET_ARM"
9c08d1fa 9070 "*
8fa3ba89 9071 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9072 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9073
8fa3ba89 9074 output_asm_insn (\"cmp\\t%2, %3\", operands);
9075 if (GET_CODE (operands[5]) == AND)
9076 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9077 else if (GET_CODE (operands[5]) == MINUS)
9078 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9079 else if (which_alternative != 0)
9080 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9081 return \"%i5%d4\\t%0, %1, #1\";
9082 "
9083 [(set_attr "conds" "clob")
9084 (set_attr "length" "12")]
9085)
9c08d1fa 9086
f7fbdd4a 9087(define_insn "*cond_sub"
9c08d1fa 9088 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9089 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9090 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9091 [(match_operand:SI 2 "s_register_operand" "r,r")
9092 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9093 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9094 "TARGET_ARM"
9c08d1fa 9095 "*
8fa3ba89 9096 output_asm_insn (\"cmp\\t%2, %3\", operands);
9097 if (which_alternative != 0)
9098 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9099 return \"sub%d4\\t%0, %1, #1\";
9100 "
9101 [(set_attr "conds" "clob")
9102 (set_attr "length" "8,12")]
9103)
9c08d1fa 9104
25f905c2 9105;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 9106(define_insn "*cmp_ite0"
cffb2a26 9107 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9108 (compare
9109 (if_then_else:SI
8fa3ba89 9110 (match_operator 4 "arm_comparison_operator"
aea4c774 9111 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9112 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9113 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9114 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9115 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9116 (const_int 0))
9117 (const_int 0)))]
cffb2a26 9118 "TARGET_ARM"
9c08d1fa 9119 "*
aea4c774 9120 {
8fa3ba89 9121 static const char * const opcodes[4][2] =
9122 {
9123 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9124 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9125 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9126 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9127 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9128 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9129 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9130 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9131 };
9132 int swap =
9133 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9134
9135 return opcodes[which_alternative][swap];
9136 }"
9137 [(set_attr "conds" "set")
9138 (set_attr "length" "8")]
9139)
9c08d1fa 9140
aea4c774 9141(define_insn "*cmp_ite1"
cffb2a26 9142 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9143 (compare
9144 (if_then_else:SI
8fa3ba89 9145 (match_operator 4 "arm_comparison_operator"
aea4c774 9146 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 9147 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9148 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9149 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 9150 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 9151 (const_int 1))
9152 (const_int 0)))]
cffb2a26 9153 "TARGET_ARM"
9c08d1fa 9154 "*
9c08d1fa 9155 {
215b30b3 9156 static const char * const opcodes[4][2] =
9157 {
9158 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9159 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9160 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9161 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9162 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9163 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9164 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9165 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9166 };
9167 int swap =
9168 comparison_dominates_p (GET_CODE (operands[5]),
9169 reverse_condition (GET_CODE (operands[4])));
9170
9171 return opcodes[which_alternative][swap];
9172 }"
8fa3ba89 9173 [(set_attr "conds" "set")
9174 (set_attr "length" "8")]
9175)
9c08d1fa 9176
f6c53574 9177(define_insn "*cmp_and"
9178 [(set (match_operand 6 "dominant_cc_register" "")
9179 (compare
9180 (and:SI
9181 (match_operator 4 "arm_comparison_operator"
9182 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9183 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9184 (match_operator:SI 5 "arm_comparison_operator"
9185 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9186 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9187 (const_int 0)))]
9188 "TARGET_ARM"
9189 "*
9190 {
35823b64 9191 static const char *const opcodes[4][2] =
f6c53574 9192 {
9193 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9194 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9195 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9196 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9197 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9198 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9199 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9200 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9201 };
9202 int swap =
9203 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9204
9205 return opcodes[which_alternative][swap];
9206 }"
9207 [(set_attr "conds" "set")
9208 (set_attr "predicable" "no")
9209 (set_attr "length" "8")]
9210)
9211
9212(define_insn "*cmp_ior"
9213 [(set (match_operand 6 "dominant_cc_register" "")
9214 (compare
9215 (ior:SI
9216 (match_operator 4 "arm_comparison_operator"
9217 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9218 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9219 (match_operator:SI 5 "arm_comparison_operator"
9220 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9221 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9222 (const_int 0)))]
9223 "TARGET_ARM"
9224 "*
9225{
35823b64 9226 static const char *const opcodes[4][2] =
f6c53574 9227 {
9228 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9229 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9230 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9231 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9232 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9233 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9234 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9235 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9236 };
9237 int swap =
9238 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9239
9240 return opcodes[which_alternative][swap];
9241}
9242"
9243 [(set_attr "conds" "set")
9244 (set_attr "length" "8")]
9245)
9246
3c5afce6 9247(define_insn_and_split "*ior_scc_scc"
9248 [(set (match_operand:SI 0 "s_register_operand" "=r")
9249 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9250 [(match_operand:SI 1 "s_register_operand" "r")
9251 (match_operand:SI 2 "arm_add_operand" "rIL")])
9252 (match_operator:SI 6 "arm_comparison_operator"
9253 [(match_operand:SI 4 "s_register_operand" "r")
9254 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9255 (clobber (reg:CC CC_REGNUM))]
9256 "TARGET_ARM
9257 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9258 != CCmode)"
9259 "#"
9260 "TARGET_ARM && reload_completed"
9261 [(set (match_dup 7)
9262 (compare
9263 (ior:SI
9264 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9265 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9266 (const_int 0)))
9267 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9268 "operands[7]
9269 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9270 DOM_CC_X_OR_Y),
601f584c 9271 CC_REGNUM);"
9272 [(set_attr "conds" "clob")
9273 (set_attr "length" "16")])
9274
9275; If the above pattern is followed by a CMP insn, then the compare is
9276; redundant, since we can rework the conditional instruction that follows.
9277(define_insn_and_split "*ior_scc_scc_cmp"
9278 [(set (match_operand 0 "dominant_cc_register" "")
9279 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9280 [(match_operand:SI 1 "s_register_operand" "r")
9281 (match_operand:SI 2 "arm_add_operand" "rIL")])
9282 (match_operator:SI 6 "arm_comparison_operator"
9283 [(match_operand:SI 4 "s_register_operand" "r")
9284 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9285 (const_int 0)))
9286 (set (match_operand:SI 7 "s_register_operand" "=r")
9287 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9288 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9289 "TARGET_ARM"
9290 "#"
9291 "TARGET_ARM && reload_completed"
9292 [(set (match_dup 0)
9293 (compare
9294 (ior:SI
9295 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9296 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9297 (const_int 0)))
9298 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9299 ""
9300 [(set_attr "conds" "set")
9301 (set_attr "length" "16")])
3c5afce6 9302
9303(define_insn_and_split "*and_scc_scc"
9304 [(set (match_operand:SI 0 "s_register_operand" "=r")
9305 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9306 [(match_operand:SI 1 "s_register_operand" "r")
9307 (match_operand:SI 2 "arm_add_operand" "rIL")])
9308 (match_operator:SI 6 "arm_comparison_operator"
9309 [(match_operand:SI 4 "s_register_operand" "r")
9310 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9311 (clobber (reg:CC CC_REGNUM))]
9312 "TARGET_ARM
9313 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9314 != CCmode)"
9315 "#"
601f584c 9316 "TARGET_ARM && reload_completed
9317 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9318 != CCmode)"
3c5afce6 9319 [(set (match_dup 7)
9320 (compare
9321 (and:SI
9322 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9323 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9324 (const_int 0)))
9325 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9326 "operands[7]
9327 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9328 DOM_CC_X_AND_Y),
601f584c 9329 CC_REGNUM);"
9330 [(set_attr "conds" "clob")
9331 (set_attr "length" "16")])
9332
9333; If the above pattern is followed by a CMP insn, then the compare is
9334; redundant, since we can rework the conditional instruction that follows.
9335(define_insn_and_split "*and_scc_scc_cmp"
9336 [(set (match_operand 0 "dominant_cc_register" "")
9337 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9338 [(match_operand:SI 1 "s_register_operand" "r")
9339 (match_operand:SI 2 "arm_add_operand" "rIL")])
9340 (match_operator:SI 6 "arm_comparison_operator"
9341 [(match_operand:SI 4 "s_register_operand" "r")
9342 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9343 (const_int 0)))
9344 (set (match_operand:SI 7 "s_register_operand" "=r")
9345 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9346 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9347 "TARGET_ARM"
9348 "#"
9349 "TARGET_ARM && reload_completed"
9350 [(set (match_dup 0)
9351 (compare
9352 (and:SI
9353 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9354 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9355 (const_int 0)))
9356 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9357 ""
9358 [(set_attr "conds" "set")
9359 (set_attr "length" "16")])
9360
9361;; If there is no dominance in the comparison, then we can still save an
9362;; instruction in the AND case, since we can know that the second compare
9363;; need only zero the value if false (if true, then the value is already
9364;; correct).
9365(define_insn_and_split "*and_scc_scc_nodom"
9366 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9367 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9368 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9369 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9370 (match_operator:SI 6 "arm_comparison_operator"
9371 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9372 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9373 (clobber (reg:CC CC_REGNUM))]
9374 "TARGET_ARM
9375 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9376 == CCmode)"
9377 "#"
9378 "TARGET_ARM && reload_completed"
9379 [(parallel [(set (match_dup 0)
9380 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9381 (clobber (reg:CC CC_REGNUM))])
9382 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9383 (set (match_dup 0)
9384 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9385 (match_dup 0)
9386 (const_int 0)))]
9387 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9388 operands[4], operands[5]),
9389 CC_REGNUM);
9390 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9391 operands[5]);"
9392 [(set_attr "conds" "clob")
9393 (set_attr "length" "20")])
3c5afce6 9394
3a0bdee0 9395(define_split
9396 [(set (reg:CC_NOOV CC_REGNUM)
9397 (compare:CC_NOOV (ior:SI
9398 (and:SI (match_operand:SI 0 "s_register_operand" "")
9399 (const_int 1))
9400 (match_operator:SI 1 "comparison_operator"
9401 [(match_operand:SI 2 "s_register_operand" "")
9402 (match_operand:SI 3 "arm_add_operand" "")]))
9403 (const_int 0)))
9404 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9405 "TARGET_ARM"
9406 [(set (match_dup 4)
9407 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9408 (match_dup 0)))
9409 (set (reg:CC_NOOV CC_REGNUM)
9410 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9411 (const_int 0)))]
9412 "")
9413
9414(define_split
9415 [(set (reg:CC_NOOV CC_REGNUM)
9416 (compare:CC_NOOV (ior:SI
9417 (match_operator:SI 1 "comparison_operator"
9418 [(match_operand:SI 2 "s_register_operand" "")
9419 (match_operand:SI 3 "arm_add_operand" "")])
9420 (and:SI (match_operand:SI 0 "s_register_operand" "")
9421 (const_int 1)))
9422 (const_int 0)))
9423 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9424 "TARGET_ARM"
9425 [(set (match_dup 4)
9426 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9427 (match_dup 0)))
9428 (set (reg:CC_NOOV CC_REGNUM)
9429 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9430 (const_int 0)))]
9431 "")
25f905c2 9432;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9433
f7fbdd4a 9434(define_insn "*negscc"
9c08d1fa 9435 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9436 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9437 [(match_operand:SI 1 "s_register_operand" "r")
9438 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9439 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9440 "TARGET_ARM"
9c08d1fa 9441 "*
2ca2ec2e 9442 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9443 return \"mov\\t%0, %1, asr #31\";
9444
9c08d1fa 9445 if (GET_CODE (operands[3]) == NE)
e2348bcb 9446 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9447
e2348bcb 9448 output_asm_insn (\"cmp\\t%1, %2\", operands);
9449 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9450 return \"mvn%d3\\t%0, #0\";
215b30b3 9451 "
8fa3ba89 9452 [(set_attr "conds" "clob")
9453 (set_attr "length" "12")]
9454)
9c08d1fa 9455
9456(define_insn "movcond"
9457 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9458 (if_then_else:SI
8fa3ba89 9459 (match_operator 5 "arm_comparison_operator"
5565501b 9460 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9461 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9462 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9463 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9464 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9465 "TARGET_ARM"
9c08d1fa 9466 "*
9467 if (GET_CODE (operands[5]) == LT
9468 && (operands[4] == const0_rtx))
9469 {
5565501b 9470 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9471 {
9c08d1fa 9472 if (operands[2] == const0_rtx)
e2348bcb 9473 return \"and\\t%0, %1, %3, asr #31\";
9474 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9475 }
9476 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9477 {
9c08d1fa 9478 if (operands[1] == const0_rtx)
e2348bcb 9479 return \"bic\\t%0, %2, %3, asr #31\";
9480 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9481 }
9482 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9483 are constants. */
9c08d1fa 9484 }
e2348bcb 9485
9c08d1fa 9486 if (GET_CODE (operands[5]) == GE
9487 && (operands[4] == const0_rtx))
9488 {
9489 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9490 {
9c08d1fa 9491 if (operands[2] == const0_rtx)
e2348bcb 9492 return \"bic\\t%0, %1, %3, asr #31\";
9493 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9494 }
9495 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9496 {
9c08d1fa 9497 if (operands[1] == const0_rtx)
e2348bcb 9498 return \"and\\t%0, %2, %3, asr #31\";
9499 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9500 }
9501 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9502 are constants. */
9c08d1fa 9503 }
9504 if (GET_CODE (operands[4]) == CONST_INT
9505 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9506 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9507 else
e2348bcb 9508 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9509 if (which_alternative != 0)
e2348bcb 9510 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9511 if (which_alternative != 1)
e2348bcb 9512 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9513 return \"\";
215b30b3 9514 "
8fa3ba89 9515 [(set_attr "conds" "clob")
9516 (set_attr "length" "8,8,12")]
9517)
9c08d1fa 9518
25f905c2 9519;; ??? The patterns below need checking for Thumb-2 usefulness.
9520
8a18b90c 9521(define_insn "*ifcompare_plus_move"
9522 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9523 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9524 [(match_operand:SI 4 "s_register_operand" "r,r")
9525 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9526 (plus:SI
9527 (match_operand:SI 2 "s_register_operand" "r,r")
9528 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9529 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9530 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9531 "TARGET_ARM"
8a18b90c 9532 "#"
8fa3ba89 9533 [(set_attr "conds" "clob")
9534 (set_attr "length" "8,12")]
9535)
8a18b90c 9536
9537(define_insn "*if_plus_move"
129a2fe4 9538 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9539 (if_then_else:SI
8fa3ba89 9540 (match_operator 4 "arm_comparison_operator"
8a18b90c 9541 [(match_operand 5 "cc_register" "") (const_int 0)])
9542 (plus:SI
129a2fe4 9543 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9544 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9545 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9546 "TARGET_ARM"
8a18b90c 9547 "@
9548 add%d4\\t%0, %2, %3
9549 sub%d4\\t%0, %2, #%n3
9550 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9551 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9552 [(set_attr "conds" "use")
9553 (set_attr "length" "4,4,8,8")
9554 (set_attr "type" "*,*,*,*")]
9555)
8a18b90c 9556
9557(define_insn "*ifcompare_move_plus"
5565501b 9558 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9559 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9560 [(match_operand:SI 4 "s_register_operand" "r,r")
9561 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9562 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9563 (plus:SI
9564 (match_operand:SI 2 "s_register_operand" "r,r")
9565 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9566 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9567 "TARGET_ARM"
8a18b90c 9568 "#"
8fa3ba89 9569 [(set_attr "conds" "clob")
9570 (set_attr "length" "8,12")]
9571)
8a18b90c 9572
9573(define_insn "*if_move_plus"
129a2fe4 9574 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9575 (if_then_else:SI
8fa3ba89 9576 (match_operator 4 "arm_comparison_operator"
8a18b90c 9577 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9578 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9579 (plus:SI
129a2fe4 9580 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9581 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9582 "TARGET_ARM"
8a18b90c 9583 "@
9584 add%D4\\t%0, %2, %3
9585 sub%D4\\t%0, %2, #%n3
9586 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9587 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9588 [(set_attr "conds" "use")
9589 (set_attr "length" "4,4,8,8")
9590 (set_attr "type" "*,*,*,*")]
9591)
8a18b90c 9592
9593(define_insn "*ifcompare_arith_arith"
9594 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9595 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9596 [(match_operand:SI 5 "s_register_operand" "r")
9597 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9598 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9599 [(match_operand:SI 1 "s_register_operand" "r")
9600 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9601 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9602 [(match_operand:SI 3 "s_register_operand" "r")
9603 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9604 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9605 "TARGET_ARM"
8a18b90c 9606 "#"
8fa3ba89 9607 [(set_attr "conds" "clob")
9608 (set_attr "length" "12")]
9609)
9c08d1fa 9610
8a18b90c 9611(define_insn "*if_arith_arith"
9612 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9613 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9614 [(match_operand 8 "cc_register" "") (const_int 0)])
9615 (match_operator:SI 6 "shiftable_operator"
9616 [(match_operand:SI 1 "s_register_operand" "r")
9617 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9618 (match_operator:SI 7 "shiftable_operator"
9619 [(match_operand:SI 3 "s_register_operand" "r")
9620 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9621 "TARGET_ARM"
8a18b90c 9622 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9623 [(set_attr "conds" "use")
9624 (set_attr "length" "8")]
9625)
8a18b90c 9626
f7fbdd4a 9627(define_insn "*ifcompare_arith_move"
9c08d1fa 9628 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9629 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9630 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9631 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9632 (match_operator:SI 7 "shiftable_operator"
9633 [(match_operand:SI 4 "s_register_operand" "r,r")
9634 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9635 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9636 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9637 "TARGET_ARM"
9c08d1fa 9638 "*
9c08d1fa 9639 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9640 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9641 everything is in registers then we can do this in two instructions. */
9c08d1fa 9642 if (operands[3] == const0_rtx
9643 && GET_CODE (operands[7]) != AND
9644 && GET_CODE (operands[5]) == REG
9645 && GET_CODE (operands[1]) == REG
9646 && REGNO (operands[1]) == REGNO (operands[4])
9647 && REGNO (operands[4]) != REGNO (operands[0]))
9648 {
9649 if (GET_CODE (operands[6]) == LT)
40dbec34 9650 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9651 else if (GET_CODE (operands[6]) == GE)
40dbec34 9652 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9653 }
9654 if (GET_CODE (operands[3]) == CONST_INT
9655 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9656 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9657 else
e2348bcb 9658 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9659 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9660 if (which_alternative != 0)
129a2fe4 9661 return \"mov%D6\\t%0, %1\";
9c08d1fa 9662 return \"\";
215b30b3 9663 "
8fa3ba89 9664 [(set_attr "conds" "clob")
9665 (set_attr "length" "8,12")]
9666)
9c08d1fa 9667
8a18b90c 9668(define_insn "*if_arith_move"
129a2fe4 9669 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9670 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9671 [(match_operand 6 "cc_register" "") (const_int 0)])
9672 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9673 [(match_operand:SI 2 "s_register_operand" "r,r")
9674 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9675 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9676 "TARGET_ARM"
8a18b90c 9677 "@
9678 %I5%d4\\t%0, %2, %3
129a2fe4 9679 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9680 [(set_attr "conds" "use")
9681 (set_attr "length" "4,8")
9682 (set_attr "type" "*,*")]
9683)
8a18b90c 9684
f7fbdd4a 9685(define_insn "*ifcompare_move_arith"
9c08d1fa 9686 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9687 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9688 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9689 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9690 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9691 (match_operator:SI 7 "shiftable_operator"
9692 [(match_operand:SI 2 "s_register_operand" "r,r")
9693 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9694 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9695 "TARGET_ARM"
9c08d1fa 9696 "*
9c08d1fa 9697 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9698 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9699 everything is in registers then we can do this in two instructions */
9700 if (operands[5] == const0_rtx
9701 && GET_CODE (operands[7]) != AND
9702 && GET_CODE (operands[3]) == REG
9703 && GET_CODE (operands[1]) == REG
9704 && REGNO (operands[1]) == REGNO (operands[2])
9705 && REGNO (operands[2]) != REGNO (operands[0]))
9706 {
9707 if (GET_CODE (operands[6]) == GE)
40dbec34 9708 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9709 else if (GET_CODE (operands[6]) == LT)
40dbec34 9710 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9711 }
40dbec34 9712
9c08d1fa 9713 if (GET_CODE (operands[5]) == CONST_INT
9714 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9715 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9716 else
e2348bcb 9717 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9718
9c08d1fa 9719 if (which_alternative != 0)
129a2fe4 9720 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9721 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9722 "
8fa3ba89 9723 [(set_attr "conds" "clob")
9724 (set_attr "length" "8,12")]
9725)
9c08d1fa 9726
8a18b90c 9727(define_insn "*if_move_arith"
129a2fe4 9728 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9729 (if_then_else:SI
8fa3ba89 9730 (match_operator 4 "arm_comparison_operator"
8a18b90c 9731 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9732 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9733 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9734 [(match_operand:SI 2 "s_register_operand" "r,r")
9735 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9736 "TARGET_ARM"
8a18b90c 9737 "@
9738 %I5%D4\\t%0, %2, %3
129a2fe4 9739 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9740 [(set_attr "conds" "use")
9741 (set_attr "length" "4,8")
9742 (set_attr "type" "*,*")]
9743)
8a18b90c 9744
9745(define_insn "*ifcompare_move_not"
9c08d1fa 9746 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9747 (if_then_else:SI
8fa3ba89 9748 (match_operator 5 "arm_comparison_operator"
8a18b90c 9749 [(match_operand:SI 3 "s_register_operand" "r,r")
9750 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9751 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9752 (not:SI
9753 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9754 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9755 "TARGET_ARM"
8a18b90c 9756 "#"
8fa3ba89 9757 [(set_attr "conds" "clob")
9758 (set_attr "length" "8,12")]
9759)
9c08d1fa 9760
8a18b90c 9761(define_insn "*if_move_not"
9762 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9763 (if_then_else:SI
8fa3ba89 9764 (match_operator 4 "arm_comparison_operator"
8a18b90c 9765 [(match_operand 3 "cc_register" "") (const_int 0)])
9766 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9767 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9768 "TARGET_ARM"
8a18b90c 9769 "@
9770 mvn%D4\\t%0, %2
9771 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9772 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9773 [(set_attr "conds" "use")
9774 (set_attr "length" "4,8,8")]
9775)
8a18b90c 9776
9777(define_insn "*ifcompare_not_move"
9c08d1fa 9778 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9779 (if_then_else:SI
8fa3ba89 9780 (match_operator 5 "arm_comparison_operator"
8a18b90c 9781 [(match_operand:SI 3 "s_register_operand" "r,r")
9782 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9783 (not:SI
9784 (match_operand:SI 2 "s_register_operand" "r,r"))
9785 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9786 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9787 "TARGET_ARM"
8a18b90c 9788 "#"
8fa3ba89 9789 [(set_attr "conds" "clob")
9790 (set_attr "length" "8,12")]
9791)
9c08d1fa 9792
8a18b90c 9793(define_insn "*if_not_move"
9794 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9795 (if_then_else:SI
8fa3ba89 9796 (match_operator 4 "arm_comparison_operator"
8a18b90c 9797 [(match_operand 3 "cc_register" "") (const_int 0)])
9798 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9799 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9800 "TARGET_ARM"
8a18b90c 9801 "@
9802 mvn%d4\\t%0, %2
9803 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9804 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9805 [(set_attr "conds" "use")
9806 (set_attr "length" "4,8,8")]
9807)
8a18b90c 9808
9809(define_insn "*ifcompare_shift_move"
9c08d1fa 9810 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9811 (if_then_else:SI
8fa3ba89 9812 (match_operator 6 "arm_comparison_operator"
8a18b90c 9813 [(match_operand:SI 4 "s_register_operand" "r,r")
9814 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9815 (match_operator:SI 7 "shift_operator"
9816 [(match_operand:SI 2 "s_register_operand" "r,r")
9817 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9818 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9819 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9820 "TARGET_ARM"
9c08d1fa 9821 "#"
8fa3ba89 9822 [(set_attr "conds" "clob")
9823 (set_attr "length" "8,12")]
9824)
9c08d1fa 9825
8a18b90c 9826(define_insn "*if_shift_move"
9827 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9828 (if_then_else:SI
8fa3ba89 9829 (match_operator 5 "arm_comparison_operator"
8a18b90c 9830 [(match_operand 6 "cc_register" "") (const_int 0)])
9831 (match_operator:SI 4 "shift_operator"
9832 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9833 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9834 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9835 "TARGET_ARM"
5565501b 9836 "@
8a18b90c 9837 mov%d5\\t%0, %2%S4
9838 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9839 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9840 [(set_attr "conds" "use")
331beb1a 9841 (set_attr "shift" "2")
a2cd141b 9842 (set_attr "length" "4,8,8")
9843 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9844 (const_string "alu_shift")
9845 (const_string "alu_shift_reg")))]
8fa3ba89 9846)
5565501b 9847
8a18b90c 9848(define_insn "*ifcompare_move_shift"
9849 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9850 (if_then_else:SI
8fa3ba89 9851 (match_operator 6 "arm_comparison_operator"
8a18b90c 9852 [(match_operand:SI 4 "s_register_operand" "r,r")
9853 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9854 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9855 (match_operator:SI 7 "shift_operator"
8a18b90c 9856 [(match_operand:SI 2 "s_register_operand" "r,r")
9857 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9858 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9859 "TARGET_ARM"
8a18b90c 9860 "#"
8fa3ba89 9861 [(set_attr "conds" "clob")
9862 (set_attr "length" "8,12")]
9863)
5565501b 9864
8a18b90c 9865(define_insn "*if_move_shift"
9866 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9867 (if_then_else:SI
8fa3ba89 9868 (match_operator 5 "arm_comparison_operator"
8a18b90c 9869 [(match_operand 6 "cc_register" "") (const_int 0)])
9870 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9871 (match_operator:SI 4 "shift_operator"
9872 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9873 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9874 "TARGET_ARM"
5565501b 9875 "@
8a18b90c 9876 mov%D5\\t%0, %2%S4
9877 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9878 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9879 [(set_attr "conds" "use")
331beb1a 9880 (set_attr "shift" "2")
a2cd141b 9881 (set_attr "length" "4,8,8")
9882 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9883 (const_string "alu_shift")
9884 (const_string "alu_shift_reg")))]
8fa3ba89 9885)
9c08d1fa 9886
f7fbdd4a 9887(define_insn "*ifcompare_shift_shift"
8a18b90c 9888 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9889 (if_then_else:SI
8fa3ba89 9890 (match_operator 7 "arm_comparison_operator"
8a18b90c 9891 [(match_operand:SI 5 "s_register_operand" "r")
9892 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9893 (match_operator:SI 8 "shift_operator"
8a18b90c 9894 [(match_operand:SI 1 "s_register_operand" "r")
9895 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9896 (match_operator:SI 9 "shift_operator"
8a18b90c 9897 [(match_operand:SI 3 "s_register_operand" "r")
9898 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9899 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9900 "TARGET_ARM"
8a18b90c 9901 "#"
8fa3ba89 9902 [(set_attr "conds" "clob")
9903 (set_attr "length" "12")]
9904)
9c08d1fa 9905
8a18b90c 9906(define_insn "*if_shift_shift"
9907 [(set (match_operand:SI 0 "s_register_operand" "=r")
9908 (if_then_else:SI
8fa3ba89 9909 (match_operator 5 "arm_comparison_operator"
8a18b90c 9910 [(match_operand 8 "cc_register" "") (const_int 0)])
9911 (match_operator:SI 6 "shift_operator"
9912 [(match_operand:SI 1 "s_register_operand" "r")
9913 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9914 (match_operator:SI 7 "shift_operator"
9915 [(match_operand:SI 3 "s_register_operand" "r")
9916 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9917 "TARGET_ARM"
8a18b90c 9918 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9919 [(set_attr "conds" "use")
331beb1a 9920 (set_attr "shift" "1")
a2cd141b 9921 (set_attr "length" "8")
9922 (set (attr "type") (if_then_else
9923 (and (match_operand 2 "const_int_operand" "")
9924 (match_operand 4 "const_int_operand" ""))
9925 (const_string "alu_shift")
9926 (const_string "alu_shift_reg")))]
8fa3ba89 9927)
8a18b90c 9928
f7fbdd4a 9929(define_insn "*ifcompare_not_arith"
8a18b90c 9930 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9931 (if_then_else:SI
8fa3ba89 9932 (match_operator 6 "arm_comparison_operator"
8a18b90c 9933 [(match_operand:SI 4 "s_register_operand" "r")
9934 (match_operand:SI 5 "arm_add_operand" "rIL")])
9935 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9936 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9937 [(match_operand:SI 2 "s_register_operand" "r")
9938 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9939 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9940 "TARGET_ARM"
8a18b90c 9941 "#"
8fa3ba89 9942 [(set_attr "conds" "clob")
9943 (set_attr "length" "12")]
9944)
9c08d1fa 9945
8a18b90c 9946(define_insn "*if_not_arith"
9947 [(set (match_operand:SI 0 "s_register_operand" "=r")
9948 (if_then_else:SI
8fa3ba89 9949 (match_operator 5 "arm_comparison_operator"
8a18b90c 9950 [(match_operand 4 "cc_register" "") (const_int 0)])
9951 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9952 (match_operator:SI 6 "shiftable_operator"
9953 [(match_operand:SI 2 "s_register_operand" "r")
9954 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9955 "TARGET_ARM"
8a18b90c 9956 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9957 [(set_attr "conds" "use")
9958 (set_attr "length" "8")]
9959)
8a18b90c 9960
9961(define_insn "*ifcompare_arith_not"
9962 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9963 (if_then_else:SI
8fa3ba89 9964 (match_operator 6 "arm_comparison_operator"
8a18b90c 9965 [(match_operand:SI 4 "s_register_operand" "r")
9966 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9967 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9968 [(match_operand:SI 2 "s_register_operand" "r")
9969 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9970 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9971 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9972 "TARGET_ARM"
8a18b90c 9973 "#"
8fa3ba89 9974 [(set_attr "conds" "clob")
9975 (set_attr "length" "12")]
9976)
9c08d1fa 9977
8a18b90c 9978(define_insn "*if_arith_not"
9979 [(set (match_operand:SI 0 "s_register_operand" "=r")
9980 (if_then_else:SI
8fa3ba89 9981 (match_operator 5 "arm_comparison_operator"
8a18b90c 9982 [(match_operand 4 "cc_register" "") (const_int 0)])
9983 (match_operator:SI 6 "shiftable_operator"
9984 [(match_operand:SI 2 "s_register_operand" "r")
9985 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9986 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9987 "TARGET_ARM"
8a18b90c 9988 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9989 [(set_attr "conds" "use")
9990 (set_attr "length" "8")]
9991)
8a18b90c 9992
f7fbdd4a 9993(define_insn "*ifcompare_neg_move"
8a18b90c 9994 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9995 (if_then_else:SI
8fa3ba89 9996 (match_operator 5 "arm_comparison_operator"
8a18b90c 9997 [(match_operand:SI 3 "s_register_operand" "r,r")
9998 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9999 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10000 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10001 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10002 "TARGET_ARM"
8a18b90c 10003 "#"
8fa3ba89 10004 [(set_attr "conds" "clob")
10005 (set_attr "length" "8,12")]
10006)
8a18b90c 10007
10008(define_insn "*if_neg_move"
10009 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10010 (if_then_else:SI
8fa3ba89 10011 (match_operator 4 "arm_comparison_operator"
8a18b90c 10012 [(match_operand 3 "cc_register" "") (const_int 0)])
10013 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10014 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10015 "TARGET_ARM"
8a18b90c 10016 "@
10017 rsb%d4\\t%0, %2, #0
10018 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10019 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10020 [(set_attr "conds" "use")
10021 (set_attr "length" "4,8,8")]
10022)
9c08d1fa 10023
f7fbdd4a 10024(define_insn "*ifcompare_move_neg"
8a18b90c 10025 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10026 (if_then_else:SI
8fa3ba89 10027 (match_operator 5 "arm_comparison_operator"
8a18b90c 10028 [(match_operand:SI 3 "s_register_operand" "r,r")
10029 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10030 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10031 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10032 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10033 "TARGET_ARM"
8a18b90c 10034 "#"
8fa3ba89 10035 [(set_attr "conds" "clob")
10036 (set_attr "length" "8,12")]
10037)
8a18b90c 10038
10039(define_insn "*if_move_neg"
10040 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10041 (if_then_else:SI
8fa3ba89 10042 (match_operator 4 "arm_comparison_operator"
8a18b90c 10043 [(match_operand 3 "cc_register" "") (const_int 0)])
10044 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10045 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10046 "TARGET_ARM"
8a18b90c 10047 "@
10048 rsb%D4\\t%0, %2, #0
10049 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10050 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10051 [(set_attr "conds" "use")
10052 (set_attr "length" "4,8,8")]
10053)
9c08d1fa 10054
f7fbdd4a 10055(define_insn "*arith_adjacentmem"
9c08d1fa 10056 [(set (match_operand:SI 0 "s_register_operand" "=r")
10057 (match_operator:SI 1 "shiftable_operator"
10058 [(match_operand:SI 2 "memory_operand" "m")
10059 (match_operand:SI 3 "memory_operand" "m")]))
10060 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10061 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10062 "*
215b30b3 10063 {
10064 rtx ldm[3];
10065 rtx arith[4];
94dee231 10066 rtx base_reg;
10067 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10068
215b30b3 10069 if (REGNO (operands[0]) > REGNO (operands[4]))
10070 {
10071 ldm[1] = operands[4];
10072 ldm[2] = operands[0];
10073 }
10074 else
10075 {
10076 ldm[1] = operands[0];
10077 ldm[2] = operands[4];
10078 }
94dee231 10079
10080 base_reg = XEXP (operands[2], 0);
10081
10082 if (!REG_P (base_reg))
10083 {
10084 val1 = INTVAL (XEXP (base_reg, 1));
10085 base_reg = XEXP (base_reg, 0);
10086 }
10087
10088 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10089 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10090
215b30b3 10091 arith[0] = operands[0];
10092 arith[3] = operands[1];
94dee231 10093
215b30b3 10094 if (val1 < val2)
10095 {
10096 arith[1] = ldm[1];
10097 arith[2] = ldm[2];
10098 }
10099 else
10100 {
10101 arith[1] = ldm[2];
10102 arith[2] = ldm[1];
10103 }
94dee231 10104
10105 ldm[0] = base_reg;
10106 if (val1 !=0 && val2 != 0)
215b30b3 10107 {
cdb1295a 10108 rtx ops[3];
10109
94dee231 10110 if (val1 == 4 || val2 == 4)
10111 /* Other val must be 8, since we know they are adjacent and neither
10112 is zero. */
25f905c2 10113 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10114 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10115 {
94dee231 10116 ldm[0] = ops[0] = operands[4];
10117 ops[1] = base_reg;
10118 ops[2] = GEN_INT (val1);
10119 output_add_immediate (ops);
10120 if (val1 < val2)
25f905c2 10121 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10122 else
25f905c2 10123 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10124 }
cdb1295a 10125 else
10126 {
10127 /* Offset is out of range for a single add, so use two ldr. */
10128 ops[0] = ldm[1];
10129 ops[1] = base_reg;
10130 ops[2] = GEN_INT (val1);
10131 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10132 ops[0] = ldm[2];
10133 ops[2] = GEN_INT (val2);
10134 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10135 }
215b30b3 10136 }
94dee231 10137 else if (val1 != 0)
215b30b3 10138 {
215b30b3 10139 if (val1 < val2)
25f905c2 10140 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10141 else
25f905c2 10142 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10143 }
10144 else
10145 {
215b30b3 10146 if (val1 < val2)
25f905c2 10147 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10148 else
25f905c2 10149 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10150 }
10151 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10152 return \"\";
10153 }"
10154 [(set_attr "length" "12")
10155 (set_attr "predicable" "yes")
a2cd141b 10156 (set_attr "type" "load1")]
215b30b3 10157)
9c08d1fa 10158
9c08d1fa 10159; This pattern is never tried by combine, so do it as a peephole
10160
a0f94409 10161(define_peephole2
372575c7 10162 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10163 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10164 (set (reg:CC CC_REGNUM)
aea4c774 10165 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10166 "TARGET_ARM"
a0f94409 10167 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10168 (set (match_dup 0) (match_dup 1))])]
10169 ""
0d66636f 10170)
9c08d1fa 10171
675d848d 10172; Peepholes to spot possible load- and store-multiples, if the ordering is
10173; reversed, check that the memory references aren't volatile.
9c08d1fa 10174
10175(define_peephole
aaa37ad6 10176 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10177 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10178 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10179 (match_operand:SI 5 "memory_operand" "m"))
aaa37ad6 10180 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10181 (match_operand:SI 6 "memory_operand" "m"))
aaa37ad6 10182 (set (match_operand:SI 3 "s_register_operand" "=rk")
aea4c774 10183 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 10184 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10185 "*
10186 return emit_ldm_seq (operands, 4);
215b30b3 10187 "
10188)
9c08d1fa 10189
10190(define_peephole
aaa37ad6 10191 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10192 (match_operand:SI 3 "memory_operand" "m"))
aaa37ad6 10193 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10194 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10195 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10196 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 10197 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10198 "*
10199 return emit_ldm_seq (operands, 3);
215b30b3 10200 "
10201)
9c08d1fa 10202
10203(define_peephole
aaa37ad6 10204 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10205 (match_operand:SI 2 "memory_operand" "m"))
aaa37ad6 10206 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10207 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 10208 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10209 "*
10210 return emit_ldm_seq (operands, 2);
215b30b3 10211 "
10212)
9c08d1fa 10213
10214(define_peephole
aea4c774 10215 [(set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10216 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10217 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10218 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10219 (set (match_operand:SI 6 "memory_operand" "=m")
aaa37ad6 10220 (match_operand:SI 2 "s_register_operand" "rk"))
aea4c774 10221 (set (match_operand:SI 7 "memory_operand" "=m")
aaa37ad6 10222 (match_operand:SI 3 "s_register_operand" "rk"))]
cffb2a26 10223 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10224 "*
10225 return emit_stm_seq (operands, 4);
215b30b3 10226 "
10227)
9c08d1fa 10228
10229(define_peephole
aea4c774 10230 [(set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10231 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10232 (set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10233 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10234 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10235 (match_operand:SI 2 "s_register_operand" "rk"))]
cffb2a26 10236 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10237 "*
10238 return emit_stm_seq (operands, 3);
215b30b3 10239 "
10240)
9c08d1fa 10241
10242(define_peephole
aea4c774 10243 [(set (match_operand:SI 2 "memory_operand" "=m")
aaa37ad6 10244 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10245 (set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10246 (match_operand:SI 1 "s_register_operand" "rk"))]
cffb2a26 10247 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10248 "*
10249 return emit_stm_seq (operands, 2);
215b30b3 10250 "
10251)
9c08d1fa 10252
9c08d1fa 10253(define_split
10254 [(set (match_operand:SI 0 "s_register_operand" "")
10255 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10256 (const_int 0))
8fa3ba89 10257 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10258 [(match_operand:SI 3 "s_register_operand" "")
10259 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10260 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10261 "TARGET_ARM"
9c08d1fa 10262 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10263 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10264 (match_dup 5)))]
215b30b3 10265 ""
10266)
9c08d1fa 10267
aea4c774 10268;; This split can be used because CC_Z mode implies that the following
10269;; branch will be an equality, or an unsigned inequality, so the sign
10270;; extension is not needed.
9c08d1fa 10271
aea4c774 10272(define_split
bd5b4116 10273 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10274 (compare:CC_Z
10275 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10276 (const_int 24))
aea4c774 10277 (match_operand 1 "const_int_operand" "")))
10278 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10279 "TARGET_ARM
10280 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10281 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10282 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10283 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10284 "
9c08d1fa 10285 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10286 "
10287)
25f905c2 10288;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10289
87b22bf7 10290(define_expand "prologue"
10291 [(clobber (const_int 0))]
cffb2a26 10292 "TARGET_EITHER"
25f905c2 10293 "if (TARGET_32BIT)
cffb2a26 10294 arm_expand_prologue ();
10295 else
25f905c2 10296 thumb1_expand_prologue ();
87b22bf7 10297 DONE;
cffb2a26 10298 "
10299)
87b22bf7 10300
56d27660 10301(define_expand "epilogue"
4c44712e 10302 [(clobber (const_int 0))]
cffb2a26 10303 "TARGET_EITHER"
56d27660 10304 "
18d50ae6 10305 if (crtl->calls_eh_return)
4c44712e 10306 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10307 if (TARGET_THUMB1)
10308 thumb1_expand_epilogue ();
cffb2a26 10309 else if (USE_RETURN_INSN (FALSE))
56d27660 10310 {
10311 emit_jump_insn (gen_return ());
10312 DONE;
10313 }
cffb2a26 10314 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10315 gen_rtvec (1,
10316 gen_rtx_RETURN (VOIDmode)),
e1159bbe 10317 VUNSPEC_EPILOGUE));
cffb2a26 10318 DONE;
10319 "
10320)
56d27660 10321
ef5651d0 10322;; Note - although unspec_volatile's USE all hard registers,
10323;; USEs are ignored after relaod has completed. Thus we need
10324;; to add an unspec of the link register to ensure that flow
10325;; does not think that it is unused by the sibcall branch that
10326;; will replace the standard function epilogue.
1c494086 10327(define_insn "sibcall_epilogue"
ef5651d0 10328 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10329 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10330 "TARGET_32BIT"
1c494086 10331 "*
ffc9d00c 10332 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10333 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10334 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10335 "
10336;; Length is absolute worst case
10337 [(set_attr "length" "44")
defc47cf 10338 (set_attr "type" "block")
10339 ;; We don't clobber the conditions, but the potential length of this
10340 ;; operation is sufficient to make conditionalizing the sequence
10341 ;; unlikely to be profitable.
10342 (set_attr "conds" "clob")]
1c494086 10343)
10344
cffb2a26 10345(define_insn "*epilogue_insns"
e1159bbe 10346 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10347 "TARGET_EITHER"
56d27660 10348 "*
25f905c2 10349 if (TARGET_32BIT)
ffc9d00c 10350 return arm_output_epilogue (NULL);
25f905c2 10351 else /* TARGET_THUMB1 */
cffb2a26 10352 return thumb_unexpanded_epilogue ();
10353 "
215b30b3 10354 ; Length is absolute worst case
cffb2a26 10355 [(set_attr "length" "44")
defc47cf 10356 (set_attr "type" "block")
10357 ;; We don't clobber the conditions, but the potential length of this
10358 ;; operation is sufficient to make conditionalizing the sequence
10359 ;; unlikely to be profitable.
10360 (set_attr "conds" "clob")]
cffb2a26 10361)
10362
10363(define_expand "eh_epilogue"
7db9af5d 10364 [(use (match_operand:SI 0 "register_operand" ""))
10365 (use (match_operand:SI 1 "register_operand" ""))
10366 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10367 "TARGET_EITHER"
10368 "
215b30b3 10369 {
10370 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10371 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10372 {
10373 rtx ra = gen_rtx_REG (Pmode, 2);
10374
10375 emit_move_insn (ra, operands[2]);
10376 operands[2] = ra;
10377 }
5cf3595a 10378 /* This is a hack -- we may have crystalized the function type too
10379 early. */
10380 cfun->machine->func_type = 0;
215b30b3 10381 }"
10382)
56d27660 10383
9c08d1fa 10384;; This split is only used during output to reduce the number of patterns
10385;; that need assembler instructions adding to them. We allowed the setting
10386;; of the conditions to be implicit during rtl generation so that
10387;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10388;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10389;; up again here.
10390
25f905c2 10391;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10392;; conditional execution sufficient?
10393
9c08d1fa 10394(define_split
10395 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10396 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10397 [(match_operand 2 "" "") (match_operand 3 "" "")])
10398 (match_dup 0)
10399 (match_operand 4 "" "")))
bd5b4116 10400 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10401 "TARGET_ARM && reload_completed"
8fa3ba89 10402 [(set (match_dup 5) (match_dup 6))
10403 (cond_exec (match_dup 7)
10404 (set (match_dup 0) (match_dup 4)))]
10405 "
10406 {
10407 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10408 operands[2], operands[3]);
10409 enum rtx_code rc = GET_CODE (operands[1]);
10410
bd5b4116 10411 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10412 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10413 if (mode == CCFPmode || mode == CCFPEmode)
10414 rc = reverse_condition_maybe_unordered (rc);
10415 else
10416 rc = reverse_condition (rc);
10417
10418 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10419 }"
10420)
10421
10422(define_split
10423 [(set (match_operand:SI 0 "s_register_operand" "")
10424 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10425 [(match_operand 2 "" "") (match_operand 3 "" "")])
10426 (match_operand 4 "" "")
10427 (match_dup 0)))
bd5b4116 10428 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10429 "TARGET_ARM && reload_completed"
8fa3ba89 10430 [(set (match_dup 5) (match_dup 6))
10431 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10432 (set (match_dup 0) (match_dup 4)))]
10433 "
10434 {
10435 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10436 operands[2], operands[3]);
10437
bd5b4116 10438 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10439 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10440 }"
10441)
10442
10443(define_split
10444 [(set (match_operand:SI 0 "s_register_operand" "")
10445 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10446 [(match_operand 2 "" "") (match_operand 3 "" "")])
10447 (match_operand 4 "" "")
10448 (match_operand 5 "" "")))
bd5b4116 10449 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10450 "TARGET_ARM && reload_completed"
8fa3ba89 10451 [(set (match_dup 6) (match_dup 7))
10452 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10453 (set (match_dup 0) (match_dup 4)))
10454 (cond_exec (match_dup 8)
10455 (set (match_dup 0) (match_dup 5)))]
10456 "
10457 {
10458 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10459 operands[2], operands[3]);
10460 enum rtx_code rc = GET_CODE (operands[1]);
10461
bd5b4116 10462 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10463 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10464 if (mode == CCFPmode || mode == CCFPEmode)
10465 rc = reverse_condition_maybe_unordered (rc);
10466 else
10467 rc = reverse_condition (rc);
10468
10469 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10470 }"
10471)
10472
cffb2a26 10473(define_split
10474 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10475 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10476 [(match_operand:SI 2 "s_register_operand" "")
10477 (match_operand:SI 3 "arm_add_operand" "")])
10478 (match_operand:SI 4 "arm_rhs_operand" "")
10479 (not:SI
10480 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10481 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10482 "TARGET_ARM && reload_completed"
cffb2a26 10483 [(set (match_dup 6) (match_dup 7))
f6c53574 10484 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10485 (set (match_dup 0) (match_dup 4)))
10486 (cond_exec (match_dup 8)
10487 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10488 "
215b30b3 10489 {
10490 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10491 operands[2], operands[3]);
f6c53574 10492 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10493
bd5b4116 10494 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10495 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10496 if (mode == CCFPmode || mode == CCFPEmode)
10497 rc = reverse_condition_maybe_unordered (rc);
10498 else
10499 rc = reverse_condition (rc);
10500
10501 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10502 }"
10503)
cffb2a26 10504
10505(define_insn "*cond_move_not"
10506 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10507 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10508 [(match_operand 3 "cc_register" "") (const_int 0)])
10509 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10510 (not:SI
10511 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10512 "TARGET_ARM"
10513 "@
10514 mvn%D4\\t%0, %2
10515 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10516 [(set_attr "conds" "use")
10517 (set_attr "length" "4,8")]
10518)
cffb2a26 10519
9c08d1fa 10520;; The next two patterns occur when an AND operation is followed by a
10521;; scc insn sequence
10522
f7fbdd4a 10523(define_insn "*sign_extract_onebit"
9c08d1fa 10524 [(set (match_operand:SI 0 "s_register_operand" "=r")
10525 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10526 (const_int 1)
ed750274 10527 (match_operand:SI 2 "const_int_operand" "n")))
10528 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10529 "TARGET_ARM"
9c08d1fa 10530 "*
0d66636f 10531 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10532 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10533 return \"mvnne\\t%0, #0\";
10534 "
10535 [(set_attr "conds" "clob")
10536 (set_attr "length" "8")]
10537)
9c08d1fa 10538
f7fbdd4a 10539(define_insn "*not_signextract_onebit"
9c08d1fa 10540 [(set (match_operand:SI 0 "s_register_operand" "=r")
10541 (not:SI
10542 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10543 (const_int 1)
ed750274 10544 (match_operand:SI 2 "const_int_operand" "n"))))
10545 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10546 "TARGET_ARM"
9c08d1fa 10547 "*
0d66636f 10548 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10549 output_asm_insn (\"tst\\t%1, %2\", operands);
10550 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10551 return \"movne\\t%0, #0\";
10552 "
10553 [(set_attr "conds" "clob")
10554 (set_attr "length" "12")]
10555)
25f905c2 10556;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10557
0d66636f 10558;; Push multiple registers to the stack. Registers are in parallel (use ...)
10559;; expressions. For simplicity, the first register is also in the unspec
10560;; part.
f7fbdd4a 10561(define_insn "*push_multi"
87b22bf7 10562 [(match_parallel 2 "multi_register_push"
10563 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10564 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10565 UNSPEC_PUSH_MULT))])]
25f905c2 10566 "TARGET_32BIT"
87b22bf7 10567 "*
215b30b3 10568 {
10569 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10570
215b30b3 10571 /* For the StrongARM at least it is faster to
25f905c2 10572 use STR to store only a single register.
542d5028 10573 In Thumb mode always use push, and the assembler will pick
10574 something appropriate. */
25f905c2 10575 if (num_saves == 1 && TARGET_ARM)
215b30b3 10576 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10577 else
10578 {
10579 int i;
10580 char pattern[100];
ed593f11 10581
25f905c2 10582 if (TARGET_ARM)
10583 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10584 else
10585 strcpy (pattern, \"push\\t{%1\");
215b30b3 10586
6079f055 10587 for (i = 1; i < num_saves; i++)
215b30b3 10588 {
10589 strcat (pattern, \", %|\");
10590 strcat (pattern,
10591 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10592 }
10593
10594 strcat (pattern, \"}\");
10595 output_asm_insn (pattern, operands);
10596 }
10597
10598 return \"\";
10599 }"
10600 [(set_attr "type" "store4")]
10601)
f7fbdd4a 10602
4c58c898 10603(define_insn "stack_tie"
10604 [(set (mem:BLK (scratch))
aaa37ad6 10605 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10606 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10607 UNSPEC_PRLG_STK))]
10608 ""
10609 ""
10610 [(set_attr "length" "0")]
10611)
10612
3398e91d 10613;; Similarly for the floating point registers
7b1d2fc4 10614(define_insn "*push_fp_multi"
10615 [(match_parallel 2 "multi_register_push"
10616 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10617 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10618 UNSPEC_PUSH_MULT))])]
25f905c2 10619 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10620 "*
215b30b3 10621 {
10622 char pattern[100];
7b1d2fc4 10623
215b30b3 10624 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10625 output_asm_insn (pattern, operands);
10626 return \"\";
10627 }"
10628 [(set_attr "type" "f_store")]
10629)
7b1d2fc4 10630
f7fbdd4a 10631;; Special patterns for dealing with the constant pool
10632
cffb2a26 10633(define_insn "align_4"
e1159bbe 10634 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10635 "TARGET_EITHER"
f7fbdd4a 10636 "*
cffb2a26 10637 assemble_align (32);
f7fbdd4a 10638 return \"\";
cffb2a26 10639 "
10640)
f7fbdd4a 10641
755eb2b4 10642(define_insn "align_8"
10643 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10644 "TARGET_EITHER"
755eb2b4 10645 "*
10646 assemble_align (64);
10647 return \"\";
10648 "
10649)
10650
cffb2a26 10651(define_insn "consttable_end"
e1159bbe 10652 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10653 "TARGET_EITHER"
f7fbdd4a 10654 "*
cffb2a26 10655 making_const_table = FALSE;
f7fbdd4a 10656 return \"\";
cffb2a26 10657 "
10658)
f7fbdd4a 10659
cffb2a26 10660(define_insn "consttable_1"
e1159bbe 10661 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10662 "TARGET_THUMB1"
f7fbdd4a 10663 "*
cffb2a26 10664 making_const_table = TRUE;
09d688ff 10665 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10666 assemble_zeros (3);
f7fbdd4a 10667 return \"\";
cffb2a26 10668 "
10669 [(set_attr "length" "4")]
10670)
f7fbdd4a 10671
cffb2a26 10672(define_insn "consttable_2"
e1159bbe 10673 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10674 "TARGET_THUMB1"
f7fbdd4a 10675 "*
cffb2a26 10676 making_const_table = TRUE;
09d688ff 10677 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10678 assemble_zeros (2);
f7fbdd4a 10679 return \"\";
cffb2a26 10680 "
10681 [(set_attr "length" "4")]
10682)
10683
10684(define_insn "consttable_4"
e1159bbe 10685 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10686 "TARGET_EITHER"
10687 "*
10688 {
10689 making_const_table = TRUE;
10690 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10691 {
10692 case MODE_FLOAT:
10693 {
badfe841 10694 REAL_VALUE_TYPE r;
10695 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10696 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10697 break;
10698 }
10699 default:
09d688ff 10700 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
af2a449c 10701 mark_symbol_refs_as_used (operands[0]);
cffb2a26 10702 break;
10703 }
10704 return \"\";
10705 }"
10706 [(set_attr "length" "4")]
10707)
10708
10709(define_insn "consttable_8"
e1159bbe 10710 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10711 "TARGET_EITHER"
10712 "*
10713 {
10714 making_const_table = TRUE;
10715 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10716 {
10717 case MODE_FLOAT:
10718 {
badfe841 10719 REAL_VALUE_TYPE r;
10720 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10721 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10722 break;
10723 }
10724 default:
09d688ff 10725 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10726 break;
10727 }
10728 return \"\";
10729 }"
10730 [(set_attr "length" "8")]
10731)
10732
d98a3884 10733(define_insn "consttable_16"
10734 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10735 "TARGET_EITHER"
10736 "*
10737 {
10738 making_const_table = TRUE;
10739 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10740 {
10741 case MODE_FLOAT:
10742 {
10743 REAL_VALUE_TYPE r;
10744 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10745 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10746 break;
10747 }
10748 default:
10749 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10750 break;
10751 }
10752 return \"\";
10753 }"
10754 [(set_attr "length" "16")]
10755)
10756
cffb2a26 10757;; Miscellaneous Thumb patterns
10758
fd957ef3 10759(define_expand "tablejump"
7db9af5d 10760 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10761 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10762 "TARGET_THUMB1"
fd957ef3 10763 "
10764 if (flag_pic)
10765 {
10766 /* Hopefully, CSE will eliminate this copy. */
10767 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10768 rtx reg2 = gen_reg_rtx (SImode);
10769
10770 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10771 operands[0] = reg2;
10772 }
10773 "
10774)
10775
f1039640 10776;; NB never uses BX.
25f905c2 10777(define_insn "*thumb1_tablejump"
cffb2a26 10778 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10779 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10780 "TARGET_THUMB1"
fd957ef3 10781 "mov\\t%|pc, %0"
cffb2a26 10782 [(set_attr "length" "2")]
10783)
0d66636f 10784
331beb1a 10785;; V5 Instructions,
10786
8f4be2be 10787(define_insn "clzsi2"
10788 [(set (match_operand:SI 0 "s_register_operand" "=r")
10789 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10790 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10791 "clz%?\\t%0, %1"
bcaec148 10792 [(set_attr "predicable" "yes")
10793 (set_attr "insn" "clz")])
331beb1a 10794
e1159bbe 10795;; V5E instructions.
331beb1a 10796
10797(define_insn "prefetch"
f4e79814 10798 [(prefetch (match_operand:SI 0 "address_operand" "p")
10799 (match_operand:SI 1 "" "")
10800 (match_operand:SI 2 "" ""))]
25f905c2 10801 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10802 "pld\\t%a0")
331beb1a 10803
0d66636f 10804;; General predication pattern
10805
10806(define_cond_exec
10807 [(match_operator 0 "arm_comparison_operator"
10808 [(match_operand 1 "cc_register" "")
10809 (const_int 0)])]
25f905c2 10810 "TARGET_32BIT"
0d66636f 10811 ""
10812)
10813
063a05c7 10814(define_insn "prologue_use"
10815 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10816 ""
10817 "%@ %0 needed for prologue"
10818)
7db9af5d 10819
4c44712e 10820
10821;; Patterns for exception handling
10822
10823(define_expand "eh_return"
10824 [(use (match_operand 0 "general_operand" ""))]
10825 "TARGET_EITHER"
10826 "
10827 {
25f905c2 10828 if (TARGET_32BIT)
4c44712e 10829 emit_insn (gen_arm_eh_return (operands[0]));
10830 else
10831 emit_insn (gen_thumb_eh_return (operands[0]));
10832 DONE;
10833 }"
10834)
10835
10836;; We can't expand this before we know where the link register is stored.
10837(define_insn_and_split "arm_eh_return"
10838 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10839 VUNSPEC_EH_RETURN)
10840 (clobber (match_scratch:SI 1 "=&r"))]
10841 "TARGET_ARM"
10842 "#"
10843 "&& reload_completed"
10844 [(const_int 0)]
10845 "
10846 {
10847 arm_set_return_address (operands[0], operands[1]);
10848 DONE;
10849 }"
10850)
10851
10852(define_insn_and_split "thumb_eh_return"
10853 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10854 VUNSPEC_EH_RETURN)
10855 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10856 "TARGET_THUMB1"
4c44712e 10857 "#"
10858 "&& reload_completed"
10859 [(const_int 0)]
10860 "
10861 {
10862 thumb_set_return_address (operands[0], operands[1]);
10863 DONE;
10864 }"
10865)
10866
f655717d 10867\f
10868;; TLS support
10869
10870(define_insn "load_tp_hard"
10871 [(set (match_operand:SI 0 "register_operand" "=r")
10872 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10873 "TARGET_HARD_TP"
10874 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10875 [(set_attr "predicable" "yes")]
10876)
10877
10878;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10879(define_insn "load_tp_soft"
10880 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10881 (clobber (reg:SI LR_REGNUM))
10882 (clobber (reg:SI IP_REGNUM))
10883 (clobber (reg:CC CC_REGNUM))]
10884 "TARGET_SOFT_TP"
10885 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10886 [(set_attr "conds" "clob")]
10887)
10888
7db9af5d 10889;; Load the FPA co-processor patterns
10890(include "fpa.md")
10891;; Load the Maverick co-processor patterns
10892(include "cirrus.md")
d98a3884 10893;; Vector bits common to IWMMXT and Neon
10894(include "vec-common.md")
755eb2b4 10895;; Load the Intel Wireless Multimedia Extension patterns
10896(include "iwmmxt.md")
a2cd141b 10897;; Load the VFP co-processor patterns
10898(include "vfp.md")
25f905c2 10899;; Thumb-2 patterns
10900(include "thumb2.md")
d98a3884 10901;; Neon patterns
10902(include "neon.md")
a2cd141b 10903