]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
2009-06-21 Thomas Koenig <tkoenig@gcc.gnu.org>
[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).
9b8516be 161(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp,vfpv3d16,vfpv3,neon,neon_fp16"
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
9b8516be 3737(define_expand "floatsihf2"
3738 [(set (match_operand:HF 0 "general_operand" "")
3739 (float:HF (match_operand:SI 1 "general_operand" "")))]
3740 "TARGET_EITHER"
3741 "
3742 {
3743 rtx op1 = gen_reg_rtx (SFmode);
3744 expand_float (op1, operands[1], 0);
3745 op1 = convert_to_mode (HFmode, op1, 0);
3746 emit_move_insn (operands[0], op1);
3747 DONE;
3748 }"
3749)
3750
3751(define_expand "floatdihf2"
3752 [(set (match_operand:HF 0 "general_operand" "")
3753 (float:HF (match_operand:DI 1 "general_operand" "")))]
3754 "TARGET_EITHER"
3755 "
3756 {
3757 rtx op1 = gen_reg_rtx (SFmode);
3758 expand_float (op1, operands[1], 0);
3759 op1 = convert_to_mode (HFmode, op1, 0);
3760 emit_move_insn (operands[0], op1);
3761 DONE;
3762 }"
3763)
3764
604f3a0a 3765(define_expand "floatsisf2"
3766 [(set (match_operand:SF 0 "s_register_operand" "")
3767 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3768 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3769 "
a2cd141b 3770 if (TARGET_MAVERICK)
604f3a0a 3771 {
3772 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3773 DONE;
3774 }
3775")
3776
604f3a0a 3777(define_expand "floatsidf2"
3778 [(set (match_operand:DF 0 "s_register_operand" "")
3779 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3780 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3781 "
a2cd141b 3782 if (TARGET_MAVERICK)
604f3a0a 3783 {
3784 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3785 DONE;
3786 }
3787")
3788
9b8516be 3789(define_expand "fix_trunchfsi2"
3790 [(set (match_operand:SI 0 "general_operand" "")
3791 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3792 "TARGET_EITHER"
3793 "
3794 {
3795 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3796 expand_fix (operands[0], op1, 0);
3797 DONE;
3798 }"
3799)
3800
3801(define_expand "fix_trunchfdi2"
3802 [(set (match_operand:DI 0 "general_operand" "")
3803 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3804 "TARGET_EITHER"
3805 "
3806 {
3807 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3808 expand_fix (operands[0], op1, 0);
3809 DONE;
3810 }"
3811)
3812
604f3a0a 3813(define_expand "fix_truncsfsi2"
3814 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3815 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3816 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3817 "
a2cd141b 3818 if (TARGET_MAVERICK)
604f3a0a 3819 {
3820 if (!cirrus_fp_register (operands[0], SImode))
3821 operands[0] = force_reg (SImode, operands[0]);
3822 if (!cirrus_fp_register (operands[1], SFmode))
3823 operands[1] = force_reg (SFmode, operands[0]);
3824 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3825 DONE;
3826 }
3827")
3828
604f3a0a 3829(define_expand "fix_truncdfsi2"
3830 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3831 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
25f905c2 3832 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3833 "
a2cd141b 3834 if (TARGET_MAVERICK)
604f3a0a 3835 {
3836 if (!cirrus_fp_register (operands[1], DFmode))
3837 operands[1] = force_reg (DFmode, operands[0]);
3838 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3839 DONE;
3840 }
3841")
3842
f544c6d2 3843;; Truncation insns
b11cae9e 3844
604f3a0a 3845(define_expand "truncdfsf2"
3846 [(set (match_operand:SF 0 "s_register_operand" "")
3847 (float_truncate:SF
3848 (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3849 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3850 ""
3851)
9b8516be 3852
3853/* DFmode -> HFmode conversions have to go through SFmode. */
3854(define_expand "truncdfhf2"
3855 [(set (match_operand:HF 0 "general_operand" "")
3856 (float_truncate:HF
3857 (match_operand:DF 1 "general_operand" "")))]
3858 "TARGET_EITHER"
3859 "
3860 {
3861 rtx op1;
3862 op1 = convert_to_mode (SFmode, operands[1], 0);
3863 op1 = convert_to_mode (HFmode, op1, 0);
3864 emit_move_insn (operands[0], op1);
3865 DONE;
3866 }"
3867)
b11cae9e 3868\f
9c08d1fa 3869;; Zero and sign extension instructions.
b11cae9e 3870
25f905c2 3871(define_expand "zero_extendsidi2"
3872 [(set (match_operand:DI 0 "s_register_operand" "")
3873 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3874 "TARGET_32BIT"
3875 ""
3876)
3877
3878(define_insn "*arm_zero_extendsidi2"
9c08d1fa 3879 [(set (match_operand:DI 0 "s_register_operand" "=r")
3880 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3881 "TARGET_ARM"
9c08d1fa 3882 "*
0d66636f 3883 if (REGNO (operands[1])
3884 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3885 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3886 return \"mov%?\\t%R0, #0\";
3887 "
3888 [(set_attr "length" "8")
3889 (set_attr "predicable" "yes")]
3890)
9c08d1fa 3891
25f905c2 3892(define_expand "zero_extendqidi2"
3893 [(set (match_operand:DI 0 "s_register_operand" "")
3894 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3895 "TARGET_32BIT"
3896 ""
3897)
3898
3899(define_insn "*arm_zero_extendqidi2"
cffb2a26 3900 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3901 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3902 "TARGET_ARM"
e2348bcb 3903 "@
97499065 3904 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
25f905c2 3905 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3906 [(set_attr "length" "8")
0d66636f 3907 (set_attr "predicable" "yes")
a2cd141b 3908 (set_attr "type" "*,load_byte")
cffb2a26 3909 (set_attr "pool_range" "*,4092")
3910 (set_attr "neg_pool_range" "*,4084")]
3911)
9c08d1fa 3912
25f905c2 3913(define_expand "extendsidi2"
3914 [(set (match_operand:DI 0 "s_register_operand" "")
3915 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3916 "TARGET_32BIT"
3917 ""
3918)
3919
3920(define_insn "*arm_extendsidi2"
9c08d1fa 3921 [(set (match_operand:DI 0 "s_register_operand" "=r")
3922 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3923 "TARGET_ARM"
9c08d1fa 3924 "*
0d66636f 3925 if (REGNO (operands[1])
3926 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3927 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3928 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3929 "
3930 [(set_attr "length" "8")
331beb1a 3931 (set_attr "shift" "1")
0d66636f 3932 (set_attr "predicable" "yes")]
3933)
9c08d1fa 3934
3935(define_expand "zero_extendhisi2"
cffb2a26 3936 [(set (match_dup 2)
0d66636f 3937 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3938 (const_int 16)))
9c08d1fa 3939 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3940 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3941 "TARGET_EITHER"
9c08d1fa 3942 "
cffb2a26 3943 {
25f905c2 3944 if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3945 {
a2cd141b 3946 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3947 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3948 DONE;
cffb2a26 3949 }
cffb2a26 3950
c1a66faf 3951 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3952 {
3953 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3954 DONE;
3955 }
cffb2a26 3956
a2cd141b 3957 if (!s_register_operand (operands[1], HImode))
3958 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3959
a2cd141b 3960 if (arm_arch6)
3961 {
3962 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3963 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3964 DONE;
cffb2a26 3965 }
a2cd141b 3966
3967 operands[1] = gen_lowpart (SImode, operands[1]);
3968 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3969 }"
3970)
3971
25f905c2 3972(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 3973 [(set (match_operand:SI 0 "register_operand" "=l")
3974 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
25f905c2 3975 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 3976 "*
3977 rtx mem = XEXP (operands[1], 0);
3978
3979 if (GET_CODE (mem) == CONST)
3980 mem = XEXP (mem, 0);
3981
3982 if (GET_CODE (mem) == LABEL_REF)
3983 return \"ldr\\t%0, %1\";
3984
3985 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3986 {
cffb2a26 3987 rtx a = XEXP (mem, 0);
3988 rtx b = XEXP (mem, 1);
3989
3990 /* This can happen due to bugs in reload. */
3991 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3992 {
3993 rtx ops[2];
3994 ops[0] = operands[0];
3995 ops[1] = a;
3996
3997 output_asm_insn (\"mov %0, %1\", ops);
3998
3999 XEXP (mem, 0) = operands[0];
4000 }
4001
4002 else if ( GET_CODE (a) == LABEL_REF
4003 && GET_CODE (b) == CONST_INT)
4004 return \"ldr\\t%0, %1\";
25f7a26e 4005 }
cffb2a26 4006
4007 return \"ldrh\\t%0, %1\";
4008 "
4009 [(set_attr "length" "4")
a2cd141b 4010 (set_attr "type" "load_byte")
cffb2a26 4011 (set_attr "pool_range" "60")]
4012)
9c08d1fa 4013
25f905c2 4014(define_insn "*thumb1_zero_extendhisi2_v6"
a2cd141b 4015 [(set (match_operand:SI 0 "register_operand" "=l,l")
4016 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4017 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4018 "*
4019 rtx mem;
4020
4021 if (which_alternative == 0)
4022 return \"uxth\\t%0, %1\";
4023
4024 mem = XEXP (operands[1], 0);
4025
4026 if (GET_CODE (mem) == CONST)
4027 mem = XEXP (mem, 0);
4028
4029 if (GET_CODE (mem) == LABEL_REF)
4030 return \"ldr\\t%0, %1\";
4031
4032 if (GET_CODE (mem) == PLUS)
4033 {
4034 rtx a = XEXP (mem, 0);
4035 rtx b = XEXP (mem, 1);
4036
4037 /* This can happen due to bugs in reload. */
4038 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4039 {
4040 rtx ops[2];
4041 ops[0] = operands[0];
4042 ops[1] = a;
4043
4044 output_asm_insn (\"mov %0, %1\", ops);
4045
4046 XEXP (mem, 0) = operands[0];
4047 }
4048
4049 else if ( GET_CODE (a) == LABEL_REF
4050 && GET_CODE (b) == CONST_INT)
4051 return \"ldr\\t%0, %1\";
4052 }
4053
4054 return \"ldrh\\t%0, %1\";
4055 "
4056 [(set_attr "length" "2,4")
4057 (set_attr "type" "alu_shift,load_byte")
4058 (set_attr "pool_range" "*,60")]
4059)
4060
cffb2a26 4061(define_insn "*arm_zero_extendhisi2"
a2cd141b 4062 [(set (match_operand:SI 0 "s_register_operand" "=r")
4063 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4064 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4065 "ldr%(h%)\\t%0, %1"
a2cd141b 4066 [(set_attr "type" "load_byte")
0d66636f 4067 (set_attr "predicable" "yes")
cffb2a26 4068 (set_attr "pool_range" "256")
4069 (set_attr "neg_pool_range" "244")]
4070)
f7fbdd4a 4071
a2cd141b 4072(define_insn "*arm_zero_extendhisi2_v6"
4073 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4074 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4075 "TARGET_ARM && arm_arch6"
4076 "@
4077 uxth%?\\t%0, %1
25f905c2 4078 ldr%(h%)\\t%0, %1"
a2cd141b 4079 [(set_attr "type" "alu_shift,load_byte")
4080 (set_attr "predicable" "yes")
4081 (set_attr "pool_range" "*,256")
4082 (set_attr "neg_pool_range" "*,244")]
4083)
4084
4085(define_insn "*arm_zero_extendhisi2addsi"
4086 [(set (match_operand:SI 0 "s_register_operand" "=r")
4087 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4088 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4089 "TARGET_INT_SIMD"
a2cd141b 4090 "uxtah%?\\t%0, %2, %1"
4091 [(set_attr "type" "alu_shift")
4092 (set_attr "predicable" "yes")]
4093)
4094
87b22bf7 4095(define_expand "zero_extendqisi2"
cffb2a26 4096 [(set (match_operand:SI 0 "s_register_operand" "")
4097 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4098 "TARGET_EITHER"
87b22bf7 4099 "
a2cd141b 4100 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4101 {
cffb2a26 4102 if (TARGET_ARM)
4103 {
215b30b3 4104 emit_insn (gen_andsi3 (operands[0],
4105 gen_lowpart (SImode, operands[1]),
cffb2a26 4106 GEN_INT (255)));
4107 }
4108 else /* TARGET_THUMB */
4109 {
4110 rtx temp = gen_reg_rtx (SImode);
4111 rtx ops[3];
4112
4113 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4114 operands[1] = gen_lowpart (SImode, operands[1]);
4115
4116 ops[0] = temp;
4117 ops[1] = operands[1];
4118 ops[2] = GEN_INT (24);
4119
215b30b3 4120 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4121 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 4122
4123 ops[0] = operands[0];
4124 ops[1] = temp;
4125 ops[2] = GEN_INT (24);
4126
215b30b3 4127 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4128 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 4129 }
87b22bf7 4130 DONE;
4131 }
215b30b3 4132 "
4133)
9c08d1fa 4134
25f905c2 4135(define_insn "*thumb1_zero_extendqisi2"
a2cd141b 4136 [(set (match_operand:SI 0 "register_operand" "=l")
4137 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
25f905c2 4138 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4139 "ldrb\\t%0, %1"
4140 [(set_attr "length" "2")
a2cd141b 4141 (set_attr "type" "load_byte")
cffb2a26 4142 (set_attr "pool_range" "32")]
4143)
4144
25f905c2 4145(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4146 [(set (match_operand:SI 0 "register_operand" "=l,l")
4147 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4148 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4149 "@
4150 uxtb\\t%0, %1
4151 ldrb\\t%0, %1"
4152 [(set_attr "length" "2,2")
4153 (set_attr "type" "alu_shift,load_byte")
4154 (set_attr "pool_range" "*,32")]
4155)
4156
cffb2a26 4157(define_insn "*arm_zero_extendqisi2"
a2cd141b 4158 [(set (match_operand:SI 0 "s_register_operand" "=r")
4159 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4160 "TARGET_ARM && !arm_arch6"
25f905c2 4161 "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4162 [(set_attr "type" "load_byte")
0d66636f 4163 (set_attr "predicable" "yes")
cffb2a26 4164 (set_attr "pool_range" "4096")
4165 (set_attr "neg_pool_range" "4084")]
4166)
87b22bf7 4167
a2cd141b 4168(define_insn "*arm_zero_extendqisi2_v6"
4169 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4170 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4171 "TARGET_ARM && arm_arch6"
4172 "@
25f905c2 4173 uxtb%(%)\\t%0, %1
4174 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4175 [(set_attr "type" "alu_shift,load_byte")
4176 (set_attr "predicable" "yes")
4177 (set_attr "pool_range" "*,4096")
4178 (set_attr "neg_pool_range" "*,4084")]
4179)
4180
4181(define_insn "*arm_zero_extendqisi2addsi"
4182 [(set (match_operand:SI 0 "s_register_operand" "=r")
4183 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4184 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4185 "TARGET_INT_SIMD"
a2cd141b 4186 "uxtab%?\\t%0, %2, %1"
4187 [(set_attr "predicable" "yes")
bcaec148 4188 (set_attr "insn" "xtab")
a2cd141b 4189 (set_attr "type" "alu_shift")]
4190)
4191
87b22bf7 4192(define_split
4193 [(set (match_operand:SI 0 "s_register_operand" "")
4194 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4195 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4196 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4197 [(set (match_dup 2) (match_dup 1))
4198 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4199 ""
4200)
9c08d1fa 4201
8a4d25d6 4202(define_split
4203 [(set (match_operand:SI 0 "s_register_operand" "")
4204 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4205 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4206 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4207 [(set (match_dup 2) (match_dup 1))
4208 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4209 ""
4210)
4211
f7fbdd4a 4212(define_insn "*compareqi_eq0"
bd5b4116 4213 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4214 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4215 (const_int 0)))]
25f905c2 4216 "TARGET_32BIT"
87b22bf7 4217 "tst\\t%0, #255"
cffb2a26 4218 [(set_attr "conds" "set")]
4219)
b11cae9e 4220
b11cae9e 4221(define_expand "extendhisi2"
c8f69309 4222 [(set (match_dup 2)
25f7a26e 4223 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 4224 (const_int 16)))
9c08d1fa 4225 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4226 (ashiftrt:SI (match_dup 2)
4227 (const_int 16)))]
cffb2a26 4228 "TARGET_EITHER"
b11cae9e 4229 "
cffb2a26 4230 {
a2cd141b 4231 if (GET_CODE (operands[1]) == MEM)
cffb2a26 4232 {
25f905c2 4233 if (TARGET_THUMB1)
a2cd141b 4234 {
25f905c2 4235 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4236 DONE;
4237 }
4238 else if (arm_arch4)
4239 {
a2cd141b 4240 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4241 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4242 DONE;
4243 }
cffb2a26 4244 }
7bd8ccc9 4245
c1a66faf 4246 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 4247 {
4248 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4249 DONE;
4250 }
a2cd141b 4251
215b30b3 4252 if (!s_register_operand (operands[1], HImode))
cffb2a26 4253 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 4254
a2cd141b 4255 if (arm_arch6)
cffb2a26 4256 {
25f905c2 4257 if (TARGET_THUMB1)
4258 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4259 else
4260 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4261 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4262
cffb2a26 4263 DONE;
4264 }
a2cd141b 4265
4266 operands[1] = gen_lowpart (SImode, operands[1]);
4267 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4268 }"
4269)
4270
25f905c2 4271(define_insn "thumb1_extendhisi2"
a2cd141b 4272 [(set (match_operand:SI 0 "register_operand" "=l")
4273 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4274 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4275 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4276 "*
4277 {
4278 rtx ops[4];
4279 rtx mem = XEXP (operands[1], 0);
4280
4281 /* This code used to try to use 'V', and fix the address only if it was
4282 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4283 range of QImode offsets, and offsettable_address_p does a QImode
4284 address check. */
4285
4286 if (GET_CODE (mem) == CONST)
4287 mem = XEXP (mem, 0);
4288
4289 if (GET_CODE (mem) == LABEL_REF)
4290 return \"ldr\\t%0, %1\";
4291
4292 if (GET_CODE (mem) == PLUS)
4293 {
4294 rtx a = XEXP (mem, 0);
4295 rtx b = XEXP (mem, 1);
4296
4297 if (GET_CODE (a) == LABEL_REF
4298 && GET_CODE (b) == CONST_INT)
4299 return \"ldr\\t%0, %1\";
4300
4301 if (GET_CODE (b) == REG)
4302 return \"ldrsh\\t%0, %1\";
4303
4304 ops[1] = a;
4305 ops[2] = b;
4306 }
4307 else
4308 {
4309 ops[1] = mem;
4310 ops[2] = const0_rtx;
4311 }
ed29c566 4312
4313 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 4314
4315 ops[0] = operands[0];
4316 ops[3] = operands[2];
4317 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4318 return \"\";
4319 }"
4320 [(set_attr "length" "4")
a2cd141b 4321 (set_attr "type" "load_byte")
cffb2a26 4322 (set_attr "pool_range" "1020")]
4323)
25f7a26e 4324
a2cd141b 4325;; We used to have an early-clobber on the scratch register here.
4326;; However, there's a bug somewhere in reload which means that this
4327;; can be partially ignored during spill allocation if the memory
ed29c566 4328;; address also needs reloading; this causes us to die later on when
a2cd141b 4329;; we try to verify the operands. Fortunately, we don't really need
4330;; the early-clobber: we can always use operand 0 if operand 2
4331;; overlaps the address.
25f905c2 4332(define_insn "*thumb1_extendhisi2_insn_v6"
a2cd141b 4333 [(set (match_operand:SI 0 "register_operand" "=l,l")
4334 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4335 (clobber (match_scratch:SI 2 "=X,l"))]
25f905c2 4336 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4337 "*
4338 {
4339 rtx ops[4];
4340 rtx mem;
4341
4342 if (which_alternative == 0)
4343 return \"sxth\\t%0, %1\";
4344
4345 mem = XEXP (operands[1], 0);
4346
4347 /* This code used to try to use 'V', and fix the address only if it was
4348 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4349 range of QImode offsets, and offsettable_address_p does a QImode
4350 address check. */
4351
4352 if (GET_CODE (mem) == CONST)
4353 mem = XEXP (mem, 0);
4354
4355 if (GET_CODE (mem) == LABEL_REF)
4356 return \"ldr\\t%0, %1\";
4357
4358 if (GET_CODE (mem) == PLUS)
4359 {
4360 rtx a = XEXP (mem, 0);
4361 rtx b = XEXP (mem, 1);
4362
4363 if (GET_CODE (a) == LABEL_REF
4364 && GET_CODE (b) == CONST_INT)
4365 return \"ldr\\t%0, %1\";
4366
4367 if (GET_CODE (b) == REG)
4368 return \"ldrsh\\t%0, %1\";
4369
4370 ops[1] = a;
4371 ops[2] = b;
4372 }
4373 else
4374 {
4375 ops[1] = mem;
4376 ops[2] = const0_rtx;
4377 }
4378
ed29c566 4379 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4380
4381 ops[0] = operands[0];
4382 if (reg_mentioned_p (operands[2], ops[1]))
4383 ops[3] = ops[0];
4384 else
4385 ops[3] = operands[2];
4386 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4387 return \"\";
4388 }"
4389 [(set_attr "length" "2,4")
4390 (set_attr "type" "alu_shift,load_byte")
4391 (set_attr "pool_range" "*,1020")]
4392)
4393
25f905c2 4394;; This pattern will only be used when ldsh is not available
25f7a26e 4395(define_expand "extendhisi2_mem"
eab14235 4396 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4397 (set (match_dup 3)
eab14235 4398 (zero_extend:SI (match_dup 7)))
25f7a26e 4399 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4400 (set (match_operand:SI 0 "" "")
4401 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4402 "TARGET_ARM"
25f7a26e 4403 "
215b30b3 4404 {
4405 rtx mem1, mem2;
4406 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4407
788fcce0 4408 mem1 = change_address (operands[1], QImode, addr);
4409 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4410 operands[0] = gen_lowpart (SImode, operands[0]);
4411 operands[1] = mem1;
4412 operands[2] = gen_reg_rtx (SImode);
4413 operands[3] = gen_reg_rtx (SImode);
4414 operands[6] = gen_reg_rtx (SImode);
4415 operands[7] = mem2;
25f7a26e 4416
215b30b3 4417 if (BYTES_BIG_ENDIAN)
4418 {
4419 operands[4] = operands[2];
4420 operands[5] = operands[3];
4421 }
4422 else
4423 {
4424 operands[4] = operands[3];
4425 operands[5] = operands[2];
4426 }
4427 }"
4428)
b11cae9e 4429
a2cd141b 4430(define_insn "*arm_extendhisi2"
4431 [(set (match_operand:SI 0 "s_register_operand" "=r")
4432 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4433 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4434 "ldr%(sh%)\\t%0, %1"
a2cd141b 4435 [(set_attr "type" "load_byte")
0d66636f 4436 (set_attr "predicable" "yes")
cffb2a26 4437 (set_attr "pool_range" "256")
4438 (set_attr "neg_pool_range" "244")]
4439)
f7fbdd4a 4440
25f905c2 4441;; ??? Check Thumb-2 pool range
a2cd141b 4442(define_insn "*arm_extendhisi2_v6"
4443 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4444 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4445 "TARGET_32BIT && arm_arch6"
a2cd141b 4446 "@
4447 sxth%?\\t%0, %1
25f905c2 4448 ldr%(sh%)\\t%0, %1"
a2cd141b 4449 [(set_attr "type" "alu_shift,load_byte")
4450 (set_attr "predicable" "yes")
4451 (set_attr "pool_range" "*,256")
4452 (set_attr "neg_pool_range" "*,244")]
4453)
4454
4455(define_insn "*arm_extendhisi2addsi"
4456 [(set (match_operand:SI 0 "s_register_operand" "=r")
4457 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4458 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4459 "TARGET_INT_SIMD"
a2cd141b 4460 "sxtah%?\\t%0, %2, %1"
4461)
4462
c8f69309 4463(define_expand "extendqihi2"
4464 [(set (match_dup 2)
bed7d9a5 4465 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4466 (const_int 24)))
9c08d1fa 4467 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4468 (ashiftrt:SI (match_dup 2)
4469 (const_int 24)))]
cffb2a26 4470 "TARGET_ARM"
c8f69309 4471 "
215b30b3 4472 {
4473 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4474 {
4475 emit_insn (gen_rtx_SET (VOIDmode,
4476 operands[0],
4477 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4478 DONE;
4479 }
4480 if (!s_register_operand (operands[1], QImode))
4481 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4482 operands[0] = gen_lowpart (SImode, operands[0]);
4483 operands[1] = gen_lowpart (SImode, operands[1]);
4484 operands[2] = gen_reg_rtx (SImode);
4485 }"
4486)
f7fbdd4a 4487
25f905c2 4488(define_insn "*arm_extendqihi_insn"
b4e8a300 4489 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4490 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4491 "TARGET_ARM && arm_arch4"
25f905c2 4492 "ldr%(sb%)\\t%0, %1"
a2cd141b 4493 [(set_attr "type" "load_byte")
0d66636f 4494 (set_attr "predicable" "yes")
cffb2a26 4495 (set_attr "pool_range" "256")
4496 (set_attr "neg_pool_range" "244")]
4497)
3fc2009e 4498
b11cae9e 4499(define_expand "extendqisi2"
c8f69309 4500 [(set (match_dup 2)
bed7d9a5 4501 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
b11cae9e 4502 (const_int 24)))
9c08d1fa 4503 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4504 (ashiftrt:SI (match_dup 2)
4505 (const_int 24)))]
cffb2a26 4506 "TARGET_EITHER"
b11cae9e 4507 "
cffb2a26 4508 {
a2cd141b 4509 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 4510 {
a2cd141b 4511 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 4512 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4513 DONE;
4514 }
a2cd141b 4515
215b30b3 4516 if (!s_register_operand (operands[1], QImode))
cffb2a26 4517 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 4518
a2cd141b 4519 if (arm_arch6)
4520 {
4521 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4522 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4523 DONE;
cffb2a26 4524 }
a2cd141b 4525
4526 operands[1] = gen_lowpart (SImode, operands[1]);
4527 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4528 }"
4529)
f7fbdd4a 4530
a2cd141b 4531(define_insn "*arm_extendqisi"
4532 [(set (match_operand:SI 0 "s_register_operand" "=r")
bed7d9a5 4533 (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
a2cd141b 4534 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4535 "ldr%(sb%)\\t%0, %1"
a2cd141b 4536 [(set_attr "type" "load_byte")
0d66636f 4537 (set_attr "predicable" "yes")
cffb2a26 4538 (set_attr "pool_range" "256")
4539 (set_attr "neg_pool_range" "244")]
4540)
3fc2009e 4541
a2cd141b 4542(define_insn "*arm_extendqisi_v6"
4543 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4544 (sign_extend:SI
4545 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4546 "TARGET_ARM && arm_arch6"
b4e8a300 4547 "@
4548 sxtb%?\\t%0, %1
25f905c2 4549 ldr%(sb%)\\t%0, %1"
a2cd141b 4550 [(set_attr "type" "alu_shift,load_byte")
4551 (set_attr "predicable" "yes")
a2cd141b 4552 (set_attr "pool_range" "*,256")
4553 (set_attr "neg_pool_range" "*,244")]
4554)
4555
4556(define_insn "*arm_extendqisi2addsi"
4557 [(set (match_operand:SI 0 "s_register_operand" "=r")
4558 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4559 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4560 "TARGET_INT_SIMD"
a2cd141b 4561 "sxtab%?\\t%0, %2, %1"
4562 [(set_attr "type" "alu_shift")
bcaec148 4563 (set_attr "insn" "xtab")
a2cd141b 4564 (set_attr "predicable" "yes")]
4565)
4566
25f905c2 4567(define_insn "*thumb1_extendqisi2"
a2cd141b 4568 [(set (match_operand:SI 0 "register_operand" "=l,l")
4569 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
25f905c2 4570 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4571 "*
4572 {
4573 rtx ops[3];
4574 rtx mem = XEXP (operands[1], 0);
4575
4576 if (GET_CODE (mem) == CONST)
4577 mem = XEXP (mem, 0);
4578
4579 if (GET_CODE (mem) == LABEL_REF)
4580 return \"ldr\\t%0, %1\";
4581
4582 if (GET_CODE (mem) == PLUS
4583 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4584 return \"ldr\\t%0, %1\";
4585
4586 if (which_alternative == 0)
4587 return \"ldrsb\\t%0, %1\";
4588
4589 ops[0] = operands[0];
4590
4591 if (GET_CODE (mem) == PLUS)
4592 {
4593 rtx a = XEXP (mem, 0);
4594 rtx b = XEXP (mem, 1);
4595
4596 ops[1] = a;
4597 ops[2] = b;
4598
4599 if (GET_CODE (a) == REG)
4600 {
4601 if (GET_CODE (b) == REG)
4602 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4603 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 4604 {
4605 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4606 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4607 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4608 }
cffb2a26 4609 else
4610 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4611 }
cffb2a26 4612 else
4613 {
ed29c566 4614 gcc_assert (GET_CODE (b) == REG);
cffb2a26 4615 if (REGNO (b) == REGNO (ops[0]))
215b30b3 4616 {
4617 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4618 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4619 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4620 }
cffb2a26 4621 else
4622 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4623 }
4624 }
4625 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4626 {
215b30b3 4627 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4628 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4629 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 4630 }
4631 else
4632 {
4633 ops[1] = mem;
4634 ops[2] = const0_rtx;
4635
4636 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4637 }
4638 return \"\";
4639 }"
4640 [(set_attr "length" "2,6")
a2cd141b 4641 (set_attr "type" "load_byte,load_byte")
cffb2a26 4642 (set_attr "pool_range" "32,32")]
4643)
4644
25f905c2 4645(define_insn "*thumb1_extendqisi2_v6"
a2cd141b 4646 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4647 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
25f905c2 4648 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4649 "*
4650 {
4651 rtx ops[3];
4652 rtx mem;
4653
4654 if (which_alternative == 0)
4655 return \"sxtb\\t%0, %1\";
4656
4657 mem = XEXP (operands[1], 0);
4658
4659 if (GET_CODE (mem) == CONST)
4660 mem = XEXP (mem, 0);
4661
4662 if (GET_CODE (mem) == LABEL_REF)
4663 return \"ldr\\t%0, %1\";
4664
4665 if (GET_CODE (mem) == PLUS
4666 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4667 return \"ldr\\t%0, %1\";
4668
4669 if (which_alternative == 0)
4670 return \"ldrsb\\t%0, %1\";
4671
4672 ops[0] = operands[0];
4673
4674 if (GET_CODE (mem) == PLUS)
4675 {
4676 rtx a = XEXP (mem, 0);
4677 rtx b = XEXP (mem, 1);
4678
4679 ops[1] = a;
4680 ops[2] = b;
4681
4682 if (GET_CODE (a) == REG)
4683 {
4684 if (GET_CODE (b) == REG)
4685 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4686 else if (REGNO (a) == REGNO (ops[0]))
4687 {
4688 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4689 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4690 }
4691 else
4692 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4693 }
a2cd141b 4694 else
4695 {
ed29c566 4696 gcc_assert (GET_CODE (b) == REG);
a2cd141b 4697 if (REGNO (b) == REGNO (ops[0]))
4698 {
4699 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4700 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4701 }
4702 else
4703 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4704 }
4705 }
4706 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4707 {
4708 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4709 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4710 }
4711 else
4712 {
4713 ops[1] = mem;
4714 ops[2] = const0_rtx;
4715
4716 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4717 }
4718 return \"\";
4719 }"
4720 [(set_attr "length" "2,2,4")
4721 (set_attr "type" "alu_shift,load_byte,load_byte")
4722 (set_attr "pool_range" "*,32,32")]
4723)
4724
caedf871 4725(define_expand "extendsfdf2"
4726 [(set (match_operand:DF 0 "s_register_operand" "")
4727 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4728 "TARGET_32BIT && TARGET_HARD_FLOAT"
caedf871 4729 ""
4730)
9b8516be 4731
4732/* HFmode -> DFmode conversions have to go through SFmode. */
4733(define_expand "extendhfdf2"
4734 [(set (match_operand:DF 0 "general_operand" "")
4735 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4736 "TARGET_EITHER"
4737 "
4738 {
4739 rtx op1;
4740 op1 = convert_to_mode (SFmode, operands[1], 0);
4741 op1 = convert_to_mode (DFmode, op1, 0);
4742 emit_insn (gen_movdf (operands[0], op1));
4743 DONE;
4744 }"
4745)
b11cae9e 4746\f
4747;; Move insns (including loads and stores)
4748
4749;; XXX Just some ideas about movti.
9c08d1fa 4750;; I don't think these are a good idea on the arm, there just aren't enough
4751;; registers
b11cae9e 4752;;(define_expand "loadti"
9c08d1fa 4753;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4754;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4755;; "" "")
4756
4757;;(define_expand "storeti"
4758;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4759;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4760;; "" "")
4761
4762;;(define_expand "movti"
4763;; [(set (match_operand:TI 0 "general_operand" "")
4764;; (match_operand:TI 1 "general_operand" ""))]
4765;; ""
4766;; "
4767;;{
4768;; rtx insn;
4769;;
4770;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4771;; operands[1] = copy_to_reg (operands[1]);
4772;; if (GET_CODE (operands[0]) == MEM)
4773;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4774;; else if (GET_CODE (operands[1]) == MEM)
4775;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4776;; else
4777;; FAIL;
4778;;
4779;; emit_insn (insn);
4780;; DONE;
4781;;}")
4782
a2f10574 4783;; Recognize garbage generated above.
b11cae9e 4784
4785;;(define_insn ""
4786;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4787;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4788;; ""
4789;; "*
4790;; {
4791;; register mem = (which_alternative < 3);
0d66636f 4792;; register const char *template;
b11cae9e 4793;;
4794;; operands[mem] = XEXP (operands[mem], 0);
4795;; switch (which_alternative)
4796;; {
4797;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4798;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4799;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4800;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4801;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4802;; case 5: template = \"stmia\\t%0, %M1\"; break;
4803;; }
e2348bcb 4804;; output_asm_insn (template, operands);
4805;; return \"\";
b11cae9e 4806;; }")
4807
cffb2a26 4808(define_expand "movdi"
4809 [(set (match_operand:DI 0 "general_operand" "")
4810 (match_operand:DI 1 "general_operand" ""))]
4811 "TARGET_EITHER"
4812 "
e1ba4a27 4813 if (can_create_pseudo_p ())
cffb2a26 4814 {
b2778788 4815 if (GET_CODE (operands[0]) != REG)
4816 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4817 }
4818 "
4819)
b11cae9e 4820
cffb2a26 4821(define_insn "*arm_movdi"
d51f92df 4822 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4823 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4824 "TARGET_ARM
b2778788 4825 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4826 && !TARGET_IWMMXT
4827 && ( register_operand (operands[0], DImode)
4828 || register_operand (operands[1], DImode))"
b11cae9e 4829 "*
d51f92df 4830 switch (which_alternative)
4831 {
4832 case 0:
4833 case 1:
4834 case 2:
4835 return \"#\";
4836 default:
4837 return output_move_double (operands);
4838 }
cffb2a26 4839 "
359a6e9f 4840 [(set_attr "length" "8,12,16,8,8")
4841 (set_attr "type" "*,*,*,load2,store2")
4842 (set_attr "pool_range" "*,*,*,1020,*")
4843 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4844)
4845
d51f92df 4846(define_split
4847 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4848 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4849 "TARGET_32BIT
d51f92df 4850 && reload_completed
4851 && (arm_const_double_inline_cost (operands[1])
4852 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4853 [(const_int 0)]
4854 "
4855 arm_split_constant (SET, SImode, curr_insn,
4856 INTVAL (gen_lowpart (SImode, operands[1])),
4857 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4858 arm_split_constant (SET, SImode, curr_insn,
4859 INTVAL (gen_highpart_mode (SImode,
4860 GET_MODE (operands[0]),
4861 operands[1])),
4862 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4863 DONE;
4864 "
4865)
4866
e5ba9289 4867; If optimizing for size, or if we have load delay slots, then
4868; we want to split the constant into two separate operations.
4869; In both cases this may split a trivial part into a single data op
4870; leaving a single complex constant to load. We can also get longer
4871; offsets in a LDR which means we get better chances of sharing the pool
4872; entries. Finally, we can normally do a better job of scheduling
4873; LDR instructions than we can with LDM.
4874; This pattern will only match if the one above did not.
4875(define_split
4876 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4877 (match_operand:ANY64 1 "const_double_operand" ""))]
4878 "TARGET_ARM && reload_completed
4879 && arm_const_double_by_parts (operands[1])"
4880 [(set (match_dup 0) (match_dup 1))
4881 (set (match_dup 2) (match_dup 3))]
4882 "
4883 operands[2] = gen_highpart (SImode, operands[0]);
4884 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4885 operands[1]);
4886 operands[0] = gen_lowpart (SImode, operands[0]);
4887 operands[1] = gen_lowpart (SImode, operands[1]);
4888 "
4889)
4890
d51f92df 4891(define_split
4892 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4893 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4894 "TARGET_EITHER && reload_completed"
4895 [(set (match_dup 0) (match_dup 1))
4896 (set (match_dup 2) (match_dup 3))]
4897 "
4898 operands[2] = gen_highpart (SImode, operands[0]);
4899 operands[3] = gen_highpart (SImode, operands[1]);
4900 operands[0] = gen_lowpart (SImode, operands[0]);
4901 operands[1] = gen_lowpart (SImode, operands[1]);
4902
4903 /* Handle a partial overlap. */
4904 if (rtx_equal_p (operands[0], operands[3]))
4905 {
4906 rtx tmp0 = operands[0];
4907 rtx tmp1 = operands[1];
4908
4909 operands[0] = operands[2];
4910 operands[1] = operands[3];
4911 operands[2] = tmp0;
4912 operands[3] = tmp1;
4913 }
4914 "
4915)
4916
a8a3b539 4917;; We can't actually do base+index doubleword loads if the index and
4918;; destination overlap. Split here so that we at least have chance to
4919;; schedule.
4920(define_split
4921 [(set (match_operand:DI 0 "s_register_operand" "")
4922 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4923 (match_operand:SI 2 "s_register_operand" ""))))]
4924 "TARGET_LDRD
4925 && reg_overlap_mentioned_p (operands[0], operands[1])
4926 && reg_overlap_mentioned_p (operands[0], operands[2])"
4927 [(set (match_dup 4)
4928 (plus:SI (match_dup 1)
4929 (match_dup 2)))
4930 (set (match_dup 0)
4931 (mem:DI (match_dup 4)))]
4932 "
4933 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4934 "
4935)
4936
cffb2a26 4937;;; ??? This should have alternatives for constants.
4938;;; ??? This was originally identical to the movdf_insn pattern.
4939;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4940;;; thumb_reorg with a memory reference.
25f905c2 4941(define_insn "*thumb1_movdi_insn"
215b30b3 4942 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4943 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4944 "TARGET_THUMB1
a2cd141b 4945 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4946 && ( register_operand (operands[0], DImode)
4947 || register_operand (operands[1], DImode))"
4948 "*
4949 {
4950 switch (which_alternative)
4951 {
4952 default:
4953 case 0:
4954 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4955 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4956 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4957 case 1:
4958 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4959 case 2:
4960 operands[1] = GEN_INT (- INTVAL (operands[1]));
4961 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4962 case 3:
4963 return \"ldmia\\t%1, {%0, %H0}\";
4964 case 4:
4965 return \"stmia\\t%0, {%1, %H1}\";
4966 case 5:
4967 return thumb_load_double_from_address (operands);
4968 case 6:
1a83b3ff 4969 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4970 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4971 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4972 return \"\";
4973 case 7:
4974 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4975 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4976 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4977 }
4978 }"
4979 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4980 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4981 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4982)
b11cae9e 4983
9c08d1fa 4984(define_expand "movsi"
4985 [(set (match_operand:SI 0 "general_operand" "")
4986 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4987 "TARGET_EITHER"
9c08d1fa 4988 "
befb0bac 4989 {
e348ff3e 4990 rtx base, offset, tmp;
4991
25f905c2 4992 if (TARGET_32BIT)
9c08d1fa 4993 {
674a8f0b 4994 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4995 if (GET_CODE (operands[0]) == MEM)
4996 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4997 if (arm_general_register_operand (operands[0], SImode)
4998 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4999 && !(const_ok_for_arm (INTVAL (operands[1]))
5000 || const_ok_for_arm (~INTVAL (operands[1]))))
5001 {
96f57e36 5002 arm_split_constant (SET, SImode, NULL_RTX,
5003 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5004 optimize && can_create_pseudo_p ());
cffb2a26 5005 DONE;
5006 }
d0e6a121 5007
5008 if (TARGET_USE_MOVT && !target_word_relocations
5009 && GET_CODE (operands[1]) == SYMBOL_REF
5010 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5011 {
5012 arm_emit_movpair (operands[0], operands[1]);
5013 DONE;
5014 }
cffb2a26 5015 }
25f905c2 5016 else /* TARGET_THUMB1... */
cffb2a26 5017 {
e1ba4a27 5018 if (can_create_pseudo_p ())
cffb2a26 5019 {
5020 if (GET_CODE (operands[0]) != REG)
5021 operands[1] = force_reg (SImode, operands[1]);
5022 }
9c08d1fa 5023 }
f655717d 5024
e348ff3e 5025 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5026 {
5027 split_const (operands[1], &base, &offset);
5028 if (GET_CODE (base) == SYMBOL_REF
5029 && !offset_within_block_p (base, INTVAL (offset)))
5030 {
b308ddcf 5031 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5032 emit_move_insn (tmp, base);
5033 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5034 DONE;
5035 }
5036 }
5037
f655717d 5038 /* Recognize the case where operand[1] is a reference to thread-local
5039 data and load its address to a register. */
5040 if (arm_tls_referenced_p (operands[1]))
5041 {
5042 rtx tmp = operands[1];
5043 rtx addend = NULL;
5044
5045 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5046 {
5047 addend = XEXP (XEXP (tmp, 0), 1);
5048 tmp = XEXP (XEXP (tmp, 0), 0);
5049 }
5050
5051 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5052 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5053
e1ba4a27 5054 tmp = legitimize_tls_address (tmp,
5055 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5056 if (addend)
5057 {
5058 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5059 tmp = force_operand (tmp, operands[0]);
5060 }
5061 operands[1] = tmp;
5062 }
5063 else if (flag_pic
5064 && (CONSTANT_P (operands[1])
5065 || symbol_mentioned_p (operands[1])
5066 || label_mentioned_p (operands[1])))
5067 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5068 (!can_create_pseudo_p ()
5069 ? operands[0]
5070 : 0));
befb0bac 5071 }
215b30b3 5072 "
5073)
9c08d1fa 5074
d0e6a121 5075;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5076;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5077;; so this does not matter.
5078(define_insn "*arm_movt"
5079 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5080 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5081 (match_operand:SI 2 "general_operand" "i")))]
5082 "TARGET_32BIT"
5083 "movt%?\t%0, #:upper16:%c2"
5084 [(set_attr "predicable" "yes")
5085 (set_attr "length" "4")]
5086)
5087
5088(define_insn "*arm_movw"
5089 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5090 (high:SI (match_operand:SI 1 "general_operand" "i")))]
5091 "TARGET_32BIT"
5092 "movw%?\t%0, #:lower16:%c1"
5093 [(set_attr "predicable" "yes")
5094 (set_attr "length" "4")]
5095)
5096
cffb2a26 5097(define_insn "*arm_movsi_insn"
aaa37ad6 5098 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5099 (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk"))]
755eb2b4 5100 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5101 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5102 && ( register_operand (operands[0], SImode)
5103 || register_operand (operands[1], SImode))"
f7fbdd4a 5104 "@
aaa37ad6 5105 mov%?\\t%0, %1
f7fbdd4a 5106 mov%?\\t%0, %1
5107 mvn%?\\t%0, #%B1
25f905c2 5108 movw%?\\t%0, %1
f7fbdd4a 5109 ldr%?\\t%0, %1
5110 str%?\\t%1, %0"
aaa37ad6 5111 [(set_attr "type" "*,*,*,*,load1,store1")
0d66636f 5112 (set_attr "predicable" "yes")
aaa37ad6 5113 (set_attr "pool_range" "*,*,*,*,4096,*")
5114 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5115)
87b22bf7 5116
5117(define_split
a2cd141b 5118 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5119 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5120 "TARGET_32BIT
215b30b3 5121 && (!(const_ok_for_arm (INTVAL (operands[1]))
5122 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5123 [(clobber (const_int 0))]
5124 "
96f57e36 5125 arm_split_constant (SET, SImode, NULL_RTX,
5126 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5127 DONE;
215b30b3 5128 "
5129)
9c08d1fa 5130
25f905c2 5131(define_insn "*thumb1_movsi_insn"
aaa37ad6 5132 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5133 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
25f905c2 5134 "TARGET_THUMB1
cffb2a26 5135 && ( register_operand (operands[0], SImode)
5136 || register_operand (operands[1], SImode))"
5137 "@
5138 mov %0, %1
5139 mov %0, %1
5140 #
5141 #
5142 ldmia\\t%1, {%0}
5143 stmia\\t%0, {%1}
5144 ldr\\t%0, %1
5145 str\\t%1, %0
5146 mov\\t%0, %1"
5147 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5148 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 5149 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5150)
5151
5152(define_split
5153 [(set (match_operand:SI 0 "register_operand" "")
5154 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5155 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
cffb2a26 5156 [(set (match_dup 0) (match_dup 1))
5157 (set (match_dup 0) (neg:SI (match_dup 0)))]
5158 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5159)
5160
5161(define_split
5162 [(set (match_operand:SI 0 "register_operand" "")
5163 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5164 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
cffb2a26 5165 [(set (match_dup 0) (match_dup 1))
5166 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5167 "
5168 {
e4aeee53 5169 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5170 unsigned HOST_WIDE_INT mask = 0xff;
5171 int i;
5172
5173 for (i = 0; i < 25; i++)
5174 if ((val & (mask << i)) == val)
5175 break;
5176
f5b3169c 5177 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 5178 if (i == 0)
5179 FAIL;
5180
5181 operands[1] = GEN_INT (val >> i);
5182 operands[2] = GEN_INT (i);
5183 }"
5184)
5185
67336bcf 5186;; When generating pic, we need to load the symbol offset into a register.
5187;; So that the optimizer does not confuse this with a normal symbol load
5188;; we use an unspec. The offset will be loaded from a constant pool entry,
5189;; since that is the only type of relocation we can use.
5190
5191;; The rather odd constraints on the following are to force reload to leave
5192;; the insn alone, and to force the minipool generation pass to then move
5193;; the GOT symbol to memory.
849170fd 5194
8c4d8060 5195(define_insn "pic_load_addr_arm"
849170fd 5196 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5197 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 5198 "TARGET_ARM && flag_pic"
67336bcf 5199 "ldr%?\\t%0, %1"
a2cd141b 5200 [(set_attr "type" "load1")
8c4d8060 5201 (set (attr "pool_range") (const_int 4096))
5202 (set (attr "neg_pool_range") (const_int 4084))]
5203)
5204
25f905c2 5205(define_insn "pic_load_addr_thumb1"
8c4d8060 5206 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5207 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5208 "TARGET_THUMB1 && flag_pic"
8c4d8060 5209 "ldr\\t%0, %1"
a2cd141b 5210 [(set_attr "type" "load1")
8c4d8060 5211 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5212)
849170fd 5213
cffb2a26 5214(define_insn "pic_add_dot_plus_four"
15d5d060 5215 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5216 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5217 (const_int 4)
beef0fb5 5218 (match_operand 2 "" "")]
5219 UNSPEC_PIC_BASE))]
25f905c2 5220 "TARGET_THUMB1"
cffb2a26 5221 "*
6cdcb15c 5222 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5223 INTVAL (operands[2]));
cffb2a26 5224 return \"add\\t%0, %|pc\";
5225 "
5226 [(set_attr "length" "2")]
5227)
849170fd 5228
5229(define_insn "pic_add_dot_plus_eight"
15d5d060 5230 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5231 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5232 (const_int 8)
beef0fb5 5233 (match_operand 2 "" "")]
5234 UNSPEC_PIC_BASE))]
f655717d 5235 "TARGET_ARM"
c4034607 5236 "*
6cdcb15c 5237 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5238 INTVAL (operands[2]));
15d5d060 5239 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5240 "
0d66636f 5241 [(set_attr "predicable" "yes")]
cffb2a26 5242)
849170fd 5243
f655717d 5244(define_insn "tls_load_dot_plus_eight"
5245 [(set (match_operand:SI 0 "register_operand" "+r")
c0c1fba5 5246 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5247 (const_int 8)
beef0fb5 5248 (match_operand 2 "" "")]
5249 UNSPEC_PIC_BASE)))]
f655717d 5250 "TARGET_ARM"
5251 "*
6cdcb15c 5252 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5253 INTVAL (operands[2]));
f655717d 5254 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5255 "
5256 [(set_attr "predicable" "yes")]
5257)
5258
5259;; PIC references to local variables can generate pic_add_dot_plus_eight
5260;; followed by a load. These sequences can be crunched down to
5261;; tls_load_dot_plus_eight by a peephole.
5262
5263(define_peephole2
c0c1fba5 5264 [(set (match_operand:SI 0 "register_operand" "")
5265 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5266 (const_int 8)
5267 (match_operand 1 "" "")]
5268 UNSPEC_PIC_BASE))
f655717d 5269 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5270 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5271 [(set (match_dup 2)
5272 (mem:SI (unspec:SI [(match_dup 3)
5273 (const_int 8)
5274 (match_dup 1)]
5275 UNSPEC_PIC_BASE)))]
f655717d 5276 ""
5277)
5278
bac7fc85 5279(define_insn "pic_offset_arm"
5280 [(set (match_operand:SI 0 "register_operand" "=r")
5281 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5282 (unspec:SI [(match_operand:SI 2 "" "X")]
5283 UNSPEC_PIC_OFFSET))))]
5284 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5285 "ldr%?\\t%0, [%1,%2]"
5286 [(set_attr "type" "load1")]
5287)
5288
95373f08 5289(define_expand "builtin_setjmp_receiver"
5290 [(label_ref (match_operand 0 "" ""))]
5291 "flag_pic"
5292 "
5293{
b935b306 5294 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5295 register. */
2cb7d577 5296 if (arm_pic_register != INVALID_REGNUM)
5297 arm_load_pic_register (1UL << 3);
95373f08 5298 DONE;
5299}")
5300
9c08d1fa 5301;; If copying one reg to another we can set the condition codes according to
5302;; its value. Such a move is common after a return from subroutine and the
5303;; result is being tested against zero.
5304
f7fbdd4a 5305(define_insn "*movsi_compare0"
bd5b4116 5306 [(set (reg:CC CC_REGNUM)
cffb2a26 5307 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5308 (const_int 0)))
5309 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5310 (match_dup 1))]
25f905c2 5311 "TARGET_32BIT"
e2348bcb 5312 "@
40dbec34 5313 cmp%?\\t%0, #0
25f905c2 5314 sub%.\\t%0, %1, #0"
cffb2a26 5315 [(set_attr "conds" "set")]
5316)
b11cae9e 5317
b11cae9e 5318;; Subroutine to store a half word from a register into memory.
5319;; Operand 0 is the source register (HImode)
c8f69309 5320;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5321
9c08d1fa 5322;; In both this routine and the next, we must be careful not to spill
01cc3b75 5323;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5324;; can generate unrecognizable rtl.
5325
b11cae9e 5326(define_expand "storehi"
c8f69309 5327 [;; store the low byte
f082f1c4 5328 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5329 ;; extract the high byte
c8f69309 5330 (set (match_dup 2)
5331 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5332 ;; store the high byte
787f8210 5333 (set (match_dup 4) (match_dup 5))]
cffb2a26 5334 "TARGET_ARM"
b11cae9e 5335 "
215b30b3 5336 {
537ffcfc 5337 rtx op1 = operands[1];
5338 rtx addr = XEXP (op1, 0);
215b30b3 5339 enum rtx_code code = GET_CODE (addr);
5340
5341 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5342 || code == MINUS)
537ffcfc 5343 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5344
537ffcfc 5345 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5346 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5347 operands[3] = gen_lowpart (QImode, operands[0]);
5348 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5349 operands[2] = gen_reg_rtx (SImode);
5350 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5351 }"
5352)
b11cae9e 5353
c7597b5d 5354(define_expand "storehi_bigend"
f082f1c4 5355 [(set (match_dup 4) (match_dup 3))
c7597b5d 5356 (set (match_dup 2)
5357 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5358 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5359 "TARGET_ARM"
b11cae9e 5360 "
215b30b3 5361 {
537ffcfc 5362 rtx op1 = operands[1];
5363 rtx addr = XEXP (op1, 0);
215b30b3 5364 enum rtx_code code = GET_CODE (addr);
5365
5366 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5367 || code == MINUS)
537ffcfc 5368 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5369
537ffcfc 5370 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5371 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5372 operands[3] = gen_lowpart (QImode, operands[0]);
5373 operands[0] = gen_lowpart (SImode, operands[0]);
5374 operands[2] = gen_reg_rtx (SImode);
787f8210 5375 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5376 }"
5377)
c7597b5d 5378
5379;; Subroutine to store a half word integer constant into memory.
5380(define_expand "storeinthi"
f082f1c4 5381 [(set (match_operand 0 "" "")
787f8210 5382 (match_operand 1 "" ""))
9e8503e6 5383 (set (match_dup 3) (match_dup 2))]
cffb2a26 5384 "TARGET_ARM"
c7597b5d 5385 "
215b30b3 5386 {
5387 HOST_WIDE_INT value = INTVAL (operands[1]);
5388 rtx addr = XEXP (operands[0], 0);
537ffcfc 5389 rtx op0 = operands[0];
215b30b3 5390 enum rtx_code code = GET_CODE (addr);
c7597b5d 5391
215b30b3 5392 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5393 || code == MINUS)
537ffcfc 5394 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5395
215b30b3 5396 operands[1] = gen_reg_rtx (SImode);
5397 if (BYTES_BIG_ENDIAN)
5398 {
5399 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5400 if ((value & 255) == ((value >> 8) & 255))
5401 operands[2] = operands[1];
5402 else
5403 {
5404 operands[2] = gen_reg_rtx (SImode);
5405 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5406 }
5407 }
5408 else
5409 {
5410 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5411 if ((value & 255) == ((value >> 8) & 255))
5412 operands[2] = operands[1];
5413 else
5414 {
5415 operands[2] = gen_reg_rtx (SImode);
5416 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5417 }
5418 }
c7597b5d 5419
537ffcfc 5420 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5421 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5422 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5423 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5424 }"
5425)
b11cae9e 5426
f7fbdd4a 5427(define_expand "storehi_single_op"
5428 [(set (match_operand:HI 0 "memory_operand" "")
5429 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5430 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5431 "
215b30b3 5432 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5433 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5434 "
5435)
f7fbdd4a 5436
b11cae9e 5437(define_expand "movhi"
5438 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5439 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5440 "TARGET_EITHER"
b11cae9e 5441 "
cffb2a26 5442 if (TARGET_ARM)
b11cae9e 5443 {
e1ba4a27 5444 if (can_create_pseudo_p ())
cffb2a26 5445 {
5446 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5447 {
cffb2a26 5448 if (arm_arch4)
5449 {
5450 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5451 DONE;
5452 }
5453 if (GET_CODE (operands[1]) == CONST_INT)
5454 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5455 else
cffb2a26 5456 {
5457 if (GET_CODE (operands[1]) == MEM)
5458 operands[1] = force_reg (HImode, operands[1]);
5459 if (BYTES_BIG_ENDIAN)
5460 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5461 else
5462 emit_insn (gen_storehi (operands[1], operands[0]));
5463 }
5464 DONE;
b11cae9e 5465 }
cffb2a26 5466 /* Sign extend a constant, and keep it in an SImode reg. */
5467 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5468 {
cffb2a26 5469 rtx reg = gen_reg_rtx (SImode);
5470 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5471
5472 /* If the constant is already valid, leave it alone. */
215b30b3 5473 if (!const_ok_for_arm (val))
cffb2a26 5474 {
5475 /* If setting all the top bits will make the constant
5476 loadable in a single instruction, then set them.
5477 Otherwise, sign extend the number. */
5478
215b30b3 5479 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5480 val |= ~0xffff;
5481 else if (val & 0x8000)
5482 val |= ~0xffff;
5483 }
5484
5485 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5486 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5487 }
e1ba4a27 5488 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5489 && GET_CODE (operands[1]) == MEM)
5490 {
5491 rtx reg = gen_reg_rtx (SImode);
5492
5493 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5494 operands[1] = gen_lowpart (HImode, reg);
5495 }
215b30b3 5496 else if (!arm_arch4)
f7fbdd4a 5497 {
cffb2a26 5498 if (GET_CODE (operands[1]) == MEM)
5499 {
c1a66faf 5500 rtx base;
5501 rtx offset = const0_rtx;
5502 rtx reg = gen_reg_rtx (SImode);
5503
5504 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5505 || (GET_CODE (base) == PLUS
5506 && (GET_CODE (offset = XEXP (base, 1))
5507 == CONST_INT)
5508 && ((INTVAL(offset) & 1) != 1)
5509 && GET_CODE (base = XEXP (base, 0)) == REG))
5510 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5511 {
8deb3959 5512 rtx new_rtx;
c1a66faf 5513
8deb3959 5514 new_rtx = widen_memory_access (operands[1], SImode,
5515 ((INTVAL (offset) & ~3)
5516 - INTVAL (offset)));
5517 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5518 if (((INTVAL (offset) & 2) != 0)
5519 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5520 {
5521 rtx reg2 = gen_reg_rtx (SImode);
5522
5523 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5524 reg = reg2;
5525 }
206ee9a2 5526 }
c1a66faf 5527 else
5528 emit_insn (gen_movhi_bytes (reg, operands[1]));
5529
5530 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5531 }
5532 }
5533 }
674a8f0b 5534 /* Handle loading a large integer during reload. */
cffb2a26 5535 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5536 && !const_ok_for_arm (INTVAL (operands[1]))
5537 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5538 {
5539 /* Writing a constant to memory needs a scratch, which should
5540 be handled with SECONDARY_RELOADs. */
ed29c566 5541 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5542
5543 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5544 emit_insn (gen_movsi (operands[0], operands[1]));
5545 DONE;
5546 }
5547 }
25f905c2 5548 else if (TARGET_THUMB2)
5549 {
5550 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5551 if (can_create_pseudo_p ())
25f905c2 5552 {
5553 if (GET_CODE (operands[0]) != REG)
5554 operands[1] = force_reg (HImode, operands[1]);
5555 /* Zero extend a constant, and keep it in an SImode reg. */
5556 else if (GET_CODE (operands[1]) == CONST_INT)
5557 {
5558 rtx reg = gen_reg_rtx (SImode);
5559 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5560
5561 emit_insn (gen_movsi (reg, GEN_INT (val)));
5562 operands[1] = gen_lowpart (HImode, reg);
5563 }
5564 }
5565 }
5566 else /* TARGET_THUMB1 */
cffb2a26 5567 {
e1ba4a27 5568 if (can_create_pseudo_p ())
cffb2a26 5569 {
6cffc037 5570 if (GET_CODE (operands[1]) == CONST_INT)
5571 {
5572 rtx reg = gen_reg_rtx (SImode);
5573
5574 emit_insn (gen_movsi (reg, operands[1]));
5575 operands[1] = gen_lowpart (HImode, reg);
5576 }
cffb2a26 5577
5578 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5579 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5580 virtual register (also rejected as illegitimate for HImode/QImode)
5581 relative address. */
cffb2a26 5582 /* ??? This should perhaps be fixed elsewhere, for instance, in
5583 fixup_stack_1, by checking for other kinds of invalid addresses,
5584 e.g. a bare reference to a virtual register. This may confuse the
5585 alpha though, which must handle this case differently. */
5586 if (GET_CODE (operands[0]) == MEM
215b30b3 5587 && !memory_address_p (GET_MODE (operands[0]),
5588 XEXP (operands[0], 0)))
537ffcfc 5589 operands[0]
5590 = replace_equiv_address (operands[0],
5591 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5592
5593 if (GET_CODE (operands[1]) == MEM
215b30b3 5594 && !memory_address_p (GET_MODE (operands[1]),
5595 XEXP (operands[1], 0)))
537ffcfc 5596 operands[1]
5597 = replace_equiv_address (operands[1],
5598 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5599
5600 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5601 {
5602 rtx reg = gen_reg_rtx (SImode);
5603
5604 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5605 operands[1] = gen_lowpart (HImode, reg);
5606 }
5607
5608 if (GET_CODE (operands[0]) == MEM)
5609 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5610 }
cffb2a26 5611 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5612 && !satisfies_constraint_I (operands[1]))
cffb2a26 5613 {
6cffc037 5614 /* Handle loading a large integer during reload. */
5615
cffb2a26 5616 /* Writing a constant to memory needs a scratch, which should
5617 be handled with SECONDARY_RELOADs. */
ed29c566 5618 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5619
1a83b3ff 5620 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5621 emit_insn (gen_movsi (operands[0], operands[1]));
5622 DONE;
5623 }
b11cae9e 5624 }
cffb2a26 5625 "
5626)
5627
25f905c2 5628(define_insn "*thumb1_movhi_insn"
a941568e 5629 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5630 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5631 "TARGET_THUMB1
cffb2a26 5632 && ( register_operand (operands[0], HImode)
5633 || register_operand (operands[1], HImode))"
5634 "*
5635 switch (which_alternative)
d79300ac 5636 {
cffb2a26 5637 case 0: return \"add %0, %1, #0\";
5638 case 2: return \"strh %1, %0\";
5639 case 3: return \"mov %0, %1\";
5640 case 4: return \"mov %0, %1\";
5641 case 5: return \"mov %0, %1\";
ed29c566 5642 default: gcc_unreachable ();
cffb2a26 5643 case 1:
5644 /* The stack pointer can end up being taken as an index register.
5645 Catch this case here and deal with it. */
5646 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5647 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5648 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5649 {
5650 rtx ops[2];
5651 ops[0] = operands[0];
5652 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5653
5654 output_asm_insn (\"mov %0, %1\", ops);
5655
5656 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5657
5658 }
5659 return \"ldrh %0, %1\";
5660 }"
5661 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 5662 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 5663)
d79300ac 5664
b11cae9e 5665
25f7a26e 5666(define_expand "movhi_bytes"
eab14235 5667 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5668 (set (match_dup 3)
eab14235 5669 (zero_extend:SI (match_dup 6)))
25f7a26e 5670 (set (match_operand:SI 0 "" "")
5671 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5672 "TARGET_ARM"
25f7a26e 5673 "
215b30b3 5674 {
5675 rtx mem1, mem2;
5676 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5677
788fcce0 5678 mem1 = change_address (operands[1], QImode, addr);
5679 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5680 operands[0] = gen_lowpart (SImode, operands[0]);
5681 operands[1] = mem1;
5682 operands[2] = gen_reg_rtx (SImode);
5683 operands[3] = gen_reg_rtx (SImode);
5684 operands[6] = mem2;
25f7a26e 5685
215b30b3 5686 if (BYTES_BIG_ENDIAN)
5687 {
5688 operands[4] = operands[2];
5689 operands[5] = operands[3];
5690 }
5691 else
5692 {
5693 operands[4] = operands[3];
5694 operands[5] = operands[2];
5695 }
5696 }"
5697)
25f7a26e 5698
c7597b5d 5699(define_expand "movhi_bigend"
5700 [(set (match_dup 2)
5701 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5702 (const_int 16)))
5703 (set (match_dup 3)
5704 (ashiftrt:SI (match_dup 2) (const_int 16)))
5705 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5706 (match_dup 4))]
cffb2a26 5707 "TARGET_ARM"
c7597b5d 5708 "
5709 operands[2] = gen_reg_rtx (SImode);
5710 operands[3] = gen_reg_rtx (SImode);
787f8210 5711 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5712 "
5713)
b11cae9e 5714
a2f10574 5715;; Pattern to recognize insn generated default case above
f7fbdd4a 5716(define_insn "*movhi_insn_arch4"
cffb2a26 5717 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5718 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5719 "TARGET_ARM
5720 && arm_arch4
f7fbdd4a 5721 && (GET_CODE (operands[1]) != CONST_INT
5722 || const_ok_for_arm (INTVAL (operands[1]))
5723 || const_ok_for_arm (~INTVAL (operands[1])))"
5724 "@
5725 mov%?\\t%0, %1\\t%@ movhi
5726 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5727 str%(h%)\\t%1, %0\\t%@ movhi
5728 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5729 [(set_attr "type" "*,*,store1,load1")
0d66636f 5730 (set_attr "predicable" "yes")
cffb2a26 5731 (set_attr "pool_range" "*,*,*,256")
5732 (set_attr "neg_pool_range" "*,*,*,244")]
5733)
f7fbdd4a 5734
f7fbdd4a 5735(define_insn "*movhi_bytes"
25f7a26e 5736 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5737 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5738 "TARGET_ARM"
25f7a26e 5739 "@
5740 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5741 mvn%?\\t%0, #%B1\\t%@ movhi"
5742 [(set_attr "predicable" "yes")]
5743)
25f7a26e 5744
f90b51f1 5745(define_expand "thumb_movhi_clobber"
5746 [(set (match_operand:HI 0 "memory_operand" "")
5747 (match_operand:HI 1 "register_operand" ""))
5748 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5749 "TARGET_THUMB1"
f90b51f1 5750 "
5751 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5752 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5753 {
5754 emit_insn (gen_movhi (operands[0], operands[1]));
5755 DONE;
5756 }
5757 /* XXX Fixme, need to handle other cases here as well. */
5758 gcc_unreachable ();
5759 "
cffb2a26 5760)
5761
bc5c7e08 5762;; We use a DImode scratch because we may occasionally need an additional
5763;; temporary if the address isn't offsettable -- push_reload doesn't seem
5764;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5765(define_expand "reload_outhi"
cffb2a26 5766 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5767 (match_operand:HI 1 "s_register_operand" "r")
5768 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5769 "TARGET_EITHER"
5770 "if (TARGET_ARM)
5771 arm_reload_out_hi (operands);
5772 else
5773 thumb_reload_out_hi (operands);
d3373b54 5774 DONE;
cffb2a26 5775 "
5776)
d3373b54 5777
25f7a26e 5778(define_expand "reload_inhi"
5779 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5780 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5781 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5782 "TARGET_EITHER"
25f7a26e 5783 "
cffb2a26 5784 if (TARGET_ARM)
5785 arm_reload_in_hi (operands);
5786 else
5787 thumb_reload_out_hi (operands);
25f7a26e 5788 DONE;
5789")
5790
9c08d1fa 5791(define_expand "movqi"
5792 [(set (match_operand:QI 0 "general_operand" "")
5793 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5794 "TARGET_EITHER"
9c08d1fa 5795 "
6cffc037 5796 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5797
e1ba4a27 5798 if (can_create_pseudo_p ())
cffb2a26 5799 {
6cffc037 5800 if (GET_CODE (operands[1]) == CONST_INT)
5801 {
5802 rtx reg = gen_reg_rtx (SImode);
5803
5804 emit_insn (gen_movsi (reg, operands[1]));
5805 operands[1] = gen_lowpart (QImode, reg);
5806 }
cffb2a26 5807
6cffc037 5808 if (TARGET_THUMB)
5809 {
cffb2a26 5810 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5811 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5812 virtual register (also rejected as illegitimate for HImode/QImode)
5813 relative address. */
cffb2a26 5814 /* ??? This should perhaps be fixed elsewhere, for instance, in
5815 fixup_stack_1, by checking for other kinds of invalid addresses,
5816 e.g. a bare reference to a virtual register. This may confuse the
5817 alpha though, which must handle this case differently. */
5818 if (GET_CODE (operands[0]) == MEM
215b30b3 5819 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5820 XEXP (operands[0], 0)))
537ffcfc 5821 operands[0]
5822 = replace_equiv_address (operands[0],
5823 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5824 if (GET_CODE (operands[1]) == MEM
5825 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5826 XEXP (operands[1], 0)))
537ffcfc 5827 operands[1]
5828 = replace_equiv_address (operands[1],
5829 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5830 }
5831
5832 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5833 {
5834 rtx reg = gen_reg_rtx (SImode);
5835
5836 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5837 operands[1] = gen_lowpart (QImode, reg);
5838 }
5839
5840 if (GET_CODE (operands[0]) == MEM)
5841 operands[1] = force_reg (QImode, operands[1]);
5842 }
5843 else if (TARGET_THUMB
5844 && GET_CODE (operands[1]) == CONST_INT
234f6557 5845 && !satisfies_constraint_I (operands[1]))
6cffc037 5846 {
674a8f0b 5847 /* Handle loading a large integer during reload. */
cffb2a26 5848
6cffc037 5849 /* Writing a constant to memory needs a scratch, which should
5850 be handled with SECONDARY_RELOADs. */
5851 gcc_assert (GET_CODE (operands[0]) == REG);
5852
5853 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5854 emit_insn (gen_movsi (operands[0], operands[1]));
5855 DONE;
cffb2a26 5856 }
5857 "
5858)
b11cae9e 5859
9c08d1fa 5860
cffb2a26 5861(define_insn "*arm_movqi_insn"
5862 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5863 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5864 "TARGET_32BIT
cffb2a26 5865 && ( register_operand (operands[0], QImode)
5866 || register_operand (operands[1], QImode))"
5565501b 5867 "@
5868 mov%?\\t%0, %1
5869 mvn%?\\t%0, #%B1
25f905c2 5870 ldr%(b%)\\t%0, %1
5871 str%(b%)\\t%1, %0"
a2cd141b 5872 [(set_attr "type" "*,*,load1,store1")
0d66636f 5873 (set_attr "predicable" "yes")]
cffb2a26 5874)
5875
25f905c2 5876(define_insn "*thumb1_movqi_insn"
cffb2a26 5877 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5878 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5879 "TARGET_THUMB1
cffb2a26 5880 && ( register_operand (operands[0], QImode)
5881 || register_operand (operands[1], QImode))"
5882 "@
5883 add\\t%0, %1, #0
5884 ldrb\\t%0, %1
5885 strb\\t%1, %0
5886 mov\\t%0, %1
5887 mov\\t%0, %1
5888 mov\\t%0, %1"
5889 [(set_attr "length" "2")
a2cd141b 5890 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5891 (set_attr "pool_range" "*,32,*,*,*,*")]
5892)
b11cae9e 5893
9b8516be 5894;; HFmode moves
5895(define_expand "movhf"
5896 [(set (match_operand:HF 0 "general_operand" "")
5897 (match_operand:HF 1 "general_operand" ""))]
5898 "TARGET_EITHER"
5899 "
5900 if (TARGET_32BIT)
5901 {
5902 if (GET_CODE (operands[0]) == MEM)
5903 operands[1] = force_reg (HFmode, operands[1]);
5904 }
5905 else /* TARGET_THUMB1 */
5906 {
5907 if (can_create_pseudo_p ())
5908 {
5909 if (GET_CODE (operands[0]) != REG)
5910 operands[1] = force_reg (HFmode, operands[1]);
5911 }
5912 }
5913 "
5914)
5915
5916(define_insn "*arm32_movhf"
5917 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5918 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
5919 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_NEON_FP16)
5920 && ( s_register_operand (operands[0], HFmode)
5921 || s_register_operand (operands[1], HFmode))"
5922 "*
5923 switch (which_alternative)
5924 {
5925 case 0: /* ARM register from memory */
5926 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5927 case 1: /* memory from ARM register */
5928 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5929 case 2: /* ARM register from ARM register */
5930 return \"mov%?\\t%0, %1\\t%@ __fp16\";
5931 case 3: /* ARM register from constant */
5932 {
5933 REAL_VALUE_TYPE r;
5934 long bits;
5935 rtx ops[4];
5936
5937 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
5938 bits = real_to_target (NULL, &r, HFmode);
5939 ops[0] = operands[0];
5940 ops[1] = GEN_INT (bits);
5941 ops[2] = GEN_INT (bits & 0xff00);
5942 ops[3] = GEN_INT (bits & 0x00ff);
5943
5944 if (arm_arch_thumb2)
5945 output_asm_insn (\"movw%?\\t%0, %1\", ops);
5946 else
5947 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
5948 return \"\";
5949 }
5950 default:
5951 gcc_unreachable ();
5952 }
5953 "
5954 [(set_attr "conds" "unconditional")
5955 (set_attr "type" "load1,store1,*,*")
5956 (set_attr "length" "4,4,4,8")
5957 (set_attr "predicable" "yes")
5958 ]
5959)
5960
5961(define_insn "*thumb1_movhf"
5962 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
5963 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
5964 "TARGET_THUMB1
5965 && ( s_register_operand (operands[0], HFmode)
5966 || s_register_operand (operands[1], HFmode))"
5967 "*
5968 switch (which_alternative)
5969 {
5970 case 1:
5971 {
5972 rtx addr;
5973 gcc_assert (GET_CODE(operands[1]) == MEM);
5974 addr = XEXP (operands[1], 0);
5975 if (GET_CODE (addr) == LABEL_REF
5976 || (GET_CODE (addr) == CONST
5977 && GET_CODE (XEXP (addr, 0)) == PLUS
5978 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
5979 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
5980 {
5981 /* Constant pool entry. */
5982 return \"ldr\\t%0, %1\";
5983 }
5984 return \"ldrh\\t%0, %1\";
5985 }
5986 case 2: return \"strh\\t%1, %0\";
5987 default: return \"mov\\t%0, %1\";
5988 }
5989 "
5990 [(set_attr "length" "2")
5991 (set_attr "type" "*,load1,store1,*,*")
5992 (set_attr "pool_range" "*,1020,*,*,*")]
5993)
5994
87b22bf7 5995(define_expand "movsf"
5996 [(set (match_operand:SF 0 "general_operand" "")
5997 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5998 "TARGET_EITHER"
87b22bf7 5999 "
25f905c2 6000 if (TARGET_32BIT)
cffb2a26 6001 {
6002 if (GET_CODE (operands[0]) == MEM)
6003 operands[1] = force_reg (SFmode, operands[1]);
6004 }
25f905c2 6005 else /* TARGET_THUMB1 */
cffb2a26 6006 {
e1ba4a27 6007 if (can_create_pseudo_p ())
cffb2a26 6008 {
6009 if (GET_CODE (operands[0]) != REG)
6010 operands[1] = force_reg (SFmode, operands[1]);
6011 }
6012 }
6013 "
6014)
6015
03d440a6 6016;; Transform a floating-point move of a constant into a core register into
6017;; an SImode operation.
cffb2a26 6018(define_split
03d440a6 6019 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6020 (match_operand:SF 1 "immediate_operand" ""))]
25f905c2 6021 "TARGET_32BIT
cffb2a26 6022 && reload_completed
6023 && GET_CODE (operands[1]) == CONST_DOUBLE"
6024 [(set (match_dup 2) (match_dup 3))]
6025 "
6026 operands[2] = gen_lowpart (SImode, operands[0]);
6027 operands[3] = gen_lowpart (SImode, operands[1]);
6028 if (operands[2] == 0 || operands[3] == 0)
6029 FAIL;
215b30b3 6030 "
6031)
87b22bf7 6032
cffb2a26 6033(define_insn "*arm_movsf_soft_insn"
6034 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6035 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6036 "TARGET_ARM
6037 && TARGET_SOFT_FLOAT
215b30b3 6038 && (GET_CODE (operands[0]) != MEM
6039 || register_operand (operands[1], SFmode))"
9a1112d7 6040 "@
6041 mov%?\\t%0, %1
6042 ldr%?\\t%0, %1\\t%@ float
6043 str%?\\t%1, %0\\t%@ float"
cffb2a26 6044 [(set_attr "length" "4,4,4")
0d66636f 6045 (set_attr "predicable" "yes")
a2cd141b 6046 (set_attr "type" "*,load1,store1")
cffb2a26 6047 (set_attr "pool_range" "*,4096,*")
6048 (set_attr "neg_pool_range" "*,4084,*")]
6049)
6050
6051;;; ??? This should have alternatives for constants.
25f905c2 6052(define_insn "*thumb1_movsf_insn"
215b30b3 6053 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6054 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6055 "TARGET_THUMB1
cffb2a26 6056 && ( register_operand (operands[0], SFmode)
6057 || register_operand (operands[1], SFmode))"
6058 "@
6059 add\\t%0, %1, #0
6060 ldmia\\t%1, {%0}
6061 stmia\\t%0, {%1}
6062 ldr\\t%0, %1
6063 str\\t%1, %0
6064 mov\\t%0, %1
6065 mov\\t%0, %1"
6066 [(set_attr "length" "2")
a2cd141b 6067 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 6068 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
6069)
9a1112d7 6070
9c08d1fa 6071(define_expand "movdf"
87b22bf7 6072 [(set (match_operand:DF 0 "general_operand" "")
6073 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6074 "TARGET_EITHER"
9c08d1fa 6075 "
25f905c2 6076 if (TARGET_32BIT)
cffb2a26 6077 {
6078 if (GET_CODE (operands[0]) == MEM)
6079 operands[1] = force_reg (DFmode, operands[1]);
6080 }
6081 else /* TARGET_THUMB */
6082 {
e1ba4a27 6083 if (can_create_pseudo_p ())
cffb2a26 6084 {
6085 if (GET_CODE (operands[0]) != REG)
6086 operands[1] = force_reg (DFmode, operands[1]);
6087 }
6088 }
6089 "
6090)
b11cae9e 6091
9c08d1fa 6092;; Reloading a df mode value stored in integer regs to memory can require a
6093;; scratch reg.
6094(define_expand "reload_outdf"
cffb2a26 6095 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6096 (match_operand:DF 1 "s_register_operand" "r")
6097 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6098 "TARGET_32BIT"
87b22bf7 6099 "
215b30b3 6100 {
6101 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6102
215b30b3 6103 if (code == REG)
6104 operands[2] = XEXP (operands[0], 0);
6105 else if (code == POST_INC || code == PRE_DEC)
6106 {
6107 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6108 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6109 emit_insn (gen_movdi (operands[0], operands[1]));
6110 DONE;
6111 }
6112 else if (code == PRE_INC)
6113 {
6114 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6115
215b30b3 6116 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6117 operands[2] = reg;
6118 }
6119 else if (code == POST_DEC)
6120 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6121 else
6122 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6123 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6124
788fcce0 6125 emit_insn (gen_rtx_SET (VOIDmode,
6126 replace_equiv_address (operands[0], operands[2]),
215b30b3 6127 operands[1]));
f7fbdd4a 6128
215b30b3 6129 if (code == POST_DEC)
6130 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6131
6132 DONE;
6133 }"
6134)
9c08d1fa 6135
9a1112d7 6136(define_insn "*movdf_soft_insn"
359a6e9f 6137 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6138 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 6139 "TARGET_ARM && TARGET_SOFT_FLOAT
b2778788 6140 && ( register_operand (operands[0], DFmode)
6141 || register_operand (operands[1], DFmode))"
d51f92df 6142 "*
6143 switch (which_alternative)
6144 {
6145 case 0:
6146 case 1:
6147 case 2:
6148 return \"#\";
6149 default:
6150 return output_move_double (operands);
6151 }
6152 "
359a6e9f 6153 [(set_attr "length" "8,12,16,8,8")
6154 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 6155 (set_attr "pool_range" "1020")
6156 (set_attr "neg_pool_range" "1008")]
cffb2a26 6157)
6158
6159;;; ??? This should have alternatives for constants.
6160;;; ??? This was originally identical to the movdi_insn pattern.
6161;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6162;;; thumb_reorg with a memory reference.
6163(define_insn "*thumb_movdf_insn"
215b30b3 6164 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6165 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6166 "TARGET_THUMB1
cffb2a26 6167 && ( register_operand (operands[0], DFmode)
6168 || register_operand (operands[1], DFmode))"
6169 "*
6170 switch (which_alternative)
6171 {
6172 default:
6173 case 0:
6174 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6175 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6176 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6177 case 1:
6178 return \"ldmia\\t%1, {%0, %H0}\";
6179 case 2:
6180 return \"stmia\\t%0, {%1, %H1}\";
6181 case 3:
6182 return thumb_load_double_from_address (operands);
6183 case 4:
1a83b3ff 6184 operands[2] = gen_rtx_MEM (SImode,
6185 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6186 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6187 return \"\";
6188 case 5:
6189 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6190 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6191 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6192 }
6193 "
6194 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6195 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 6196 (set_attr "pool_range" "*,*,*,1020,*,*")]
6197)
755eb2b4 6198
ccd90aaa 6199(define_expand "movxf"
6200 [(set (match_operand:XF 0 "general_operand" "")
6201 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6202 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6203 "
6204 if (GET_CODE (operands[0]) == MEM)
6205 operands[1] = force_reg (XFmode, operands[1]);
6206 "
6207)
6208
b11cae9e 6209\f
b11cae9e 6210
9c08d1fa 6211;; load- and store-multiple insns
6212;; The arm can load/store any set of registers, provided that they are in
6213;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 6214
9c08d1fa 6215(define_expand "load_multiple"
6216 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6217 (match_operand:SI 1 "" ""))
6218 (use (match_operand:SI 2 "" ""))])]
25f905c2 6219 "TARGET_32BIT"
9580c25f 6220{
6221 HOST_WIDE_INT offset = 0;
6222
bd5b4116 6223 /* Support only fixed point registers. */
9c08d1fa 6224 if (GET_CODE (operands[2]) != CONST_INT
6225 || INTVAL (operands[2]) > 14
6226 || INTVAL (operands[2]) < 2
6227 || GET_CODE (operands[1]) != MEM
6228 || GET_CODE (operands[0]) != REG
bd5b4116 6229 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6230 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6231 FAIL;
6232
6233 operands[3]
f082f1c4 6234 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6235 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 6236 TRUE, FALSE, operands[1], &offset);
6237})
b11cae9e 6238
9c08d1fa 6239;; Load multiple with write-back
6240
2162064c 6241(define_insn "*ldmsi_postinc4"
9c08d1fa 6242 [(match_parallel 0 "load_multiple_operation"
13e9316a 6243 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6244 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6245 (const_int 16)))
6246 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6247 (mem:SI (match_dup 2)))
a0a72ac3 6248 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 6249 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6250 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6251 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6252 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6253 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6254 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6255 "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
a2cd141b 6256 [(set_attr "type" "load4")
2162064c 6257 (set_attr "predicable" "yes")]
6258)
b11cae9e 6259
25f905c2 6260(define_insn "*ldmsi_postinc4_thumb1"
ccd90aaa 6261 [(match_parallel 0 "load_multiple_operation"
6262 [(set (match_operand:SI 1 "s_register_operand" "=l")
6263 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6264 (const_int 16)))
6265 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6266 (mem:SI (match_dup 2)))
6267 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6268 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6269 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6270 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6271 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6272 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6273 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6274 "ldmia\\t%1!, {%3, %4, %5, %6}"
6275 [(set_attr "type" "load4")]
6276)
6277
2162064c 6278(define_insn "*ldmsi_postinc3"
6279 [(match_parallel 0 "load_multiple_operation"
13e9316a 6280 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6281 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6282 (const_int 12)))
6283 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6284 (mem:SI (match_dup 2)))
6285 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6286 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6287 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6288 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
25f905c2 6289 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6290 "ldm%(ia%)\\t%1!, {%3, %4, %5}"
a2cd141b 6291 [(set_attr "type" "load3")
2162064c 6292 (set_attr "predicable" "yes")]
6293)
b11cae9e 6294
2162064c 6295(define_insn "*ldmsi_postinc2"
6296 [(match_parallel 0 "load_multiple_operation"
13e9316a 6297 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6298 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6299 (const_int 8)))
6300 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6301 (mem:SI (match_dup 2)))
6302 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6303 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
25f905c2 6304 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6305 "ldm%(ia%)\\t%1!, {%3, %4}"
a2cd141b 6306 [(set_attr "type" "load2")
0d66636f 6307 (set_attr "predicable" "yes")]
6308)
b11cae9e 6309
9c08d1fa 6310;; Ordinary load multiple
b11cae9e 6311
2162064c 6312(define_insn "*ldmsi4"
9c08d1fa 6313 [(match_parallel 0 "load_multiple_operation"
2162064c 6314 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6315 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6316 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6317 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6318 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6319 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6320 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6321 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
25f905c2 6322 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6323 "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
a2cd141b 6324 [(set_attr "type" "load4")
2162064c 6325 (set_attr "predicable" "yes")]
6326)
9c08d1fa 6327
2162064c 6328(define_insn "*ldmsi3"
6329 [(match_parallel 0 "load_multiple_operation"
6330 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6331 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6332 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6333 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6334 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6335 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
25f905c2 6336 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6337 "ldm%(ia%)\\t%1, {%2, %3, %4}"
a2cd141b 6338 [(set_attr "type" "load3")
2162064c 6339 (set_attr "predicable" "yes")]
6340)
9c08d1fa 6341
2162064c 6342(define_insn "*ldmsi2"
6343 [(match_parallel 0 "load_multiple_operation"
6344 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6345 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6346 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6347 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
25f905c2 6348 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6349 "ldm%(ia%)\\t%1, {%2, %3}"
a2cd141b 6350 [(set_attr "type" "load2")
0d66636f 6351 (set_attr "predicable" "yes")]
6352)
9c08d1fa 6353
6354(define_expand "store_multiple"
6355 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6356 (match_operand:SI 1 "" ""))
6357 (use (match_operand:SI 2 "" ""))])]
25f905c2 6358 "TARGET_32BIT"
9580c25f 6359{
6360 HOST_WIDE_INT offset = 0;
6361
674a8f0b 6362 /* Support only fixed point registers. */
9c08d1fa 6363 if (GET_CODE (operands[2]) != CONST_INT
6364 || INTVAL (operands[2]) > 14
6365 || INTVAL (operands[2]) < 2
6366 || GET_CODE (operands[1]) != REG
6367 || GET_CODE (operands[0]) != MEM
bd5b4116 6368 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6369 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6370 FAIL;
6371
6372 operands[3]
f082f1c4 6373 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6374 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 6375 TRUE, FALSE, operands[0], &offset);
6376})
b11cae9e 6377
9c08d1fa 6378;; Store multiple with write-back
6379
2162064c 6380(define_insn "*stmsi_postinc4"
9c08d1fa 6381 [(match_parallel 0 "store_multiple_operation"
13e9316a 6382 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6383 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6384 (const_int 16)))
a0a72ac3 6385 (set (mem:SI (match_dup 2))
2162064c 6386 (match_operand:SI 3 "arm_hard_register_operand" ""))
6387 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6388 (match_operand:SI 4 "arm_hard_register_operand" ""))
6389 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6390 (match_operand:SI 5 "arm_hard_register_operand" ""))
6391 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6392 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6393 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6394 "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
2162064c 6395 [(set_attr "predicable" "yes")
6396 (set_attr "type" "store4")]
6397)
b11cae9e 6398
25f905c2 6399(define_insn "*stmsi_postinc4_thumb1"
ccd90aaa 6400 [(match_parallel 0 "store_multiple_operation"
6401 [(set (match_operand:SI 1 "s_register_operand" "=l")
6402 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6403 (const_int 16)))
6404 (set (mem:SI (match_dup 2))
6405 (match_operand:SI 3 "arm_hard_register_operand" ""))
6406 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6407 (match_operand:SI 4 "arm_hard_register_operand" ""))
6408 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6409 (match_operand:SI 5 "arm_hard_register_operand" ""))
6410 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6411 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6412 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6413 "stmia\\t%1!, {%3, %4, %5, %6}"
6414 [(set_attr "type" "store4")]
6415)
6416
2162064c 6417(define_insn "*stmsi_postinc3"
6418 [(match_parallel 0 "store_multiple_operation"
13e9316a 6419 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6420 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6421 (const_int 12)))
6422 (set (mem:SI (match_dup 2))
6423 (match_operand:SI 3 "arm_hard_register_operand" ""))
6424 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6425 (match_operand:SI 4 "arm_hard_register_operand" ""))
6426 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6427 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6428 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6429 "stm%(ia%)\\t%1!, {%3, %4, %5}"
2162064c 6430 [(set_attr "predicable" "yes")
6431 (set_attr "type" "store3")]
6432)
9c08d1fa 6433
2162064c 6434(define_insn "*stmsi_postinc2"
6435 [(match_parallel 0 "store_multiple_operation"
13e9316a 6436 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6437 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6438 (const_int 8)))
6439 (set (mem:SI (match_dup 2))
6440 (match_operand:SI 3 "arm_hard_register_operand" ""))
6441 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6442 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6443 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6444 "stm%(ia%)\\t%1!, {%3, %4}"
0d66636f 6445 [(set_attr "predicable" "yes")
2162064c 6446 (set_attr "type" "store2")]
cffb2a26 6447)
9c08d1fa 6448
6449;; Ordinary store multiple
6450
2162064c 6451(define_insn "*stmsi4"
9c08d1fa 6452 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 6453 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 6454 (match_operand:SI 2 "arm_hard_register_operand" ""))
6455 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6456 (match_operand:SI 3 "arm_hard_register_operand" ""))
6457 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6458 (match_operand:SI 4 "arm_hard_register_operand" ""))
6459 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6460 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6461 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6462 "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
2162064c 6463 [(set_attr "predicable" "yes")
6464 (set_attr "type" "store4")]
6465)
9c08d1fa 6466
2162064c 6467(define_insn "*stmsi3"
6468 [(match_parallel 0 "store_multiple_operation"
6469 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6470 (match_operand:SI 2 "arm_hard_register_operand" ""))
6471 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6472 (match_operand:SI 3 "arm_hard_register_operand" ""))
6473 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6474 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6475 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6476 "stm%(ia%)\\t%1, {%2, %3, %4}"
2162064c 6477 [(set_attr "predicable" "yes")
6478 (set_attr "type" "store3")]
6479)
9c08d1fa 6480
2162064c 6481(define_insn "*stmsi2"
6482 [(match_parallel 0 "store_multiple_operation"
6483 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6484 (match_operand:SI 2 "arm_hard_register_operand" ""))
6485 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6486 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
25f905c2 6487 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6488 "stm%(ia%)\\t%1, {%2, %3}"
0d66636f 6489 [(set_attr "predicable" "yes")
2162064c 6490 (set_attr "type" "store2")]
cffb2a26 6491)
9c08d1fa 6492
6493;; Move a block of memory if it is word aligned and MORE than 2 words long.
6494;; We could let this apply for blocks of less than this, but it clobbers so
6495;; many registers that there is then probably a better way.
6496
008c057d 6497(define_expand "movmemqi"
34191dd1 6498 [(match_operand:BLK 0 "general_operand" "")
6499 (match_operand:BLK 1 "general_operand" "")
6500 (match_operand:SI 2 "const_int_operand" "")
6501 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6502 "TARGET_EITHER"
9c08d1fa 6503 "
25f905c2 6504 if (TARGET_32BIT)
cffb2a26 6505 {
008c057d 6506 if (arm_gen_movmemqi (operands))
cffb2a26 6507 DONE;
6508 FAIL;
6509 }
25f905c2 6510 else /* TARGET_THUMB1 */
cffb2a26 6511 {
6512 if ( INTVAL (operands[3]) != 4
6513 || INTVAL (operands[2]) > 48)
6514 FAIL;
6515
008c057d 6516 thumb_expand_movmemqi (operands);
cffb2a26 6517 DONE;
6518 }
6519 "
6520)
6521
2162064c 6522;; Thumb block-move insns
cffb2a26 6523
6524(define_insn "movmem12b"
960f3acf 6525 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6526 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6527 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6528 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6529 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6530 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6531 (set (match_operand:SI 0 "register_operand" "=l")
6532 (plus:SI (match_dup 2) (const_int 12)))
6533 (set (match_operand:SI 1 "register_operand" "=l")
6534 (plus:SI (match_dup 3) (const_int 12)))
6535 (clobber (match_scratch:SI 4 "=&l"))
6536 (clobber (match_scratch:SI 5 "=&l"))
6537 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6538 "TARGET_THUMB1"
cffb2a26 6539 "* return thumb_output_move_mem_multiple (3, operands);"
6540 [(set_attr "length" "4")
215b30b3 6541 ; This isn't entirely accurate... It loads as well, but in terms of
6542 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6543 (set_attr "type" "store3")]
6544)
6545
6546(define_insn "movmem8b"
960f3acf 6547 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6548 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6549 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6550 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6551 (set (match_operand:SI 0 "register_operand" "=l")
6552 (plus:SI (match_dup 2) (const_int 8)))
6553 (set (match_operand:SI 1 "register_operand" "=l")
6554 (plus:SI (match_dup 3) (const_int 8)))
6555 (clobber (match_scratch:SI 4 "=&l"))
6556 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6557 "TARGET_THUMB1"
cffb2a26 6558 "* return thumb_output_move_mem_multiple (2, operands);"
6559 [(set_attr "length" "4")
215b30b3 6560 ; This isn't entirely accurate... It loads as well, but in terms of
6561 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6562 (set_attr "type" "store2")]
6563)
6564
9c08d1fa 6565\f
b11cae9e 6566
341940e8 6567;; Compare & branch insns
8d232dc7 6568;; The range calculations are based as follows:
341940e8 6569;; For forward branches, the address calculation returns the address of
6570;; the next instruction. This is 2 beyond the branch instruction.
6571;; For backward branches, the address calculation returns the address of
6572;; the first instruction in this pattern (cmp). This is 2 before the branch
6573;; instruction for the shortest sequence, and 4 before the branch instruction
6574;; if we have to jump around an unconditional branch.
6575;; To the basic branch range the PC offset must be added (this is +4).
6576;; So for forward branches we have
6577;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6578;; And for backward branches we have
6579;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6580;;
6581;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6582;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6583
aeac46d4 6584(define_expand "cbranchsi4"
6585 [(set (pc) (if_then_else
6586 (match_operator 0 "arm_comparison_operator"
6587 [(match_operand:SI 1 "s_register_operand" "")
6588 (match_operand:SI 2 "nonmemory_operand" "")])
6589 (label_ref (match_operand 3 "" ""))
6590 (pc)))]
74f4459c 6591 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6592 "
74f4459c 6593 if (!TARGET_THUMB1)
6594 {
6595 if (!arm_add_operand (operands[2], SImode))
6596 operands[2] = force_reg (SImode, operands[2]);
6597 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6598 operands[3]));
6599 DONE;
6600 }
25f905c2 6601 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6602 {
6603 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6604 operands[3], operands[0]));
6605 DONE;
6606 }
25f905c2 6607 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6608 operands[2] = force_reg (SImode, operands[2]);
6609 ")
6610
74f4459c 6611(define_expand "cbranchsf4"
6612 [(set (pc) (if_then_else
6613 (match_operator 0 "arm_comparison_operator"
6614 [(match_operand:SF 1 "s_register_operand" "")
6615 (match_operand:SF 2 "arm_float_compare_operand" "")])
6616 (label_ref (match_operand 3 "" ""))
6617 (pc)))]
6618 "TARGET_32BIT && TARGET_HARD_FLOAT"
6619 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6620 operands[3])); DONE;"
6621)
6622
6623(define_expand "cbranchdf4"
6624 [(set (pc) (if_then_else
6625 (match_operator 0 "arm_comparison_operator"
6626 [(match_operand:DF 1 "s_register_operand" "")
6627 (match_operand:DF 2 "arm_float_compare_operand" "")])
6628 (label_ref (match_operand 3 "" ""))
6629 (pc)))]
6630 "TARGET_32BIT && TARGET_HARD_FLOAT"
6631 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6632 operands[3])); DONE;"
6633)
6634
6635;; this uses the Cirrus DI compare instruction
6636(define_expand "cbranchdi4"
6637 [(set (pc) (if_then_else
6638 (match_operator 0 "arm_comparison_operator"
6639 [(match_operand:DI 1 "cirrus_fp_register" "")
6640 (match_operand:DI 2 "cirrus_fp_register" "")])
6641 (label_ref (match_operand 3 "" ""))
6642 (pc)))]
6643 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6644 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6645 operands[3])); DONE;"
6646)
6647
aeac46d4 6648(define_insn "*cbranchsi4_insn"
6649 [(set (pc) (if_then_else
6650 (match_operator 0 "arm_comparison_operator"
6651 [(match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 6652 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6653 (label_ref (match_operand 3 "" ""))
6654 (pc)))]
25f905c2 6655 "TARGET_THUMB1"
cffb2a26 6656 "*
6657 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 6658
cffb2a26 6659 switch (get_attr_length (insn))
6660 {
6661 case 4: return \"b%d0\\t%l3\";
6662 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6663 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6664 }
6665 "
6666 [(set (attr "far_jump")
6667 (if_then_else
6668 (eq_attr "length" "8")
6669 (const_string "yes")
6670 (const_string "no")))
6671 (set (attr "length")
6672 (if_then_else
6673 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6674 (le (minus (match_dup 3) (pc)) (const_int 256)))
6675 (const_int 4)
6676 (if_then_else
6677 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6678 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6679 (const_int 6)
6680 (const_int 8))))]
6681)
6682
aeac46d4 6683(define_insn "cbranchsi4_scratch"
6684 [(set (pc) (if_then_else
6685 (match_operator 4 "arm_comparison_operator"
6686 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6687 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6688 (label_ref (match_operand 3 "" ""))
6689 (pc)))
6690 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6691 "TARGET_THUMB1"
aeac46d4 6692 "*
6693 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6694
6695 switch (get_attr_length (insn))
6696 {
6697 case 4: return \"b%d4\\t%l3\";
6698 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6699 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6700 }
6701 "
6702 [(set (attr "far_jump")
6703 (if_then_else
6704 (eq_attr "length" "8")
6705 (const_string "yes")
6706 (const_string "no")))
6707 (set (attr "length")
6708 (if_then_else
6709 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6710 (le (minus (match_dup 3) (pc)) (const_int 256)))
6711 (const_int 4)
6712 (if_then_else
6713 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6714 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6715 (const_int 6)
6716 (const_int 8))))]
6717)
6718(define_insn "*movsi_cbranchsi4"
6719 [(set (pc)
6720 (if_then_else
6721 (match_operator 3 "arm_comparison_operator"
6722 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6723 (const_int 0)])
6724 (label_ref (match_operand 2 "" ""))
6725 (pc)))
6726 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6727 (match_dup 1))]
25f905c2 6728 "TARGET_THUMB1"
aeac46d4 6729 "*{
6730 if (which_alternative == 0)
6731 output_asm_insn (\"cmp\t%0, #0\", operands);
6732 else if (which_alternative == 1)
6733 output_asm_insn (\"sub\t%0, %1, #0\", operands);
6734 else
6735 {
6736 output_asm_insn (\"cmp\t%1, #0\", operands);
6737 if (which_alternative == 2)
6738 output_asm_insn (\"mov\t%0, %1\", operands);
6739 else
6740 output_asm_insn (\"str\t%1, %0\", operands);
6741 }
6742 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6743 {
6744 case 4: return \"b%d3\\t%l2\";
6745 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6746 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6747 }
6748 }"
6749 [(set (attr "far_jump")
6750 (if_then_else
6751 (ior (and (gt (symbol_ref ("which_alternative"))
6752 (const_int 1))
6753 (eq_attr "length" "8"))
6754 (eq_attr "length" "10"))
6755 (const_string "yes")
6756 (const_string "no")))
6757 (set (attr "length")
6758 (if_then_else
6759 (le (symbol_ref ("which_alternative"))
6760 (const_int 1))
6761 (if_then_else
6762 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6763 (le (minus (match_dup 2) (pc)) (const_int 256)))
6764 (const_int 4)
6765 (if_then_else
6766 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6767 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6768 (const_int 6)
6769 (const_int 8)))
6770 (if_then_else
6771 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6772 (le (minus (match_dup 2) (pc)) (const_int 256)))
6773 (const_int 6)
6774 (if_then_else
6775 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6776 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6777 (const_int 8)
6778 (const_int 10)))))]
6779)
6780
cffb2a26 6781(define_insn "*negated_cbranchsi4"
6782 [(set (pc)
6783 (if_then_else
aed179ae 6784 (match_operator 0 "equality_operator"
aeac46d4 6785 [(match_operand:SI 1 "s_register_operand" "l")
6786 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6787 (label_ref (match_operand 3 "" ""))
215b30b3 6788 (pc)))]
25f905c2 6789 "TARGET_THUMB1"
cffb2a26 6790 "*
6791 output_asm_insn (\"cmn\\t%1, %2\", operands);
6792 switch (get_attr_length (insn))
6793 {
6794 case 4: return \"b%d0\\t%l3\";
6795 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6796 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6797 }
6798 "
6799 [(set (attr "far_jump")
6800 (if_then_else
6801 (eq_attr "length" "8")
6802 (const_string "yes")
6803 (const_string "no")))
6804 (set (attr "length")
6805 (if_then_else
6806 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6807 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6808 (const_int 4)
6809 (if_then_else
341940e8 6810 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6811 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6812 (const_int 6)
6813 (const_int 8))))]
6814)
6815
58d6528b 6816(define_insn "*tbit_cbranch"
6817 [(set (pc)
6818 (if_then_else
6819 (match_operator 0 "equality_operator"
6820 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6821 (const_int 1)
6822 (match_operand:SI 2 "const_int_operand" "i"))
6823 (const_int 0)])
6824 (label_ref (match_operand 3 "" ""))
6825 (pc)))
6826 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6827 "TARGET_THUMB1"
58d6528b 6828 "*
6829 {
6830 rtx op[3];
6831 op[0] = operands[4];
6832 op[1] = operands[1];
6833 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6834
86efa74d 6835 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6836 switch (get_attr_length (insn))
6837 {
6838 case 4: return \"b%d0\\t%l3\";
6839 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6840 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6841 }
6842 }"
6843 [(set (attr "far_jump")
6844 (if_then_else
6845 (eq_attr "length" "8")
6846 (const_string "yes")
6847 (const_string "no")))
6848 (set (attr "length")
6849 (if_then_else
6850 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6851 (le (minus (match_dup 3) (pc)) (const_int 256)))
6852 (const_int 4)
6853 (if_then_else
6854 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6855 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6856 (const_int 6)
6857 (const_int 8))))]
6858)
6859
6860(define_insn "*tlobits_cbranch"
6861 [(set (pc)
6862 (if_then_else
6863 (match_operator 0 "equality_operator"
6864 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6865 (match_operand:SI 2 "const_int_operand" "i")
6866 (const_int 0))
6867 (const_int 0)])
6868 (label_ref (match_operand 3 "" ""))
6869 (pc)))
6870 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6871 "TARGET_THUMB1"
86efa74d 6872 "*
6873 {
6874 rtx op[3];
6875 op[0] = operands[4];
6876 op[1] = operands[1];
6877 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6878
58d6528b 6879 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6880 switch (get_attr_length (insn))
6881 {
6882 case 4: return \"b%d0\\t%l3\";
6883 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6884 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6885 }
6886 }"
6887 [(set (attr "far_jump")
6888 (if_then_else
6889 (eq_attr "length" "8")
6890 (const_string "yes")
6891 (const_string "no")))
6892 (set (attr "length")
6893 (if_then_else
6894 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6895 (le (minus (match_dup 3) (pc)) (const_int 256)))
6896 (const_int 4)
6897 (if_then_else
6898 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6899 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6900 (const_int 6)
6901 (const_int 8))))]
6902)
6903
aeac46d4 6904(define_insn "*tstsi3_cbranch"
58d6528b 6905 [(set (pc)
6906 (if_then_else
aeac46d4 6907 (match_operator 3 "equality_operator"
6908 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6909 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6910 (const_int 0)])
aeac46d4 6911 (label_ref (match_operand 2 "" ""))
6912 (pc)))]
25f905c2 6913 "TARGET_THUMB1"
58d6528b 6914 "*
6915 {
aeac46d4 6916 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6917 switch (get_attr_length (insn))
6918 {
aeac46d4 6919 case 4: return \"b%d3\\t%l2\";
6920 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6921 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6922 }
6923 }"
6924 [(set (attr "far_jump")
6925 (if_then_else
6926 (eq_attr "length" "8")
6927 (const_string "yes")
6928 (const_string "no")))
6929 (set (attr "length")
6930 (if_then_else
aeac46d4 6931 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6932 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6933 (const_int 4)
6934 (if_then_else
aeac46d4 6935 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6936 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6937 (const_int 6)
6938 (const_int 8))))]
6939)
6940
6941(define_insn "*andsi3_cbranch"
6942 [(set (pc)
6943 (if_then_else
6944 (match_operator 5 "equality_operator"
6945 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6946 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6947 (const_int 0)])
6948 (label_ref (match_operand 4 "" ""))
6949 (pc)))
aeac46d4 6950 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6951 (and:SI (match_dup 2) (match_dup 3)))
6952 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6953 "TARGET_THUMB1"
58d6528b 6954 "*
6955 {
6956 if (which_alternative == 0)
6957 output_asm_insn (\"and\\t%0, %3\", operands);
6958 else if (which_alternative == 1)
6959 {
6960 output_asm_insn (\"and\\t%1, %3\", operands);
6961 output_asm_insn (\"mov\\t%0, %1\", operands);
6962 }
6963 else
6964 {
6965 output_asm_insn (\"and\\t%1, %3\", operands);
6966 output_asm_insn (\"str\\t%1, %0\", operands);
6967 }
6968
6969 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6970 {
6971 case 4: return \"b%d5\\t%l4\";
6972 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6973 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6974 }
6975 }"
6976 [(set (attr "far_jump")
6977 (if_then_else
6978 (ior (and (eq (symbol_ref ("which_alternative"))
6979 (const_int 0))
6980 (eq_attr "length" "8"))
6981 (eq_attr "length" "10"))
6982 (const_string "yes")
6983 (const_string "no")))
6984 (set (attr "length")
6985 (if_then_else
6986 (eq (symbol_ref ("which_alternative"))
6987 (const_int 0))
6988 (if_then_else
6989 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6990 (le (minus (match_dup 4) (pc)) (const_int 256)))
6991 (const_int 4)
6992 (if_then_else
6993 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6994 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6995 (const_int 6)
6996 (const_int 8)))
6997 (if_then_else
6998 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6999 (le (minus (match_dup 4) (pc)) (const_int 256)))
7000 (const_int 6)
7001 (if_then_else
7002 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7003 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7004 (const_int 8)
7005 (const_int 10)))))]
7006)
7007
7008(define_insn "*orrsi3_cbranch_scratch"
7009 [(set (pc)
7010 (if_then_else
7011 (match_operator 4 "equality_operator"
7012 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
7013 (match_operand:SI 2 "s_register_operand" "l"))
7014 (const_int 0)])
7015 (label_ref (match_operand 3 "" ""))
7016 (pc)))
7017 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7018 "TARGET_THUMB1"
58d6528b 7019 "*
7020 {
7021 output_asm_insn (\"orr\\t%0, %2\", operands);
7022 switch (get_attr_length (insn))
7023 {
7024 case 4: return \"b%d4\\t%l3\";
7025 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7026 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7027 }
7028 }"
7029 [(set (attr "far_jump")
7030 (if_then_else
7031 (eq_attr "length" "8")
7032 (const_string "yes")
7033 (const_string "no")))
7034 (set (attr "length")
7035 (if_then_else
7036 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7037 (le (minus (match_dup 3) (pc)) (const_int 256)))
7038 (const_int 4)
7039 (if_then_else
7040 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7041 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7042 (const_int 6)
7043 (const_int 8))))]
7044)
7045
7046(define_insn "*orrsi3_cbranch"
7047 [(set (pc)
7048 (if_then_else
7049 (match_operator 5 "equality_operator"
7050 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7051 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7052 (const_int 0)])
7053 (label_ref (match_operand 4 "" ""))
7054 (pc)))
aeac46d4 7055 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7056 (ior:SI (match_dup 2) (match_dup 3)))
7057 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7058 "TARGET_THUMB1"
58d6528b 7059 "*
7060 {
7061 if (which_alternative == 0)
7062 output_asm_insn (\"orr\\t%0, %3\", operands);
7063 else if (which_alternative == 1)
7064 {
7065 output_asm_insn (\"orr\\t%1, %3\", operands);
7066 output_asm_insn (\"mov\\t%0, %1\", operands);
7067 }
7068 else
7069 {
7070 output_asm_insn (\"orr\\t%1, %3\", operands);
7071 output_asm_insn (\"str\\t%1, %0\", operands);
7072 }
7073
7074 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7075 {
7076 case 4: return \"b%d5\\t%l4\";
7077 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7078 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7079 }
7080 }"
7081 [(set (attr "far_jump")
7082 (if_then_else
7083 (ior (and (eq (symbol_ref ("which_alternative"))
7084 (const_int 0))
7085 (eq_attr "length" "8"))
7086 (eq_attr "length" "10"))
7087 (const_string "yes")
7088 (const_string "no")))
7089 (set (attr "length")
7090 (if_then_else
7091 (eq (symbol_ref ("which_alternative"))
7092 (const_int 0))
7093 (if_then_else
7094 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7095 (le (minus (match_dup 4) (pc)) (const_int 256)))
7096 (const_int 4)
7097 (if_then_else
7098 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7099 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7100 (const_int 6)
7101 (const_int 8)))
7102 (if_then_else
7103 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7104 (le (minus (match_dup 4) (pc)) (const_int 256)))
7105 (const_int 6)
7106 (if_then_else
7107 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7108 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7109 (const_int 8)
7110 (const_int 10)))))]
7111)
7112
7113(define_insn "*xorsi3_cbranch_scratch"
7114 [(set (pc)
7115 (if_then_else
7116 (match_operator 4 "equality_operator"
7117 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
7118 (match_operand:SI 2 "s_register_operand" "l"))
7119 (const_int 0)])
7120 (label_ref (match_operand 3 "" ""))
7121 (pc)))
7122 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7123 "TARGET_THUMB1"
58d6528b 7124 "*
7125 {
7126 output_asm_insn (\"eor\\t%0, %2\", operands);
7127 switch (get_attr_length (insn))
7128 {
7129 case 4: return \"b%d4\\t%l3\";
7130 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7131 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7132 }
7133 }"
7134 [(set (attr "far_jump")
7135 (if_then_else
7136 (eq_attr "length" "8")
7137 (const_string "yes")
7138 (const_string "no")))
7139 (set (attr "length")
7140 (if_then_else
7141 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7142 (le (minus (match_dup 3) (pc)) (const_int 256)))
7143 (const_int 4)
7144 (if_then_else
7145 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7146 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7147 (const_int 6)
7148 (const_int 8))))]
7149)
7150
7151(define_insn "*xorsi3_cbranch"
7152 [(set (pc)
7153 (if_then_else
7154 (match_operator 5 "equality_operator"
7155 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7156 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7157 (const_int 0)])
7158 (label_ref (match_operand 4 "" ""))
7159 (pc)))
aeac46d4 7160 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7161 (xor:SI (match_dup 2) (match_dup 3)))
7162 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7163 "TARGET_THUMB1"
58d6528b 7164 "*
7165 {
7166 if (which_alternative == 0)
7167 output_asm_insn (\"eor\\t%0, %3\", operands);
7168 else if (which_alternative == 1)
7169 {
7170 output_asm_insn (\"eor\\t%1, %3\", operands);
7171 output_asm_insn (\"mov\\t%0, %1\", operands);
7172 }
7173 else
7174 {
7175 output_asm_insn (\"eor\\t%1, %3\", operands);
7176 output_asm_insn (\"str\\t%1, %0\", operands);
7177 }
7178
7179 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7180 {
7181 case 4: return \"b%d5\\t%l4\";
7182 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7183 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7184 }
7185 }"
7186 [(set (attr "far_jump")
7187 (if_then_else
7188 (ior (and (eq (symbol_ref ("which_alternative"))
7189 (const_int 0))
7190 (eq_attr "length" "8"))
7191 (eq_attr "length" "10"))
7192 (const_string "yes")
7193 (const_string "no")))
7194 (set (attr "length")
7195 (if_then_else
7196 (eq (symbol_ref ("which_alternative"))
7197 (const_int 0))
7198 (if_then_else
7199 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7200 (le (minus (match_dup 4) (pc)) (const_int 256)))
7201 (const_int 4)
7202 (if_then_else
7203 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7204 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7205 (const_int 6)
7206 (const_int 8)))
7207 (if_then_else
7208 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7209 (le (minus (match_dup 4) (pc)) (const_int 256)))
7210 (const_int 6)
7211 (if_then_else
7212 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7213 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7214 (const_int 8)
7215 (const_int 10)))))]
7216)
7217
aeac46d4 7218(define_insn "*bicsi3_cbranch_scratch"
7219 [(set (pc)
7220 (if_then_else
7221 (match_operator 4 "equality_operator"
7222 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7223 (match_operand:SI 1 "s_register_operand" "0"))
7224 (const_int 0)])
7225 (label_ref (match_operand 3 "" ""))
7226 (pc)))
7227 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7228 "TARGET_THUMB1"
aeac46d4 7229 "*
7230 {
7231 output_asm_insn (\"bic\\t%0, %2\", operands);
7232 switch (get_attr_length (insn))
7233 {
7234 case 4: return \"b%d4\\t%l3\";
7235 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7236 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7237 }
7238 }"
7239 [(set (attr "far_jump")
7240 (if_then_else
7241 (eq_attr "length" "8")
7242 (const_string "yes")
7243 (const_string "no")))
7244 (set (attr "length")
7245 (if_then_else
7246 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7247 (le (minus (match_dup 3) (pc)) (const_int 256)))
7248 (const_int 4)
7249 (if_then_else
7250 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7251 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7252 (const_int 6)
7253 (const_int 8))))]
7254)
7255
7256(define_insn "*bicsi3_cbranch"
7257 [(set (pc)
7258 (if_then_else
7259 (match_operator 5 "equality_operator"
01145ae6 7260 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7261 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 7262 (const_int 0)])
7263 (label_ref (match_operand 4 "" ""))
7264 (pc)))
01145ae6 7265 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 7266 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 7267 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
25f905c2 7268 "TARGET_THUMB1"
aeac46d4 7269 "*
7270 {
7271 if (which_alternative == 0)
7272 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 7273 else if (which_alternative <= 2)
aeac46d4 7274 {
7275 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 7276 /* It's ok if OP0 is a lo-reg, even though the mov will set the
7277 conditions again, since we're only testing for equality. */
aeac46d4 7278 output_asm_insn (\"mov\\t%0, %1\", operands);
7279 }
7280 else
7281 {
7282 output_asm_insn (\"bic\\t%1, %3\", operands);
7283 output_asm_insn (\"str\\t%1, %0\", operands);
7284 }
7285
7286 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7287 {
7288 case 4: return \"b%d5\\t%l4\";
7289 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7290 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7291 }
7292 }"
7293 [(set (attr "far_jump")
7294 (if_then_else
7295 (ior (and (eq (symbol_ref ("which_alternative"))
7296 (const_int 0))
7297 (eq_attr "length" "8"))
7298 (eq_attr "length" "10"))
7299 (const_string "yes")
7300 (const_string "no")))
7301 (set (attr "length")
7302 (if_then_else
7303 (eq (symbol_ref ("which_alternative"))
7304 (const_int 0))
7305 (if_then_else
7306 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7307 (le (minus (match_dup 4) (pc)) (const_int 256)))
7308 (const_int 4)
7309 (if_then_else
7310 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7311 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7312 (const_int 6)
7313 (const_int 8)))
7314 (if_then_else
7315 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7316 (le (minus (match_dup 4) (pc)) (const_int 256)))
7317 (const_int 6)
7318 (if_then_else
7319 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7320 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7321 (const_int 8)
7322 (const_int 10)))))]
7323)
7324
203c488f 7325(define_insn "*cbranchne_decr1"
7326 [(set (pc)
7327 (if_then_else (match_operator 3 "equality_operator"
7328 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7329 (const_int 0)])
7330 (label_ref (match_operand 4 "" ""))
7331 (pc)))
aeac46d4 7332 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7333 (plus:SI (match_dup 2) (const_int -1)))
7334 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7335 "TARGET_THUMB1"
203c488f 7336 "*
7337 {
7338 rtx cond[2];
7339 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7340 ? GEU : LTU),
58d6528b 7341 VOIDmode, operands[2], const1_rtx);
203c488f 7342 cond[1] = operands[4];
7343
7344 if (which_alternative == 0)
7345 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7346 else if (which_alternative == 1)
7347 {
7348 /* We must provide an alternative for a hi reg because reload
7349 cannot handle output reloads on a jump instruction, but we
7350 can't subtract into that. Fortunately a mov from lo to hi
7351 does not clobber the condition codes. */
7352 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7353 output_asm_insn (\"mov\\t%0, %1\", operands);
7354 }
7355 else
7356 {
7357 /* Similarly, but the target is memory. */
7358 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7359 output_asm_insn (\"str\\t%1, %0\", operands);
7360 }
7361
7362 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7363 {
7364 case 4:
8aea555f 7365 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7366 return \"\";
7367 case 6:
8aea555f 7368 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7369 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7370 default:
8aea555f 7371 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7372 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7373 }
7374 }
7375 "
7376 [(set (attr "far_jump")
7377 (if_then_else
7378 (ior (and (eq (symbol_ref ("which_alternative"))
7379 (const_int 0))
7380 (eq_attr "length" "8"))
7381 (eq_attr "length" "10"))
7382 (const_string "yes")
7383 (const_string "no")))
7384 (set_attr_alternative "length"
7385 [
7386 ;; Alternative 0
7387 (if_then_else
7388 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7389 (le (minus (match_dup 4) (pc)) (const_int 256)))
7390 (const_int 4)
7391 (if_then_else
7392 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7393 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7394 (const_int 6)
7395 (const_int 8)))
7396 ;; Alternative 1
7397 (if_then_else
7398 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7399 (le (minus (match_dup 4) (pc)) (const_int 256)))
7400 (const_int 6)
7401 (if_then_else
7402 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7403 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7404 (const_int 8)
7405 (const_int 10)))
7406 ;; Alternative 2
7407 (if_then_else
7408 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7409 (le (minus (match_dup 4) (pc)) (const_int 256)))
7410 (const_int 6)
7411 (if_then_else
7412 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7413 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7414 (const_int 8)
7415 (const_int 10)))
7416 ;; Alternative 3
7417 (if_then_else
7418 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7419 (le (minus (match_dup 4) (pc)) (const_int 256)))
7420 (const_int 6)
7421 (if_then_else
7422 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7423 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7424 (const_int 8)
7425 (const_int 10)))])]
7426)
cffb2a26 7427
58d6528b 7428(define_insn "*addsi3_cbranch"
7429 [(set (pc)
7430 (if_then_else
7431 (match_operator 4 "comparison_operator"
7432 [(plus:SI
7433 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
7434 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
7435 (const_int 0)])
7436 (label_ref (match_operand 5 "" ""))
7437 (pc)))
aeac46d4 7438 (set
7439 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7440 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 7441 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
25f905c2 7442 "TARGET_THUMB1
58d6528b 7443 && (GET_CODE (operands[4]) == EQ
7444 || GET_CODE (operands[4]) == NE
7445 || GET_CODE (operands[4]) == GE
7446 || GET_CODE (operands[4]) == LT)"
7447 "*
7448 {
7449 rtx cond[3];
7450
7451
7452 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
7453 cond[1] = operands[2];
7454 cond[2] = operands[3];
7455
7456 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7457 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7458 else
7459 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7460
7461 if (which_alternative >= 3
7462 && which_alternative < 4)
7463 output_asm_insn (\"mov\\t%0, %1\", operands);
7464 else if (which_alternative >= 4)
7465 output_asm_insn (\"str\\t%1, %0\", operands);
7466
7467 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7468 {
7469 case 4:
7470 return \"b%d4\\t%l5\";
7471 case 6:
7472 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7473 default:
7474 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7475 }
7476 }
7477 "
7478 [(set (attr "far_jump")
7479 (if_then_else
7480 (ior (and (lt (symbol_ref ("which_alternative"))
7481 (const_int 3))
7482 (eq_attr "length" "8"))
7483 (eq_attr "length" "10"))
7484 (const_string "yes")
7485 (const_string "no")))
7486 (set (attr "length")
7487 (if_then_else
7488 (lt (symbol_ref ("which_alternative"))
7489 (const_int 3))
7490 (if_then_else
7491 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7492 (le (minus (match_dup 5) (pc)) (const_int 256)))
7493 (const_int 4)
7494 (if_then_else
7495 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7496 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7497 (const_int 6)
7498 (const_int 8)))
7499 (if_then_else
7500 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7501 (le (minus (match_dup 5) (pc)) (const_int 256)))
7502 (const_int 6)
7503 (if_then_else
7504 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7505 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7506 (const_int 8)
7507 (const_int 10)))))]
7508)
7509
7510(define_insn "*addsi3_cbranch_scratch"
7511 [(set (pc)
7512 (if_then_else
7513 (match_operator 3 "comparison_operator"
7514 [(plus:SI
7515 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7516 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7517 (const_int 0)])
7518 (label_ref (match_operand 4 "" ""))
7519 (pc)))
7520 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7521 "TARGET_THUMB1
58d6528b 7522 && (GET_CODE (operands[3]) == EQ
7523 || GET_CODE (operands[3]) == NE
7524 || GET_CODE (operands[3]) == GE
7525 || GET_CODE (operands[3]) == LT)"
7526 "*
7527 {
7528 switch (which_alternative)
7529 {
7530 case 0:
7531 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7532 break;
7533 case 1:
7534 output_asm_insn (\"cmn\t%1, %2\", operands);
7535 break;
0f5e9701 7536 case 2:
3a445a04 7537 if (INTVAL (operands[2]) < 0)
7538 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7539 else
7540 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7541 break;
0f5e9701 7542 case 3:
3a445a04 7543 if (INTVAL (operands[2]) < 0)
7544 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7545 else
7546 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7547 break;
7548 }
7549
7550 switch (get_attr_length (insn))
7551 {
7552 case 4:
7553 return \"b%d3\\t%l4\";
7554 case 6:
7555 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7556 default:
7557 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7558 }
7559 }
7560 "
7561 [(set (attr "far_jump")
7562 (if_then_else
7563 (eq_attr "length" "8")
7564 (const_string "yes")
7565 (const_string "no")))
7566 (set (attr "length")
7567 (if_then_else
7568 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7569 (le (minus (match_dup 4) (pc)) (const_int 256)))
7570 (const_int 4)
7571 (if_then_else
7572 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7573 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7574 (const_int 6)
7575 (const_int 8))))]
7576)
7577
7578(define_insn "*subsi3_cbranch"
7579 [(set (pc)
7580 (if_then_else
7581 (match_operator 4 "comparison_operator"
7582 [(minus:SI
7583 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7584 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7585 (const_int 0)])
7586 (label_ref (match_operand 5 "" ""))
7587 (pc)))
aeac46d4 7588 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7589 (minus:SI (match_dup 2) (match_dup 3)))
7590 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7591 "TARGET_THUMB1
58d6528b 7592 && (GET_CODE (operands[4]) == EQ
7593 || GET_CODE (operands[4]) == NE
7594 || GET_CODE (operands[4]) == GE
7595 || GET_CODE (operands[4]) == LT)"
7596 "*
7597 {
7598 if (which_alternative == 0)
7599 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7600 else if (which_alternative == 1)
7601 {
7602 /* We must provide an alternative for a hi reg because reload
7603 cannot handle output reloads on a jump instruction, but we
7604 can't subtract into that. Fortunately a mov from lo to hi
7605 does not clobber the condition codes. */
7606 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7607 output_asm_insn (\"mov\\t%0, %1\", operands);
7608 }
7609 else
7610 {
7611 /* Similarly, but the target is memory. */
7612 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7613 output_asm_insn (\"str\\t%1, %0\", operands);
7614 }
7615
7616 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7617 {
7618 case 4:
7619 return \"b%d4\\t%l5\";
7620 case 6:
7621 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7622 default:
7623 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7624 }
7625 }
7626 "
7627 [(set (attr "far_jump")
7628 (if_then_else
7629 (ior (and (eq (symbol_ref ("which_alternative"))
7630 (const_int 0))
7631 (eq_attr "length" "8"))
7632 (eq_attr "length" "10"))
7633 (const_string "yes")
7634 (const_string "no")))
7635 (set (attr "length")
7636 (if_then_else
7637 (eq (symbol_ref ("which_alternative"))
7638 (const_int 0))
7639 (if_then_else
7640 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7641 (le (minus (match_dup 5) (pc)) (const_int 256)))
7642 (const_int 4)
7643 (if_then_else
7644 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7645 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7646 (const_int 6)
7647 (const_int 8)))
7648 (if_then_else
7649 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7650 (le (minus (match_dup 5) (pc)) (const_int 256)))
7651 (const_int 6)
7652 (if_then_else
7653 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7654 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7655 (const_int 8)
7656 (const_int 10)))))]
7657)
7658
7659(define_insn "*subsi3_cbranch_scratch"
7660 [(set (pc)
7661 (if_then_else
7662 (match_operator 0 "arm_comparison_operator"
7663 [(minus:SI (match_operand:SI 1 "register_operand" "l")
7664 (match_operand:SI 2 "nonmemory_operand" "l"))
7665 (const_int 0)])
7666 (label_ref (match_operand 3 "" ""))
7667 (pc)))]
25f905c2 7668 "TARGET_THUMB1
58d6528b 7669 && (GET_CODE (operands[0]) == EQ
7670 || GET_CODE (operands[0]) == NE
7671 || GET_CODE (operands[0]) == GE
7672 || GET_CODE (operands[0]) == LT)"
7673 "*
7674 output_asm_insn (\"cmp\\t%1, %2\", operands);
7675 switch (get_attr_length (insn))
7676 {
7677 case 4: return \"b%d0\\t%l3\";
7678 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7679 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7680 }
7681 "
7682 [(set (attr "far_jump")
7683 (if_then_else
7684 (eq_attr "length" "8")
7685 (const_string "yes")
7686 (const_string "no")))
7687 (set (attr "length")
7688 (if_then_else
7689 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7690 (le (minus (match_dup 3) (pc)) (const_int 256)))
7691 (const_int 4)
7692 (if_then_else
7693 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7694 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7695 (const_int 6)
7696 (const_int 8))))]
7697)
7698
9c08d1fa 7699;; Comparison and test insns
7700
cffb2a26 7701(define_insn "*arm_cmpsi_insn"
bd5b4116 7702 [(set (reg:CC CC_REGNUM)
aea4c774 7703 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7704 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7705 "TARGET_32BIT"
5565501b 7706 "@
aea4c774 7707 cmp%?\\t%0, %1
7708 cmn%?\\t%0, #%n1"
cffb2a26 7709 [(set_attr "conds" "set")]
7710)
b11cae9e 7711
25f905c2 7712(define_insn "*arm_cmpsi_shiftsi"
bd5b4116 7713 [(set (reg:CC CC_REGNUM)
cffb2a26 7714 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
7715 (match_operator:SI 3 "shift_operator"
aea4c774 7716 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 7717 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
7718 "TARGET_ARM"
aea4c774 7719 "cmp%?\\t%0, %1%S3"
344495ea 7720 [(set_attr "conds" "set")
331beb1a 7721 (set_attr "shift" "1")
a2cd141b 7722 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7723 (const_string "alu_shift")
7724 (const_string "alu_shift_reg")))]
0d66636f 7725)
b11cae9e 7726
25f905c2 7727(define_insn "*arm_cmpsi_shiftsi_swp"
bd5b4116 7728 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7729 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7730 [(match_operand:SI 1 "s_register_operand" "r")
7731 (match_operand:SI 2 "reg_or_int_operand" "rM")])
7732 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7733 "TARGET_ARM"
aea4c774 7734 "cmp%?\\t%0, %1%S3"
344495ea 7735 [(set_attr "conds" "set")
331beb1a 7736 (set_attr "shift" "1")
a2cd141b 7737 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7738 (const_string "alu_shift")
7739 (const_string "alu_shift_reg")))]
0d66636f 7740)
b11cae9e 7741
25f905c2 7742(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7743 [(set (reg:CC_Z CC_REGNUM)
7744 (compare:CC_Z
7745 (neg:SI (match_operator:SI 1 "shift_operator"
7746 [(match_operand:SI 2 "s_register_operand" "r")
7747 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7748 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7749 "TARGET_ARM"
aed179ae 7750 "cmn%?\\t%0, %2%S1"
344495ea 7751 [(set_attr "conds" "set")
aed179ae 7752 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7753 (const_string "alu_shift")
7754 (const_string "alu_shift_reg")))]
0d66636f 7755)
b11cae9e 7756
7d57ec45 7757;; Cirrus SF compare instruction
7758(define_insn "*cirrus_cmpsf"
7759 [(set (reg:CCFP CC_REGNUM)
7760 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7761 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7762 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7763 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7764 [(set_attr "type" "mav_farith")
7d57ec45 7765 (set_attr "cirrus" "compare")]
7766)
7767
7768;; Cirrus DF compare instruction
7769(define_insn "*cirrus_cmpdf"
7770 [(set (reg:CCFP CC_REGNUM)
7771 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7772 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7773 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7774 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7775 [(set_attr "type" "mav_farith")
7d57ec45 7776 (set_attr "cirrus" "compare")]
7777)
7778
7d57ec45 7779(define_insn "*cirrus_cmpdi"
7780 [(set (reg:CC CC_REGNUM)
7781 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7782 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7783 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7784 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7785 [(set_attr "type" "mav_farith")
7d57ec45 7786 (set_attr "cirrus" "compare")]
7787)
7788
9c08d1fa 7789; This insn allows redundant compares to be removed by cse, nothing should
7790; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7791; is deleted later on. The match_dup will match the mode here, so that
7792; mode changes of the condition codes aren't lost by this even though we don't
7793; specify what they are.
7794
8a18b90c 7795(define_insn "*deleted_compare"
9c08d1fa 7796 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7797 "TARGET_32BIT"
40dbec34 7798 "\\t%@ deleted compare"
cffb2a26 7799 [(set_attr "conds" "set")
7800 (set_attr "length" "0")]
7801)
9c08d1fa 7802
7803\f
7804;; Conditional branch insns
7805
74f4459c 7806(define_expand "cbranch_cc"
9c08d1fa 7807 [(set (pc)
74f4459c 7808 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7809 (match_operand 2 "" "")])
7810 (label_ref (match_operand 3 "" ""))
9c08d1fa 7811 (pc)))]
25f905c2 7812 "TARGET_32BIT"
74f4459c 7813 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7814 operands[1], operands[2]);
7815 operands[2] = const0_rtx;"
8fa3ba89 7816)
7817
7818;;
7819;; Patterns to match conditional branch insns.
7820;;
7821
7822; Special pattern to match UNEQ.
7823(define_insn "*arm_buneq"
7824 [(set (pc)
7825 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7826 (label_ref (match_operand 0 "" ""))
7827 (pc)))]
25f905c2 7828 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7829 "*
ed29c566 7830 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7831
278b301d 7832 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7833 "
7834 [(set_attr "conds" "jump_clob")
7835 (set_attr "length" "8")]
7836)
7837
7838; Special pattern to match LTGT.
7839(define_insn "*arm_bltgt"
7840 [(set (pc)
7841 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7842 (label_ref (match_operand 0 "" ""))
7843 (pc)))]
25f905c2 7844 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7845 "*
ed29c566 7846 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7847
278b301d 7848 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7849 "
7850 [(set_attr "conds" "jump_clob")
7851 (set_attr "length" "8")]
7852)
9c08d1fa 7853
cffb2a26 7854(define_insn "*arm_cond_branch"
9c08d1fa 7855 [(set (pc)
8fa3ba89 7856 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7857 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7858 (label_ref (match_operand 0 "" ""))
7859 (pc)))]
25f905c2 7860 "TARGET_32BIT"
d75350ce 7861 "*
9c08d1fa 7862 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7863 {
7864 arm_ccfsm_state += 2;
7865 return \"\";
7866 }
e2348bcb 7867 return \"b%d1\\t%l0\";
cffb2a26 7868 "
a2cd141b 7869 [(set_attr "conds" "use")
7870 (set_attr "type" "branch")]
cffb2a26 7871)
d75350ce 7872
8fa3ba89 7873; Special pattern to match reversed UNEQ.
7874(define_insn "*arm_buneq_reversed"
7875 [(set (pc)
7876 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7877 (pc)
7878 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7879 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7880 "*
ed29c566 7881 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7882
278b301d 7883 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7884 "
7885 [(set_attr "conds" "jump_clob")
7886 (set_attr "length" "8")]
7887)
7888
7889; Special pattern to match reversed LTGT.
7890(define_insn "*arm_bltgt_reversed"
7891 [(set (pc)
7892 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7893 (pc)
7894 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7895 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7896 "*
ed29c566 7897 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7898
278b301d 7899 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7900 "
7901 [(set_attr "conds" "jump_clob")
7902 (set_attr "length" "8")]
7903)
7904
cffb2a26 7905(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7906 [(set (pc)
8fa3ba89 7907 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7908 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7909 (pc)
7910 (label_ref (match_operand 0 "" ""))))]
25f905c2 7911 "TARGET_32BIT"
d75350ce 7912 "*
9c08d1fa 7913 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7914 {
7915 arm_ccfsm_state += 2;
7916 return \"\";
7917 }
e2348bcb 7918 return \"b%D1\\t%l0\";
cffb2a26 7919 "
a2cd141b 7920 [(set_attr "conds" "use")
7921 (set_attr "type" "branch")]
cffb2a26 7922)
7923
b11cae9e 7924\f
9c08d1fa 7925
7926; scc insns
7927
74f4459c 7928(define_expand "cstore_cc"
7db9af5d 7929 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7930 (match_operator:SI 1 "" [(match_operand 2 "" "")
7931 (match_operand 3 "" "")]))]
25f905c2 7932 "TARGET_32BIT"
74f4459c 7933 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7934 operands[2], operands[3]);
7935 operands[3] = const0_rtx;"
8fa3ba89 7936)
7937
f7fbdd4a 7938(define_insn "*mov_scc"
9c08d1fa 7939 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7940 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7941 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7942 "TARGET_ARM"
4d61e570 7943 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7944 [(set_attr "conds" "use")
7945 (set_attr "length" "8")]
7946)
9c08d1fa 7947
f7fbdd4a 7948(define_insn "*mov_negscc"
9c08d1fa 7949 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7950 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7951 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7952 "TARGET_ARM"
4d61e570 7953 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7954 [(set_attr "conds" "use")
7955 (set_attr "length" "8")]
7956)
9c08d1fa 7957
f7fbdd4a 7958(define_insn "*mov_notscc"
9c08d1fa 7959 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7960 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7961 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7962 "TARGET_ARM"
4d61e570 7963 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7964 [(set_attr "conds" "use")
7965 (set_attr "length" "8")]
7966)
9c08d1fa 7967
595d88b5 7968(define_expand "cstoresi4"
7969 [(set (match_operand:SI 0 "s_register_operand" "")
7970 (match_operator:SI 1 "arm_comparison_operator"
7971 [(match_operand:SI 2 "s_register_operand" "")
7972 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7973 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7974 "{
7975 rtx op3, scratch, scratch2;
7976
74f4459c 7977 if (!TARGET_THUMB1)
7978 {
7979 if (!arm_add_operand (operands[3], SImode))
7980 operands[3] = force_reg (SImode, operands[3]);
7981 emit_insn (gen_cstore_cc (operands[0], operands[1],
7982 operands[2], operands[3]));
7983 DONE;
7984 }
7985
595d88b5 7986 if (operands[3] == const0_rtx)
7987 {
7988 switch (GET_CODE (operands[1]))
7989 {
7990 case EQ:
25f905c2 7991 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7992 break;
7993
7994 case NE:
25f905c2 7995 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7996 break;
7997
7998 case LE:
7999 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8000 NULL_RTX, 0, OPTAB_WIDEN);
8001 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8002 NULL_RTX, 0, OPTAB_WIDEN);
8003 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8004 operands[0], 1, OPTAB_WIDEN);
8005 break;
8006
8007 case GE:
8008 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8009 NULL_RTX, 1);
8010 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8011 NULL_RTX, 1, OPTAB_WIDEN);
8012 break;
8013
8014 case GT:
8015 scratch = expand_binop (SImode, ashr_optab, operands[2],
8016 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8017 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8018 NULL_RTX, 0, OPTAB_WIDEN);
8019 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8020 0, OPTAB_WIDEN);
8021 break;
8022
8023 /* LT is handled by generic code. No need for unsigned with 0. */
8024 default:
8025 FAIL;
8026 }
8027 DONE;
8028 }
8029
8030 switch (GET_CODE (operands[1]))
8031 {
8032 case EQ:
8033 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8034 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8035 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 8036 break;
8037
8038 case NE:
8039 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8040 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8041 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 8042 break;
8043
8044 case LE:
8045 op3 = force_reg (SImode, operands[3]);
8046
8047 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8048 NULL_RTX, 1, OPTAB_WIDEN);
8049 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8050 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8051 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8052 op3, operands[2]));
8053 break;
8054
8055 case GE:
8056 op3 = operands[3];
25f905c2 8057 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8058 op3 = force_reg (SImode, op3);
8059 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8060 NULL_RTX, 0, OPTAB_WIDEN);
8061 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8062 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 8063 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8064 operands[2], op3));
8065 break;
8066
8067 case LEU:
8068 op3 = force_reg (SImode, operands[3]);
8069 scratch = force_reg (SImode, const0_rtx);
25f905c2 8070 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8071 op3, operands[2]));
8072 break;
8073
8074 case GEU:
8075 op3 = operands[3];
25f905c2 8076 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8077 op3 = force_reg (SImode, op3);
8078 scratch = force_reg (SImode, const0_rtx);
25f905c2 8079 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8080 operands[2], op3));
8081 break;
8082
8083 case LTU:
8084 op3 = operands[3];
25f905c2 8085 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8086 op3 = force_reg (SImode, op3);
8087 scratch = gen_reg_rtx (SImode);
25f905c2 8088 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
595d88b5 8089 emit_insn (gen_negsi2 (operands[0], scratch));
8090 break;
8091
8092 case GTU:
8093 op3 = force_reg (SImode, operands[3]);
8094 scratch = gen_reg_rtx (SImode);
25f905c2 8095 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
595d88b5 8096 emit_insn (gen_negsi2 (operands[0], scratch));
8097 break;
8098
8099 /* No good sequences for GT, LT. */
8100 default:
8101 FAIL;
8102 }
8103 DONE;
8104}")
8105
74f4459c 8106(define_expand "cstoresf4"
8107 [(set (match_operand:SI 0 "s_register_operand" "")
8108 (match_operator:SI 1 "arm_comparison_operator"
8109 [(match_operand:SF 2 "s_register_operand" "")
8110 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8111 "TARGET_32BIT && TARGET_HARD_FLOAT"
8112 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8113 operands[2], operands[3])); DONE;"
8114)
8115
8116(define_expand "cstoredf4"
8117 [(set (match_operand:SI 0 "s_register_operand" "")
8118 (match_operator:SI 1 "arm_comparison_operator"
8119 [(match_operand:DF 2 "s_register_operand" "")
8120 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8121 "TARGET_32BIT && TARGET_HARD_FLOAT"
8122 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8123 operands[2], operands[3])); DONE;"
8124)
8125
8126;; this uses the Cirrus DI compare instruction
8127(define_expand "cstoredi4"
8128 [(set (match_operand:SI 0 "s_register_operand" "")
8129 (match_operator:SI 1 "arm_comparison_operator"
8130 [(match_operand:DI 2 "cirrus_fp_register" "")
8131 (match_operand:DI 3 "cirrus_fp_register" "")]))]
8132 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
8133 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8134 operands[2], operands[3])); DONE;"
8135)
8136
8137
25f905c2 8138(define_expand "cstoresi_eq0_thumb1"
595d88b5 8139 [(parallel
8140 [(set (match_operand:SI 0 "s_register_operand" "")
8141 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8142 (const_int 0)))
8143 (clobber (match_dup:SI 2))])]
25f905c2 8144 "TARGET_THUMB1"
595d88b5 8145 "operands[2] = gen_reg_rtx (SImode);"
8146)
8147
25f905c2 8148(define_expand "cstoresi_ne0_thumb1"
595d88b5 8149 [(parallel
8150 [(set (match_operand:SI 0 "s_register_operand" "")
8151 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8152 (const_int 0)))
8153 (clobber (match_dup:SI 2))])]
25f905c2 8154 "TARGET_THUMB1"
595d88b5 8155 "operands[2] = gen_reg_rtx (SImode);"
8156)
8157
25f905c2 8158(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 8159 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8160 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8161 (const_int 0)))
8162 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 8163 "TARGET_THUMB1"
595d88b5 8164 "@
8165 neg\\t%0, %1\;adc\\t%0, %0, %1
8166 neg\\t%2, %1\;adc\\t%0, %1, %2"
8167 [(set_attr "length" "4")]
8168)
8169
25f905c2 8170(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 8171 [(set (match_operand:SI 0 "s_register_operand" "=l")
8172 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8173 (const_int 0)))
8174 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8175 "TARGET_THUMB1"
595d88b5 8176 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8177 [(set_attr "length" "4")]
8178)
8179
25f905c2 8180(define_insn "cstoresi_nltu_thumb1"
595d88b5 8181 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8182 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8183 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8184 "TARGET_THUMB1"
595d88b5 8185 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8186 [(set_attr "length" "4")]
8187)
8188
8189;; Used as part of the expansion of thumb les sequence.
25f905c2 8190(define_insn "thumb1_addsi3_addgeu"
595d88b5 8191 [(set (match_operand:SI 0 "s_register_operand" "=l")
8192 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8193 (match_operand:SI 2 "s_register_operand" "l"))
8194 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8195 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8196 "TARGET_THUMB1"
595d88b5 8197 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8198 [(set_attr "length" "4")]
8199)
8200
9c08d1fa 8201\f
39b5e676 8202;; Conditional move insns
8203
8204(define_expand "movsicc"
8a18b90c 8205 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 8206 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 8207 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8208 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8209 "TARGET_32BIT"
39b5e676 8210 "
215b30b3 8211 {
8212 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8213 rtx ccreg;
8214
8215 if (code == UNEQ || code == LTGT)
8216 FAIL;
39b5e676 8217
74f4459c 8218 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8219 XEXP (operands[1], 1));
29bb088d 8220 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8221 }"
8222)
39b5e676 8223
8224(define_expand "movsfcc"
8a18b90c 8225 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 8226 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8227 (match_operand:SF 2 "s_register_operand" "")
8228 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 8229 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8230 "
215b30b3 8231 {
8232 enum rtx_code code = GET_CODE (operands[1]);
8233 rtx ccreg;
f082f1c4 8234
278b301d 8235 if (code == UNEQ || code == LTGT)
8236 FAIL;
8237
215b30b3 8238 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 8239 Otherwise, ensure it is a valid FP add operand */
8240 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8241 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 8242 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8243
74f4459c 8244 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8245 XEXP (operands[1], 1));
29bb088d 8246 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8247 }"
8248)
39b5e676 8249
8250(define_expand "movdfcc"
8a18b90c 8251 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 8252 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8253 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8254 (match_operand:DF 3 "arm_float_add_operand" "")))]
25f905c2 8255 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 8256 "
215b30b3 8257 {
8258 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8259 rtx ccreg;
39b5e676 8260
278b301d 8261 if (code == UNEQ || code == LTGT)
8262 FAIL;
8263
74f4459c 8264 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8265 XEXP (operands[1], 1));
29bb088d 8266 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8267 }"
8268)
39b5e676 8269
8270(define_insn "*movsicc_insn"
f082f1c4 8271 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8272 (if_then_else:SI
8fa3ba89 8273 (match_operator 3 "arm_comparison_operator"
8a18b90c 8274 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8275 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8276 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8277 "TARGET_ARM"
39b5e676 8278 "@
8a18b90c 8279 mov%D3\\t%0, %2
8280 mvn%D3\\t%0, #%B2
f082f1c4 8281 mov%d3\\t%0, %1
8282 mvn%d3\\t%0, #%B1
8a18b90c 8283 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8284 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8285 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8286 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8287 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 8288 (set_attr "conds" "use")]
8289)
39b5e676 8290
39b5e676 8291(define_insn "*movsfcc_soft_insn"
f082f1c4 8292 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8293 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8294 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8295 (match_operand:SF 1 "s_register_operand" "0,r")
8296 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8297 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8298 "@
8299 mov%D3\\t%0, %2
8300 mov%d3\\t%0, %1"
8fa3ba89 8301 [(set_attr "conds" "use")]
8302)
39b5e676 8303
39b5e676 8304\f
9c08d1fa 8305;; Jump and linkage insns
8306
cffb2a26 8307(define_expand "jump"
9c08d1fa 8308 [(set (pc)
8309 (label_ref (match_operand 0 "" "")))]
cffb2a26 8310 "TARGET_EITHER"
9c08d1fa 8311 ""
cffb2a26 8312)
8313
8314(define_insn "*arm_jump"
8315 [(set (pc)
8316 (label_ref (match_operand 0 "" "")))]
25f905c2 8317 "TARGET_32BIT"
9c08d1fa 8318 "*
0d66636f 8319 {
8320 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8321 {
8322 arm_ccfsm_state += 2;
8323 return \"\";
8324 }
8325 return \"b%?\\t%l0\";
8326 }
8327 "
8328 [(set_attr "predicable" "yes")]
8329)
9c08d1fa 8330
cffb2a26 8331(define_insn "*thumb_jump"
8332 [(set (pc)
8333 (label_ref (match_operand 0 "" "")))]
25f905c2 8334 "TARGET_THUMB1"
cffb2a26 8335 "*
8336 if (get_attr_length (insn) == 2)
8337 return \"b\\t%l0\";
8338 return \"bl\\t%l0\\t%@ far jump\";
8339 "
8340 [(set (attr "far_jump")
8341 (if_then_else
8342 (eq_attr "length" "4")
8343 (const_string "yes")
8344 (const_string "no")))
8345 (set (attr "length")
8346 (if_then_else
911ed8af 8347 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8348 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8349 (const_int 2)
8350 (const_int 4)))]
8351)
8352
d3373b54 8353(define_expand "call"
8354 [(parallel [(call (match_operand 0 "memory_operand" "")
8355 (match_operand 1 "general_operand" ""))
cffb2a26 8356 (use (match_operand 2 "" ""))
bd5b4116 8357 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8358 "TARGET_EITHER"
6c4c2133 8359 "
8360 {
bac7fc85 8361 rtx callee, pat;
bbe777ea 8362
bbe777ea 8363 /* In an untyped call, we can get NULL for operand 2. */
8364 if (operands[2] == NULL_RTX)
8365 operands[2] = const0_rtx;
8366
de55252a 8367 /* Decide if we should generate indirect calls by loading the
85c36fd1 8368 32-bit address of the callee into a register before performing the
de55252a 8369 branch and link. */
8370 callee = XEXP (operands[0], 0);
8371 if (GET_CODE (callee) == SYMBOL_REF
8372 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8373 : !REG_P (callee))
bbe777ea 8374 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8375
8376 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8377 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8378 DONE;
6c4c2133 8379 }"
8380)
d3373b54 8381
bac7fc85 8382(define_expand "call_internal"
8383 [(parallel [(call (match_operand 0 "memory_operand" "")
8384 (match_operand 1 "general_operand" ""))
8385 (use (match_operand 2 "" ""))
8386 (clobber (reg:SI LR_REGNUM))])])
8387
f1039640 8388(define_insn "*call_reg_armv5"
d3373b54 8389 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8390 (match_operand 1 "" ""))
8391 (use (match_operand 2 "" ""))
bd5b4116 8392 (clobber (reg:SI LR_REGNUM))]
f1039640 8393 "TARGET_ARM && arm_arch5"
8394 "blx%?\\t%0"
8395 [(set_attr "type" "call")]
8396)
8397
8398(define_insn "*call_reg_arm"
8399 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8400 (match_operand 1 "" ""))
8401 (use (match_operand 2 "" ""))
8402 (clobber (reg:SI LR_REGNUM))]
8403 "TARGET_ARM && !arm_arch5"
9c08d1fa 8404 "*
5565501b 8405 return output_call (operands);
cffb2a26 8406 "
8407 ;; length is worst case, normally it is only two
8408 [(set_attr "length" "12")
8409 (set_attr "type" "call")]
8410)
9c08d1fa 8411
f7fbdd4a 8412(define_insn "*call_mem"
a3c63a9d 8413 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8414 (match_operand 1 "" ""))
8415 (use (match_operand 2 "" ""))
bd5b4116 8416 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8417 "TARGET_ARM"
9c08d1fa 8418 "*
5565501b 8419 return output_call_mem (operands);
cffb2a26 8420 "
8421 [(set_attr "length" "12")
8422 (set_attr "type" "call")]
8423)
8424
25f905c2 8425(define_insn "*call_reg_thumb1_v5"
cffb2a26 8426 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8427 (match_operand 1 "" ""))
8428 (use (match_operand 2 "" ""))
bd5b4116 8429 (clobber (reg:SI LR_REGNUM))]
25f905c2 8430 "TARGET_THUMB1 && arm_arch5"
f1039640 8431 "blx\\t%0"
8432 [(set_attr "length" "2")
8433 (set_attr "type" "call")]
cffb2a26 8434)
8435
25f905c2 8436(define_insn "*call_reg_thumb1"
f1039640 8437 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8438 (match_operand 1 "" ""))
8439 (use (match_operand 2 "" ""))
bd5b4116 8440 (clobber (reg:SI LR_REGNUM))]
25f905c2 8441 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8442 "*
8443 {
150502c9 8444 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8445 return thumb_call_via_reg (operands[0]);
150502c9 8446 else if (operands[1] == const0_rtx)
f1039640 8447 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8448 else if (frame_pointer_needed)
8449 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8450 else
150502c9 8451 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8452 }"
8453 [(set_attr "type" "call")]
8454)
9c08d1fa 8455
d3373b54 8456(define_expand "call_value"
e0698af7 8457 [(parallel [(set (match_operand 0 "" "")
8458 (call (match_operand 1 "memory_operand" "")
8459 (match_operand 2 "general_operand" "")))
cffb2a26 8460 (use (match_operand 3 "" ""))
bd5b4116 8461 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8462 "TARGET_EITHER"
6c4c2133 8463 "
8464 {
bac7fc85 8465 rtx pat, callee;
bbe777ea 8466
8467 /* In an untyped call, we can get NULL for operand 2. */
8468 if (operands[3] == 0)
8469 operands[3] = const0_rtx;
8470
de55252a 8471 /* Decide if we should generate indirect calls by loading the
8472 32-bit address of the callee into a register before performing the
8473 branch and link. */
8474 callee = XEXP (operands[1], 0);
8475 if (GET_CODE (callee) == SYMBOL_REF
8476 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8477 : !REG_P (callee))
78fe751b 8478 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8479
8480 pat = gen_call_value_internal (operands[0], operands[1],
8481 operands[2], operands[3]);
8482 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8483 DONE;
6c4c2133 8484 }"
8485)
d3373b54 8486
bac7fc85 8487(define_expand "call_value_internal"
8488 [(parallel [(set (match_operand 0 "" "")
8489 (call (match_operand 1 "memory_operand" "")
8490 (match_operand 2 "general_operand" "")))
8491 (use (match_operand 3 "" ""))
8492 (clobber (reg:SI LR_REGNUM))])])
8493
f1039640 8494(define_insn "*call_value_reg_armv5"
27ed6835 8495 [(set (match_operand 0 "" "")
755eb2b4 8496 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8497 (match_operand 2 "" "")))
bbe777ea 8498 (use (match_operand 3 "" ""))
bd5b4116 8499 (clobber (reg:SI LR_REGNUM))]
f1039640 8500 "TARGET_ARM && arm_arch5"
8501 "blx%?\\t%1"
8502 [(set_attr "type" "call")]
8503)
8504
8505(define_insn "*call_value_reg_arm"
8506 [(set (match_operand 0 "" "")
8507 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8508 (match_operand 2 "" "")))
8509 (use (match_operand 3 "" ""))
8510 (clobber (reg:SI LR_REGNUM))]
8511 "TARGET_ARM && !arm_arch5"
9c08d1fa 8512 "*
215b30b3 8513 return output_call (&operands[1]);
cffb2a26 8514 "
8515 [(set_attr "length" "12")
8516 (set_attr "type" "call")]
8517)
9c08d1fa 8518
f7fbdd4a 8519(define_insn "*call_value_mem"
27ed6835 8520 [(set (match_operand 0 "" "")
a3c63a9d 8521 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8522 (match_operand 2 "" "")))
bbe777ea 8523 (use (match_operand 3 "" ""))
bd5b4116 8524 (clobber (reg:SI LR_REGNUM))]
215b30b3 8525 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8526 "*
215b30b3 8527 return output_call_mem (&operands[1]);
cffb2a26 8528 "
8529 [(set_attr "length" "12")
8530 (set_attr "type" "call")]
8531)
9c08d1fa 8532
25f905c2 8533(define_insn "*call_value_reg_thumb1_v5"
f1039640 8534 [(set (match_operand 0 "" "")
8535 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8536 (match_operand 2 "" "")))
8537 (use (match_operand 3 "" ""))
8538 (clobber (reg:SI LR_REGNUM))]
25f905c2 8539 "TARGET_THUMB1 && arm_arch5"
f1039640 8540 "blx\\t%1"
8541 [(set_attr "length" "2")
8542 (set_attr "type" "call")]
8543)
8544
25f905c2 8545(define_insn "*call_value_reg_thumb1"
f1039640 8546 [(set (match_operand 0 "" "")
8547 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8548 (match_operand 2 "" "")))
8549 (use (match_operand 3 "" ""))
8550 (clobber (reg:SI LR_REGNUM))]
25f905c2 8551 "TARGET_THUMB1 && !arm_arch5"
f1039640 8552 "*
8553 {
150502c9 8554 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8555 return thumb_call_via_reg (operands[1]);
150502c9 8556 else if (operands[2] == const0_rtx)
f1039640 8557 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8558 else if (frame_pointer_needed)
8559 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8560 else
150502c9 8561 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8562 }"
8563 [(set_attr "type" "call")]
8564)
8565
9c08d1fa 8566;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8567;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8568
f7fbdd4a 8569(define_insn "*call_symbol"
27ed6835 8570 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8571 (match_operand 1 "" ""))
bbe777ea 8572 (use (match_operand 2 "" ""))
bd5b4116 8573 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8574 "TARGET_ARM
8575 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8576 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8577 "*
8578 {
55c1e470 8579 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8580 }"
cffb2a26 8581 [(set_attr "type" "call")]
8582)
9c08d1fa 8583
f7fbdd4a 8584(define_insn "*call_value_symbol"
ccd90aaa 8585 [(set (match_operand 0 "" "")
27ed6835 8586 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8587 (match_operand:SI 2 "" "")))
bbe777ea 8588 (use (match_operand 3 "" ""))
bd5b4116 8589 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8590 "TARGET_ARM
8591 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8592 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8593 "*
8594 {
55c1e470 8595 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8596 }"
cffb2a26 8597 [(set_attr "type" "call")]
8598)
8599
8600(define_insn "*call_insn"
27ed6835 8601 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8602 (match_operand:SI 1 "" ""))
8603 (use (match_operand 2 "" ""))
bd5b4116 8604 (clobber (reg:SI LR_REGNUM))]
1c494086 8605 "TARGET_THUMB
1675c6e9 8606 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8607 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8608 "bl\\t%a0"
8609 [(set_attr "length" "4")
8610 (set_attr "type" "call")]
8611)
8612
8613(define_insn "*call_value_insn"
ccd90aaa 8614 [(set (match_operand 0 "" "")
27ed6835 8615 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8616 (match_operand 2 "" "")))
8617 (use (match_operand 3 "" ""))
bd5b4116 8618 (clobber (reg:SI LR_REGNUM))]
1c494086 8619 "TARGET_THUMB
1675c6e9 8620 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8621 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8622 "bl\\t%a1"
8623 [(set_attr "length" "4")
8624 (set_attr "type" "call")]
8625)
9c08d1fa 8626
1c494086 8627;; We may also be able to do sibcalls for Thumb, but it's much harder...
8628(define_expand "sibcall"
8629 [(parallel [(call (match_operand 0 "memory_operand" "")
8630 (match_operand 1 "general_operand" ""))
2ba80634 8631 (return)
8632 (use (match_operand 2 "" ""))])]
1c494086 8633 "TARGET_ARM"
8634 "
8635 {
8636 if (operands[2] == NULL_RTX)
8637 operands[2] = const0_rtx;
1c494086 8638 }"
8639)
8640
8641(define_expand "sibcall_value"
ccd90aaa 8642 [(parallel [(set (match_operand 0 "" "")
1c494086 8643 (call (match_operand 1 "memory_operand" "")
8644 (match_operand 2 "general_operand" "")))
2ba80634 8645 (return)
8646 (use (match_operand 3 "" ""))])]
1c494086 8647 "TARGET_ARM"
8648 "
8649 {
8650 if (operands[3] == NULL_RTX)
8651 operands[3] = const0_rtx;
1c494086 8652 }"
8653)
8654
8655(define_insn "*sibcall_insn"
8656 [(call (mem:SI (match_operand:SI 0 "" "X"))
8657 (match_operand 1 "" ""))
2ba80634 8658 (return)
8659 (use (match_operand 2 "" ""))]
1c494086 8660 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8661 "*
8662 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8663 "
8664 [(set_attr "type" "call")]
8665)
8666
8667(define_insn "*sibcall_value_insn"
ccd90aaa 8668 [(set (match_operand 0 "" "")
755eb2b4 8669 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8670 (match_operand 2 "" "")))
2ba80634 8671 (return)
8672 (use (match_operand 3 "" ""))]
1c494086 8673 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8674 "*
8675 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8676 "
8677 [(set_attr "type" "call")]
8678)
8679
9c08d1fa 8680;; Often the return insn will be the same as loading from memory, so set attr
8681(define_insn "return"
8682 [(return)]
cffb2a26 8683 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8684 "*
9c08d1fa 8685 {
cffb2a26 8686 if (arm_ccfsm_state == 2)
8687 {
8688 arm_ccfsm_state += 2;
8689 return \"\";
8690 }
5db468b7 8691 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8692 }"
a2cd141b 8693 [(set_attr "type" "load1")
755eb2b4 8694 (set_attr "length" "12")
0d66636f 8695 (set_attr "predicable" "yes")]
cffb2a26 8696)
9c08d1fa 8697
f7fbdd4a 8698(define_insn "*cond_return"
9c08d1fa 8699 [(set (pc)
8fa3ba89 8700 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8701 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8702 (return)
8703 (pc)))]
cffb2a26 8704 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8705 "*
8fa3ba89 8706 {
8707 if (arm_ccfsm_state == 2)
8708 {
8709 arm_ccfsm_state += 2;
8710 return \"\";
8711 }
8712 return output_return_instruction (operands[0], TRUE, FALSE);
8713 }"
8714 [(set_attr "conds" "use")
755eb2b4 8715 (set_attr "length" "12")
a2cd141b 8716 (set_attr "type" "load1")]
8fa3ba89 8717)
9c08d1fa 8718
f7fbdd4a 8719(define_insn "*cond_return_inverted"
9c08d1fa 8720 [(set (pc)
8fa3ba89 8721 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8722 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8723 (pc)
8724 (return)))]
cffb2a26 8725 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8726 "*
8fa3ba89 8727 {
8728 if (arm_ccfsm_state == 2)
8729 {
8730 arm_ccfsm_state += 2;
8731 return \"\";
8732 }
8733 return output_return_instruction (operands[0], TRUE, TRUE);
8734 }"
8735 [(set_attr "conds" "use")
37a1317b 8736 (set_attr "length" "12")
a2cd141b 8737 (set_attr "type" "load1")]
8fa3ba89 8738)
9c08d1fa 8739
68121397 8740;; Generate a sequence of instructions to determine if the processor is
8741;; in 26-bit or 32-bit mode, and return the appropriate return address
8742;; mask.
8743
8744(define_expand "return_addr_mask"
8745 [(set (match_dup 1)
8746 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8747 (const_int 0)))
8748 (set (match_operand:SI 0 "s_register_operand" "")
8749 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8750 (const_int -1)
8751 (const_int 67108860)))] ; 0x03fffffc
8752 "TARGET_ARM"
8753 "
62eddbd4 8754 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8755 ")
8756
8757(define_insn "*check_arch2"
8758 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8759 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8760 (const_int 0)))]
8761 "TARGET_ARM"
8762 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8763 [(set_attr "length" "8")
8764 (set_attr "conds" "set")]
8765)
8766
9c08d1fa 8767;; Call subroutine returning any type.
8768
8769(define_expand "untyped_call"
8770 [(parallel [(call (match_operand 0 "" "")
8771 (const_int 0))
8772 (match_operand 1 "" "")
8773 (match_operand 2 "" "")])]
ccd90aaa 8774 "TARGET_EITHER"
9c08d1fa 8775 "
215b30b3 8776 {
8777 int i;
ccd90aaa 8778 rtx par = gen_rtx_PARALLEL (VOIDmode,
8779 rtvec_alloc (XVECLEN (operands[2], 0)));
8780 rtx addr = gen_reg_rtx (Pmode);
8781 rtx mem;
8782 int size = 0;
9c08d1fa 8783
ccd90aaa 8784 emit_move_insn (addr, XEXP (operands[1], 0));
8785 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8786
215b30b3 8787 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8788 {
ccd90aaa 8789 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8790
ccd90aaa 8791 /* Default code only uses r0 as a return value, but we could
8792 be using anything up to 4 registers. */
8793 if (REGNO (src) == R0_REGNUM)
8794 src = gen_rtx_REG (TImode, R0_REGNUM);
8795
8796 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8797 GEN_INT (size));
8798 size += GET_MODE_SIZE (GET_MODE (src));
8799 }
8800
8801 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8802 const0_rtx));
8803
8804 size = 0;
8805
8806 for (i = 0; i < XVECLEN (par, 0); i++)
8807 {
8808 HOST_WIDE_INT offset = 0;
8809 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8810
8811 if (size != 0)
8812 emit_move_insn (addr, plus_constant (addr, size));
8813
8814 mem = change_address (mem, GET_MODE (reg), NULL);
8815 if (REGNO (reg) == R0_REGNUM)
8816 {
8817 /* On thumb we have to use a write-back instruction. */
8818 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8819 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8820 size = TARGET_ARM ? 16 : 0;
8821 }
8822 else
8823 {
8824 emit_move_insn (mem, reg);
8825 size = GET_MODE_SIZE (GET_MODE (reg));
8826 }
215b30b3 8827 }
9c08d1fa 8828
215b30b3 8829 /* The optimizer does not know that the call sets the function value
8830 registers we stored in the result block. We avoid problems by
8831 claiming that all hard registers are used and clobbered at this
8832 point. */
8833 emit_insn (gen_blockage ());
8834
8835 DONE;
8836 }"
8837)
9c08d1fa 8838
ccd90aaa 8839(define_expand "untyped_return"
8840 [(match_operand:BLK 0 "memory_operand" "")
8841 (match_operand 1 "" "")]
8842 "TARGET_EITHER"
8843 "
8844 {
8845 int i;
8846 rtx addr = gen_reg_rtx (Pmode);
8847 rtx mem;
8848 int size = 0;
8849
8850 emit_move_insn (addr, XEXP (operands[0], 0));
8851 mem = change_address (operands[0], BLKmode, addr);
8852
8853 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8854 {
8855 HOST_WIDE_INT offset = 0;
8856 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8857
8858 if (size != 0)
8859 emit_move_insn (addr, plus_constant (addr, size));
8860
8861 mem = change_address (mem, GET_MODE (reg), NULL);
8862 if (REGNO (reg) == R0_REGNUM)
8863 {
8864 /* On thumb we have to use a write-back instruction. */
8865 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8866 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8867 size = TARGET_ARM ? 16 : 0;
8868 }
8869 else
8870 {
8871 emit_move_insn (reg, mem);
8872 size = GET_MODE_SIZE (GET_MODE (reg));
8873 }
8874 }
8875
8876 /* Emit USE insns before the return. */
8877 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8878 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8879
8880 /* Construct the return. */
8881 expand_naked_return ();
8882
8883 DONE;
8884 }"
8885)
8886
9c08d1fa 8887;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8888;; all of memory. This blocks insns from being moved across this point.
8889
8890(define_insn "blockage"
e1159bbe 8891 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8892 "TARGET_EITHER"
9c08d1fa 8893 ""
cffb2a26 8894 [(set_attr "length" "0")
8895 (set_attr "type" "block")]
8896)
9c08d1fa 8897
f7fbdd4a 8898(define_expand "casesi"
8899 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8900 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8901 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8902 (match_operand:SI 3 "" "") ; table label
8903 (match_operand:SI 4 "" "")] ; Out of range label
25f905c2 8904 "TARGET_32BIT"
f7fbdd4a 8905 "
215b30b3 8906 {
8907 rtx reg;
8908 if (operands[1] != const0_rtx)
8909 {
8910 reg = gen_reg_rtx (SImode);
f7fbdd4a 8911
215b30b3 8912 emit_insn (gen_addsi3 (reg, operands[0],
8913 GEN_INT (-INTVAL (operands[1]))));
8914 operands[0] = reg;
8915 }
9c08d1fa 8916
215b30b3 8917 if (!const_ok_for_arm (INTVAL (operands[2])))
8918 operands[2] = force_reg (SImode, operands[2]);
8919
25f905c2 8920 if (TARGET_ARM)
8921 {
8922 emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
8923 operands[3], operands[4]));
8924 }
8925 else if (flag_pic)
8926 {
8927 emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
8928 operands[2], operands[3], operands[4]));
8929 }
8930 else
8931 {
8932 emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
8933 operands[3], operands[4]));
8934 }
215b30b3 8935 DONE;
8936 }"
8937)
f7fbdd4a 8938
f082f1c4 8939;; The USE in this pattern is needed to tell flow analysis that this is
8940;; a CASESI insn. It has no other purpose.
25f905c2 8941(define_insn "arm_casesi_internal"
f082f1c4 8942 [(parallel [(set (pc)
8943 (if_then_else
8944 (leu (match_operand:SI 0 "s_register_operand" "r")
8945 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8946 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8947 (label_ref (match_operand 2 "" ""))))
8948 (label_ref (match_operand 3 "" ""))))
bd5b4116 8949 (clobber (reg:CC CC_REGNUM))
f082f1c4 8950 (use (label_ref (match_dup 2)))])]
cffb2a26 8951 "TARGET_ARM"
f7fbdd4a 8952 "*
0d66636f 8953 if (flag_pic)
8954 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8955 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8956 "
8957 [(set_attr "conds" "clob")
8958 (set_attr "length" "12")]
8959)
9c08d1fa 8960
cffb2a26 8961(define_expand "indirect_jump"
9c08d1fa 8962 [(set (pc)
cffb2a26 8963 (match_operand:SI 0 "s_register_operand" ""))]
8964 "TARGET_EITHER"
25f905c2 8965 "
8966 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8967 address and use bx. */
8968 if (TARGET_THUMB2)
8969 {
8970 rtx tmp;
8971 tmp = gen_reg_rtx (SImode);
8972 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8973 operands[0] = tmp;
8974 }
8975 "
cffb2a26 8976)
8977
f1039640 8978;; NB Never uses BX.
cffb2a26 8979(define_insn "*arm_indirect_jump"
8980 [(set (pc)
8981 (match_operand:SI 0 "s_register_operand" "r"))]
8982 "TARGET_ARM"
8983 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8984 [(set_attr "predicable" "yes")]
cffb2a26 8985)
9c08d1fa 8986
f7fbdd4a 8987(define_insn "*load_indirect_jump"
9c08d1fa 8988 [(set (pc)
8989 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8990 "TARGET_ARM"
8991 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8992 [(set_attr "type" "load1")
61a2d04c 8993 (set_attr "pool_range" "4096")
8994 (set_attr "neg_pool_range" "4084")
0d66636f 8995 (set_attr "predicable" "yes")]
cffb2a26 8996)
8997
f1039640 8998;; NB Never uses BX.
25f905c2 8999(define_insn "*thumb1_indirect_jump"
cffb2a26 9000 [(set (pc)
9001 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 9002 "TARGET_THUMB1"
cffb2a26 9003 "mov\\tpc, %0"
9004 [(set_attr "conds" "clob")
9005 (set_attr "length" "2")]
9006)
9007
9c08d1fa 9008\f
9009;; Misc insns
9010
9011(define_insn "nop"
9012 [(const_int 0)]
cffb2a26 9013 "TARGET_EITHER"
9014 "*
25f905c2 9015 if (TARGET_UNIFIED_ASM)
9016 return \"nop\";
cffb2a26 9017 if (TARGET_ARM)
9018 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9019 return \"mov\\tr8, r8\";
9020 "
9021 [(set (attr "length")
9022 (if_then_else (eq_attr "is_thumb" "yes")
9023 (const_int 2)
9024 (const_int 4)))]
9025)
9026
9c08d1fa 9027\f
9028;; Patterns to allow combination of arithmetic, cond code and shifts
9029
f7fbdd4a 9030(define_insn "*arith_shiftsi"
9c08d1fa 9031 [(set (match_operand:SI 0 "s_register_operand" "=r")
9032 (match_operator:SI 1 "shiftable_operator"
9033 [(match_operator:SI 3 "shift_operator"
9034 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9035 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9036 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 9037 "TARGET_ARM"
6c4c2133 9038 "%i1%?\\t%0, %2, %4%S3"
344495ea 9039 [(set_attr "predicable" "yes")
331beb1a 9040 (set_attr "shift" "4")
a2cd141b 9041 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9042 (const_string "alu_shift")
9043 (const_string "alu_shift_reg")))]
6c4c2133 9044)
9c08d1fa 9045
d7863cfe 9046(define_split
9047 [(set (match_operand:SI 0 "s_register_operand" "")
9048 (match_operator:SI 1 "shiftable_operator"
9049 [(match_operator:SI 2 "shiftable_operator"
9050 [(match_operator:SI 3 "shift_operator"
9051 [(match_operand:SI 4 "s_register_operand" "")
9052 (match_operand:SI 5 "reg_or_int_operand" "")])
9053 (match_operand:SI 6 "s_register_operand" "")])
9054 (match_operand:SI 7 "arm_rhs_operand" "")]))
9055 (clobber (match_operand:SI 8 "s_register_operand" ""))]
9056 "TARGET_ARM"
9057 [(set (match_dup 8)
9058 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9059 (match_dup 6)]))
9060 (set (match_dup 0)
9061 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9062 "")
9063
f7fbdd4a 9064(define_insn "*arith_shiftsi_compare0"
bd5b4116 9065 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 9066 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9067 [(match_operator:SI 3 "shift_operator"
9068 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9069 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9070 (match_operand:SI 2 "s_register_operand" "r")])
9071 (const_int 0)))
9072 (set (match_operand:SI 0 "s_register_operand" "=r")
9073 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9074 (match_dup 2)]))]
cffb2a26 9075 "TARGET_ARM"
25f905c2 9076 "%i1%.\\t%0, %2, %4%S3"
344495ea 9077 [(set_attr "conds" "set")
331beb1a 9078 (set_attr "shift" "4")
a2cd141b 9079 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9080 (const_string "alu_shift")
9081 (const_string "alu_shift_reg")))]
0d66636f 9082)
9c08d1fa 9083
f7fbdd4a 9084(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9085 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 9086 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9087 [(match_operator:SI 3 "shift_operator"
9088 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9089 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9090 (match_operand:SI 2 "s_register_operand" "r")])
9091 (const_int 0)))
9092 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 9093 "TARGET_ARM"
25f905c2 9094 "%i1%.\\t%0, %2, %4%S3"
344495ea 9095 [(set_attr "conds" "set")
331beb1a 9096 (set_attr "shift" "4")
a2cd141b 9097 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9098 (const_string "alu_shift")
9099 (const_string "alu_shift_reg")))]
0d66636f 9100)
9c08d1fa 9101
f7fbdd4a 9102(define_insn "*sub_shiftsi"
9c08d1fa 9103 [(set (match_operand:SI 0 "s_register_operand" "=r")
9104 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9105 (match_operator:SI 2 "shift_operator"
9106 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9107 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 9108 "TARGET_ARM"
6c4c2133 9109 "sub%?\\t%0, %1, %3%S2"
344495ea 9110 [(set_attr "predicable" "yes")
331beb1a 9111 (set_attr "shift" "3")
a2cd141b 9112 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9113 (const_string "alu_shift")
9114 (const_string "alu_shift_reg")))]
6c4c2133 9115)
9c08d1fa 9116
f7fbdd4a 9117(define_insn "*sub_shiftsi_compare0"
bd5b4116 9118 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9119 (compare:CC_NOOV
9120 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9121 (match_operator:SI 2 "shift_operator"
9122 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9123 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 9124 (const_int 0)))
9c08d1fa 9125 (set (match_operand:SI 0 "s_register_operand" "=r")
9126 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9127 (match_dup 4)])))]
cffb2a26 9128 "TARGET_ARM"
25f905c2 9129 "sub%.\\t%0, %1, %3%S2"
344495ea 9130 [(set_attr "conds" "set")
a2cd141b 9131 (set_attr "shift" "3")
9132 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9133 (const_string "alu_shift")
9134 (const_string "alu_shift_reg")))]
0d66636f 9135)
9c08d1fa 9136
f7fbdd4a 9137(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9138 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9139 (compare:CC_NOOV
9140 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9141 (match_operator:SI 2 "shift_operator"
9142 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9143 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 9144 (const_int 0)))
9c08d1fa 9145 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 9146 "TARGET_ARM"
25f905c2 9147 "sub%.\\t%0, %1, %3%S2"
344495ea 9148 [(set_attr "conds" "set")
a2cd141b 9149 (set_attr "shift" "3")
9150 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9151 (const_string "alu_shift")
9152 (const_string "alu_shift_reg")))]
0d66636f 9153)
9c08d1fa 9154
9c08d1fa 9155\f
9156
f7fbdd4a 9157(define_insn "*and_scc"
9c08d1fa 9158 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9159 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9160 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9161 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9162 "TARGET_ARM"
e2348bcb 9163 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9164 [(set_attr "conds" "use")
9165 (set_attr "length" "8")]
9166)
9c08d1fa 9167
f7fbdd4a 9168(define_insn "*ior_scc"
9c08d1fa 9169 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9170 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9171 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9172 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9173 "TARGET_ARM"
e2348bcb 9174 "@
899850b0 9175 orr%d2\\t%0, %1, #1
9176 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9177 [(set_attr "conds" "use")
9178 (set_attr "length" "4,8")]
9179)
9c08d1fa 9180
f7fbdd4a 9181(define_insn "*compare_scc"
5565501b 9182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9183 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9184 [(match_operand:SI 2 "s_register_operand" "r,r")
9185 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9186 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9187 "TARGET_ARM"
9c08d1fa 9188 "*
601f584c 9189 if (operands[3] == const0_rtx)
9190 {
9191 if (GET_CODE (operands[1]) == LT)
9192 return \"mov\\t%0, %2, lsr #31\";
9193
9194 if (GET_CODE (operands[1]) == GE)
9195 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 9196
601f584c 9197 if (GET_CODE (operands[1]) == EQ)
9198 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9199 }
e2348bcb 9200
8fa3ba89 9201 if (GET_CODE (operands[1]) == NE)
9202 {
9203 if (which_alternative == 1)
9204 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9205 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9206 }
9207 if (which_alternative == 1)
9208 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9209 else
9210 output_asm_insn (\"cmp\\t%2, %3\", operands);
9211 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9212 "
9213 [(set_attr "conds" "clob")
9214 (set_attr "length" "12")]
9215)
9c08d1fa 9216
f7fbdd4a 9217(define_insn "*cond_move"
9c08d1fa 9218 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9219 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9220 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9221 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9222 (const_int 0)])
9223 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9224 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9225 "TARGET_ARM"
9c08d1fa 9226 "*
8fa3ba89 9227 if (GET_CODE (operands[3]) == NE)
9228 {
9229 if (which_alternative != 1)
9230 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9231 if (which_alternative != 0)
9232 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9233 return \"\";
9234 }
9235 if (which_alternative != 0)
9236 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9237 if (which_alternative != 1)
9238 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9239 return \"\";
9240 "
9241 [(set_attr "conds" "use")
9242 (set_attr "length" "4,4,8")]
9243)
9c08d1fa 9244
f7fbdd4a 9245(define_insn "*cond_arith"
9c08d1fa 9246 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9247 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9248 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9249 [(match_operand:SI 2 "s_register_operand" "r,r")
9250 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9251 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9252 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9253 "TARGET_ARM"
9c08d1fa 9254 "*
8fa3ba89 9255 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9256 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9257
8fa3ba89 9258 output_asm_insn (\"cmp\\t%2, %3\", operands);
9259 if (GET_CODE (operands[5]) == AND)
9260 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9261 else if (GET_CODE (operands[5]) == MINUS)
9262 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9263 else if (which_alternative != 0)
9264 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9265 return \"%i5%d4\\t%0, %1, #1\";
9266 "
9267 [(set_attr "conds" "clob")
9268 (set_attr "length" "12")]
9269)
9c08d1fa 9270
f7fbdd4a 9271(define_insn "*cond_sub"
9c08d1fa 9272 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9273 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9274 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9275 [(match_operand:SI 2 "s_register_operand" "r,r")
9276 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9277 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9278 "TARGET_ARM"
9c08d1fa 9279 "*
8fa3ba89 9280 output_asm_insn (\"cmp\\t%2, %3\", operands);
9281 if (which_alternative != 0)
9282 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9283 return \"sub%d4\\t%0, %1, #1\";
9284 "
9285 [(set_attr "conds" "clob")
9286 (set_attr "length" "8,12")]
9287)
9c08d1fa 9288
25f905c2 9289;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 9290(define_insn "*cmp_ite0"
cffb2a26 9291 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9292 (compare
9293 (if_then_else:SI
8fa3ba89 9294 (match_operator 4 "arm_comparison_operator"
aea4c774 9295 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9296 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9297 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9298 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9299 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9300 (const_int 0))
9301 (const_int 0)))]
cffb2a26 9302 "TARGET_ARM"
9c08d1fa 9303 "*
aea4c774 9304 {
8fa3ba89 9305 static const char * const opcodes[4][2] =
9306 {
9307 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9308 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9309 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9310 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9311 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9312 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9313 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9314 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9315 };
9316 int swap =
9317 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9318
9319 return opcodes[which_alternative][swap];
9320 }"
9321 [(set_attr "conds" "set")
9322 (set_attr "length" "8")]
9323)
9c08d1fa 9324
aea4c774 9325(define_insn "*cmp_ite1"
cffb2a26 9326 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9327 (compare
9328 (if_then_else:SI
8fa3ba89 9329 (match_operator 4 "arm_comparison_operator"
aea4c774 9330 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 9331 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9332 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9333 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 9334 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 9335 (const_int 1))
9336 (const_int 0)))]
cffb2a26 9337 "TARGET_ARM"
9c08d1fa 9338 "*
9c08d1fa 9339 {
215b30b3 9340 static const char * const opcodes[4][2] =
9341 {
9342 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9343 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9344 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9345 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9346 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9347 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9348 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9349 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9350 };
9351 int swap =
9352 comparison_dominates_p (GET_CODE (operands[5]),
9353 reverse_condition (GET_CODE (operands[4])));
9354
9355 return opcodes[which_alternative][swap];
9356 }"
8fa3ba89 9357 [(set_attr "conds" "set")
9358 (set_attr "length" "8")]
9359)
9c08d1fa 9360
f6c53574 9361(define_insn "*cmp_and"
9362 [(set (match_operand 6 "dominant_cc_register" "")
9363 (compare
9364 (and:SI
9365 (match_operator 4 "arm_comparison_operator"
9366 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9367 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9368 (match_operator:SI 5 "arm_comparison_operator"
9369 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9370 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9371 (const_int 0)))]
9372 "TARGET_ARM"
9373 "*
9374 {
35823b64 9375 static const char *const opcodes[4][2] =
f6c53574 9376 {
9377 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9378 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9379 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9380 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9381 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9382 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9383 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9384 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9385 };
9386 int swap =
9387 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9388
9389 return opcodes[which_alternative][swap];
9390 }"
9391 [(set_attr "conds" "set")
9392 (set_attr "predicable" "no")
9393 (set_attr "length" "8")]
9394)
9395
9396(define_insn "*cmp_ior"
9397 [(set (match_operand 6 "dominant_cc_register" "")
9398 (compare
9399 (ior:SI
9400 (match_operator 4 "arm_comparison_operator"
9401 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9402 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9403 (match_operator:SI 5 "arm_comparison_operator"
9404 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9405 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9406 (const_int 0)))]
9407 "TARGET_ARM"
9408 "*
9409{
35823b64 9410 static const char *const opcodes[4][2] =
f6c53574 9411 {
9412 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9413 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9414 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9415 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9416 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9417 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9418 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9419 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9420 };
9421 int swap =
9422 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9423
9424 return opcodes[which_alternative][swap];
9425}
9426"
9427 [(set_attr "conds" "set")
9428 (set_attr "length" "8")]
9429)
9430
3c5afce6 9431(define_insn_and_split "*ior_scc_scc"
9432 [(set (match_operand:SI 0 "s_register_operand" "=r")
9433 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9434 [(match_operand:SI 1 "s_register_operand" "r")
9435 (match_operand:SI 2 "arm_add_operand" "rIL")])
9436 (match_operator:SI 6 "arm_comparison_operator"
9437 [(match_operand:SI 4 "s_register_operand" "r")
9438 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9439 (clobber (reg:CC CC_REGNUM))]
9440 "TARGET_ARM
9441 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9442 != CCmode)"
9443 "#"
9444 "TARGET_ARM && reload_completed"
9445 [(set (match_dup 7)
9446 (compare
9447 (ior:SI
9448 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9449 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9450 (const_int 0)))
9451 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9452 "operands[7]
9453 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9454 DOM_CC_X_OR_Y),
601f584c 9455 CC_REGNUM);"
9456 [(set_attr "conds" "clob")
9457 (set_attr "length" "16")])
9458
9459; If the above pattern is followed by a CMP insn, then the compare is
9460; redundant, since we can rework the conditional instruction that follows.
9461(define_insn_and_split "*ior_scc_scc_cmp"
9462 [(set (match_operand 0 "dominant_cc_register" "")
9463 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9464 [(match_operand:SI 1 "s_register_operand" "r")
9465 (match_operand:SI 2 "arm_add_operand" "rIL")])
9466 (match_operator:SI 6 "arm_comparison_operator"
9467 [(match_operand:SI 4 "s_register_operand" "r")
9468 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9469 (const_int 0)))
9470 (set (match_operand:SI 7 "s_register_operand" "=r")
9471 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9472 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9473 "TARGET_ARM"
9474 "#"
9475 "TARGET_ARM && reload_completed"
9476 [(set (match_dup 0)
9477 (compare
9478 (ior:SI
9479 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9480 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9481 (const_int 0)))
9482 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9483 ""
9484 [(set_attr "conds" "set")
9485 (set_attr "length" "16")])
3c5afce6 9486
9487(define_insn_and_split "*and_scc_scc"
9488 [(set (match_operand:SI 0 "s_register_operand" "=r")
9489 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9490 [(match_operand:SI 1 "s_register_operand" "r")
9491 (match_operand:SI 2 "arm_add_operand" "rIL")])
9492 (match_operator:SI 6 "arm_comparison_operator"
9493 [(match_operand:SI 4 "s_register_operand" "r")
9494 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9495 (clobber (reg:CC CC_REGNUM))]
9496 "TARGET_ARM
9497 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9498 != CCmode)"
9499 "#"
601f584c 9500 "TARGET_ARM && reload_completed
9501 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9502 != CCmode)"
3c5afce6 9503 [(set (match_dup 7)
9504 (compare
9505 (and:SI
9506 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9507 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9508 (const_int 0)))
9509 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9510 "operands[7]
9511 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9512 DOM_CC_X_AND_Y),
601f584c 9513 CC_REGNUM);"
9514 [(set_attr "conds" "clob")
9515 (set_attr "length" "16")])
9516
9517; If the above pattern is followed by a CMP insn, then the compare is
9518; redundant, since we can rework the conditional instruction that follows.
9519(define_insn_and_split "*and_scc_scc_cmp"
9520 [(set (match_operand 0 "dominant_cc_register" "")
9521 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9522 [(match_operand:SI 1 "s_register_operand" "r")
9523 (match_operand:SI 2 "arm_add_operand" "rIL")])
9524 (match_operator:SI 6 "arm_comparison_operator"
9525 [(match_operand:SI 4 "s_register_operand" "r")
9526 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9527 (const_int 0)))
9528 (set (match_operand:SI 7 "s_register_operand" "=r")
9529 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9530 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9531 "TARGET_ARM"
9532 "#"
9533 "TARGET_ARM && reload_completed"
9534 [(set (match_dup 0)
9535 (compare
9536 (and:SI
9537 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9538 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9539 (const_int 0)))
9540 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9541 ""
9542 [(set_attr "conds" "set")
9543 (set_attr "length" "16")])
9544
9545;; If there is no dominance in the comparison, then we can still save an
9546;; instruction in the AND case, since we can know that the second compare
9547;; need only zero the value if false (if true, then the value is already
9548;; correct).
9549(define_insn_and_split "*and_scc_scc_nodom"
9550 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9551 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9552 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9553 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9554 (match_operator:SI 6 "arm_comparison_operator"
9555 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9556 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9557 (clobber (reg:CC CC_REGNUM))]
9558 "TARGET_ARM
9559 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9560 == CCmode)"
9561 "#"
9562 "TARGET_ARM && reload_completed"
9563 [(parallel [(set (match_dup 0)
9564 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9565 (clobber (reg:CC CC_REGNUM))])
9566 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9567 (set (match_dup 0)
9568 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9569 (match_dup 0)
9570 (const_int 0)))]
9571 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9572 operands[4], operands[5]),
9573 CC_REGNUM);
9574 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9575 operands[5]);"
9576 [(set_attr "conds" "clob")
9577 (set_attr "length" "20")])
3c5afce6 9578
3a0bdee0 9579(define_split
9580 [(set (reg:CC_NOOV CC_REGNUM)
9581 (compare:CC_NOOV (ior:SI
9582 (and:SI (match_operand:SI 0 "s_register_operand" "")
9583 (const_int 1))
9584 (match_operator:SI 1 "comparison_operator"
9585 [(match_operand:SI 2 "s_register_operand" "")
9586 (match_operand:SI 3 "arm_add_operand" "")]))
9587 (const_int 0)))
9588 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9589 "TARGET_ARM"
9590 [(set (match_dup 4)
9591 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9592 (match_dup 0)))
9593 (set (reg:CC_NOOV CC_REGNUM)
9594 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9595 (const_int 0)))]
9596 "")
9597
9598(define_split
9599 [(set (reg:CC_NOOV CC_REGNUM)
9600 (compare:CC_NOOV (ior:SI
9601 (match_operator:SI 1 "comparison_operator"
9602 [(match_operand:SI 2 "s_register_operand" "")
9603 (match_operand:SI 3 "arm_add_operand" "")])
9604 (and:SI (match_operand:SI 0 "s_register_operand" "")
9605 (const_int 1)))
9606 (const_int 0)))
9607 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9608 "TARGET_ARM"
9609 [(set (match_dup 4)
9610 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9611 (match_dup 0)))
9612 (set (reg:CC_NOOV CC_REGNUM)
9613 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9614 (const_int 0)))]
9615 "")
25f905c2 9616;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9617
f7fbdd4a 9618(define_insn "*negscc"
9c08d1fa 9619 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9620 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9621 [(match_operand:SI 1 "s_register_operand" "r")
9622 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9623 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9624 "TARGET_ARM"
9c08d1fa 9625 "*
2ca2ec2e 9626 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9627 return \"mov\\t%0, %1, asr #31\";
9628
9c08d1fa 9629 if (GET_CODE (operands[3]) == NE)
e2348bcb 9630 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9631
e2348bcb 9632 output_asm_insn (\"cmp\\t%1, %2\", operands);
9633 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9634 return \"mvn%d3\\t%0, #0\";
215b30b3 9635 "
8fa3ba89 9636 [(set_attr "conds" "clob")
9637 (set_attr "length" "12")]
9638)
9c08d1fa 9639
9640(define_insn "movcond"
9641 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9642 (if_then_else:SI
8fa3ba89 9643 (match_operator 5 "arm_comparison_operator"
5565501b 9644 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9645 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9646 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9647 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9648 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9649 "TARGET_ARM"
9c08d1fa 9650 "*
9651 if (GET_CODE (operands[5]) == LT
9652 && (operands[4] == const0_rtx))
9653 {
5565501b 9654 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9655 {
9c08d1fa 9656 if (operands[2] == const0_rtx)
e2348bcb 9657 return \"and\\t%0, %1, %3, asr #31\";
9658 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9659 }
9660 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9661 {
9c08d1fa 9662 if (operands[1] == const0_rtx)
e2348bcb 9663 return \"bic\\t%0, %2, %3, asr #31\";
9664 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9665 }
9666 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9667 are constants. */
9c08d1fa 9668 }
e2348bcb 9669
9c08d1fa 9670 if (GET_CODE (operands[5]) == GE
9671 && (operands[4] == const0_rtx))
9672 {
9673 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9674 {
9c08d1fa 9675 if (operands[2] == const0_rtx)
e2348bcb 9676 return \"bic\\t%0, %1, %3, asr #31\";
9677 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9678 }
9679 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9680 {
9c08d1fa 9681 if (operands[1] == const0_rtx)
e2348bcb 9682 return \"and\\t%0, %2, %3, asr #31\";
9683 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9684 }
9685 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9686 are constants. */
9c08d1fa 9687 }
9688 if (GET_CODE (operands[4]) == CONST_INT
9689 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9690 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9691 else
e2348bcb 9692 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9693 if (which_alternative != 0)
e2348bcb 9694 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9695 if (which_alternative != 1)
e2348bcb 9696 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9697 return \"\";
215b30b3 9698 "
8fa3ba89 9699 [(set_attr "conds" "clob")
9700 (set_attr "length" "8,8,12")]
9701)
9c08d1fa 9702
25f905c2 9703;; ??? The patterns below need checking for Thumb-2 usefulness.
9704
8a18b90c 9705(define_insn "*ifcompare_plus_move"
9706 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9707 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9708 [(match_operand:SI 4 "s_register_operand" "r,r")
9709 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9710 (plus:SI
9711 (match_operand:SI 2 "s_register_operand" "r,r")
9712 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9713 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9714 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9715 "TARGET_ARM"
8a18b90c 9716 "#"
8fa3ba89 9717 [(set_attr "conds" "clob")
9718 (set_attr "length" "8,12")]
9719)
8a18b90c 9720
9721(define_insn "*if_plus_move"
129a2fe4 9722 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9723 (if_then_else:SI
8fa3ba89 9724 (match_operator 4 "arm_comparison_operator"
8a18b90c 9725 [(match_operand 5 "cc_register" "") (const_int 0)])
9726 (plus:SI
129a2fe4 9727 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9728 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9729 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9730 "TARGET_ARM"
8a18b90c 9731 "@
9732 add%d4\\t%0, %2, %3
9733 sub%d4\\t%0, %2, #%n3
9734 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9735 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9736 [(set_attr "conds" "use")
9737 (set_attr "length" "4,4,8,8")
9738 (set_attr "type" "*,*,*,*")]
9739)
8a18b90c 9740
9741(define_insn "*ifcompare_move_plus"
5565501b 9742 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9743 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9744 [(match_operand:SI 4 "s_register_operand" "r,r")
9745 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9746 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9747 (plus:SI
9748 (match_operand:SI 2 "s_register_operand" "r,r")
9749 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9750 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9751 "TARGET_ARM"
8a18b90c 9752 "#"
8fa3ba89 9753 [(set_attr "conds" "clob")
9754 (set_attr "length" "8,12")]
9755)
8a18b90c 9756
9757(define_insn "*if_move_plus"
129a2fe4 9758 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9759 (if_then_else:SI
8fa3ba89 9760 (match_operator 4 "arm_comparison_operator"
8a18b90c 9761 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9762 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9763 (plus:SI
129a2fe4 9764 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9765 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9766 "TARGET_ARM"
8a18b90c 9767 "@
9768 add%D4\\t%0, %2, %3
9769 sub%D4\\t%0, %2, #%n3
9770 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9771 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9772 [(set_attr "conds" "use")
9773 (set_attr "length" "4,4,8,8")
9774 (set_attr "type" "*,*,*,*")]
9775)
8a18b90c 9776
9777(define_insn "*ifcompare_arith_arith"
9778 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9779 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9780 [(match_operand:SI 5 "s_register_operand" "r")
9781 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9782 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9783 [(match_operand:SI 1 "s_register_operand" "r")
9784 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9785 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9786 [(match_operand:SI 3 "s_register_operand" "r")
9787 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9788 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9789 "TARGET_ARM"
8a18b90c 9790 "#"
8fa3ba89 9791 [(set_attr "conds" "clob")
9792 (set_attr "length" "12")]
9793)
9c08d1fa 9794
8a18b90c 9795(define_insn "*if_arith_arith"
9796 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9797 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9798 [(match_operand 8 "cc_register" "") (const_int 0)])
9799 (match_operator:SI 6 "shiftable_operator"
9800 [(match_operand:SI 1 "s_register_operand" "r")
9801 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9802 (match_operator:SI 7 "shiftable_operator"
9803 [(match_operand:SI 3 "s_register_operand" "r")
9804 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9805 "TARGET_ARM"
8a18b90c 9806 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9807 [(set_attr "conds" "use")
9808 (set_attr "length" "8")]
9809)
8a18b90c 9810
f7fbdd4a 9811(define_insn "*ifcompare_arith_move"
9c08d1fa 9812 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9813 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9814 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9815 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9816 (match_operator:SI 7 "shiftable_operator"
9817 [(match_operand:SI 4 "s_register_operand" "r,r")
9818 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9819 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9820 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9821 "TARGET_ARM"
9c08d1fa 9822 "*
9c08d1fa 9823 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9824 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9825 everything is in registers then we can do this in two instructions. */
9c08d1fa 9826 if (operands[3] == const0_rtx
9827 && GET_CODE (operands[7]) != AND
9828 && GET_CODE (operands[5]) == REG
9829 && GET_CODE (operands[1]) == REG
9830 && REGNO (operands[1]) == REGNO (operands[4])
9831 && REGNO (operands[4]) != REGNO (operands[0]))
9832 {
9833 if (GET_CODE (operands[6]) == LT)
40dbec34 9834 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9835 else if (GET_CODE (operands[6]) == GE)
40dbec34 9836 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9837 }
9838 if (GET_CODE (operands[3]) == CONST_INT
9839 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9840 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9841 else
e2348bcb 9842 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9843 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9844 if (which_alternative != 0)
129a2fe4 9845 return \"mov%D6\\t%0, %1\";
9c08d1fa 9846 return \"\";
215b30b3 9847 "
8fa3ba89 9848 [(set_attr "conds" "clob")
9849 (set_attr "length" "8,12")]
9850)
9c08d1fa 9851
8a18b90c 9852(define_insn "*if_arith_move"
129a2fe4 9853 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9854 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9855 [(match_operand 6 "cc_register" "") (const_int 0)])
9856 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9857 [(match_operand:SI 2 "s_register_operand" "r,r")
9858 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9859 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9860 "TARGET_ARM"
8a18b90c 9861 "@
9862 %I5%d4\\t%0, %2, %3
129a2fe4 9863 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9864 [(set_attr "conds" "use")
9865 (set_attr "length" "4,8")
9866 (set_attr "type" "*,*")]
9867)
8a18b90c 9868
f7fbdd4a 9869(define_insn "*ifcompare_move_arith"
9c08d1fa 9870 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9871 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9872 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9873 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9874 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9875 (match_operator:SI 7 "shiftable_operator"
9876 [(match_operand:SI 2 "s_register_operand" "r,r")
9877 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9878 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9879 "TARGET_ARM"
9c08d1fa 9880 "*
9c08d1fa 9881 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9882 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9883 everything is in registers then we can do this in two instructions */
9884 if (operands[5] == const0_rtx
9885 && GET_CODE (operands[7]) != AND
9886 && GET_CODE (operands[3]) == REG
9887 && GET_CODE (operands[1]) == REG
9888 && REGNO (operands[1]) == REGNO (operands[2])
9889 && REGNO (operands[2]) != REGNO (operands[0]))
9890 {
9891 if (GET_CODE (operands[6]) == GE)
40dbec34 9892 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9893 else if (GET_CODE (operands[6]) == LT)
40dbec34 9894 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9895 }
40dbec34 9896
9c08d1fa 9897 if (GET_CODE (operands[5]) == CONST_INT
9898 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9899 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9900 else
e2348bcb 9901 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9902
9c08d1fa 9903 if (which_alternative != 0)
129a2fe4 9904 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9905 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9906 "
8fa3ba89 9907 [(set_attr "conds" "clob")
9908 (set_attr "length" "8,12")]
9909)
9c08d1fa 9910
8a18b90c 9911(define_insn "*if_move_arith"
129a2fe4 9912 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9913 (if_then_else:SI
8fa3ba89 9914 (match_operator 4 "arm_comparison_operator"
8a18b90c 9915 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9916 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9917 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9918 [(match_operand:SI 2 "s_register_operand" "r,r")
9919 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9920 "TARGET_ARM"
8a18b90c 9921 "@
9922 %I5%D4\\t%0, %2, %3
129a2fe4 9923 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9924 [(set_attr "conds" "use")
9925 (set_attr "length" "4,8")
9926 (set_attr "type" "*,*")]
9927)
8a18b90c 9928
9929(define_insn "*ifcompare_move_not"
9c08d1fa 9930 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9931 (if_then_else:SI
8fa3ba89 9932 (match_operator 5 "arm_comparison_operator"
8a18b90c 9933 [(match_operand:SI 3 "s_register_operand" "r,r")
9934 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9935 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9936 (not:SI
9937 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9938 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9939 "TARGET_ARM"
8a18b90c 9940 "#"
8fa3ba89 9941 [(set_attr "conds" "clob")
9942 (set_attr "length" "8,12")]
9943)
9c08d1fa 9944
8a18b90c 9945(define_insn "*if_move_not"
9946 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9947 (if_then_else:SI
8fa3ba89 9948 (match_operator 4 "arm_comparison_operator"
8a18b90c 9949 [(match_operand 3 "cc_register" "") (const_int 0)])
9950 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9951 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9952 "TARGET_ARM"
8a18b90c 9953 "@
9954 mvn%D4\\t%0, %2
9955 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9956 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9957 [(set_attr "conds" "use")
9958 (set_attr "length" "4,8,8")]
9959)
8a18b90c 9960
9961(define_insn "*ifcompare_not_move"
9c08d1fa 9962 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9963 (if_then_else:SI
8fa3ba89 9964 (match_operator 5 "arm_comparison_operator"
8a18b90c 9965 [(match_operand:SI 3 "s_register_operand" "r,r")
9966 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9967 (not:SI
9968 (match_operand:SI 2 "s_register_operand" "r,r"))
9969 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9970 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9971 "TARGET_ARM"
8a18b90c 9972 "#"
8fa3ba89 9973 [(set_attr "conds" "clob")
9974 (set_attr "length" "8,12")]
9975)
9c08d1fa 9976
8a18b90c 9977(define_insn "*if_not_move"
9978 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9979 (if_then_else:SI
8fa3ba89 9980 (match_operator 4 "arm_comparison_operator"
8a18b90c 9981 [(match_operand 3 "cc_register" "") (const_int 0)])
9982 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9983 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9984 "TARGET_ARM"
8a18b90c 9985 "@
9986 mvn%d4\\t%0, %2
9987 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9988 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9989 [(set_attr "conds" "use")
9990 (set_attr "length" "4,8,8")]
9991)
8a18b90c 9992
9993(define_insn "*ifcompare_shift_move"
9c08d1fa 9994 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9995 (if_then_else:SI
8fa3ba89 9996 (match_operator 6 "arm_comparison_operator"
8a18b90c 9997 [(match_operand:SI 4 "s_register_operand" "r,r")
9998 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9999 (match_operator:SI 7 "shift_operator"
10000 [(match_operand:SI 2 "s_register_operand" "r,r")
10001 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10002 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10003 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10004 "TARGET_ARM"
9c08d1fa 10005 "#"
8fa3ba89 10006 [(set_attr "conds" "clob")
10007 (set_attr "length" "8,12")]
10008)
9c08d1fa 10009
8a18b90c 10010(define_insn "*if_shift_move"
10011 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10012 (if_then_else:SI
8fa3ba89 10013 (match_operator 5 "arm_comparison_operator"
8a18b90c 10014 [(match_operand 6 "cc_register" "") (const_int 0)])
10015 (match_operator:SI 4 "shift_operator"
10016 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10017 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10018 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10019 "TARGET_ARM"
5565501b 10020 "@
8a18b90c 10021 mov%d5\\t%0, %2%S4
10022 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10023 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10024 [(set_attr "conds" "use")
331beb1a 10025 (set_attr "shift" "2")
a2cd141b 10026 (set_attr "length" "4,8,8")
10027 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10028 (const_string "alu_shift")
10029 (const_string "alu_shift_reg")))]
8fa3ba89 10030)
5565501b 10031
8a18b90c 10032(define_insn "*ifcompare_move_shift"
10033 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10034 (if_then_else:SI
8fa3ba89 10035 (match_operator 6 "arm_comparison_operator"
8a18b90c 10036 [(match_operand:SI 4 "s_register_operand" "r,r")
10037 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10038 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10039 (match_operator:SI 7 "shift_operator"
8a18b90c 10040 [(match_operand:SI 2 "s_register_operand" "r,r")
10041 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10042 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10043 "TARGET_ARM"
8a18b90c 10044 "#"
8fa3ba89 10045 [(set_attr "conds" "clob")
10046 (set_attr "length" "8,12")]
10047)
5565501b 10048
8a18b90c 10049(define_insn "*if_move_shift"
10050 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10051 (if_then_else:SI
8fa3ba89 10052 (match_operator 5 "arm_comparison_operator"
8a18b90c 10053 [(match_operand 6 "cc_register" "") (const_int 0)])
10054 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10055 (match_operator:SI 4 "shift_operator"
10056 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10057 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10058 "TARGET_ARM"
5565501b 10059 "@
8a18b90c 10060 mov%D5\\t%0, %2%S4
10061 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10062 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10063 [(set_attr "conds" "use")
331beb1a 10064 (set_attr "shift" "2")
a2cd141b 10065 (set_attr "length" "4,8,8")
10066 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10067 (const_string "alu_shift")
10068 (const_string "alu_shift_reg")))]
8fa3ba89 10069)
9c08d1fa 10070
f7fbdd4a 10071(define_insn "*ifcompare_shift_shift"
8a18b90c 10072 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10073 (if_then_else:SI
8fa3ba89 10074 (match_operator 7 "arm_comparison_operator"
8a18b90c 10075 [(match_operand:SI 5 "s_register_operand" "r")
10076 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10077 (match_operator:SI 8 "shift_operator"
8a18b90c 10078 [(match_operand:SI 1 "s_register_operand" "r")
10079 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10080 (match_operator:SI 9 "shift_operator"
8a18b90c 10081 [(match_operand:SI 3 "s_register_operand" "r")
10082 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10083 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10084 "TARGET_ARM"
8a18b90c 10085 "#"
8fa3ba89 10086 [(set_attr "conds" "clob")
10087 (set_attr "length" "12")]
10088)
9c08d1fa 10089
8a18b90c 10090(define_insn "*if_shift_shift"
10091 [(set (match_operand:SI 0 "s_register_operand" "=r")
10092 (if_then_else:SI
8fa3ba89 10093 (match_operator 5 "arm_comparison_operator"
8a18b90c 10094 [(match_operand 8 "cc_register" "") (const_int 0)])
10095 (match_operator:SI 6 "shift_operator"
10096 [(match_operand:SI 1 "s_register_operand" "r")
10097 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10098 (match_operator:SI 7 "shift_operator"
10099 [(match_operand:SI 3 "s_register_operand" "r")
10100 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10101 "TARGET_ARM"
8a18b90c 10102 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10103 [(set_attr "conds" "use")
331beb1a 10104 (set_attr "shift" "1")
a2cd141b 10105 (set_attr "length" "8")
10106 (set (attr "type") (if_then_else
10107 (and (match_operand 2 "const_int_operand" "")
10108 (match_operand 4 "const_int_operand" ""))
10109 (const_string "alu_shift")
10110 (const_string "alu_shift_reg")))]
8fa3ba89 10111)
8a18b90c 10112
f7fbdd4a 10113(define_insn "*ifcompare_not_arith"
8a18b90c 10114 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10115 (if_then_else:SI
8fa3ba89 10116 (match_operator 6 "arm_comparison_operator"
8a18b90c 10117 [(match_operand:SI 4 "s_register_operand" "r")
10118 (match_operand:SI 5 "arm_add_operand" "rIL")])
10119 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10120 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10121 [(match_operand:SI 2 "s_register_operand" "r")
10122 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10123 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10124 "TARGET_ARM"
8a18b90c 10125 "#"
8fa3ba89 10126 [(set_attr "conds" "clob")
10127 (set_attr "length" "12")]
10128)
9c08d1fa 10129
8a18b90c 10130(define_insn "*if_not_arith"
10131 [(set (match_operand:SI 0 "s_register_operand" "=r")
10132 (if_then_else:SI
8fa3ba89 10133 (match_operator 5 "arm_comparison_operator"
8a18b90c 10134 [(match_operand 4 "cc_register" "") (const_int 0)])
10135 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10136 (match_operator:SI 6 "shiftable_operator"
10137 [(match_operand:SI 2 "s_register_operand" "r")
10138 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10139 "TARGET_ARM"
8a18b90c 10140 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10141 [(set_attr "conds" "use")
10142 (set_attr "length" "8")]
10143)
8a18b90c 10144
10145(define_insn "*ifcompare_arith_not"
10146 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10147 (if_then_else:SI
8fa3ba89 10148 (match_operator 6 "arm_comparison_operator"
8a18b90c 10149 [(match_operand:SI 4 "s_register_operand" "r")
10150 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10151 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10152 [(match_operand:SI 2 "s_register_operand" "r")
10153 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10154 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10155 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10156 "TARGET_ARM"
8a18b90c 10157 "#"
8fa3ba89 10158 [(set_attr "conds" "clob")
10159 (set_attr "length" "12")]
10160)
9c08d1fa 10161
8a18b90c 10162(define_insn "*if_arith_not"
10163 [(set (match_operand:SI 0 "s_register_operand" "=r")
10164 (if_then_else:SI
8fa3ba89 10165 (match_operator 5 "arm_comparison_operator"
8a18b90c 10166 [(match_operand 4 "cc_register" "") (const_int 0)])
10167 (match_operator:SI 6 "shiftable_operator"
10168 [(match_operand:SI 2 "s_register_operand" "r")
10169 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10170 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10171 "TARGET_ARM"
8a18b90c 10172 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10173 [(set_attr "conds" "use")
10174 (set_attr "length" "8")]
10175)
8a18b90c 10176
f7fbdd4a 10177(define_insn "*ifcompare_neg_move"
8a18b90c 10178 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10179 (if_then_else:SI
8fa3ba89 10180 (match_operator 5 "arm_comparison_operator"
8a18b90c 10181 [(match_operand:SI 3 "s_register_operand" "r,r")
10182 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10183 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10184 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10185 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10186 "TARGET_ARM"
8a18b90c 10187 "#"
8fa3ba89 10188 [(set_attr "conds" "clob")
10189 (set_attr "length" "8,12")]
10190)
8a18b90c 10191
10192(define_insn "*if_neg_move"
10193 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10194 (if_then_else:SI
8fa3ba89 10195 (match_operator 4 "arm_comparison_operator"
8a18b90c 10196 [(match_operand 3 "cc_register" "") (const_int 0)])
10197 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10198 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10199 "TARGET_ARM"
8a18b90c 10200 "@
10201 rsb%d4\\t%0, %2, #0
10202 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10203 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10204 [(set_attr "conds" "use")
10205 (set_attr "length" "4,8,8")]
10206)
9c08d1fa 10207
f7fbdd4a 10208(define_insn "*ifcompare_move_neg"
8a18b90c 10209 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10210 (if_then_else:SI
8fa3ba89 10211 (match_operator 5 "arm_comparison_operator"
8a18b90c 10212 [(match_operand:SI 3 "s_register_operand" "r,r")
10213 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10214 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10215 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10216 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10217 "TARGET_ARM"
8a18b90c 10218 "#"
8fa3ba89 10219 [(set_attr "conds" "clob")
10220 (set_attr "length" "8,12")]
10221)
8a18b90c 10222
10223(define_insn "*if_move_neg"
10224 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10225 (if_then_else:SI
8fa3ba89 10226 (match_operator 4 "arm_comparison_operator"
8a18b90c 10227 [(match_operand 3 "cc_register" "") (const_int 0)])
10228 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10229 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10230 "TARGET_ARM"
8a18b90c 10231 "@
10232 rsb%D4\\t%0, %2, #0
10233 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10234 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10235 [(set_attr "conds" "use")
10236 (set_attr "length" "4,8,8")]
10237)
9c08d1fa 10238
f7fbdd4a 10239(define_insn "*arith_adjacentmem"
9c08d1fa 10240 [(set (match_operand:SI 0 "s_register_operand" "=r")
10241 (match_operator:SI 1 "shiftable_operator"
10242 [(match_operand:SI 2 "memory_operand" "m")
10243 (match_operand:SI 3 "memory_operand" "m")]))
10244 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10245 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10246 "*
215b30b3 10247 {
10248 rtx ldm[3];
10249 rtx arith[4];
94dee231 10250 rtx base_reg;
10251 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10252
215b30b3 10253 if (REGNO (operands[0]) > REGNO (operands[4]))
10254 {
10255 ldm[1] = operands[4];
10256 ldm[2] = operands[0];
10257 }
10258 else
10259 {
10260 ldm[1] = operands[0];
10261 ldm[2] = operands[4];
10262 }
94dee231 10263
10264 base_reg = XEXP (operands[2], 0);
10265
10266 if (!REG_P (base_reg))
10267 {
10268 val1 = INTVAL (XEXP (base_reg, 1));
10269 base_reg = XEXP (base_reg, 0);
10270 }
10271
10272 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10273 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10274
215b30b3 10275 arith[0] = operands[0];
10276 arith[3] = operands[1];
94dee231 10277
215b30b3 10278 if (val1 < val2)
10279 {
10280 arith[1] = ldm[1];
10281 arith[2] = ldm[2];
10282 }
10283 else
10284 {
10285 arith[1] = ldm[2];
10286 arith[2] = ldm[1];
10287 }
94dee231 10288
10289 ldm[0] = base_reg;
10290 if (val1 !=0 && val2 != 0)
215b30b3 10291 {
cdb1295a 10292 rtx ops[3];
10293
94dee231 10294 if (val1 == 4 || val2 == 4)
10295 /* Other val must be 8, since we know they are adjacent and neither
10296 is zero. */
25f905c2 10297 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10298 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10299 {
94dee231 10300 ldm[0] = ops[0] = operands[4];
10301 ops[1] = base_reg;
10302 ops[2] = GEN_INT (val1);
10303 output_add_immediate (ops);
10304 if (val1 < val2)
25f905c2 10305 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10306 else
25f905c2 10307 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10308 }
cdb1295a 10309 else
10310 {
10311 /* Offset is out of range for a single add, so use two ldr. */
10312 ops[0] = ldm[1];
10313 ops[1] = base_reg;
10314 ops[2] = GEN_INT (val1);
10315 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10316 ops[0] = ldm[2];
10317 ops[2] = GEN_INT (val2);
10318 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10319 }
215b30b3 10320 }
94dee231 10321 else if (val1 != 0)
215b30b3 10322 {
215b30b3 10323 if (val1 < val2)
25f905c2 10324 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10325 else
25f905c2 10326 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10327 }
10328 else
10329 {
215b30b3 10330 if (val1 < val2)
25f905c2 10331 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10332 else
25f905c2 10333 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10334 }
10335 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10336 return \"\";
10337 }"
10338 [(set_attr "length" "12")
10339 (set_attr "predicable" "yes")
a2cd141b 10340 (set_attr "type" "load1")]
215b30b3 10341)
9c08d1fa 10342
9c08d1fa 10343; This pattern is never tried by combine, so do it as a peephole
10344
a0f94409 10345(define_peephole2
372575c7 10346 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10347 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10348 (set (reg:CC CC_REGNUM)
aea4c774 10349 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10350 "TARGET_ARM"
a0f94409 10351 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10352 (set (match_dup 0) (match_dup 1))])]
10353 ""
0d66636f 10354)
9c08d1fa 10355
675d848d 10356; Peepholes to spot possible load- and store-multiples, if the ordering is
10357; reversed, check that the memory references aren't volatile.
9c08d1fa 10358
10359(define_peephole
aaa37ad6 10360 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10361 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10362 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10363 (match_operand:SI 5 "memory_operand" "m"))
aaa37ad6 10364 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10365 (match_operand:SI 6 "memory_operand" "m"))
aaa37ad6 10366 (set (match_operand:SI 3 "s_register_operand" "=rk")
aea4c774 10367 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 10368 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10369 "*
10370 return emit_ldm_seq (operands, 4);
215b30b3 10371 "
10372)
9c08d1fa 10373
10374(define_peephole
aaa37ad6 10375 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10376 (match_operand:SI 3 "memory_operand" "m"))
aaa37ad6 10377 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10378 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10379 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10380 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 10381 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10382 "*
10383 return emit_ldm_seq (operands, 3);
215b30b3 10384 "
10385)
9c08d1fa 10386
10387(define_peephole
aaa37ad6 10388 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10389 (match_operand:SI 2 "memory_operand" "m"))
aaa37ad6 10390 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10391 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 10392 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10393 "*
10394 return emit_ldm_seq (operands, 2);
215b30b3 10395 "
10396)
9c08d1fa 10397
10398(define_peephole
aea4c774 10399 [(set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10400 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10401 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10402 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10403 (set (match_operand:SI 6 "memory_operand" "=m")
aaa37ad6 10404 (match_operand:SI 2 "s_register_operand" "rk"))
aea4c774 10405 (set (match_operand:SI 7 "memory_operand" "=m")
aaa37ad6 10406 (match_operand:SI 3 "s_register_operand" "rk"))]
cffb2a26 10407 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10408 "*
10409 return emit_stm_seq (operands, 4);
215b30b3 10410 "
10411)
9c08d1fa 10412
10413(define_peephole
aea4c774 10414 [(set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10415 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10416 (set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10417 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10418 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10419 (match_operand:SI 2 "s_register_operand" "rk"))]
cffb2a26 10420 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10421 "*
10422 return emit_stm_seq (operands, 3);
215b30b3 10423 "
10424)
9c08d1fa 10425
10426(define_peephole
aea4c774 10427 [(set (match_operand:SI 2 "memory_operand" "=m")
aaa37ad6 10428 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10429 (set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10430 (match_operand:SI 1 "s_register_operand" "rk"))]
cffb2a26 10431 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10432 "*
10433 return emit_stm_seq (operands, 2);
215b30b3 10434 "
10435)
9c08d1fa 10436
9c08d1fa 10437(define_split
10438 [(set (match_operand:SI 0 "s_register_operand" "")
10439 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10440 (const_int 0))
8fa3ba89 10441 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10442 [(match_operand:SI 3 "s_register_operand" "")
10443 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10444 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10445 "TARGET_ARM"
9c08d1fa 10446 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10447 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10448 (match_dup 5)))]
215b30b3 10449 ""
10450)
9c08d1fa 10451
aea4c774 10452;; This split can be used because CC_Z mode implies that the following
10453;; branch will be an equality, or an unsigned inequality, so the sign
10454;; extension is not needed.
9c08d1fa 10455
aea4c774 10456(define_split
bd5b4116 10457 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10458 (compare:CC_Z
10459 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10460 (const_int 24))
aea4c774 10461 (match_operand 1 "const_int_operand" "")))
10462 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10463 "TARGET_ARM
10464 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10465 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10466 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10467 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10468 "
9c08d1fa 10469 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10470 "
10471)
25f905c2 10472;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10473
87b22bf7 10474(define_expand "prologue"
10475 [(clobber (const_int 0))]
cffb2a26 10476 "TARGET_EITHER"
25f905c2 10477 "if (TARGET_32BIT)
cffb2a26 10478 arm_expand_prologue ();
10479 else
25f905c2 10480 thumb1_expand_prologue ();
87b22bf7 10481 DONE;
cffb2a26 10482 "
10483)
87b22bf7 10484
56d27660 10485(define_expand "epilogue"
4c44712e 10486 [(clobber (const_int 0))]
cffb2a26 10487 "TARGET_EITHER"
56d27660 10488 "
18d50ae6 10489 if (crtl->calls_eh_return)
4c44712e 10490 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10491 if (TARGET_THUMB1)
10492 thumb1_expand_epilogue ();
cffb2a26 10493 else if (USE_RETURN_INSN (FALSE))
56d27660 10494 {
10495 emit_jump_insn (gen_return ());
10496 DONE;
10497 }
cffb2a26 10498 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10499 gen_rtvec (1,
10500 gen_rtx_RETURN (VOIDmode)),
e1159bbe 10501 VUNSPEC_EPILOGUE));
cffb2a26 10502 DONE;
10503 "
10504)
56d27660 10505
ef5651d0 10506;; Note - although unspec_volatile's USE all hard registers,
10507;; USEs are ignored after relaod has completed. Thus we need
10508;; to add an unspec of the link register to ensure that flow
10509;; does not think that it is unused by the sibcall branch that
10510;; will replace the standard function epilogue.
1c494086 10511(define_insn "sibcall_epilogue"
ef5651d0 10512 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10513 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10514 "TARGET_32BIT"
1c494086 10515 "*
ffc9d00c 10516 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10517 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10518 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10519 "
10520;; Length is absolute worst case
10521 [(set_attr "length" "44")
defc47cf 10522 (set_attr "type" "block")
10523 ;; We don't clobber the conditions, but the potential length of this
10524 ;; operation is sufficient to make conditionalizing the sequence
10525 ;; unlikely to be profitable.
10526 (set_attr "conds" "clob")]
1c494086 10527)
10528
cffb2a26 10529(define_insn "*epilogue_insns"
e1159bbe 10530 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10531 "TARGET_EITHER"
56d27660 10532 "*
25f905c2 10533 if (TARGET_32BIT)
ffc9d00c 10534 return arm_output_epilogue (NULL);
25f905c2 10535 else /* TARGET_THUMB1 */
cffb2a26 10536 return thumb_unexpanded_epilogue ();
10537 "
215b30b3 10538 ; Length is absolute worst case
cffb2a26 10539 [(set_attr "length" "44")
defc47cf 10540 (set_attr "type" "block")
10541 ;; We don't clobber the conditions, but the potential length of this
10542 ;; operation is sufficient to make conditionalizing the sequence
10543 ;; unlikely to be profitable.
10544 (set_attr "conds" "clob")]
cffb2a26 10545)
10546
10547(define_expand "eh_epilogue"
7db9af5d 10548 [(use (match_operand:SI 0 "register_operand" ""))
10549 (use (match_operand:SI 1 "register_operand" ""))
10550 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10551 "TARGET_EITHER"
10552 "
215b30b3 10553 {
10554 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10555 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10556 {
10557 rtx ra = gen_rtx_REG (Pmode, 2);
10558
10559 emit_move_insn (ra, operands[2]);
10560 operands[2] = ra;
10561 }
5cf3595a 10562 /* This is a hack -- we may have crystalized the function type too
10563 early. */
10564 cfun->machine->func_type = 0;
215b30b3 10565 }"
10566)
56d27660 10567
9c08d1fa 10568;; This split is only used during output to reduce the number of patterns
10569;; that need assembler instructions adding to them. We allowed the setting
10570;; of the conditions to be implicit during rtl generation so that
10571;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10572;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10573;; up again here.
10574
25f905c2 10575;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10576;; conditional execution sufficient?
10577
9c08d1fa 10578(define_split
10579 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10580 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10581 [(match_operand 2 "" "") (match_operand 3 "" "")])
10582 (match_dup 0)
10583 (match_operand 4 "" "")))
bd5b4116 10584 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10585 "TARGET_ARM && reload_completed"
8fa3ba89 10586 [(set (match_dup 5) (match_dup 6))
10587 (cond_exec (match_dup 7)
10588 (set (match_dup 0) (match_dup 4)))]
10589 "
10590 {
10591 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10592 operands[2], operands[3]);
10593 enum rtx_code rc = GET_CODE (operands[1]);
10594
bd5b4116 10595 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10596 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10597 if (mode == CCFPmode || mode == CCFPEmode)
10598 rc = reverse_condition_maybe_unordered (rc);
10599 else
10600 rc = reverse_condition (rc);
10601
10602 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10603 }"
10604)
10605
10606(define_split
10607 [(set (match_operand:SI 0 "s_register_operand" "")
10608 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10609 [(match_operand 2 "" "") (match_operand 3 "" "")])
10610 (match_operand 4 "" "")
10611 (match_dup 0)))
bd5b4116 10612 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10613 "TARGET_ARM && reload_completed"
8fa3ba89 10614 [(set (match_dup 5) (match_dup 6))
10615 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10616 (set (match_dup 0) (match_dup 4)))]
10617 "
10618 {
10619 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10620 operands[2], operands[3]);
10621
bd5b4116 10622 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10623 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10624 }"
10625)
10626
10627(define_split
10628 [(set (match_operand:SI 0 "s_register_operand" "")
10629 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10630 [(match_operand 2 "" "") (match_operand 3 "" "")])
10631 (match_operand 4 "" "")
10632 (match_operand 5 "" "")))
bd5b4116 10633 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10634 "TARGET_ARM && reload_completed"
8fa3ba89 10635 [(set (match_dup 6) (match_dup 7))
10636 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10637 (set (match_dup 0) (match_dup 4)))
10638 (cond_exec (match_dup 8)
10639 (set (match_dup 0) (match_dup 5)))]
10640 "
10641 {
10642 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10643 operands[2], operands[3]);
10644 enum rtx_code rc = GET_CODE (operands[1]);
10645
bd5b4116 10646 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10647 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10648 if (mode == CCFPmode || mode == CCFPEmode)
10649 rc = reverse_condition_maybe_unordered (rc);
10650 else
10651 rc = reverse_condition (rc);
10652
10653 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10654 }"
10655)
10656
cffb2a26 10657(define_split
10658 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10659 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10660 [(match_operand:SI 2 "s_register_operand" "")
10661 (match_operand:SI 3 "arm_add_operand" "")])
10662 (match_operand:SI 4 "arm_rhs_operand" "")
10663 (not:SI
10664 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10665 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10666 "TARGET_ARM && reload_completed"
cffb2a26 10667 [(set (match_dup 6) (match_dup 7))
f6c53574 10668 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10669 (set (match_dup 0) (match_dup 4)))
10670 (cond_exec (match_dup 8)
10671 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10672 "
215b30b3 10673 {
10674 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10675 operands[2], operands[3]);
f6c53574 10676 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10677
bd5b4116 10678 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10679 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10680 if (mode == CCFPmode || mode == CCFPEmode)
10681 rc = reverse_condition_maybe_unordered (rc);
10682 else
10683 rc = reverse_condition (rc);
10684
10685 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10686 }"
10687)
cffb2a26 10688
10689(define_insn "*cond_move_not"
10690 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10691 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10692 [(match_operand 3 "cc_register" "") (const_int 0)])
10693 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10694 (not:SI
10695 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10696 "TARGET_ARM"
10697 "@
10698 mvn%D4\\t%0, %2
10699 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10700 [(set_attr "conds" "use")
10701 (set_attr "length" "4,8")]
10702)
cffb2a26 10703
9c08d1fa 10704;; The next two patterns occur when an AND operation is followed by a
10705;; scc insn sequence
10706
f7fbdd4a 10707(define_insn "*sign_extract_onebit"
9c08d1fa 10708 [(set (match_operand:SI 0 "s_register_operand" "=r")
10709 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10710 (const_int 1)
ed750274 10711 (match_operand:SI 2 "const_int_operand" "n")))
10712 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10713 "TARGET_ARM"
9c08d1fa 10714 "*
0d66636f 10715 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10716 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10717 return \"mvnne\\t%0, #0\";
10718 "
10719 [(set_attr "conds" "clob")
10720 (set_attr "length" "8")]
10721)
9c08d1fa 10722
f7fbdd4a 10723(define_insn "*not_signextract_onebit"
9c08d1fa 10724 [(set (match_operand:SI 0 "s_register_operand" "=r")
10725 (not:SI
10726 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10727 (const_int 1)
ed750274 10728 (match_operand:SI 2 "const_int_operand" "n"))))
10729 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10730 "TARGET_ARM"
9c08d1fa 10731 "*
0d66636f 10732 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10733 output_asm_insn (\"tst\\t%1, %2\", operands);
10734 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10735 return \"movne\\t%0, #0\";
10736 "
10737 [(set_attr "conds" "clob")
10738 (set_attr "length" "12")]
10739)
25f905c2 10740;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10741
0d66636f 10742;; Push multiple registers to the stack. Registers are in parallel (use ...)
10743;; expressions. For simplicity, the first register is also in the unspec
10744;; part.
f7fbdd4a 10745(define_insn "*push_multi"
87b22bf7 10746 [(match_parallel 2 "multi_register_push"
10747 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10748 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10749 UNSPEC_PUSH_MULT))])]
25f905c2 10750 "TARGET_32BIT"
87b22bf7 10751 "*
215b30b3 10752 {
10753 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10754
215b30b3 10755 /* For the StrongARM at least it is faster to
25f905c2 10756 use STR to store only a single register.
542d5028 10757 In Thumb mode always use push, and the assembler will pick
10758 something appropriate. */
25f905c2 10759 if (num_saves == 1 && TARGET_ARM)
215b30b3 10760 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10761 else
10762 {
10763 int i;
10764 char pattern[100];
ed593f11 10765
25f905c2 10766 if (TARGET_ARM)
10767 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10768 else
10769 strcpy (pattern, \"push\\t{%1\");
215b30b3 10770
6079f055 10771 for (i = 1; i < num_saves; i++)
215b30b3 10772 {
10773 strcat (pattern, \", %|\");
10774 strcat (pattern,
10775 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10776 }
10777
10778 strcat (pattern, \"}\");
10779 output_asm_insn (pattern, operands);
10780 }
10781
10782 return \"\";
10783 }"
10784 [(set_attr "type" "store4")]
10785)
f7fbdd4a 10786
4c58c898 10787(define_insn "stack_tie"
10788 [(set (mem:BLK (scratch))
aaa37ad6 10789 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10790 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10791 UNSPEC_PRLG_STK))]
10792 ""
10793 ""
10794 [(set_attr "length" "0")]
10795)
10796
3398e91d 10797;; Similarly for the floating point registers
7b1d2fc4 10798(define_insn "*push_fp_multi"
10799 [(match_parallel 2 "multi_register_push"
10800 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10801 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10802 UNSPEC_PUSH_MULT))])]
25f905c2 10803 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10804 "*
215b30b3 10805 {
10806 char pattern[100];
7b1d2fc4 10807
215b30b3 10808 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10809 output_asm_insn (pattern, operands);
10810 return \"\";
10811 }"
10812 [(set_attr "type" "f_store")]
10813)
7b1d2fc4 10814
f7fbdd4a 10815;; Special patterns for dealing with the constant pool
10816
cffb2a26 10817(define_insn "align_4"
e1159bbe 10818 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10819 "TARGET_EITHER"
f7fbdd4a 10820 "*
cffb2a26 10821 assemble_align (32);
f7fbdd4a 10822 return \"\";
cffb2a26 10823 "
10824)
f7fbdd4a 10825
755eb2b4 10826(define_insn "align_8"
10827 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10828 "TARGET_EITHER"
755eb2b4 10829 "*
10830 assemble_align (64);
10831 return \"\";
10832 "
10833)
10834
cffb2a26 10835(define_insn "consttable_end"
e1159bbe 10836 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10837 "TARGET_EITHER"
f7fbdd4a 10838 "*
cffb2a26 10839 making_const_table = FALSE;
f7fbdd4a 10840 return \"\";
cffb2a26 10841 "
10842)
f7fbdd4a 10843
cffb2a26 10844(define_insn "consttable_1"
e1159bbe 10845 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10846 "TARGET_THUMB1"
f7fbdd4a 10847 "*
cffb2a26 10848 making_const_table = TRUE;
09d688ff 10849 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10850 assemble_zeros (3);
f7fbdd4a 10851 return \"\";
cffb2a26 10852 "
10853 [(set_attr "length" "4")]
10854)
f7fbdd4a 10855
cffb2a26 10856(define_insn "consttable_2"
e1159bbe 10857 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10858 "TARGET_THUMB1"
f7fbdd4a 10859 "*
cffb2a26 10860 making_const_table = TRUE;
9b8516be 10861 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10862 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10863 assemble_zeros (2);
f7fbdd4a 10864 return \"\";
cffb2a26 10865 "
10866 [(set_attr "length" "4")]
10867)
10868
10869(define_insn "consttable_4"
e1159bbe 10870 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10871 "TARGET_EITHER"
10872 "*
10873 {
9b8516be 10874 rtx x = operands[0];
cffb2a26 10875 making_const_table = TRUE;
9b8516be 10876 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10877 {
10878 case MODE_FLOAT:
9b8516be 10879 if (GET_MODE (x) == HFmode)
10880 arm_emit_fp16_const (x);
10881 else
10882 {
10883 REAL_VALUE_TYPE r;
10884 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10885 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10886 }
10887 break;
cffb2a26 10888 default:
9b8516be 10889 assemble_integer (x, 4, BITS_PER_WORD, 1);
10890 mark_symbol_refs_as_used (x);
cffb2a26 10891 break;
10892 }
10893 return \"\";
10894 }"
10895 [(set_attr "length" "4")]
10896)
10897
10898(define_insn "consttable_8"
e1159bbe 10899 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10900 "TARGET_EITHER"
10901 "*
10902 {
10903 making_const_table = TRUE;
10904 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10905 {
10906 case MODE_FLOAT:
10907 {
badfe841 10908 REAL_VALUE_TYPE r;
10909 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10910 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10911 break;
10912 }
10913 default:
09d688ff 10914 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10915 break;
10916 }
10917 return \"\";
10918 }"
10919 [(set_attr "length" "8")]
10920)
10921
d98a3884 10922(define_insn "consttable_16"
10923 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10924 "TARGET_EITHER"
10925 "*
10926 {
10927 making_const_table = TRUE;
10928 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10929 {
10930 case MODE_FLOAT:
10931 {
10932 REAL_VALUE_TYPE r;
10933 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10934 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10935 break;
10936 }
10937 default:
10938 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10939 break;
10940 }
10941 return \"\";
10942 }"
10943 [(set_attr "length" "16")]
10944)
10945
cffb2a26 10946;; Miscellaneous Thumb patterns
10947
fd957ef3 10948(define_expand "tablejump"
7db9af5d 10949 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10950 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10951 "TARGET_THUMB1"
fd957ef3 10952 "
10953 if (flag_pic)
10954 {
10955 /* Hopefully, CSE will eliminate this copy. */
10956 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10957 rtx reg2 = gen_reg_rtx (SImode);
10958
10959 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10960 operands[0] = reg2;
10961 }
10962 "
10963)
10964
f1039640 10965;; NB never uses BX.
25f905c2 10966(define_insn "*thumb1_tablejump"
cffb2a26 10967 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10968 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10969 "TARGET_THUMB1"
fd957ef3 10970 "mov\\t%|pc, %0"
cffb2a26 10971 [(set_attr "length" "2")]
10972)
0d66636f 10973
331beb1a 10974;; V5 Instructions,
10975
8f4be2be 10976(define_insn "clzsi2"
10977 [(set (match_operand:SI 0 "s_register_operand" "=r")
10978 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10979 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10980 "clz%?\\t%0, %1"
bcaec148 10981 [(set_attr "predicable" "yes")
10982 (set_attr "insn" "clz")])
331beb1a 10983
e1159bbe 10984;; V5E instructions.
331beb1a 10985
10986(define_insn "prefetch"
f4e79814 10987 [(prefetch (match_operand:SI 0 "address_operand" "p")
10988 (match_operand:SI 1 "" "")
10989 (match_operand:SI 2 "" ""))]
25f905c2 10990 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10991 "pld\\t%a0")
331beb1a 10992
0d66636f 10993;; General predication pattern
10994
10995(define_cond_exec
10996 [(match_operator 0 "arm_comparison_operator"
10997 [(match_operand 1 "cc_register" "")
10998 (const_int 0)])]
25f905c2 10999 "TARGET_32BIT"
0d66636f 11000 ""
11001)
11002
063a05c7 11003(define_insn "prologue_use"
11004 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11005 ""
11006 "%@ %0 needed for prologue"
11007)
7db9af5d 11008
4c44712e 11009
11010;; Patterns for exception handling
11011
11012(define_expand "eh_return"
11013 [(use (match_operand 0 "general_operand" ""))]
11014 "TARGET_EITHER"
11015 "
11016 {
25f905c2 11017 if (TARGET_32BIT)
4c44712e 11018 emit_insn (gen_arm_eh_return (operands[0]));
11019 else
11020 emit_insn (gen_thumb_eh_return (operands[0]));
11021 DONE;
11022 }"
11023)
11024
11025;; We can't expand this before we know where the link register is stored.
11026(define_insn_and_split "arm_eh_return"
11027 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11028 VUNSPEC_EH_RETURN)
11029 (clobber (match_scratch:SI 1 "=&r"))]
11030 "TARGET_ARM"
11031 "#"
11032 "&& reload_completed"
11033 [(const_int 0)]
11034 "
11035 {
11036 arm_set_return_address (operands[0], operands[1]);
11037 DONE;
11038 }"
11039)
11040
11041(define_insn_and_split "thumb_eh_return"
11042 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11043 VUNSPEC_EH_RETURN)
11044 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 11045 "TARGET_THUMB1"
4c44712e 11046 "#"
11047 "&& reload_completed"
11048 [(const_int 0)]
11049 "
11050 {
11051 thumb_set_return_address (operands[0], operands[1]);
11052 DONE;
11053 }"
11054)
11055
f655717d 11056\f
11057;; TLS support
11058
11059(define_insn "load_tp_hard"
11060 [(set (match_operand:SI 0 "register_operand" "=r")
11061 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11062 "TARGET_HARD_TP"
11063 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11064 [(set_attr "predicable" "yes")]
11065)
11066
11067;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11068(define_insn "load_tp_soft"
11069 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11070 (clobber (reg:SI LR_REGNUM))
11071 (clobber (reg:SI IP_REGNUM))
11072 (clobber (reg:CC CC_REGNUM))]
11073 "TARGET_SOFT_TP"
11074 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11075 [(set_attr "conds" "clob")]
11076)
11077
7db9af5d 11078;; Load the FPA co-processor patterns
11079(include "fpa.md")
11080;; Load the Maverick co-processor patterns
11081(include "cirrus.md")
d98a3884 11082;; Vector bits common to IWMMXT and Neon
11083(include "vec-common.md")
755eb2b4 11084;; Load the Intel Wireless Multimedia Extension patterns
11085(include "iwmmxt.md")
a2cd141b 11086;; Load the VFP co-processor patterns
11087(include "vfp.md")
25f905c2 11088;; Thumb-2 patterns
11089(include "thumb2.md")
d98a3884 11090;; Neon patterns
11091(include "neon.md")
a2cd141b 11092