]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* ipa-reference.c (add_static_var): Remove redundant all_module_statics check.
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
7cf0dbf3 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
934a1e72 4;; Free Software Foundation, Inc.
b11cae9e 5;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 6;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 7;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 8
acf6ed70 9;; This file is part of GCC.
b11cae9e 10
acf6ed70 11;; GCC is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published
038d1e19 13;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 14;; option) any later version.
b11cae9e 15
acf6ed70 16;; GCC is distributed in the hope that it will be useful, but WITHOUT
17;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19;; License for more details.
b11cae9e 20
21;; You should have received a copy of the GNU General Public License
038d1e19 22;; along with GCC; see the file COPYING3. If not see
23;; <http://www.gnu.org/licenses/>.
b11cae9e 24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
9c08d1fa 27\f
e1159bbe 28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
ccd90aaa 33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
e1159bbe 35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
ccd90aaa 39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
e1159bbe 51
9c08d1fa 52;; UNSPEC Usage:
8a18b90c 53;; Note: sin and cos are no-longer used.
d98a3884 54;; Unspec constants for Neon are defined in neon.md.
e1159bbe 55
56(define_constants
57 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
58 ; operand 0 is the result,
59 ; operand 1 the parameter.
60 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
61 ; operand 0 is the result,
62 ; operand 1 the parameter.
63 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
64 ; operand 0 is the first register,
65 ; subsequent registers are in parallel (use ...)
66 ; expressions.
67 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
68 ; usage, that is, we will add the pic_register
69 ; value to it before trying to dereference it.
c0c1fba5 70 (UNSPEC_PIC_BASE 4) ; Add PC and all but the last operand together,
71 ; The last operand is the number of a PIC_LABEL
72 ; that points at the containing instruction.
2c96dc5a 73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
e1159bbe 74 ; being scheduled before the stack adjustment insn.
063a05c7 75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
79 ; register to "use".
68121397 80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
8d232dc7 81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
f655717d 93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
6cdcb15c 94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95 ; instruction stream.
2c2d2f40 96 (UNSPEC_STACK_ALIGN 22) ; Doubleword aligned stack pointer. Used to
25f905c2 97 ; generate correct unwind information.
2c2d2f40 98 (UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
bac7fc85 99 ; correctly for PIC usage.
c0c1fba5 100 (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
101 ; a given symbolic address.
e6ac8414 102 (UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
099ad98b 103 (UNSPEC_RBIT 26) ; rbit operation.
825ae2ed 104 (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
105 ; another symbolic address.
e1159bbe 106 ]
107)
108
215b30b3 109;; UNSPEC_VOLATILE Usage:
e1159bbe 110
111(define_constants
112 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
113 ; insn in the code.
114 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
115 ; instruction epilogue sequence that isn't expanded
116 ; into normal RTL. Used for both normal and sibcall
117 ; epilogues.
118 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
119 ; for inlined constants.
120 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
121 ; table.
122 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
123 ; an 8-bit object.
124 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
125 ; a 16-bit object.
126 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
127 ; a 32-bit object.
128 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
129 ; a 64-bit object.
d98a3884 130 (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
131 ; a 128-bit object.
132 (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
133 (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
134 (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
135 (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
136 (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
137 (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 138 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 139 ; handling.
e1159bbe 140 ]
141)
b11cae9e 142\f
e1159bbe 143;;---------------------------------------------------------------------------
9c08d1fa 144;; Attributes
145
215b30b3 146; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
147; generating ARM code. This is used to control the length of some insn
148; patterns that share the same RTL in both ARM and Thumb code.
1c494086 149(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 150
331beb1a 151;; Operand number of an input operand that is shifted. Zero if the
152;; given instruction does not shift one of its input operands.
331beb1a 153(define_attr "shift" "" (const_int 0))
154
3d91c5d6 155; Floating Point Unit. If we only have floating point emulation, then there
156; is no point in scheduling the floating point insns. (Well, for best
157; performance we should try and group them together).
4fea7d65 158(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 159 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 160
094e994f 161; LENGTH of an instruction (in bytes)
162(define_attr "length" "" (const_int 4))
9c08d1fa 163
56d27660 164; POOL_RANGE is how far away from a constant pool entry that this insn
165; can be placed. If the distance is zero, then this insn will never
166; reference the pool.
cffb2a26 167; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
168; before its address.
56d27660 169(define_attr "pool_range" "" (const_int 0))
cffb2a26 170(define_attr "neg_pool_range" "" (const_int 0))
56d27660 171
215b30b3 172; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 173; If such an insn references the pool, then we have no way of knowing how,
174; so use the most conservative value for pool_range.
9c08d1fa 175(define_asm_attributes
4d7a8451 176 [(set_attr "conds" "clob")
177 (set_attr "length" "4")
178 (set_attr "pool_range" "250")])
9c08d1fa 179
a2cd141b 180;; The instruction used to implement a particular pattern. This
181;; information is used by pipeline descriptions to provide accurate
182;; scheduling information.
183
184(define_attr "insn"
934a1e72 185 "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 186 (const_string "other"))
187
9c08d1fa 188; TYPE attribute is used to detect floating point instructions which, if
189; running on a co-processor can run in parallel with other, basic instructions
190; If write-buffer scheduling is enabled then it can also be used in the
191; scheduling of writes.
192
193; Classification of each insn
607978a1 194; Note: vfp.md has different meanings for some of these, and some further
195; types as well. See that file for details.
a2cd141b 196; alu any alu instruction that doesn't hit memory or fp
197; regs or have a shifted source operand
198; alu_shift any data instruction that doesn't hit memory or fp
199; regs, but has a source operand shifted by a constant
200; alu_shift_reg any data instruction that doesn't hit memory or fp
201; regs, but has a source operand shifted by a register value
f7fbdd4a 202; mult a multiply instruction
9c08d1fa 203; block blockage insn, this blocks all functional units
204; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 205; fdivd DFmode floating point division
206; fdivs SFmode floating point division
207; fmul Floating point multiply
208; ffmul Fast floating point multiply
209; farith Floating point arithmetic (4 cycle)
210; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 211; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 212; even on a machine with an fpa.
9c08d1fa 213; f_load a floating point load from memory
214; f_store a floating point store to memory
9aff9709 215; f_load[sd] single/double load from memory
216; f_store[sd] single/double store to memory
c0e1af52 217; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 218; f_mem_r a transfer of a floating point register to a real reg via mem
219; r_mem_f the reverse of f_mem_r
220; f_2_r fast transfer float to arm (no memory needed)
221; r_2_f fast transfer arm to float
c0e1af52 222; f_cvt convert floating<->integral
a2cd141b 223; branch a branch
9c08d1fa 224; call a subroutine call
a2cd141b 225; load_byte load byte(s) from memory to arm registers
226; load1 load 1 word from memory to arm registers
227; load2 load 2 words from memory to arm registers
228; load3 load 3 words from memory to arm registers
229; load4 load 4 words from memory to arm registers
230; store store 1 word to memory from arm registers
9c08d1fa 231; store2 store 2 words
232; store3 store 3 words
a2cd141b 233; store4 store 4 (or more) words
2c6c7d8b 234; Additions for Cirrus Maverick co-processor:
235; mav_farith Floating point arithmetic (4 cycle)
236; mav_dmult Double multiplies (7 cycle)
9c08d1fa 237;
bcaec148 238
9c08d1fa 239(define_attr "type"
e3879fd0 240 "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 241 (if_then_else
242 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
243 (const_string "mult")
244 (const_string "alu")))
9c08d1fa 245
9888ad6d 246; Load scheduling, set from the arm_ld_sched variable
457275b6 247; initialized by arm_override_options()
9888ad6d 248(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 249
c52acdd2 250;; Classification of NEON instructions for scheduling purposes.
251;; Do not set this attribute and the "type" attribute together in
252;; any one instruction pattern.
253(define_attr "neon_type"
254 "neon_int_1,\
255 neon_int_2,\
256 neon_int_3,\
257 neon_int_4,\
258 neon_int_5,\
259 neon_vqneg_vqabs,\
260 neon_vmov,\
261 neon_vaba,\
262 neon_vsma,\
263 neon_vaba_qqq,\
264 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
265 neon_mul_qqq_8_16_32_ddd_32,\
266 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
267 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
268 neon_mla_qqq_8_16,\
269 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
270 neon_mla_qqq_32_qqd_32_scalar,\
271 neon_mul_ddd_16_scalar_32_16_long_scalar,\
272 neon_mul_qqd_32_scalar,\
273 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
274 neon_shift_1,\
275 neon_shift_2,\
276 neon_shift_3,\
277 neon_vshl_ddd,\
278 neon_vqshl_vrshl_vqrshl_qqq,\
279 neon_vsra_vrsra,\
280 neon_fp_vadd_ddd_vabs_dd,\
281 neon_fp_vadd_qqq_vabs_qq,\
282 neon_fp_vsum,\
283 neon_fp_vmul_ddd,\
284 neon_fp_vmul_qqd,\
285 neon_fp_vmla_ddd,\
286 neon_fp_vmla_qqq,\
287 neon_fp_vmla_ddd_scalar,\
288 neon_fp_vmla_qqq_scalar,\
289 neon_fp_vrecps_vrsqrts_ddd,\
290 neon_fp_vrecps_vrsqrts_qqq,\
291 neon_bp_simple,\
292 neon_bp_2cycle,\
293 neon_bp_3cycle,\
294 neon_ldr,\
295 neon_str,\
296 neon_vld1_1_2_regs,\
297 neon_vld1_3_4_regs,\
298 neon_vld2_2_regs_vld1_vld2_all_lanes,\
299 neon_vld2_4_regs,\
300 neon_vld3_vld4,\
301 neon_vst1_1_2_regs_vst2_2_regs,\
302 neon_vst1_3_4_regs,\
303 neon_vst2_4_regs_vst3_vst4,\
304 neon_vst3_vst4,\
305 neon_vld1_vld2_lane,\
306 neon_vld3_vld4_lane,\
307 neon_vst1_vst2_lane,\
308 neon_vst3_vst4_lane,\
309 neon_vld3_vld4_all_lanes,\
310 neon_mcr,\
311 neon_mcr_2_mcrr,\
312 neon_mrc,\
313 neon_mrrc,\
314 neon_ldm_2,\
315 neon_stm_2,\
316 none"
317 (const_string "none"))
318
f7fbdd4a 319; condition codes: this one is used by final_prescan_insn to speed up
320; conditionalizing instructions. It saves having to scan the rtl to see if
321; it uses or alters the condition codes.
215b30b3 322;
f7fbdd4a 323; USE means that the condition codes are used by the insn in the process of
215b30b3 324; outputting code, this means (at present) that we can't use the insn in
325; inlined branches
326;
f7fbdd4a 327; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 328; well defined manner.
329;
f7fbdd4a 330; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 331; they are altered at all
332;
c52acdd2 333; UNCONDITIONAL means the instions can not be conditionally executed.
334;
f7fbdd4a 335; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 336; output of this insn
f7fbdd4a 337
b0694be0 338(define_attr "conds" "use,set,clob,unconditional,nocond"
f7fbdd4a 339 (if_then_else (eq_attr "type" "call")
c1a66faf 340 (const_string "clob")
c52acdd2 341 (if_then_else (eq_attr "neon_type" "none")
342 (const_string "nocond")
343 (const_string "unconditional"))))
f7fbdd4a 344
215b30b3 345; Predicable means that the insn can be conditionally executed based on
346; an automatically added predicate (additional patterns are generated by
347; gen...). We default to 'no' because no Thumb patterns match this rule
348; and not all ARM patterns do.
0d66636f 349(define_attr "predicable" "no,yes" (const_string "no"))
350
129a2fe4 351; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
352; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 353; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 354; affect the schedule).
74a71f7d 355(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 356
215b30b3 357; WRITE_CONFLICT implies that a read following an unrelated write is likely
358; to stall the processor. Used with model_wbuf above.
9c08d1fa 359(define_attr "write_conflict" "no,yes"
360 (if_then_else (eq_attr "type"
a2cd141b 361 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 362 (const_string "yes")
363 (const_string "no")))
364
215b30b3 365; Classify the insns into those that take one cycle and those that take more
366; than one on the main cpu execution unit.
f7fbdd4a 367(define_attr "core_cycles" "single,multi"
368 (if_then_else (eq_attr "type"
a2cd141b 369 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 370 (const_string "single")
371 (const_string "multi")))
372
cffb2a26 373;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 374;; distant label. Only applicable to Thumb code.
cffb2a26 375(define_attr "far_jump" "yes,no" (const_string "no"))
376
d51f92df 377
25f905c2 378;; The number of machine instructions this pattern expands to.
379;; Used for Thumb-2 conditional execution.
380(define_attr "ce_count" "" (const_int 1))
381
d51f92df 382;;---------------------------------------------------------------------------
fd781bb2 383;; Mode iterators
d51f92df 384
385; A list of modes that are exactly 64 bits in size. We use this to expand
386; some splits that are the same for all modes when operating on ARM
387; registers.
fd781bb2 388(define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
d51f92df 389
03770691 390;; The integer modes up to word size
391(define_mode_iterator QHSI [QI HI SI])
392
d51f92df 393;;---------------------------------------------------------------------------
394;; Predicates
395
9c9db025 396(include "predicates.md")
234f6557 397(include "constraints.md")
9c9db025 398
a2cd141b 399;;---------------------------------------------------------------------------
400;; Pipeline descriptions
215b30b3 401
06469f9e 402;; Processor type. This is created automatically from arm-cores.def.
403(include "arm-tune.md")
331beb1a 404
e3879fd0 405(define_attr "tune_cortexr4" "yes,no"
406 (const (if_then_else
407 (eq_attr "tune" "cortexr4,cortexr4f")
408 (const_string "yes")
409 (const_string "no"))))
410
a2cd141b 411;; True if the generic scheduling description should be used.
412
413(define_attr "generic_sched" "yes,no"
4d5cb40d 414 (const (if_then_else
036068af 415 (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
e3879fd0 416 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 417 (const_string "no")
418 (const_string "yes"))))
419
c0e1af52 420(define_attr "generic_vfp" "yes,no"
421 (const (if_then_else
422 (and (eq_attr "fpu" "vfp")
036068af 423 (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
e3879fd0 424 (eq_attr "tune_cortexr4" "no"))
c0e1af52 425 (const_string "yes")
426 (const_string "no"))))
427
a2cd141b 428(include "arm-generic.md")
429(include "arm926ejs.md")
c0e1af52 430(include "arm1020e.md")
a2cd141b 431(include "arm1026ejs.md")
432(include "arm1136jfs.md")
bcaec148 433(include "cortex-a8.md")
036068af 434(include "cortex-a9.md")
934a1e72 435(include "cortex-r4.md")
e3879fd0 436(include "cortex-r4f.md")
55e3ada8 437(include "vfp11.md")
3586df96 438
9c08d1fa 439\f
215b30b3 440;;---------------------------------------------------------------------------
e1159bbe 441;; Insn patterns
442;;
a0f94409 443;; Addition insns.
215b30b3 444
9c08d1fa 445;; Note: For DImode insns, there is normally no reason why operands should
446;; not be in the same register, what we don't want is for something being
447;; written to partially overlap something that is an input.
7d57ec45 448;; Cirrus 64bit additions should not be split because we have a native
449;; 64bit addition instructions.
9c08d1fa 450
cffb2a26 451(define_expand "adddi3"
452 [(parallel
215b30b3 453 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 454 (plus:DI (match_operand:DI 1 "s_register_operand" "")
455 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 456 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 457 "TARGET_EITHER"
458 "
a2cd141b 459 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 460 {
461 if (!cirrus_fp_register (operands[0], DImode))
462 operands[0] = force_reg (DImode, operands[0]);
463 if (!cirrus_fp_register (operands[1], DImode))
464 operands[1] = force_reg (DImode, operands[1]);
465 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
466 DONE;
467 }
468
25f905c2 469 if (TARGET_THUMB1)
cffb2a26 470 {
471 if (GET_CODE (operands[1]) != REG)
bc5a93af 472 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 473 if (GET_CODE (operands[2]) != REG)
bc5a93af 474 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 475 }
476 "
477)
478
25f905c2 479(define_insn "*thumb1_adddi3"
cffb2a26 480 [(set (match_operand:DI 0 "register_operand" "=l")
481 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 482 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 483 (clobber (reg:CC CC_REGNUM))
cffb2a26 484 ]
25f905c2 485 "TARGET_THUMB1"
cffb2a26 486 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
487 [(set_attr "length" "4")]
488)
489
a0f94409 490(define_insn_and_split "*arm_adddi3"
cffb2a26 491 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 492 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
493 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 494 (clobber (reg:CC CC_REGNUM))]
25f905c2 495 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 496 "#"
25f905c2 497 "TARGET_32BIT && reload_completed"
a0f94409 498 [(parallel [(set (reg:CC_C CC_REGNUM)
499 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
500 (match_dup 1)))
501 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
502 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
503 (plus:SI (match_dup 4) (match_dup 5))))]
504 "
505 {
506 operands[3] = gen_highpart (SImode, operands[0]);
507 operands[0] = gen_lowpart (SImode, operands[0]);
508 operands[4] = gen_highpart (SImode, operands[1]);
509 operands[1] = gen_lowpart (SImode, operands[1]);
510 operands[5] = gen_highpart (SImode, operands[2]);
511 operands[2] = gen_lowpart (SImode, operands[2]);
512 }"
cffb2a26 513 [(set_attr "conds" "clob")
514 (set_attr "length" "8")]
515)
9c08d1fa 516
a0f94409 517(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 518 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
519 (plus:DI (sign_extend:DI
97499065 520 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 521 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 522 (clobber (reg:CC CC_REGNUM))]
25f905c2 523 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 524 "#"
25f905c2 525 "TARGET_32BIT && reload_completed"
a0f94409 526 [(parallel [(set (reg:CC_C CC_REGNUM)
527 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
528 (match_dup 1)))
529 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
530 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
531 (plus:SI (ashiftrt:SI (match_dup 2)
532 (const_int 31))
533 (match_dup 4))))]
534 "
535 {
536 operands[3] = gen_highpart (SImode, operands[0]);
537 operands[0] = gen_lowpart (SImode, operands[0]);
538 operands[4] = gen_highpart (SImode, operands[1]);
539 operands[1] = gen_lowpart (SImode, operands[1]);
540 operands[2] = gen_lowpart (SImode, operands[2]);
541 }"
215b30b3 542 [(set_attr "conds" "clob")
543 (set_attr "length" "8")]
544)
9c08d1fa 545
a0f94409 546(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 547 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
548 (plus:DI (zero_extend:DI
97499065 549 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 550 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 551 (clobber (reg:CC CC_REGNUM))]
25f905c2 552 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 553 "#"
25f905c2 554 "TARGET_32BIT && reload_completed"
a0f94409 555 [(parallel [(set (reg:CC_C CC_REGNUM)
556 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
557 (match_dup 1)))
558 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
559 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
560 (plus:SI (match_dup 4) (const_int 0))))]
561 "
562 {
563 operands[3] = gen_highpart (SImode, operands[0]);
564 operands[0] = gen_lowpart (SImode, operands[0]);
565 operands[4] = gen_highpart (SImode, operands[1]);
566 operands[1] = gen_lowpart (SImode, operands[1]);
567 operands[2] = gen_lowpart (SImode, operands[2]);
568 }"
cffb2a26 569 [(set_attr "conds" "clob")
570 (set_attr "length" "8")]
571)
b11cae9e 572
87b22bf7 573(define_expand "addsi3"
cffb2a26 574 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 575 (plus:SI (match_operand:SI 1 "s_register_operand" "")
576 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 577 "TARGET_EITHER"
87b22bf7 578 "
25f905c2 579 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 580 {
96f57e36 581 arm_split_constant (PLUS, SImode, NULL_RTX,
582 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 583 optimize && can_create_pseudo_p ());
87b22bf7 584 DONE;
585 }
cffb2a26 586 "
587)
87b22bf7 588
5bd751ff 589; If there is a scratch available, this will be faster than synthesizing the
a0f94409 590; addition.
591(define_peephole2
592 [(match_scratch:SI 3 "r")
372575c7 593 (set (match_operand:SI 0 "arm_general_register_operand" "")
594 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 595 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 596 "TARGET_32BIT &&
a0f94409 597 !(const_ok_for_arm (INTVAL (operands[2]))
598 || const_ok_for_arm (-INTVAL (operands[2])))
599 && const_ok_for_arm (~INTVAL (operands[2]))"
600 [(set (match_dup 3) (match_dup 2))
601 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
602 ""
603)
87b22bf7 604
2f02c19f 605;; The r/r/k alternative is required when reloading the address
606;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
607;; put the duplicated register first, and not try the commutative version.
a0f94409 608(define_insn_and_split "*arm_addsi3"
2f02c19f 609 [(set (match_operand:SI 0 "s_register_operand" "=r, !k, r,r, !k,r")
610 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
611 (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
25f905c2 612 "TARGET_32BIT"
5565501b 613 "@
614 add%?\\t%0, %1, %2
aaa37ad6 615 add%?\\t%0, %1, %2
2f02c19f 616 add%?\\t%0, %2, %1
aaa37ad6 617 sub%?\\t%0, %1, #%n2
87b22bf7 618 sub%?\\t%0, %1, #%n2
619 #"
a3ffc315 620 "TARGET_32BIT
621 && GET_CODE (operands[2]) == CONST_INT
a0f94409 622 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 623 || const_ok_for_arm (-INTVAL (operands[2])))
624 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 625 [(clobber (const_int 0))]
626 "
96f57e36 627 arm_split_constant (PLUS, SImode, curr_insn,
628 INTVAL (operands[2]), operands[0],
a0f94409 629 operands[1], 0);
630 DONE;
631 "
2f02c19f 632 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 633 (set_attr "predicable" "yes")]
cffb2a26 634)
635
636;; Register group 'k' is a single register group containing only the stack
637;; register. Trying to reload it will always fail catastrophically,
638;; so never allow those alternatives to match if reloading is needed.
639
0bdb6455 640(define_insn_and_split "*thumb1_addsi3"
641 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
642 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
643 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
25f905c2 644 "TARGET_THUMB1"
cffb2a26 645 "*
0d66636f 646 static const char * const asms[] =
cffb2a26 647 {
648 \"add\\t%0, %0, %2\",
649 \"sub\\t%0, %0, #%n2\",
650 \"add\\t%0, %1, %2\",
651 \"add\\t%0, %0, %2\",
652 \"add\\t%0, %0, %2\",
653 \"add\\t%0, %1, %2\",
0bdb6455 654 \"add\\t%0, %1, %2\",
655 \"#\",
656 \"#\"
cffb2a26 657 };
658 if ((which_alternative == 2 || which_alternative == 6)
659 && GET_CODE (operands[2]) == CONST_INT
660 && INTVAL (operands[2]) < 0)
661 return \"sub\\t%0, %1, #%n2\";
662 return asms[which_alternative];
663 "
0bdb6455 664 "&& reload_completed && CONST_INT_P (operands[2])
665 && operands[1] != stack_pointer_rtx
666 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
667 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
668 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
669 {
670 HOST_WIDE_INT offset = INTVAL (operands[2]);
671 if (offset > 255)
672 offset = 255;
673 else if (offset < -255)
674 offset = -255;
675
676 operands[3] = GEN_INT (offset);
677 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
678 }
679 [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
cffb2a26 680)
681
682;; Reloading and elimination of the frame pointer can
683;; sometimes cause this optimization to be missed.
a0f94409 684(define_peephole2
372575c7 685 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 686 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 687 (set (match_dup 0)
372575c7 688 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 689 "TARGET_THUMB1
cffb2a26 690 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
691 && (INTVAL (operands[1]) & 3) == 0"
372575c7 692 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 693 ""
cffb2a26 694)
b11cae9e 695
25f905c2 696;; ??? Make Thumb-2 variants which prefer low regs
f7fbdd4a 697(define_insn "*addsi3_compare0"
bd5b4116 698 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 699 (compare:CC_NOOV
215b30b3 700 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
701 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 702 (const_int 0)))
703 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 704 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 705 "TARGET_32BIT"
5565501b 706 "@
25f905c2 707 add%.\\t%0, %1, %2
708 sub%.\\t%0, %1, #%n2"
cffb2a26 709 [(set_attr "conds" "set")]
710)
9c08d1fa 711
aea4c774 712(define_insn "*addsi3_compare0_scratch"
bd5b4116 713 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 714 (compare:CC_NOOV
215b30b3 715 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
716 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 717 (const_int 0)))]
25f905c2 718 "TARGET_32BIT"
cffb2a26 719 "@
720 cmn%?\\t%0, %1
721 cmp%?\\t%0, #%n1"
0d66636f 722 [(set_attr "conds" "set")]
723)
cffb2a26 724
aed179ae 725(define_insn "*compare_negsi_si"
726 [(set (reg:CC_Z CC_REGNUM)
727 (compare:CC_Z
728 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
729 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 730 "TARGET_32BIT"
aed179ae 731 "cmn%?\\t%1, %0"
0d66636f 732 [(set_attr "conds" "set")]
733)
aea4c774 734
203c488f 735;; This is the canonicalization of addsi3_compare0_for_combiner when the
736;; addend is a constant.
737(define_insn "*cmpsi2_addneg"
738 [(set (reg:CC CC_REGNUM)
739 (compare:CC
740 (match_operand:SI 1 "s_register_operand" "r,r")
741 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
742 (set (match_operand:SI 0 "s_register_operand" "=r,r")
743 (plus:SI (match_dup 1)
744 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
25f905c2 745 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 746 "@
25f905c2 747 sub%.\\t%0, %1, %2
748 add%.\\t%0, %1, #%n2"
203c488f 749 [(set_attr "conds" "set")]
750)
751
752;; Convert the sequence
753;; sub rd, rn, #1
754;; cmn rd, #1 (equivalent to cmp rd, #-1)
755;; bne dest
756;; into
757;; subs rd, rn, #1
758;; bcs dest ((unsigned)rn >= 1)
759;; similarly for the beq variant using bcc.
760;; This is a common looping idiom (while (n--))
761(define_peephole2
372575c7 762 [(set (match_operand:SI 0 "arm_general_register_operand" "")
763 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 764 (const_int -1)))
765 (set (match_operand 2 "cc_register" "")
766 (compare (match_dup 0) (const_int -1)))
767 (set (pc)
768 (if_then_else (match_operator 3 "equality_operator"
769 [(match_dup 2) (const_int 0)])
770 (match_operand 4 "" "")
771 (match_operand 5 "" "")))]
25f905c2 772 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 773 [(parallel[
774 (set (match_dup 2)
775 (compare:CC
776 (match_dup 1) (const_int 1)))
777 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
778 (set (pc)
779 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
780 (match_dup 4)
781 (match_dup 5)))]
782 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
783 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
784 ? GEU : LTU),
785 VOIDmode,
786 operands[2], const0_rtx);"
787)
788
ebcc79bc 789;; The next four insns work because they compare the result with one of
790;; the operands, and we know that the use of the condition code is
791;; either GEU or LTU, so we can use the carry flag from the addition
792;; instead of doing the compare a second time.
793(define_insn "*addsi3_compare_op1"
bd5b4116 794 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 795 (compare:CC_C
796 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
797 (match_operand:SI 2 "arm_add_operand" "rI,L"))
798 (match_dup 1)))
799 (set (match_operand:SI 0 "s_register_operand" "=r,r")
800 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 801 "TARGET_32BIT"
ebcc79bc 802 "@
25f905c2 803 add%.\\t%0, %1, %2
804 sub%.\\t%0, %1, #%n2"
0d66636f 805 [(set_attr "conds" "set")]
806)
ebcc79bc 807
808(define_insn "*addsi3_compare_op2"
bd5b4116 809 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 810 (compare:CC_C
811 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
812 (match_operand:SI 2 "arm_add_operand" "rI,L"))
813 (match_dup 2)))
5565501b 814 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 815 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 816 "TARGET_32BIT"
5565501b 817 "@
25f905c2 818 add%.\\t%0, %1, %2
819 sub%.\\t%0, %1, #%n2"
0d66636f 820 [(set_attr "conds" "set")]
821)
9c08d1fa 822
ebcc79bc 823(define_insn "*compare_addsi2_op0"
bd5b4116 824 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 825 (compare:CC_C
826 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
827 (match_operand:SI 1 "arm_add_operand" "rI,L"))
828 (match_dup 0)))]
25f905c2 829 "TARGET_32BIT"
ebcc79bc 830 "@
831 cmn%?\\t%0, %1
832 cmp%?\\t%0, #%n1"
0d66636f 833 [(set_attr "conds" "set")]
834)
ebcc79bc 835
836(define_insn "*compare_addsi2_op1"
bd5b4116 837 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 838 (compare:CC_C
839 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
840 (match_operand:SI 1 "arm_add_operand" "rI,L"))
841 (match_dup 1)))]
25f905c2 842 "TARGET_32BIT"
ebcc79bc 843 "@
844 cmn%?\\t%0, %1
845 cmp%?\\t%0, #%n1"
0d66636f 846 [(set_attr "conds" "set")]
847)
ebcc79bc 848
849(define_insn "*addsi3_carryin"
850 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 851 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 852 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
853 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
25f905c2 854 "TARGET_32BIT"
ebcc79bc 855 "adc%?\\t%0, %1, %2"
cffb2a26 856 [(set_attr "conds" "use")]
857)
ebcc79bc 858
33782ec7 859(define_insn "*addsi3_carryin_shift"
7b63a8dd 860 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 861 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 862 (plus:SI
863 (match_operator:SI 2 "shift_operator"
7b63a8dd 864 [(match_operand:SI 3 "s_register_operand" "r")
865 (match_operand:SI 4 "reg_or_int_operand" "rM")])
866 (match_operand:SI 1 "s_register_operand" "r"))))]
25f905c2 867 "TARGET_32BIT"
33782ec7 868 "adc%?\\t%0, %1, %3%S2"
a2cd141b 869 [(set_attr "conds" "use")
870 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
871 (const_string "alu_shift")
872 (const_string "alu_shift_reg")))]
33782ec7 873)
874
ebcc79bc 875(define_insn "*addsi3_carryin_alt1"
876 [(set (match_operand:SI 0 "s_register_operand" "=r")
877 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
878 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 879 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
25f905c2 880 "TARGET_32BIT"
ebcc79bc 881 "adc%?\\t%0, %1, %2"
cffb2a26 882 [(set_attr "conds" "use")]
883)
ebcc79bc 884
885(define_insn "*addsi3_carryin_alt2"
886 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 887 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 888 (match_operand:SI 1 "s_register_operand" "r"))
889 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 890 "TARGET_32BIT"
ebcc79bc 891 "adc%?\\t%0, %1, %2"
0d66636f 892 [(set_attr "conds" "use")]
893)
ebcc79bc 894
895(define_insn "*addsi3_carryin_alt3"
896 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 897 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 898 (match_operand:SI 2 "arm_rhs_operand" "rI"))
899 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 900 "TARGET_32BIT"
ebcc79bc 901 "adc%?\\t%0, %1, %2"
cffb2a26 902 [(set_attr "conds" "use")]
903)
ebcc79bc 904
25f905c2 905(define_expand "incscc"
906 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
907 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
908 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
909 (match_operand:SI 1 "s_register_operand" "0,?r")))]
910 "TARGET_32BIT"
911 ""
912)
913
914(define_insn "*arm_incscc"
9c08d1fa 915 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 916 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 917 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 918 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 919 "TARGET_ARM"
5565501b 920 "@
921 add%d2\\t%0, %1, #1
922 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 923 [(set_attr "conds" "use")
215b30b3 924 (set_attr "length" "4,8")]
925)
9c08d1fa 926
d795fb69 927; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
928(define_split
929 [(set (match_operand:SI 0 "s_register_operand" "")
930 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
931 (match_operand:SI 2 "s_register_operand" ""))
932 (const_int -1)))
933 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 934 "TARGET_32BIT"
d795fb69 935 [(set (match_dup 3) (match_dup 1))
936 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
937 "
938 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
939")
940
604f3a0a 941(define_expand "addsf3"
942 [(set (match_operand:SF 0 "s_register_operand" "")
943 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 944 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 945 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 946 "
a2cd141b 947 if (TARGET_MAVERICK
604f3a0a 948 && !cirrus_fp_register (operands[2], SFmode))
949 operands[2] = force_reg (SFmode, operands[2]);
950")
951
604f3a0a 952(define_expand "adddf3"
953 [(set (match_operand:DF 0 "s_register_operand" "")
954 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 955 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 956 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 957 "
a2cd141b 958 if (TARGET_MAVERICK
604f3a0a 959 && !cirrus_fp_register (operands[2], DFmode))
960 operands[2] = force_reg (DFmode, operands[2]);
961")
962
cffb2a26 963(define_expand "subdi3"
964 [(parallel
965 [(set (match_operand:DI 0 "s_register_operand" "")
966 (minus:DI (match_operand:DI 1 "s_register_operand" "")
967 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 968 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 969 "TARGET_EITHER"
970 "
a2cd141b 971 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 972 && TARGET_32BIT
7d57ec45 973 && cirrus_fp_register (operands[0], DImode)
974 && cirrus_fp_register (operands[1], DImode))
975 {
976 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
977 DONE;
978 }
979
25f905c2 980 if (TARGET_THUMB1)
cffb2a26 981 {
982 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 983 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 984 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 985 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 986 }
987 "
988)
989
990(define_insn "*arm_subdi3"
991 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 992 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
993 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 994 (clobber (reg:CC CC_REGNUM))]
25f905c2 995 "TARGET_32BIT"
97499065 996 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 997 [(set_attr "conds" "clob")
998 (set_attr "length" "8")]
999)
1000
1001(define_insn "*thumb_subdi3"
1002 [(set (match_operand:DI 0 "register_operand" "=l")
1003 (minus:DI (match_operand:DI 1 "register_operand" "0")
1004 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1005 (clobber (reg:CC CC_REGNUM))]
25f905c2 1006 "TARGET_THUMB1"
cffb2a26 1007 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1008 [(set_attr "length" "4")]
1009)
9c08d1fa 1010
f7fbdd4a 1011(define_insn "*subdi_di_zesidi"
cffb2a26 1012 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1013 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1014 (zero_extend:DI
cffb2a26 1015 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1016 (clobber (reg:CC CC_REGNUM))]
25f905c2 1017 "TARGET_32BIT"
97499065 1018 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1019 [(set_attr "conds" "clob")
1020 (set_attr "length" "8")]
1021)
9c08d1fa 1022
f7fbdd4a 1023(define_insn "*subdi_di_sesidi"
cffb2a26 1024 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1025 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1026 (sign_extend:DI
cffb2a26 1027 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1028 (clobber (reg:CC CC_REGNUM))]
25f905c2 1029 "TARGET_32BIT"
97499065 1030 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1031 [(set_attr "conds" "clob")
1032 (set_attr "length" "8")]
1033)
9c08d1fa 1034
f7fbdd4a 1035(define_insn "*subdi_zesidi_di"
cffb2a26 1036 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1037 (minus:DI (zero_extend:DI
cffb2a26 1038 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1039 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1040 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1041 "TARGET_ARM"
97499065 1042 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1043 [(set_attr "conds" "clob")
1044 (set_attr "length" "8")]
1045)
9c08d1fa 1046
f7fbdd4a 1047(define_insn "*subdi_sesidi_di"
cffb2a26 1048 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1049 (minus:DI (sign_extend:DI
cffb2a26 1050 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1051 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1052 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1053 "TARGET_ARM"
97499065 1054 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1055 [(set_attr "conds" "clob")
1056 (set_attr "length" "8")]
1057)
9c08d1fa 1058
f7fbdd4a 1059(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1060 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1061 (minus:DI (zero_extend:DI
cffb2a26 1062 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1063 (zero_extend:DI
cffb2a26 1064 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1065 (clobber (reg:CC CC_REGNUM))]
25f905c2 1066 "TARGET_32BIT"
1067 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1068 [(set_attr "conds" "clob")
1069 (set_attr "length" "8")]
1070)
b11cae9e 1071
87b22bf7 1072(define_expand "subsi3"
cffb2a26 1073 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1074 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1075 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1076 "TARGET_EITHER"
87b22bf7 1077 "
1078 if (GET_CODE (operands[1]) == CONST_INT)
1079 {
25f905c2 1080 if (TARGET_32BIT)
cffb2a26 1081 {
96f57e36 1082 arm_split_constant (MINUS, SImode, NULL_RTX,
1083 INTVAL (operands[1]), operands[0],
e1ba4a27 1084 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1085 DONE;
1086 }
25f905c2 1087 else /* TARGET_THUMB1 */
cffb2a26 1088 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1089 }
cffb2a26 1090 "
1091)
87b22bf7 1092
25f905c2 1093(define_insn "*thumb1_subsi3_insn"
cffb2a26 1094 [(set (match_operand:SI 0 "register_operand" "=l")
1095 (minus:SI (match_operand:SI 1 "register_operand" "l")
1096 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1097 "TARGET_THUMB1"
cffb2a26 1098 "sub\\t%0, %1, %2"
1099 [(set_attr "length" "2")]
1100)
1101
25f905c2 1102; ??? Check Thumb-2 split length
a0f94409 1103(define_insn_and_split "*arm_subsi3_insn"
aaa37ad6 1104 [(set (match_operand:SI 0 "s_register_operand" "=r,rk,r")
1105 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n")
1106 (match_operand:SI 2 "s_register_operand" "r, r, r")))]
25f905c2 1107 "TARGET_32BIT"
e2348bcb 1108 "@
87b22bf7 1109 rsb%?\\t%0, %2, %1
aaa37ad6 1110 sub%?\\t%0, %1, %2
87b22bf7 1111 #"
25f905c2 1112 "TARGET_32BIT
a0f94409 1113 && GET_CODE (operands[1]) == CONST_INT
1114 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 1115 [(clobber (const_int 0))]
1116 "
96f57e36 1117 arm_split_constant (MINUS, SImode, curr_insn,
1118 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1119 DONE;
cffb2a26 1120 "
aaa37ad6 1121 [(set_attr "length" "4,4,16")
a0f94409 1122 (set_attr "predicable" "yes")]
1123)
1124
1125(define_peephole2
1126 [(match_scratch:SI 3 "r")
372575c7 1127 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1128 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1129 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1130 "TARGET_32BIT
a0f94409 1131 && !const_ok_for_arm (INTVAL (operands[1]))
1132 && const_ok_for_arm (~INTVAL (operands[1]))"
1133 [(set (match_dup 3) (match_dup 1))
1134 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1135 ""
cffb2a26 1136)
b11cae9e 1137
f7fbdd4a 1138(define_insn "*subsi3_compare0"
bd5b4116 1139 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1140 (compare:CC_NOOV
1141 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1142 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1143 (const_int 0)))
9c08d1fa 1144 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1145 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1146 "TARGET_32BIT"
e2348bcb 1147 "@
25f905c2 1148 sub%.\\t%0, %1, %2
1149 rsb%.\\t%0, %2, %1"
cffb2a26 1150 [(set_attr "conds" "set")]
1151)
9c08d1fa 1152
25f905c2 1153(define_expand "decscc"
1154 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1155 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1156 (match_operator:SI 2 "arm_comparison_operator"
1157 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1158 "TARGET_32BIT"
1159 ""
1160)
1161
1162(define_insn "*arm_decscc"
cffb2a26 1163 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1164 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1165 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1166 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1167 "TARGET_ARM"
e2348bcb 1168 "@
215b30b3 1169 sub%d2\\t%0, %1, #1
1170 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1171 [(set_attr "conds" "use")
1172 (set_attr "length" "*,8")]
1173)
9c08d1fa 1174
604f3a0a 1175(define_expand "subsf3"
1176 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1177 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1178 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1179 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1180 "
a2cd141b 1181 if (TARGET_MAVERICK)
604f3a0a 1182 {
1183 if (!cirrus_fp_register (operands[1], SFmode))
1184 operands[1] = force_reg (SFmode, operands[1]);
1185 if (!cirrus_fp_register (operands[2], SFmode))
1186 operands[2] = force_reg (SFmode, operands[2]);
1187 }
1188")
1189
604f3a0a 1190(define_expand "subdf3"
1191 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1192 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1193 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1194 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1195 "
a2cd141b 1196 if (TARGET_MAVERICK)
604f3a0a 1197 {
1198 if (!cirrus_fp_register (operands[1], DFmode))
1199 operands[1] = force_reg (DFmode, operands[1]);
1200 if (!cirrus_fp_register (operands[2], DFmode))
1201 operands[2] = force_reg (DFmode, operands[2]);
1202 }
1203")
1204
b11cae9e 1205\f
1206;; Multiplication insns
1207
cffb2a26 1208(define_expand "mulsi3"
1209 [(set (match_operand:SI 0 "s_register_operand" "")
1210 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1211 (match_operand:SI 1 "s_register_operand" "")))]
1212 "TARGET_EITHER"
1213 ""
1214)
1215
9c08d1fa 1216;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1217(define_insn "*arm_mulsi3"
1218 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1219 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1220 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1221 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1222 "mul%?\\t%0, %2, %1"
a2cd141b 1223 [(set_attr "insn" "mul")
0d66636f 1224 (set_attr "predicable" "yes")]
cffb2a26 1225)
1226
58d7d654 1227(define_insn "*arm_mulsi3_v6"
1228 [(set (match_operand:SI 0 "s_register_operand" "=r")
1229 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1230 (match_operand:SI 2 "s_register_operand" "r")))]
1231 "TARGET_32BIT && arm_arch6"
1232 "mul%?\\t%0, %1, %2"
1233 [(set_attr "insn" "mul")
1234 (set_attr "predicable" "yes")]
1235)
1236
215b30b3 1237; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1238; 1 and 2; are the same, because reload will make operand 0 match
1239; operand 1 without realizing that this conflicts with operand 2. We fix
1240; this by adding another alternative to match this case, and then `reload'
1241; it ourselves. This alternative must come first.
cffb2a26 1242(define_insn "*thumb_mulsi3"
1243 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1244 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1245 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1246 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1247 "*
1248 if (which_alternative < 2)
20c4e896 1249 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1250 else
20c4e896 1251 return \"mul\\t%0, %2\";
cffb2a26 1252 "
1253 [(set_attr "length" "4,4,2")
a2cd141b 1254 (set_attr "insn" "mul")]
cffb2a26 1255)
b11cae9e 1256
58d7d654 1257(define_insn "*thumb_mulsi3_v6"
1258 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1259 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1260 (match_operand:SI 2 "register_operand" "l,0,0")))]
1261 "TARGET_THUMB1 && arm_arch6"
1262 "@
1490694c 1263 mul\\t%0, %2
1264 mul\\t%0, %1
58d7d654 1265 mul\\t%0, %1"
1266 [(set_attr "length" "2")
1267 (set_attr "insn" "mul")]
1268)
1269
f7fbdd4a 1270(define_insn "*mulsi3_compare0"
bd5b4116 1271 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1272 (compare:CC_NOOV (mult:SI
1273 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1274 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1275 (const_int 0)))
1276 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1277 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1278 "TARGET_ARM && !arm_arch6"
1279 "mul%.\\t%0, %2, %1"
1280 [(set_attr "conds" "set")
1281 (set_attr "insn" "muls")]
1282)
1283
1284(define_insn "*mulsi3_compare0_v6"
1285 [(set (reg:CC_NOOV CC_REGNUM)
1286 (compare:CC_NOOV (mult:SI
1287 (match_operand:SI 2 "s_register_operand" "r")
1288 (match_operand:SI 1 "s_register_operand" "r"))
1289 (const_int 0)))
1290 (set (match_operand:SI 0 "s_register_operand" "=r")
1291 (mult:SI (match_dup 2) (match_dup 1)))]
1292 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1293 "mul%.\\t%0, %2, %1"
cffb2a26 1294 [(set_attr "conds" "set")
a2cd141b 1295 (set_attr "insn" "muls")]
cffb2a26 1296)
9c08d1fa 1297
f7fbdd4a 1298(define_insn "*mulsi_compare0_scratch"
bd5b4116 1299 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1300 (compare:CC_NOOV (mult:SI
1301 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1302 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1303 (const_int 0)))
1304 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1305 "TARGET_ARM && !arm_arch6"
1306 "mul%.\\t%0, %2, %1"
1307 [(set_attr "conds" "set")
1308 (set_attr "insn" "muls")]
1309)
1310
1311(define_insn "*mulsi_compare0_scratch_v6"
1312 [(set (reg:CC_NOOV CC_REGNUM)
1313 (compare:CC_NOOV (mult:SI
1314 (match_operand:SI 2 "s_register_operand" "r")
1315 (match_operand:SI 1 "s_register_operand" "r"))
1316 (const_int 0)))
1317 (clobber (match_scratch:SI 0 "=r"))]
1318 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1319 "mul%.\\t%0, %2, %1"
cffb2a26 1320 [(set_attr "conds" "set")
a2cd141b 1321 (set_attr "insn" "muls")]
cffb2a26 1322)
9c08d1fa 1323
b11cae9e 1324;; Unnamed templates to match MLA instruction.
1325
f7fbdd4a 1326(define_insn "*mulsi3addsi"
9c08d1fa 1327 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1328 (plus:SI
9c08d1fa 1329 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1330 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1331 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1332 "TARGET_32BIT && !arm_arch6"
1333 "mla%?\\t%0, %2, %1, %3"
1334 [(set_attr "insn" "mla")
1335 (set_attr "predicable" "yes")]
1336)
1337
1338(define_insn "*mulsi3addsi_v6"
1339 [(set (match_operand:SI 0 "s_register_operand" "=r")
1340 (plus:SI
1341 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1342 (match_operand:SI 1 "s_register_operand" "r"))
1343 (match_operand:SI 3 "s_register_operand" "r")))]
1344 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1345 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1346 [(set_attr "insn" "mla")
0d66636f 1347 (set_attr "predicable" "yes")]
1348)
b11cae9e 1349
f7fbdd4a 1350(define_insn "*mulsi3addsi_compare0"
bd5b4116 1351 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1352 (compare:CC_NOOV
1353 (plus:SI (mult:SI
1354 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1355 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1356 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1357 (const_int 0)))
9c08d1fa 1358 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1359 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1360 (match_dup 3)))]
58d7d654 1361 "TARGET_ARM && arm_arch6"
1362 "mla%.\\t%0, %2, %1, %3"
1363 [(set_attr "conds" "set")
1364 (set_attr "insn" "mlas")]
1365)
1366
1367(define_insn "*mulsi3addsi_compare0_v6"
1368 [(set (reg:CC_NOOV CC_REGNUM)
1369 (compare:CC_NOOV
1370 (plus:SI (mult:SI
1371 (match_operand:SI 2 "s_register_operand" "r")
1372 (match_operand:SI 1 "s_register_operand" "r"))
1373 (match_operand:SI 3 "s_register_operand" "r"))
1374 (const_int 0)))
1375 (set (match_operand:SI 0 "s_register_operand" "=r")
1376 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1377 (match_dup 3)))]
1378 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1379 "mla%.\\t%0, %2, %1, %3"
0d66636f 1380 [(set_attr "conds" "set")
a2cd141b 1381 (set_attr "insn" "mlas")]
0d66636f 1382)
9c08d1fa 1383
f7fbdd4a 1384(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1385 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1386 (compare:CC_NOOV
1387 (plus:SI (mult:SI
1388 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1389 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1390 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1391 (const_int 0)))
9c08d1fa 1392 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1393 "TARGET_ARM && !arm_arch6"
1394 "mla%.\\t%0, %2, %1, %3"
1395 [(set_attr "conds" "set")
1396 (set_attr "insn" "mlas")]
1397)
1398
1399(define_insn "*mulsi3addsi_compare0_scratch_v6"
1400 [(set (reg:CC_NOOV CC_REGNUM)
1401 (compare:CC_NOOV
1402 (plus:SI (mult:SI
1403 (match_operand:SI 2 "s_register_operand" "r")
1404 (match_operand:SI 1 "s_register_operand" "r"))
1405 (match_operand:SI 3 "s_register_operand" "r"))
1406 (const_int 0)))
1407 (clobber (match_scratch:SI 0 "=r"))]
1408 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1409 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1410 [(set_attr "conds" "set")
a2cd141b 1411 (set_attr "insn" "mlas")]
cffb2a26 1412)
f7fbdd4a 1413
89545238 1414(define_insn "*mulsi3subsi"
1415 [(set (match_operand:SI 0 "s_register_operand" "=r")
1416 (minus:SI
1417 (match_operand:SI 3 "s_register_operand" "r")
1418 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1419 (match_operand:SI 1 "s_register_operand" "r"))))]
1420 "TARGET_32BIT && arm_arch_thumb2"
1421 "mls%?\\t%0, %2, %1, %3"
1422 [(set_attr "insn" "mla")
1423 (set_attr "predicable" "yes")]
1424)
1425
efee20da 1426;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1427
1428(define_insn "*mulsidi3adddi"
fe8dbf85 1429 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1430 (plus:DI
215b30b3 1431 (mult:DI
fe8dbf85 1432 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1433 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1434 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1435 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1436 "smlal%?\\t%Q0, %R0, %3, %2"
1437 [(set_attr "insn" "smlal")
1438 (set_attr "predicable" "yes")]
1439)
1440
1441(define_insn "*mulsidi3adddi_v6"
1442 [(set (match_operand:DI 0 "s_register_operand" "=r")
1443 (plus:DI
1444 (mult:DI
1445 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1446 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1447 (match_operand:DI 1 "s_register_operand" "0")))]
1448 "TARGET_32BIT && arm_arch6"
fe8dbf85 1449 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1450 [(set_attr "insn" "smlal")
0d66636f 1451 (set_attr "predicable" "yes")]
1452)
82b85d08 1453
957788b0 1454;; 32x32->64 widening multiply.
1455;; As with mulsi3, the only difference between the v3-5 and v6+
1456;; versions of these patterns is the requirement that the output not
1457;; overlap the inputs, but that still means we have to have a named
1458;; expander and two different starred insns.
1459
1460(define_expand "mulsidi3"
1461 [(set (match_operand:DI 0 "s_register_operand" "")
1462 (mult:DI
1463 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1464 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1465 "TARGET_32BIT && arm_arch3m"
1466 ""
1467)
1468
1469(define_insn "*mulsidi3_nov6"
f7fbdd4a 1470 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1471 (mult:DI
1472 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1473 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1474 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1475 "smull%?\\t%Q0, %R0, %1, %2"
1476 [(set_attr "insn" "smull")
1477 (set_attr "predicable" "yes")]
1478)
1479
957788b0 1480(define_insn "*mulsidi3_v6"
58d7d654 1481 [(set (match_operand:DI 0 "s_register_operand" "=r")
1482 (mult:DI
1483 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1484 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1485 "TARGET_32BIT && arm_arch6"
97499065 1486 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1487 [(set_attr "insn" "smull")
0d66636f 1488 (set_attr "predicable" "yes")]
1489)
f7fbdd4a 1490
957788b0 1491(define_expand "umulsidi3"
1492 [(set (match_operand:DI 0 "s_register_operand" "")
1493 (mult:DI
1494 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1495 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1496 "TARGET_32BIT && arm_arch3m"
1497 ""
1498)
1499
1500(define_insn "*umulsidi3_nov6"
f7fbdd4a 1501 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1502 (mult:DI
1503 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1504 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1505 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1506 "umull%?\\t%Q0, %R0, %1, %2"
1507 [(set_attr "insn" "umull")
1508 (set_attr "predicable" "yes")]
1509)
1510
957788b0 1511(define_insn "*umulsidi3_v6"
58d7d654 1512 [(set (match_operand:DI 0 "s_register_operand" "=r")
1513 (mult:DI
1514 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1515 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1516 "TARGET_32BIT && arm_arch6"
97499065 1517 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1518 [(set_attr "insn" "umull")
0d66636f 1519 (set_attr "predicable" "yes")]
1520)
b11cae9e 1521
efee20da 1522;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1523
1524(define_insn "*umulsidi3adddi"
8ead09f9 1525 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1526 (plus:DI
215b30b3 1527 (mult:DI
fe8dbf85 1528 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1529 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1530 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1531 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1532 "umlal%?\\t%Q0, %R0, %3, %2"
1533 [(set_attr "insn" "umlal")
1534 (set_attr "predicable" "yes")]
1535)
1536
1537(define_insn "*umulsidi3adddi_v6"
1538 [(set (match_operand:DI 0 "s_register_operand" "=r")
1539 (plus:DI
1540 (mult:DI
1541 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1542 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1543 (match_operand:DI 1 "s_register_operand" "0")))]
1544 "TARGET_32BIT && arm_arch6"
fe8dbf85 1545 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1546 [(set_attr "insn" "umlal")
0d66636f 1547 (set_attr "predicable" "yes")]
1548)
82b85d08 1549
957788b0 1550(define_expand "smulsi3_highpart"
1551 [(parallel
1552 [(set (match_operand:SI 0 "s_register_operand" "")
1553 (truncate:SI
1554 (lshiftrt:DI
1555 (mult:DI
1556 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1557 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1558 (const_int 32))))
1559 (clobber (match_scratch:SI 3 ""))])]
1560 "TARGET_32BIT && arm_arch3m"
1561 ""
1562)
1563
1564(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1565 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1566 (truncate:SI
1567 (lshiftrt:DI
215b30b3 1568 (mult:DI
e5fea38e 1569 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1570 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1571 (const_int 32))))
1572 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1573 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1574 "smull%?\\t%3, %0, %2, %1"
1575 [(set_attr "insn" "smull")
1576 (set_attr "predicable" "yes")]
1577)
1578
957788b0 1579(define_insn "*smulsi3_highpart_v6"
58d7d654 1580 [(set (match_operand:SI 0 "s_register_operand" "=r")
1581 (truncate:SI
1582 (lshiftrt:DI
1583 (mult:DI
1584 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1585 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1586 (const_int 32))))
1587 (clobber (match_scratch:SI 3 "=r"))]
1588 "TARGET_32BIT && arm_arch6"
f082f1c4 1589 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1590 [(set_attr "insn" "smull")
0d66636f 1591 (set_attr "predicable" "yes")]
cffb2a26 1592)
f082f1c4 1593
957788b0 1594(define_expand "umulsi3_highpart"
1595 [(parallel
1596 [(set (match_operand:SI 0 "s_register_operand" "")
1597 (truncate:SI
1598 (lshiftrt:DI
1599 (mult:DI
1600 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1601 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1602 (const_int 32))))
1603 (clobber (match_scratch:SI 3 ""))])]
1604 "TARGET_32BIT && arm_arch3m"
1605 ""
1606)
1607
1608(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1609 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1610 (truncate:SI
1611 (lshiftrt:DI
215b30b3 1612 (mult:DI
e5fea38e 1613 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1614 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1615 (const_int 32))))
1616 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1617 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1618 "umull%?\\t%3, %0, %2, %1"
1619 [(set_attr "insn" "umull")
1620 (set_attr "predicable" "yes")]
1621)
1622
957788b0 1623(define_insn "*umulsi3_highpart_v6"
58d7d654 1624 [(set (match_operand:SI 0 "s_register_operand" "=r")
1625 (truncate:SI
1626 (lshiftrt:DI
1627 (mult:DI
1628 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1629 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1630 (const_int 32))))
1631 (clobber (match_scratch:SI 3 "=r"))]
1632 "TARGET_32BIT && arm_arch6"
f082f1c4 1633 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1634 [(set_attr "insn" "umull")
0d66636f 1635 (set_attr "predicable" "yes")]
cffb2a26 1636)
f082f1c4 1637
331beb1a 1638(define_insn "mulhisi3"
1639 [(set (match_operand:SI 0 "s_register_operand" "=r")
1640 (mult:SI (sign_extend:SI
1641 (match_operand:HI 1 "s_register_operand" "%r"))
1642 (sign_extend:SI
1643 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1644 "TARGET_DSP_MULTIPLY"
61a2d04c 1645 "smulbb%?\\t%0, %1, %2"
a2cd141b 1646 [(set_attr "insn" "smulxy")
fec538d9 1647 (set_attr "predicable" "yes")]
1648)
1649
1650(define_insn "*mulhisi3tb"
1651 [(set (match_operand:SI 0 "s_register_operand" "=r")
1652 (mult:SI (ashiftrt:SI
1653 (match_operand:SI 1 "s_register_operand" "r")
1654 (const_int 16))
1655 (sign_extend:SI
1656 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1657 "TARGET_DSP_MULTIPLY"
fec538d9 1658 "smultb%?\\t%0, %1, %2"
a2cd141b 1659 [(set_attr "insn" "smulxy")
fec538d9 1660 (set_attr "predicable" "yes")]
1661)
1662
1663(define_insn "*mulhisi3bt"
1664 [(set (match_operand:SI 0 "s_register_operand" "=r")
1665 (mult:SI (sign_extend:SI
1666 (match_operand:HI 1 "s_register_operand" "r"))
1667 (ashiftrt:SI
1668 (match_operand:SI 2 "s_register_operand" "r")
1669 (const_int 16))))]
25f905c2 1670 "TARGET_DSP_MULTIPLY"
fec538d9 1671 "smulbt%?\\t%0, %1, %2"
a2cd141b 1672 [(set_attr "insn" "smulxy")
fec538d9 1673 (set_attr "predicable" "yes")]
1674)
1675
1676(define_insn "*mulhisi3tt"
1677 [(set (match_operand:SI 0 "s_register_operand" "=r")
1678 (mult:SI (ashiftrt:SI
1679 (match_operand:SI 1 "s_register_operand" "r")
1680 (const_int 16))
1681 (ashiftrt:SI
1682 (match_operand:SI 2 "s_register_operand" "r")
1683 (const_int 16))))]
25f905c2 1684 "TARGET_DSP_MULTIPLY"
fec538d9 1685 "smultt%?\\t%0, %1, %2"
a2cd141b 1686 [(set_attr "insn" "smulxy")
fec538d9 1687 (set_attr "predicable" "yes")]
331beb1a 1688)
1689
1690(define_insn "*mulhisi3addsi"
1691 [(set (match_operand:SI 0 "s_register_operand" "=r")
1692 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1693 (mult:SI (sign_extend:SI
1694 (match_operand:HI 2 "s_register_operand" "%r"))
1695 (sign_extend:SI
1696 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1697 "TARGET_DSP_MULTIPLY"
61a2d04c 1698 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1699 [(set_attr "insn" "smlaxy")
fec538d9 1700 (set_attr "predicable" "yes")]
331beb1a 1701)
1702
1703(define_insn "*mulhidi3adddi"
1704 [(set (match_operand:DI 0 "s_register_operand" "=r")
1705 (plus:DI
1706 (match_operand:DI 1 "s_register_operand" "0")
1707 (mult:DI (sign_extend:DI
1708 (match_operand:HI 2 "s_register_operand" "%r"))
1709 (sign_extend:DI
1710 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1711 "TARGET_DSP_MULTIPLY"
331beb1a 1712 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1713 [(set_attr "insn" "smlalxy")
fec538d9 1714 (set_attr "predicable" "yes")])
331beb1a 1715
604f3a0a 1716(define_expand "mulsf3"
1717 [(set (match_operand:SF 0 "s_register_operand" "")
1718 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1719 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1720 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1721 "
a2cd141b 1722 if (TARGET_MAVERICK
604f3a0a 1723 && !cirrus_fp_register (operands[2], SFmode))
1724 operands[2] = force_reg (SFmode, operands[2]);
1725")
1726
604f3a0a 1727(define_expand "muldf3"
1728 [(set (match_operand:DF 0 "s_register_operand" "")
1729 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1730 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1731 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1732 "
a2cd141b 1733 if (TARGET_MAVERICK
604f3a0a 1734 && !cirrus_fp_register (operands[2], DFmode))
1735 operands[2] = force_reg (DFmode, operands[2]);
1736")
b11cae9e 1737\f
1738;; Division insns
1739
7db9af5d 1740(define_expand "divsf3"
1741 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1742 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1743 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1744 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1745 "")
9c08d1fa 1746
7db9af5d 1747(define_expand "divdf3"
1748 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1749 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1750 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1751 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1752 "")
b11cae9e 1753\f
1754;; Modulo insns
1755
7db9af5d 1756(define_expand "modsf3"
1757 [(set (match_operand:SF 0 "s_register_operand" "")
1758 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1759 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1760 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1761 "")
9c08d1fa 1762
7db9af5d 1763(define_expand "moddf3"
1764 [(set (match_operand:DF 0 "s_register_operand" "")
1765 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1766 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1767 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1768 "")
b11cae9e 1769\f
1770;; Boolean and,ior,xor insns
1771
f6ebffac 1772;; Split up double word logical operations
1773
1774;; Split up simple DImode logical operations. Simply perform the logical
1775;; operation on the upper and lower halves of the registers.
1776(define_split
1777 [(set (match_operand:DI 0 "s_register_operand" "")
1778 (match_operator:DI 6 "logical_binary_operator"
1779 [(match_operand:DI 1 "s_register_operand" "")
1780 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1781 "TARGET_32BIT && reload_completed
1782 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1783 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1784 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1785 "
215b30b3 1786 {
1787 operands[3] = gen_highpart (SImode, operands[0]);
1788 operands[0] = gen_lowpart (SImode, operands[0]);
1789 operands[4] = gen_highpart (SImode, operands[1]);
1790 operands[1] = gen_lowpart (SImode, operands[1]);
1791 operands[5] = gen_highpart (SImode, operands[2]);
1792 operands[2] = gen_lowpart (SImode, operands[2]);
1793 }"
1794)
f6ebffac 1795
f6ebffac 1796(define_split
1797 [(set (match_operand:DI 0 "s_register_operand" "")
1798 (match_operator:DI 6 "logical_binary_operator"
1799 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1800 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1801 "TARGET_32BIT && reload_completed"
f6ebffac 1802 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1803 (set (match_dup 3) (match_op_dup:SI 6
1804 [(ashiftrt:SI (match_dup 2) (const_int 31))
1805 (match_dup 4)]))]
1806 "
215b30b3 1807 {
1808 operands[3] = gen_highpart (SImode, operands[0]);
1809 operands[0] = gen_lowpart (SImode, operands[0]);
1810 operands[4] = gen_highpart (SImode, operands[1]);
1811 operands[1] = gen_lowpart (SImode, operands[1]);
1812 operands[5] = gen_highpart (SImode, operands[2]);
1813 operands[2] = gen_lowpart (SImode, operands[2]);
1814 }"
1815)
f6ebffac 1816
f6ebffac 1817;; The zero extend of operand 2 means we can just copy the high part of
1818;; operand1 into operand0.
1819(define_split
1820 [(set (match_operand:DI 0 "s_register_operand" "")
1821 (ior:DI
1822 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1823 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1824 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1825 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1826 (set (match_dup 3) (match_dup 4))]
1827 "
215b30b3 1828 {
1829 operands[4] = gen_highpart (SImode, operands[1]);
1830 operands[3] = gen_highpart (SImode, operands[0]);
1831 operands[0] = gen_lowpart (SImode, operands[0]);
1832 operands[1] = gen_lowpart (SImode, operands[1]);
1833 }"
1834)
f6ebffac 1835
1836;; The zero extend of operand 2 means we can just copy the high part of
1837;; operand1 into operand0.
1838(define_split
1839 [(set (match_operand:DI 0 "s_register_operand" "")
1840 (xor:DI
1841 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1842 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1843 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1844 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1845 (set (match_dup 3) (match_dup 4))]
1846 "
215b30b3 1847 {
1848 operands[4] = gen_highpart (SImode, operands[1]);
1849 operands[3] = gen_highpart (SImode, operands[0]);
1850 operands[0] = gen_lowpart (SImode, operands[0]);
1851 operands[1] = gen_lowpart (SImode, operands[1]);
1852 }"
1853)
f6ebffac 1854
b11cae9e 1855(define_insn "anddi3"
cffb2a26 1856 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1857 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1858 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 1859 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 1860 "#"
215b30b3 1861 [(set_attr "length" "8")]
1862)
b11cae9e 1863
a0f94409 1864(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1865 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1866 (and:DI (zero_extend:DI
1867 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1868 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1869 "TARGET_32BIT"
f6ebffac 1870 "#"
25f905c2 1871 "TARGET_32BIT && reload_completed"
a0f94409 1872 ; The zero extend of operand 2 clears the high word of the output
1873 ; operand.
1874 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1875 (set (match_dup 3) (const_int 0))]
1876 "
1877 {
1878 operands[3] = gen_highpart (SImode, operands[0]);
1879 operands[0] = gen_lowpart (SImode, operands[0]);
1880 operands[1] = gen_lowpart (SImode, operands[1]);
1881 }"
215b30b3 1882 [(set_attr "length" "8")]
1883)
b11cae9e 1884
f7fbdd4a 1885(define_insn "*anddi_sesdi_di"
cffb2a26 1886 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1887 (and:DI (sign_extend:DI
1888 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1889 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 1890 "TARGET_32BIT"
f6ebffac 1891 "#"
cffb2a26 1892 [(set_attr "length" "8")]
1893)
b11cae9e 1894
87b22bf7 1895(define_expand "andsi3"
cffb2a26 1896 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1897 (and:SI (match_operand:SI 1 "s_register_operand" "")
1898 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1899 "TARGET_EITHER"
87b22bf7 1900 "
25f905c2 1901 if (TARGET_32BIT)
87b22bf7 1902 {
cffb2a26 1903 if (GET_CODE (operands[2]) == CONST_INT)
1904 {
96f57e36 1905 arm_split_constant (AND, SImode, NULL_RTX,
1906 INTVAL (operands[2]), operands[0],
e1ba4a27 1907 operands[1], optimize && can_create_pseudo_p ());
615caa51 1908
cffb2a26 1909 DONE;
1910 }
87b22bf7 1911 }
25f905c2 1912 else /* TARGET_THUMB1 */
cffb2a26 1913 {
1914 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 1915 {
1916 rtx tmp = force_reg (SImode, operands[2]);
1917 if (rtx_equal_p (operands[0], operands[1]))
1918 operands[2] = tmp;
1919 else
1920 {
1921 operands[2] = operands[1];
1922 operands[1] = tmp;
1923 }
1924 }
cffb2a26 1925 else
1926 {
1927 int i;
1928
215b30b3 1929 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1930 {
215b30b3 1931 operands[2] = force_reg (SImode,
1932 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1933
1934 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1935
1936 DONE;
1937 }
87b22bf7 1938
cffb2a26 1939 for (i = 9; i <= 31; i++)
1940 {
1941 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1942 {
1943 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1944 const0_rtx));
1945 DONE;
1946 }
215b30b3 1947 else if ((((HOST_WIDE_INT) 1) << i) - 1
1948 == ~INTVAL (operands[2]))
cffb2a26 1949 {
1950 rtx shift = GEN_INT (i);
1951 rtx reg = gen_reg_rtx (SImode);
1952
1953 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1954 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1955
1956 DONE;
1957 }
1958 }
1959
1960 operands[2] = force_reg (SImode, operands[2]);
1961 }
215b30b3 1962 }
1963 "
cffb2a26 1964)
1965
25f905c2 1966; ??? Check split length for Thumb-2
a0f94409 1967(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1968 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1969 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1970 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 1971 "TARGET_32BIT"
5565501b 1972 "@
1973 and%?\\t%0, %1, %2
87b22bf7 1974 bic%?\\t%0, %1, #%B2
1975 #"
25f905c2 1976 "TARGET_32BIT
a0f94409 1977 && GET_CODE (operands[2]) == CONST_INT
1978 && !(const_ok_for_arm (INTVAL (operands[2]))
1979 || const_ok_for_arm (~INTVAL (operands[2])))"
1980 [(clobber (const_int 0))]
1981 "
96f57e36 1982 arm_split_constant (AND, SImode, curr_insn,
1983 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1984 DONE;
1985 "
0d66636f 1986 [(set_attr "length" "4,4,16")
1987 (set_attr "predicable" "yes")]
cffb2a26 1988)
1989
25f905c2 1990(define_insn "*thumb1_andsi3_insn"
cffb2a26 1991 [(set (match_operand:SI 0 "register_operand" "=l")
1992 (and:SI (match_operand:SI 1 "register_operand" "%0")
1993 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1994 "TARGET_THUMB1"
cffb2a26 1995 "and\\t%0, %0, %2"
1996 [(set_attr "length" "2")]
1997)
87b22bf7 1998
f7fbdd4a 1999(define_insn "*andsi3_compare0"
bd5b4116 2000 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2001 (compare:CC_NOOV
2002 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2003 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2004 (const_int 0)))
cffb2a26 2005 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2006 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2007 "TARGET_32BIT"
5565501b 2008 "@
25f905c2 2009 and%.\\t%0, %1, %2
2010 bic%.\\t%0, %1, #%B2"
cffb2a26 2011 [(set_attr "conds" "set")]
2012)
9c08d1fa 2013
f7fbdd4a 2014(define_insn "*andsi3_compare0_scratch"
bd5b4116 2015 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2016 (compare:CC_NOOV
2017 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2018 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2019 (const_int 0)))
dd193d7c 2020 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2021 "TARGET_32BIT"
5565501b 2022 "@
2023 tst%?\\t%0, %1
25f905c2 2024 bic%.\\t%2, %0, #%B1"
0d66636f 2025 [(set_attr "conds" "set")]
2026)
9c08d1fa 2027
f7fbdd4a 2028(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2029 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2030 (compare:CC_NOOV (zero_extract:SI
2031 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2032 (match_operand 1 "const_int_operand" "n")
2033 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2034 (const_int 0)))]
25f905c2 2035 "TARGET_32BIT
cffb2a26 2036 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2037 && INTVAL (operands[1]) > 0
2038 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2039 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2040 "*
5c49a439 2041 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2042 << INTVAL (operands[2]));
40dbec34 2043 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2044 return \"\";
0d66636f 2045 "
2046 [(set_attr "conds" "set")]
2047)
9c08d1fa 2048
f4462328 2049(define_insn_and_split "*ne_zeroextractsi"
c4034607 2050 [(set (match_operand:SI 0 "s_register_operand" "=r")
2051 (ne:SI (zero_extract:SI
2052 (match_operand:SI 1 "s_register_operand" "r")
2053 (match_operand:SI 2 "const_int_operand" "n")
2054 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2055 (const_int 0)))
2056 (clobber (reg:CC CC_REGNUM))]
25f905c2 2057 "TARGET_32BIT
cffb2a26 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)"
f4462328 2062 "#"
25f905c2 2063 "TARGET_32BIT
f4462328 2064 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2065 && INTVAL (operands[2]) > 0
2066 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2067 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2068 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2069 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2070 (const_int 0)))
2071 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2072 (set (match_dup 0)
2073 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2074 (match_dup 0) (const_int 1)))]
2075 "
2076 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2077 << INTVAL (operands[3]));
2078 "
2079 [(set_attr "conds" "clob")
25f905c2 2080 (set (attr "length")
2081 (if_then_else (eq_attr "is_thumb" "yes")
2082 (const_int 12)
2083 (const_int 8)))]
f4462328 2084)
2085
2086(define_insn_and_split "*ne_zeroextractsi_shifted"
2087 [(set (match_operand:SI 0 "s_register_operand" "=r")
2088 (ne:SI (zero_extract:SI
2089 (match_operand:SI 1 "s_register_operand" "r")
2090 (match_operand:SI 2 "const_int_operand" "n")
2091 (const_int 0))
2092 (const_int 0)))
2093 (clobber (reg:CC CC_REGNUM))]
2094 "TARGET_ARM"
2095 "#"
2096 "TARGET_ARM"
2097 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2098 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2099 (const_int 0)))
2100 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2101 (set (match_dup 0)
2102 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2103 (match_dup 0) (const_int 1)))]
2104 "
2105 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2106 "
2107 [(set_attr "conds" "clob")
2108 (set_attr "length" "8")]
2109)
2110
2111(define_insn_and_split "*ite_ne_zeroextractsi"
2112 [(set (match_operand:SI 0 "s_register_operand" "=r")
2113 (if_then_else:SI (ne (zero_extract:SI
2114 (match_operand:SI 1 "s_register_operand" "r")
2115 (match_operand:SI 2 "const_int_operand" "n")
2116 (match_operand:SI 3 "const_int_operand" "n"))
2117 (const_int 0))
2118 (match_operand:SI 4 "arm_not_operand" "rIK")
2119 (const_int 0)))
2120 (clobber (reg:CC CC_REGNUM))]
2121 "TARGET_ARM
2122 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2123 && INTVAL (operands[2]) > 0
2124 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2125 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2126 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2127 "#"
2128 "TARGET_ARM
2129 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2130 && INTVAL (operands[2]) > 0
2131 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2132 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2133 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2134 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2135 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2136 (const_int 0)))
2137 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2138 (set (match_dup 0)
2139 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2140 (match_dup 0) (match_dup 4)))]
2141 "
c4034607 2142 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2143 << INTVAL (operands[3]));
2144 "
2145 [(set_attr "conds" "clob")
2146 (set_attr "length" "8")]
2147)
2148
2149(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2150 [(set (match_operand:SI 0 "s_register_operand" "=r")
2151 (if_then_else:SI (ne (zero_extract:SI
2152 (match_operand:SI 1 "s_register_operand" "r")
2153 (match_operand:SI 2 "const_int_operand" "n")
2154 (const_int 0))
2155 (const_int 0))
2156 (match_operand:SI 3 "arm_not_operand" "rIK")
2157 (const_int 0)))
2158 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2159 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2160 "#"
f8d7bf2f 2161 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2162 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2163 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2164 (const_int 0)))
2165 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2166 (set (match_dup 0)
2167 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2168 (match_dup 0) (match_dup 3)))]
2169 "
2170 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2171 "
2172 [(set_attr "conds" "clob")
215b30b3 2173 (set_attr "length" "8")]
2174)
9c08d1fa 2175
58d6528b 2176(define_split
2177 [(set (match_operand:SI 0 "s_register_operand" "")
2178 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2179 (match_operand:SI 2 "const_int_operand" "")
2180 (match_operand:SI 3 "const_int_operand" "")))
2181 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2182 "TARGET_THUMB1"
58d6528b 2183 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2184 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2185 "{
2186 HOST_WIDE_INT temp = INTVAL (operands[2]);
2187
2188 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2189 operands[3] = GEN_INT (32 - temp);
2190 }"
2191)
2192
25f905c2 2193;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2194(define_split
2195 [(set (match_operand:SI 0 "s_register_operand" "")
2196 (match_operator:SI 1 "shiftable_operator"
2197 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2198 (match_operand:SI 3 "const_int_operand" "")
2199 (match_operand:SI 4 "const_int_operand" ""))
2200 (match_operand:SI 5 "s_register_operand" "")]))
2201 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2202 "TARGET_ARM"
2203 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2204 (set (match_dup 0)
2205 (match_op_dup 1
2206 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2207 (match_dup 5)]))]
2208 "{
2209 HOST_WIDE_INT temp = INTVAL (operands[3]);
2210
2211 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2212 operands[4] = GEN_INT (32 - temp);
2213 }"
2214)
2215
58d6528b 2216(define_split
2217 [(set (match_operand:SI 0 "s_register_operand" "")
2218 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2219 (match_operand:SI 2 "const_int_operand" "")
2220 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2221 "TARGET_THUMB1"
58d6528b 2222 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2223 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2224 "{
2225 HOST_WIDE_INT temp = INTVAL (operands[2]);
2226
2227 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2228 operands[3] = GEN_INT (32 - temp);
2229 }"
2230)
2231
d7863cfe 2232(define_split
2233 [(set (match_operand:SI 0 "s_register_operand" "")
2234 (match_operator:SI 1 "shiftable_operator"
2235 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2236 (match_operand:SI 3 "const_int_operand" "")
2237 (match_operand:SI 4 "const_int_operand" ""))
2238 (match_operand:SI 5 "s_register_operand" "")]))
2239 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2240 "TARGET_ARM"
2241 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2242 (set (match_dup 0)
2243 (match_op_dup 1
2244 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2245 (match_dup 5)]))]
2246 "{
2247 HOST_WIDE_INT temp = INTVAL (operands[3]);
2248
2249 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2250 operands[4] = GEN_INT (32 - temp);
2251 }"
2252)
2253
a42059fd 2254;;; ??? This pattern is bogus. If operand3 has bits outside the range
2255;;; represented by the bitfield, then this will produce incorrect results.
2256;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2257;;; which have a real bit-field insert instruction, the truncation happens
2258;;; in the bit-field insert instruction itself. Since arm does not have a
2259;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2260;;; the value before we insert. This loses some of the advantage of having
2261;;; this insv pattern, so this pattern needs to be reevalutated.
2262
8a18b90c 2263(define_expand "insv"
2264 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2265 (match_operand:SI 1 "general_operand" "")
2266 (match_operand:SI 2 "general_operand" ""))
19335226 2267 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2268 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2269 "
215b30b3 2270 {
2271 int start_bit = INTVAL (operands[2]);
2272 int width = INTVAL (operands[1]);
2273 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2274 rtx target, subtarget;
2275
8b054d5a 2276 if (arm_arch_thumb2)
2277 {
2278 bool use_bfi = TRUE;
2279
2280 if (GET_CODE (operands[3]) == CONST_INT)
2281 {
2282 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2283
2284 if (val == 0)
2285 {
2286 emit_insn (gen_insv_zero (operands[0], operands[1],
2287 operands[2]));
2288 DONE;
2289 }
2290
2291 /* See if the set can be done with a single orr instruction. */
2292 if (val == mask && const_ok_for_arm (val << start_bit))
2293 use_bfi = FALSE;
2294 }
2295
2296 if (use_bfi)
2297 {
2298 if (GET_CODE (operands[3]) != REG)
2299 operands[3] = force_reg (SImode, operands[3]);
2300
2301 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2302 operands[3]));
2303 DONE;
2304 }
2305 }
2306
3f8fde42 2307 target = copy_rtx (operands[0]);
215b30b3 2308 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2309 subreg as the final target. */
2310 if (GET_CODE (target) == SUBREG)
2311 {
2312 subtarget = gen_reg_rtx (SImode);
2313 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2314 < GET_MODE_SIZE (SImode))
2315 target = SUBREG_REG (target);
2316 }
2317 else
2318 subtarget = target;
8a18b90c 2319
215b30b3 2320 if (GET_CODE (operands[3]) == CONST_INT)
2321 {
2322 /* Since we are inserting a known constant, we may be able to
2323 reduce the number of bits that we have to clear so that
2324 the mask becomes simple. */
2325 /* ??? This code does not check to see if the new mask is actually
2326 simpler. It may not be. */
2327 rtx op1 = gen_reg_rtx (SImode);
2328 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2329 start of this pattern. */
2330 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2331 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2332
c5b3a71b 2333 emit_insn (gen_andsi3 (op1, operands[0],
2334 gen_int_mode (~mask2, SImode)));
215b30b3 2335 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2336 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2337 }
2338 else if (start_bit == 0
2339 && !(const_ok_for_arm (mask)
2340 || const_ok_for_arm (~mask)))
2341 {
2342 /* A Trick, since we are setting the bottom bits in the word,
2343 we can shift operand[3] up, operand[0] down, OR them together
2344 and rotate the result back again. This takes 3 insns, and
5910bb95 2345 the third might be mergeable into another op. */
215b30b3 2346 /* The shift up copes with the possibility that operand[3] is
2347 wider than the bitfield. */
2348 rtx op0 = gen_reg_rtx (SImode);
2349 rtx op1 = gen_reg_rtx (SImode);
2350
2351 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2352 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2353 emit_insn (gen_iorsi3 (op1, op1, op0));
2354 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2355 }
2356 else if ((width + start_bit == 32)
2357 && !(const_ok_for_arm (mask)
2358 || const_ok_for_arm (~mask)))
2359 {
2360 /* Similar trick, but slightly less efficient. */
8a18b90c 2361
215b30b3 2362 rtx op0 = gen_reg_rtx (SImode);
2363 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2364
215b30b3 2365 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2366 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2367 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2368 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2369 }
2370 else
2371 {
c5b3a71b 2372 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2373 rtx op1 = gen_reg_rtx (SImode);
2374 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2375
215b30b3 2376 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2377 {
2378 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2379
215b30b3 2380 emit_insn (gen_movsi (tmp, op0));
2381 op0 = tmp;
2382 }
8a18b90c 2383
215b30b3 2384 /* Mask out any bits in operand[3] that are not needed. */
2385 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2386
215b30b3 2387 if (GET_CODE (op0) == CONST_INT
2388 && (const_ok_for_arm (mask << start_bit)
2389 || const_ok_for_arm (~(mask << start_bit))))
2390 {
c5b3a71b 2391 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2392 emit_insn (gen_andsi3 (op2, operands[0], op0));
2393 }
2394 else
2395 {
2396 if (GET_CODE (op0) == CONST_INT)
2397 {
2398 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2399
215b30b3 2400 emit_insn (gen_movsi (tmp, op0));
2401 op0 = tmp;
2402 }
2403
2404 if (start_bit != 0)
2405 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2406
215b30b3 2407 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2408 }
8a18b90c 2409
215b30b3 2410 if (start_bit != 0)
2411 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2412
215b30b3 2413 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2414 }
f082f1c4 2415
215b30b3 2416 if (subtarget != target)
2417 {
2418 /* If TARGET is still a SUBREG, then it must be wider than a word,
2419 so we must be careful only to set the subword we were asked to. */
2420 if (GET_CODE (target) == SUBREG)
2421 emit_move_insn (target, subtarget);
2422 else
2423 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2424 }
8a18b90c 2425
215b30b3 2426 DONE;
2427 }"
2428)
8a18b90c 2429
8b054d5a 2430(define_insn "insv_zero"
2431 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2432 (match_operand:SI 1 "const_int_operand" "M")
2433 (match_operand:SI 2 "const_int_operand" "M"))
2434 (const_int 0))]
2435 "arm_arch_thumb2"
2436 "bfc%?\t%0, %2, %1"
2437 [(set_attr "length" "4")
2438 (set_attr "predicable" "yes")]
2439)
2440
2441(define_insn "insv_t2"
2442 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2443 (match_operand:SI 1 "const_int_operand" "M")
2444 (match_operand:SI 2 "const_int_operand" "M"))
2445 (match_operand:SI 3 "s_register_operand" "r"))]
2446 "arm_arch_thumb2"
2447 "bfi%?\t%0, %3, %2, %1"
2448 [(set_attr "length" "4")
2449 (set_attr "predicable" "yes")]
2450)
2451
215b30b3 2452; constants for op 2 will never be given to these patterns.
a0f94409 2453(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2454 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2455 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2456 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2457 "TARGET_32BIT"
f6ebffac 2458 "#"
25f905c2 2459 "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2460 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2461 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2462 "
2463 {
2464 operands[3] = gen_highpart (SImode, operands[0]);
2465 operands[0] = gen_lowpart (SImode, operands[0]);
2466 operands[4] = gen_highpart (SImode, operands[1]);
2467 operands[1] = gen_lowpart (SImode, operands[1]);
2468 operands[5] = gen_highpart (SImode, operands[2]);
2469 operands[2] = gen_lowpart (SImode, operands[2]);
2470 }"
0d66636f 2471 [(set_attr "length" "8")
2472 (set_attr "predicable" "yes")]
2473)
9c08d1fa 2474
a0f94409 2475(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2476 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2477 (and:DI (not:DI (zero_extend:DI
2478 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2479 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2480 "TARGET_32BIT"
e2348bcb 2481 "@
97499065 2482 bic%?\\t%Q0, %Q1, %2
f6ebffac 2483 #"
a0f94409 2484 ; (not (zero_extend ...)) allows us to just copy the high word from
2485 ; operand1 to operand0.
25f905c2 2486 "TARGET_32BIT
a0f94409 2487 && reload_completed
2488 && operands[0] != operands[1]"
5a097f7d 2489 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2490 (set (match_dup 3) (match_dup 4))]
2491 "
2492 {
2493 operands[3] = gen_highpart (SImode, operands[0]);
2494 operands[0] = gen_lowpart (SImode, operands[0]);
2495 operands[4] = gen_highpart (SImode, operands[1]);
2496 operands[1] = gen_lowpart (SImode, operands[1]);
2497 }"
0d66636f 2498 [(set_attr "length" "4,8")
2499 (set_attr "predicable" "yes")]
2500)
9c08d1fa 2501
a0f94409 2502(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2503 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2504 (and:DI (not:DI (sign_extend:DI
2505 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2506 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2507 "TARGET_32BIT"
f6ebffac 2508 "#"
25f905c2 2509 "TARGET_32BIT && reload_completed"
5a097f7d 2510 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2511 (set (match_dup 3) (and:SI (not:SI
2512 (ashiftrt:SI (match_dup 2) (const_int 31)))
2513 (match_dup 4)))]
2514 "
2515 {
2516 operands[3] = gen_highpart (SImode, operands[0]);
2517 operands[0] = gen_lowpart (SImode, operands[0]);
2518 operands[4] = gen_highpart (SImode, operands[1]);
2519 operands[1] = gen_lowpart (SImode, operands[1]);
2520 }"
0d66636f 2521 [(set_attr "length" "8")
2522 (set_attr "predicable" "yes")]
2523)
9c08d1fa 2524
8a18b90c 2525(define_insn "andsi_notsi_si"
9c08d1fa 2526 [(set (match_operand:SI 0 "s_register_operand" "=r")
2527 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2528 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2529 "TARGET_32BIT"
0d66636f 2530 "bic%?\\t%0, %1, %2"
2531 [(set_attr "predicable" "yes")]
2532)
b11cae9e 2533
cffb2a26 2534(define_insn "bicsi3"
2535 [(set (match_operand:SI 0 "register_operand" "=l")
2536 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2537 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2538 "TARGET_THUMB1"
cffb2a26 2539 "bic\\t%0, %0, %1"
2540 [(set_attr "length" "2")]
2541)
2542
8a18b90c 2543(define_insn "andsi_not_shiftsi_si"
a2cd141b 2544 [(set (match_operand:SI 0 "s_register_operand" "=r")
2545 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2546 [(match_operand:SI 2 "s_register_operand" "r")
2547 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2548 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2549 "TARGET_ARM"
6c4c2133 2550 "bic%?\\t%0, %1, %2%S4"
344495ea 2551 [(set_attr "predicable" "yes")
331beb1a 2552 (set_attr "shift" "2")
a2cd141b 2553 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2554 (const_string "alu_shift")
2555 (const_string "alu_shift_reg")))]
6c4c2133 2556)
8a18b90c 2557
f7fbdd4a 2558(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2559 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2560 (compare:CC_NOOV
2561 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2562 (match_operand:SI 1 "s_register_operand" "r"))
2563 (const_int 0)))
9c08d1fa 2564 (set (match_operand:SI 0 "s_register_operand" "=r")
2565 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2566 "TARGET_32BIT"
2567 "bic%.\\t%0, %1, %2"
0d66636f 2568 [(set_attr "conds" "set")]
2569)
9c08d1fa 2570
f7fbdd4a 2571(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2572 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2573 (compare:CC_NOOV
2574 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2575 (match_operand:SI 1 "s_register_operand" "r"))
2576 (const_int 0)))
9c08d1fa 2577 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2578 "TARGET_32BIT"
2579 "bic%.\\t%0, %1, %2"
0d66636f 2580 [(set_attr "conds" "set")]
2581)
9c08d1fa 2582
2583(define_insn "iordi3"
cffb2a26 2584 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2585 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2586 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2587 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 2588 "#"
0d66636f 2589 [(set_attr "length" "8")
2590 (set_attr "predicable" "yes")]
cffb2a26 2591)
9c08d1fa 2592
f7fbdd4a 2593(define_insn "*iordi_zesidi_di"
9c08d1fa 2594 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2595 (ior:DI (zero_extend:DI
2596 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2597 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2598 "TARGET_32BIT"
e2348bcb 2599 "@
97499065 2600 orr%?\\t%Q0, %Q1, %2
f6ebffac 2601 #"
0d66636f 2602 [(set_attr "length" "4,8")
2603 (set_attr "predicable" "yes")]
cffb2a26 2604)
9c08d1fa 2605
f7fbdd4a 2606(define_insn "*iordi_sesidi_di"
9c08d1fa 2607 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2608 (ior:DI (sign_extend:DI
2609 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2610 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2611 "TARGET_32BIT"
f6ebffac 2612 "#"
0d66636f 2613 [(set_attr "length" "8")
2614 (set_attr "predicable" "yes")]
cffb2a26 2615)
9c08d1fa 2616
87b22bf7 2617(define_expand "iorsi3"
cffb2a26 2618 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2619 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2620 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2621 "TARGET_EITHER"
87b22bf7 2622 "
2623 if (GET_CODE (operands[2]) == CONST_INT)
2624 {
25f905c2 2625 if (TARGET_32BIT)
cffb2a26 2626 {
96f57e36 2627 arm_split_constant (IOR, SImode, NULL_RTX,
2628 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2629 optimize && can_create_pseudo_p ());
cffb2a26 2630 DONE;
2631 }
25f905c2 2632 else /* TARGET_THUMB1 */
923ffadb 2633 {
2634 rtx tmp = force_reg (SImode, operands[2]);
2635 if (rtx_equal_p (operands[0], operands[1]))
2636 operands[2] = tmp;
2637 else
2638 {
2639 operands[2] = operands[1];
2640 operands[1] = tmp;
2641 }
2642 }
87b22bf7 2643 }
cffb2a26 2644 "
2645)
87b22bf7 2646
a0f94409 2647(define_insn_and_split "*arm_iorsi3"
cffb2a26 2648 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2649 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2650 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
90560cad 2651 "TARGET_ARM"
87b22bf7 2652 "@
2653 orr%?\\t%0, %1, %2
2654 #"
90560cad 2655 "TARGET_ARM
a0f94409 2656 && GET_CODE (operands[2]) == CONST_INT
2657 && !const_ok_for_arm (INTVAL (operands[2]))"
2658 [(clobber (const_int 0))]
2659 "
96f57e36 2660 arm_split_constant (IOR, SImode, curr_insn,
2661 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2662 DONE;
2663 "
0d66636f 2664 [(set_attr "length" "4,16")
2665 (set_attr "predicable" "yes")]
cffb2a26 2666)
2667
25f905c2 2668(define_insn "*thumb1_iorsi3"
cffb2a26 2669 [(set (match_operand:SI 0 "register_operand" "=l")
2670 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2671 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2672 "TARGET_THUMB1"
cffb2a26 2673 "orr\\t%0, %0, %2"
2674 [(set_attr "length" "2")]
2675)
9c08d1fa 2676
a0f94409 2677(define_peephole2
2678 [(match_scratch:SI 3 "r")
372575c7 2679 (set (match_operand:SI 0 "arm_general_register_operand" "")
2680 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2681 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2682 "TARGET_ARM
a0f94409 2683 && !const_ok_for_arm (INTVAL (operands[2]))
2684 && const_ok_for_arm (~INTVAL (operands[2]))"
2685 [(set (match_dup 3) (match_dup 2))
2686 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2687 ""
215b30b3 2688)
a0f94409 2689
f7fbdd4a 2690(define_insn "*iorsi3_compare0"
bd5b4116 2691 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2692 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2693 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2694 (const_int 0)))
2695 (set (match_operand:SI 0 "s_register_operand" "=r")
2696 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2697 "TARGET_32BIT"
2698 "orr%.\\t%0, %1, %2"
cffb2a26 2699 [(set_attr "conds" "set")]
2700)
9c08d1fa 2701
f7fbdd4a 2702(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2703 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2704 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2705 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2706 (const_int 0)))
2707 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2708 "TARGET_32BIT"
2709 "orr%.\\t%0, %1, %2"
0d66636f 2710 [(set_attr "conds" "set")]
2711)
9c08d1fa 2712
2713(define_insn "xordi3"
cffb2a26 2714 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2715 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2716 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2717 "TARGET_32BIT && !TARGET_IWMMXT"
f6ebffac 2718 "#"
0d66636f 2719 [(set_attr "length" "8")
2720 (set_attr "predicable" "yes")]
cffb2a26 2721)
9c08d1fa 2722
f7fbdd4a 2723(define_insn "*xordi_zesidi_di"
9c08d1fa 2724 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2725 (xor:DI (zero_extend:DI
2726 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2727 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2728 "TARGET_32BIT"
e2348bcb 2729 "@
97499065 2730 eor%?\\t%Q0, %Q1, %2
f6ebffac 2731 #"
0d66636f 2732 [(set_attr "length" "4,8")
2733 (set_attr "predicable" "yes")]
cffb2a26 2734)
9c08d1fa 2735
f7fbdd4a 2736(define_insn "*xordi_sesidi_di"
9c08d1fa 2737 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2738 (xor:DI (sign_extend:DI
2739 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2740 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2741 "TARGET_32BIT"
f6ebffac 2742 "#"
0d66636f 2743 [(set_attr "length" "8")
2744 (set_attr "predicable" "yes")]
cffb2a26 2745)
9c08d1fa 2746
cffb2a26 2747(define_expand "xorsi3"
2748 [(set (match_operand:SI 0 "s_register_operand" "")
2749 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2750 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2751 "TARGET_EITHER"
923ffadb 2752 "if (GET_CODE (operands[2]) == CONST_INT)
2753 {
2754 if (TARGET_32BIT)
2755 {
2756 arm_split_constant (XOR, SImode, NULL_RTX,
2757 INTVAL (operands[2]), operands[0], operands[1],
2758 optimize && can_create_pseudo_p ());
2759 DONE;
2760 }
2761 else /* TARGET_THUMB1 */
2762 {
2763 rtx tmp = force_reg (SImode, operands[2]);
2764 if (rtx_equal_p (operands[0], operands[1]))
2765 operands[2] = tmp;
2766 else
2767 {
2768 operands[2] = operands[1];
2769 operands[1] = tmp;
2770 }
2771 }
2772 }"
cffb2a26 2773)
2774
2775(define_insn "*arm_xorsi3"
2776 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2777 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2778 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2779 "TARGET_32BIT"
cffb2a26 2780 "eor%?\\t%0, %1, %2"
0d66636f 2781 [(set_attr "predicable" "yes")]
cffb2a26 2782)
2783
25f905c2 2784(define_insn "*thumb1_xorsi3"
cffb2a26 2785 [(set (match_operand:SI 0 "register_operand" "=l")
2786 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2787 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2788 "TARGET_THUMB1"
cffb2a26 2789 "eor\\t%0, %0, %2"
2790 [(set_attr "length" "2")]
2791)
9c08d1fa 2792
f7fbdd4a 2793(define_insn "*xorsi3_compare0"
bd5b4116 2794 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2795 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2796 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2797 (const_int 0)))
2798 (set (match_operand:SI 0 "s_register_operand" "=r")
2799 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2800 "TARGET_32BIT"
2801 "eor%.\\t%0, %1, %2"
0d66636f 2802 [(set_attr "conds" "set")]
2803)
9c08d1fa 2804
f7fbdd4a 2805(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2806 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2807 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2808 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2809 (const_int 0)))]
25f905c2 2810 "TARGET_32BIT"
40dbec34 2811 "teq%?\\t%0, %1"
cffb2a26 2812 [(set_attr "conds" "set")]
2813)
9c08d1fa 2814
215b30b3 2815; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2816; (NOT D) we can sometimes merge the final NOT into one of the following
2817; insns.
9c08d1fa 2818
2819(define_split
a058e94a 2820 [(set (match_operand:SI 0 "s_register_operand" "")
2821 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2822 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2823 (match_operand:SI 3 "arm_rhs_operand" "")))
2824 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2825 "TARGET_32BIT"
9c08d1fa 2826 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2827 (not:SI (match_dup 3))))
2828 (set (match_dup 0) (not:SI (match_dup 4)))]
2829 ""
2830)
2831
f7fbdd4a 2832(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2833 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 2834 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 2835 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2836 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2837 "TARGET_32BIT"
40dbec34 2838 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2839 [(set_attr "length" "8")
25f905c2 2840 (set_attr "ce_count" "2")
0d66636f 2841 (set_attr "predicable" "yes")]
cffb2a26 2842)
9c08d1fa 2843
25f905c2 2844; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2845; insns are available?
d7863cfe 2846(define_split
2847 [(set (match_operand:SI 0 "s_register_operand" "")
2848 (match_operator:SI 1 "logical_binary_operator"
2849 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2850 (match_operand:SI 3 "const_int_operand" "")
2851 (match_operand:SI 4 "const_int_operand" ""))
2852 (match_operator:SI 9 "logical_binary_operator"
2853 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2854 (match_operand:SI 6 "const_int_operand" ""))
2855 (match_operand:SI 7 "s_register_operand" "")])]))
2856 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2857 "TARGET_32BIT
d7863cfe 2858 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2859 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2860 [(set (match_dup 8)
2861 (match_op_dup 1
2862 [(ashift:SI (match_dup 2) (match_dup 4))
2863 (match_dup 5)]))
2864 (set (match_dup 0)
2865 (match_op_dup 1
2866 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2867 (match_dup 7)]))]
2868 "
2869 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2870")
2871
2872(define_split
2873 [(set (match_operand:SI 0 "s_register_operand" "")
2874 (match_operator:SI 1 "logical_binary_operator"
2875 [(match_operator:SI 9 "logical_binary_operator"
2876 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2877 (match_operand:SI 6 "const_int_operand" ""))
2878 (match_operand:SI 7 "s_register_operand" "")])
2879 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2880 (match_operand:SI 3 "const_int_operand" "")
2881 (match_operand:SI 4 "const_int_operand" ""))]))
2882 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2883 "TARGET_32BIT
d7863cfe 2884 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2885 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2886 [(set (match_dup 8)
2887 (match_op_dup 1
2888 [(ashift:SI (match_dup 2) (match_dup 4))
2889 (match_dup 5)]))
2890 (set (match_dup 0)
2891 (match_op_dup 1
2892 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2893 (match_dup 7)]))]
2894 "
2895 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2896")
2897
2898(define_split
2899 [(set (match_operand:SI 0 "s_register_operand" "")
2900 (match_operator:SI 1 "logical_binary_operator"
2901 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2902 (match_operand:SI 3 "const_int_operand" "")
2903 (match_operand:SI 4 "const_int_operand" ""))
2904 (match_operator:SI 9 "logical_binary_operator"
2905 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2906 (match_operand:SI 6 "const_int_operand" ""))
2907 (match_operand:SI 7 "s_register_operand" "")])]))
2908 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2909 "TARGET_32BIT
d7863cfe 2910 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2911 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2912 [(set (match_dup 8)
2913 (match_op_dup 1
2914 [(ashift:SI (match_dup 2) (match_dup 4))
2915 (match_dup 5)]))
2916 (set (match_dup 0)
2917 (match_op_dup 1
2918 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2919 (match_dup 7)]))]
2920 "
2921 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2922")
2923
2924(define_split
2925 [(set (match_operand:SI 0 "s_register_operand" "")
2926 (match_operator:SI 1 "logical_binary_operator"
2927 [(match_operator:SI 9 "logical_binary_operator"
2928 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2929 (match_operand:SI 6 "const_int_operand" ""))
2930 (match_operand:SI 7 "s_register_operand" "")])
2931 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2932 (match_operand:SI 3 "const_int_operand" "")
2933 (match_operand:SI 4 "const_int_operand" ""))]))
2934 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2935 "TARGET_32BIT
d7863cfe 2936 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2937 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2938 [(set (match_dup 8)
2939 (match_op_dup 1
2940 [(ashift:SI (match_dup 2) (match_dup 4))
2941 (match_dup 5)]))
2942 (set (match_dup 0)
2943 (match_op_dup 1
2944 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2945 (match_dup 7)]))]
2946 "
2947 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2948")
9c08d1fa 2949\f
2950
2951;; Minimum and maximum insns
2952
8b9dc177 2953(define_expand "smaxsi3"
2954 [(parallel [
2955 (set (match_operand:SI 0 "s_register_operand" "")
2956 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2957 (match_operand:SI 2 "arm_rhs_operand" "")))
2958 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2959 "TARGET_32BIT"
8b9dc177 2960 "
8774928b 2961 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 2962 {
2963 /* No need for a clobber of the condition code register here. */
2964 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2965 gen_rtx_SMAX (SImode, operands[1],
2966 operands[2])));
2967 DONE;
2968 }
2969")
2970
2971(define_insn "*smax_0"
2972 [(set (match_operand:SI 0 "s_register_operand" "=r")
2973 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2974 (const_int 0)))]
25f905c2 2975 "TARGET_32BIT"
8b9dc177 2976 "bic%?\\t%0, %1, %1, asr #31"
2977 [(set_attr "predicable" "yes")]
2978)
2979
8774928b 2980(define_insn "*smax_m1"
2981 [(set (match_operand:SI 0 "s_register_operand" "=r")
2982 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2983 (const_int -1)))]
25f905c2 2984 "TARGET_32BIT"
8774928b 2985 "orr%?\\t%0, %1, %1, asr #31"
2986 [(set_attr "predicable" "yes")]
2987)
2988
25f905c2 2989(define_insn "*arm_smax_insn"
8b9dc177 2990 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2991 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2992 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 2993 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2994 "TARGET_ARM"
e2348bcb 2995 "@
2996 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 2997 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2998 [(set_attr "conds" "clob")
8b9dc177 2999 (set_attr "length" "8,12")]
cffb2a26 3000)
9c08d1fa 3001
8b9dc177 3002(define_expand "sminsi3"
3003 [(parallel [
3004 (set (match_operand:SI 0 "s_register_operand" "")
3005 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3006 (match_operand:SI 2 "arm_rhs_operand" "")))
3007 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3008 "TARGET_32BIT"
8b9dc177 3009 "
3010 if (operands[2] == const0_rtx)
3011 {
3012 /* No need for a clobber of the condition code register here. */
3013 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3014 gen_rtx_SMIN (SImode, operands[1],
3015 operands[2])));
3016 DONE;
3017 }
3018")
3019
3020(define_insn "*smin_0"
3021 [(set (match_operand:SI 0 "s_register_operand" "=r")
3022 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3023 (const_int 0)))]
25f905c2 3024 "TARGET_32BIT"
8b9dc177 3025 "and%?\\t%0, %1, %1, asr #31"
3026 [(set_attr "predicable" "yes")]
3027)
3028
25f905c2 3029(define_insn "*arm_smin_insn"
8b9dc177 3030 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3031 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3032 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3033 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3034 "TARGET_ARM"
e2348bcb 3035 "@
3036 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3037 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3038 [(set_attr "conds" "clob")
8b9dc177 3039 (set_attr "length" "8,12")]
0d66636f 3040)
9c08d1fa 3041
25f905c2 3042(define_expand "umaxsi3"
3043 [(parallel [
3044 (set (match_operand:SI 0 "s_register_operand" "")
3045 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3046 (match_operand:SI 2 "arm_rhs_operand" "")))
3047 (clobber (reg:CC CC_REGNUM))])]
3048 "TARGET_32BIT"
3049 ""
3050)
3051
3052(define_insn "*arm_umaxsi3"
9c08d1fa 3053 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3054 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3055 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3056 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3057 "TARGET_ARM"
e2348bcb 3058 "@
3059 cmp\\t%1, %2\;movcc\\t%0, %2
3060 cmp\\t%1, %2\;movcs\\t%0, %1
3061 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3062 [(set_attr "conds" "clob")
3063 (set_attr "length" "8,8,12")]
3064)
9c08d1fa 3065
25f905c2 3066(define_expand "uminsi3"
3067 [(parallel [
3068 (set (match_operand:SI 0 "s_register_operand" "")
3069 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3070 (match_operand:SI 2 "arm_rhs_operand" "")))
3071 (clobber (reg:CC CC_REGNUM))])]
3072 "TARGET_32BIT"
3073 ""
3074)
3075
3076(define_insn "*arm_uminsi3"
9c08d1fa 3077 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3078 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3079 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3080 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3081 "TARGET_ARM"
e2348bcb 3082 "@
3083 cmp\\t%1, %2\;movcs\\t%0, %2
3084 cmp\\t%1, %2\;movcc\\t%0, %1
3085 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3086 [(set_attr "conds" "clob")
3087 (set_attr "length" "8,8,12")]
3088)
9c08d1fa 3089
8a18b90c 3090(define_insn "*store_minmaxsi"
9c08d1fa 3091 [(set (match_operand:SI 0 "memory_operand" "=m")
3092 (match_operator:SI 3 "minmax_operator"
3093 [(match_operand:SI 1 "s_register_operand" "r")
3094 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3095 (clobber (reg:CC CC_REGNUM))]
25f905c2 3096 "TARGET_32BIT"
9c08d1fa 3097 "*
dc55b8a9 3098 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3099 operands[1], operands[2]);
e2348bcb 3100 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3101 if (TARGET_THUMB2)
3102 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3103 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3104 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3105 return \"\";
0d66636f 3106 "
3107 [(set_attr "conds" "clob")
25f905c2 3108 (set (attr "length")
3109 (if_then_else (eq_attr "is_thumb" "yes")
3110 (const_int 14)
3111 (const_int 12)))
0d66636f 3112 (set_attr "type" "store1")]
3113)
9c08d1fa 3114
8a18b90c 3115; Reject the frame pointer in operand[1], since reloading this after
3116; it has been eliminated can cause carnage.
f7fbdd4a 3117(define_insn "*minmax_arithsi"
9c08d1fa 3118 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3119 (match_operator:SI 4 "shiftable_operator"
3120 [(match_operator:SI 5 "minmax_operator"
3121 [(match_operand:SI 2 "s_register_operand" "r,r")
3122 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3123 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3124 (clobber (reg:CC CC_REGNUM))]
25f905c2 3125 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3126 "*
0d66636f 3127 {
3128 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3129 bool need_else;
3130
3131 if (which_alternative != 0 || operands[3] != const0_rtx
3132 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3133 need_else = true;
3134 else
3135 need_else = false;
0d66636f 3136
dc55b8a9 3137 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3138 operands[2], operands[3]);
0d66636f 3139 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3140 if (TARGET_THUMB2)
3141 {
3142 if (need_else)
3143 output_asm_insn (\"ite\\t%d5\", operands);
3144 else
3145 output_asm_insn (\"it\\t%d5\", operands);
3146 }
0d66636f 3147 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3148 if (need_else)
0d66636f 3149 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3150 return \"\";
215b30b3 3151 }"
0d66636f 3152 [(set_attr "conds" "clob")
25f905c2 3153 (set (attr "length")
3154 (if_then_else (eq_attr "is_thumb" "yes")
3155 (const_int 14)
3156 (const_int 12)))]
0d66636f 3157)
9c08d1fa 3158
b11cae9e 3159\f
3160;; Shift and rotation insns
3161
a2cd141b 3162(define_expand "ashldi3"
3163 [(set (match_operand:DI 0 "s_register_operand" "")
3164 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3165 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3166 "TARGET_32BIT"
a2cd141b 3167 "
3168 if (GET_CODE (operands[2]) == CONST_INT)
3169 {
3170 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3171 {
3172 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3173 DONE;
3174 }
3175 /* Ideally we shouldn't fail here if we could know that operands[1]
3176 ends up already living in an iwmmxt register. Otherwise it's
3177 cheaper to have the alternate code being generated than moving
1d60d981 3178 values to iwmmxt regs and back. */
a2cd141b 3179 FAIL;
3180 }
3181 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3182 FAIL;
3183 "
3184)
3185
3186(define_insn "arm_ashldi3_1bit"
3187 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3188 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3189 (const_int 1)))
3190 (clobber (reg:CC CC_REGNUM))]
25f905c2 3191 "TARGET_32BIT"
a2cd141b 3192 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3193 [(set_attr "conds" "clob")
3194 (set_attr "length" "8")]
3195)
3196
87b22bf7 3197(define_expand "ashlsi3"
cffb2a26 3198 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3199 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3200 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3201 "TARGET_EITHER"
87b22bf7 3202 "
3203 if (GET_CODE (operands[2]) == CONST_INT
3204 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3205 {
3206 emit_insn (gen_movsi (operands[0], const0_rtx));
3207 DONE;
3208 }
cffb2a26 3209 "
3210)
3211
25f905c2 3212(define_insn "*thumb1_ashlsi3"
cffb2a26 3213 [(set (match_operand:SI 0 "register_operand" "=l,l")
3214 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3215 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3216 "TARGET_THUMB1"
cffb2a26 3217 "lsl\\t%0, %1, %2"
3218 [(set_attr "length" "2")]
3219)
b11cae9e 3220
a2cd141b 3221(define_expand "ashrdi3"
3222 [(set (match_operand:DI 0 "s_register_operand" "")
3223 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3224 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3225 "TARGET_32BIT"
a2cd141b 3226 "
3227 if (GET_CODE (operands[2]) == CONST_INT)
3228 {
3229 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3230 {
3231 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3232 DONE;
3233 }
3234 /* Ideally we shouldn't fail here if we could know that operands[1]
3235 ends up already living in an iwmmxt register. Otherwise it's
3236 cheaper to have the alternate code being generated than moving
1d60d981 3237 values to iwmmxt regs and back. */
a2cd141b 3238 FAIL;
3239 }
3240 else if (!TARGET_REALLY_IWMMXT)
3241 FAIL;
3242 "
3243)
3244
3245(define_insn "arm_ashrdi3_1bit"
3246 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3247 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3248 (const_int 1)))
3249 (clobber (reg:CC CC_REGNUM))]
25f905c2 3250 "TARGET_32BIT"
a2cd141b 3251 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3252 [(set_attr "conds" "clob")
3253 (set_attr "length" "8")]
3254)
3255
87b22bf7 3256(define_expand "ashrsi3"
cffb2a26 3257 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3258 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3259 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3260 "TARGET_EITHER"
87b22bf7 3261 "
3262 if (GET_CODE (operands[2]) == CONST_INT
3263 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3264 operands[2] = GEN_INT (31);
cffb2a26 3265 "
3266)
3267
25f905c2 3268(define_insn "*thumb1_ashrsi3"
cffb2a26 3269 [(set (match_operand:SI 0 "register_operand" "=l,l")
3270 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3271 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3272 "TARGET_THUMB1"
cffb2a26 3273 "asr\\t%0, %1, %2"
3274 [(set_attr "length" "2")]
3275)
b11cae9e 3276
a2cd141b 3277(define_expand "lshrdi3"
3278 [(set (match_operand:DI 0 "s_register_operand" "")
3279 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3280 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3281 "TARGET_32BIT"
a2cd141b 3282 "
3283 if (GET_CODE (operands[2]) == CONST_INT)
3284 {
3285 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3286 {
3287 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3288 DONE;
3289 }
3290 /* Ideally we shouldn't fail here if we could know that operands[1]
3291 ends up already living in an iwmmxt register. Otherwise it's
3292 cheaper to have the alternate code being generated than moving
1d60d981 3293 values to iwmmxt regs and back. */
a2cd141b 3294 FAIL;
3295 }
3296 else if (!TARGET_REALLY_IWMMXT)
3297 FAIL;
3298 "
3299)
3300
3301(define_insn "arm_lshrdi3_1bit"
3302 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3303 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3304 (const_int 1)))
3305 (clobber (reg:CC CC_REGNUM))]
25f905c2 3306 "TARGET_32BIT"
a2cd141b 3307 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3308 [(set_attr "conds" "clob")
3309 (set_attr "length" "8")]
3310)
3311
87b22bf7 3312(define_expand "lshrsi3"
cffb2a26 3313 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3314 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3315 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3316 "TARGET_EITHER"
87b22bf7 3317 "
3318 if (GET_CODE (operands[2]) == CONST_INT
3319 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3320 {
3321 emit_insn (gen_movsi (operands[0], const0_rtx));
3322 DONE;
3323 }
cffb2a26 3324 "
3325)
3326
25f905c2 3327(define_insn "*thumb1_lshrsi3"
cffb2a26 3328 [(set (match_operand:SI 0 "register_operand" "=l,l")
3329 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3330 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3331 "TARGET_THUMB1"
cffb2a26 3332 "lsr\\t%0, %1, %2"
3333 [(set_attr "length" "2")]
3334)
b11cae9e 3335
87b22bf7 3336(define_expand "rotlsi3"
cffb2a26 3337 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3338 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3339 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3340 "TARGET_32BIT"
87b22bf7 3341 "
3342 if (GET_CODE (operands[2]) == CONST_INT)
3343 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3344 else
b11cae9e 3345 {
87b22bf7 3346 rtx reg = gen_reg_rtx (SImode);
3347 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3348 operands[2] = reg;
b11cae9e 3349 }
cffb2a26 3350 "
3351)
9c08d1fa 3352
87b22bf7 3353(define_expand "rotrsi3"
cffb2a26 3354 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3355 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3356 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3357 "TARGET_EITHER"
87b22bf7 3358 "
25f905c2 3359 if (TARGET_32BIT)
cffb2a26 3360 {
3361 if (GET_CODE (operands[2]) == CONST_INT
3362 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3363 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3364 }
25f905c2 3365 else /* TARGET_THUMB1 */
cffb2a26 3366 {
3367 if (GET_CODE (operands [2]) == CONST_INT)
3368 operands [2] = force_reg (SImode, operands[2]);
3369 }
3370 "
3371)
87b22bf7 3372
25f905c2 3373(define_insn "*thumb1_rotrsi3"
cffb2a26 3374 [(set (match_operand:SI 0 "register_operand" "=l")
3375 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3376 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3377 "TARGET_THUMB1"
cffb2a26 3378 "ror\\t%0, %0, %2"
3379 [(set_attr "length" "2")]
3380)
3381
3382(define_insn "*arm_shiftsi3"
3383 [(set (match_operand:SI 0 "s_register_operand" "=r")
3384 (match_operator:SI 3 "shift_operator"
3385 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3386 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3387 "TARGET_32BIT"
3388 "* return arm_output_shift(operands, 0);"
344495ea 3389 [(set_attr "predicable" "yes")
331beb1a 3390 (set_attr "shift" "1")
a2cd141b 3391 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3392 (const_string "alu_shift")
3393 (const_string "alu_shift_reg")))]
6c4c2133 3394)
87b22bf7 3395
f7fbdd4a 3396(define_insn "*shiftsi3_compare0"
bd5b4116 3397 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3398 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3399 [(match_operand:SI 1 "s_register_operand" "r")
3400 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3401 (const_int 0)))
3402 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3403 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3404 "TARGET_32BIT"
3405 "* return arm_output_shift(operands, 1);"
344495ea 3406 [(set_attr "conds" "set")
331beb1a 3407 (set_attr "shift" "1")
a2cd141b 3408 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3409 (const_string "alu_shift")
3410 (const_string "alu_shift_reg")))]
0d66636f 3411)
9c08d1fa 3412
f7fbdd4a 3413(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3414 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3415 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3416 [(match_operand:SI 1 "s_register_operand" "r")
3417 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3418 (const_int 0)))
3419 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3420 "TARGET_32BIT"
3421 "* return arm_output_shift(operands, 1);"
344495ea 3422 [(set_attr "conds" "set")
a2cd141b 3423 (set_attr "shift" "1")]
0d66636f 3424)
9c08d1fa 3425
25f905c2 3426(define_insn "*arm_notsi_shiftsi"
9c08d1fa 3427 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3428 (not:SI (match_operator:SI 3 "shift_operator"
3429 [(match_operand:SI 1 "s_register_operand" "r")
3430 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 3431 "TARGET_ARM"
6c4c2133 3432 "mvn%?\\t%0, %1%S3"
344495ea 3433 [(set_attr "predicable" "yes")
331beb1a 3434 (set_attr "shift" "1")
a2cd141b 3435 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3436 (const_string "alu_shift")
3437 (const_string "alu_shift_reg")))]
0d66636f 3438)
9c08d1fa 3439
25f905c2 3440(define_insn "*arm_notsi_shiftsi_compare0"
bd5b4116 3441 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3442 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3443 [(match_operand:SI 1 "s_register_operand" "r")
3444 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3445 (const_int 0)))
3446 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3447 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 3448 "TARGET_ARM"
25f905c2 3449 "mvn%.\\t%0, %1%S3"
344495ea 3450 [(set_attr "conds" "set")
331beb1a 3451 (set_attr "shift" "1")
a2cd141b 3452 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3453 (const_string "alu_shift")
3454 (const_string "alu_shift_reg")))]
0d66636f 3455)
9c08d1fa 3456
25f905c2 3457(define_insn "*arm_not_shiftsi_compare0_scratch"
bd5b4116 3458 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3459 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3460 [(match_operand:SI 1 "s_register_operand" "r")
3461 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3462 (const_int 0)))
3463 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3464 "TARGET_ARM"
25f905c2 3465 "mvn%.\\t%0, %1%S3"
344495ea 3466 [(set_attr "conds" "set")
331beb1a 3467 (set_attr "shift" "1")
a2cd141b 3468 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3469 (const_string "alu_shift")
3470 (const_string "alu_shift_reg")))]
0d66636f 3471)
9c08d1fa 3472
cffb2a26 3473;; We don't really have extzv, but defining this using shifts helps
3474;; to reduce register pressure later on.
3475
3476(define_expand "extzv"
3477 [(set (match_dup 4)
3478 (ashift:SI (match_operand:SI 1 "register_operand" "")
3479 (match_operand:SI 2 "const_int_operand" "")))
3480 (set (match_operand:SI 0 "register_operand" "")
3481 (lshiftrt:SI (match_dup 4)
215b30b3 3482 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3483 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3484 "
3485 {
3486 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3487 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3488
8b054d5a 3489 if (arm_arch_thumb2)
3490 {
3491 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3492 operands[3]));
3493 DONE;
3494 }
3495
cffb2a26 3496 operands[3] = GEN_INT (rshift);
3497
3498 if (lshift == 0)
3499 {
3500 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3501 DONE;
3502 }
3503
3504 operands[2] = GEN_INT (lshift);
3505 operands[4] = gen_reg_rtx (SImode);
215b30b3 3506 }"
cffb2a26 3507)
3508
8b054d5a 3509(define_insn "extv"
3510 [(set (match_operand:SI 0 "s_register_operand" "=r")
3511 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3512 (match_operand:SI 2 "const_int_operand" "M")
3513 (match_operand:SI 3 "const_int_operand" "M")))]
3514 "arm_arch_thumb2"
3515 "sbfx%?\t%0, %1, %3, %2"
3516 [(set_attr "length" "4")
3517 (set_attr "predicable" "yes")]
3518)
3519
3520(define_insn "extzv_t2"
3521 [(set (match_operand:SI 0 "s_register_operand" "=r")
3522 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3523 (match_operand:SI 2 "const_int_operand" "M")
3524 (match_operand:SI 3 "const_int_operand" "M")))]
3525 "arm_arch_thumb2"
3526 "ubfx%?\t%0, %1, %3, %2"
3527 [(set_attr "length" "4")
3528 (set_attr "predicable" "yes")]
3529)
3530
b11cae9e 3531\f
3532;; Unary arithmetic insns
3533
cffb2a26 3534(define_expand "negdi2"
3535 [(parallel
8135a42b 3536 [(set (match_operand:DI 0 "s_register_operand" "")
3537 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3538 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3539 "TARGET_EITHER"
8135a42b 3540 ""
cffb2a26 3541)
3542
3543;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 3544;; The first alternative allows the common case of a *full* overlap.
cffb2a26 3545(define_insn "*arm_negdi2"
3546 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
e5fea38e 3547 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 3548 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3549 "TARGET_ARM"
97499065 3550 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3551 [(set_attr "conds" "clob")
3552 (set_attr "length" "8")]
3553)
b11cae9e 3554
25f905c2 3555(define_insn "*thumb1_negdi2"
8135a42b 3556 [(set (match_operand:DI 0 "register_operand" "=&l")
3557 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3558 (clobber (reg:CC CC_REGNUM))]
25f905c2 3559 "TARGET_THUMB1"
cffb2a26 3560 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3561 [(set_attr "length" "6")]
3562)
3563
3564(define_expand "negsi2"
3565 [(set (match_operand:SI 0 "s_register_operand" "")
3566 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3567 "TARGET_EITHER"
b11cae9e 3568 ""
cffb2a26 3569)
3570
3571(define_insn "*arm_negsi2"
3572 [(set (match_operand:SI 0 "s_register_operand" "=r")
3573 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3574 "TARGET_32BIT"
cffb2a26 3575 "rsb%?\\t%0, %1, #0"
0d66636f 3576 [(set_attr "predicable" "yes")]
cffb2a26 3577)
3578
25f905c2 3579(define_insn "*thumb1_negsi2"
cffb2a26 3580 [(set (match_operand:SI 0 "register_operand" "=l")
3581 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3582 "TARGET_THUMB1"
cffb2a26 3583 "neg\\t%0, %1"
3584 [(set_attr "length" "2")]
3585)
b11cae9e 3586
604f3a0a 3587(define_expand "negsf2"
3588 [(set (match_operand:SF 0 "s_register_operand" "")
3589 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3590 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3591 ""
3592)
3593
3594(define_expand "negdf2"
3595 [(set (match_operand:DF 0 "s_register_operand" "")
3596 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3597 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3598 "")
3599
9c08d1fa 3600;; abssi2 doesn't really clobber the condition codes if a different register
3601;; is being set. To keep things simple, assume during rtl manipulations that
3602;; it does, but tell the final scan operator the truth. Similarly for
3603;; (neg (abs...))
3604
604f3a0a 3605(define_expand "abssi2"
3606 [(parallel
3607 [(set (match_operand:SI 0 "s_register_operand" "")
3608 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3609 (clobber (match_dup 2))])]
3610 "TARGET_EITHER"
3611 "
25f905c2 3612 if (TARGET_THUMB1)
ba156559 3613 operands[2] = gen_rtx_SCRATCH (SImode);
3614 else
3615 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3616")
604f3a0a 3617
7d57ec45 3618(define_insn "*arm_abssi2"
ba156559 3619 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3620 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3621 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3622 "TARGET_ARM"
e2348bcb 3623 "@
3624 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3625 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3626 [(set_attr "conds" "clob,*")
331beb1a 3627 (set_attr "shift" "1")
0d66636f 3628 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3629 (set_attr "length" "8")]
3630)
9c08d1fa 3631
25f905c2 3632(define_insn_and_split "*thumb1_abssi2"
ba156559 3633 [(set (match_operand:SI 0 "s_register_operand" "=l")
3634 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3635 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3636 "TARGET_THUMB1"
ba156559 3637 "#"
25f905c2 3638 "TARGET_THUMB1 && reload_completed"
ba156559 3639 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3640 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3641 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3642 ""
3643 [(set_attr "length" "6")]
3644)
3645
3646(define_insn "*arm_neg_abssi2"
9c08d1fa 3647 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3648 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3649 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3650 "TARGET_ARM"
e2348bcb 3651 "@
3652 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3653 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3654 [(set_attr "conds" "clob,*")
331beb1a 3655 (set_attr "shift" "1")
0d66636f 3656 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3657 (set_attr "length" "8")]
3658)
b11cae9e 3659
25f905c2 3660(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3661 [(set (match_operand:SI 0 "s_register_operand" "=l")
3662 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3663 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3664 "TARGET_THUMB1"
ba156559 3665 "#"
25f905c2 3666 "TARGET_THUMB1 && reload_completed"
ba156559 3667 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3668 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3669 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3670 ""
3671 [(set_attr "length" "6")]
3672)
3673
604f3a0a 3674(define_expand "abssf2"
3675 [(set (match_operand:SF 0 "s_register_operand" "")
3676 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3677 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3678 "")
3679
604f3a0a 3680(define_expand "absdf2"
3681 [(set (match_operand:DF 0 "s_register_operand" "")
3682 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3683 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3684 "")
3685
7db9af5d 3686(define_expand "sqrtsf2"
3687 [(set (match_operand:SF 0 "s_register_operand" "")
3688 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3689 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3690 "")
9c08d1fa 3691
7db9af5d 3692(define_expand "sqrtdf2"
3693 [(set (match_operand:DF 0 "s_register_operand" "")
3694 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3695 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3696 "")
9c08d1fa 3697
a0f94409 3698(define_insn_and_split "one_cmpldi2"
9c08d1fa 3699 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 3700 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3701 "TARGET_32BIT"
f6ebffac 3702 "#"
25f905c2 3703 "TARGET_32BIT && reload_completed"
a0f94409 3704 [(set (match_dup 0) (not:SI (match_dup 1)))
3705 (set (match_dup 2) (not:SI (match_dup 3)))]
3706 "
3707 {
3708 operands[2] = gen_highpart (SImode, operands[0]);
3709 operands[0] = gen_lowpart (SImode, operands[0]);
3710 operands[3] = gen_highpart (SImode, operands[1]);
3711 operands[1] = gen_lowpart (SImode, operands[1]);
3712 }"
0d66636f 3713 [(set_attr "length" "8")
3714 (set_attr "predicable" "yes")]
cffb2a26 3715)
b11cae9e 3716
cffb2a26 3717(define_expand "one_cmplsi2"
3718 [(set (match_operand:SI 0 "s_register_operand" "")
3719 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3720 "TARGET_EITHER"
b11cae9e 3721 ""
cffb2a26 3722)
3723
3724(define_insn "*arm_one_cmplsi2"
3725 [(set (match_operand:SI 0 "s_register_operand" "=r")
3726 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3727 "TARGET_32BIT"
cffb2a26 3728 "mvn%?\\t%0, %1"
0d66636f 3729 [(set_attr "predicable" "yes")]
cffb2a26 3730)
3731
25f905c2 3732(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3733 [(set (match_operand:SI 0 "register_operand" "=l")
3734 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3735 "TARGET_THUMB1"
cffb2a26 3736 "mvn\\t%0, %1"
3737 [(set_attr "length" "2")]
3738)
9c08d1fa 3739
f7fbdd4a 3740(define_insn "*notsi_compare0"
bd5b4116 3741 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3742 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3743 (const_int 0)))
3744 (set (match_operand:SI 0 "s_register_operand" "=r")
3745 (not:SI (match_dup 1)))]
25f905c2 3746 "TARGET_32BIT"
3747 "mvn%.\\t%0, %1"
cffb2a26 3748 [(set_attr "conds" "set")]
3749)
9c08d1fa 3750
f7fbdd4a 3751(define_insn "*notsi_compare0_scratch"
bd5b4116 3752 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3753 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3754 (const_int 0)))
3755 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3756 "TARGET_32BIT"
3757 "mvn%.\\t%0, %1"
cffb2a26 3758 [(set_attr "conds" "set")]
3759)
b11cae9e 3760\f
3761;; Fixed <--> Floating conversion insns
3762
9b8516be 3763(define_expand "floatsihf2"
3764 [(set (match_operand:HF 0 "general_operand" "")
3765 (float:HF (match_operand:SI 1 "general_operand" "")))]
3766 "TARGET_EITHER"
3767 "
3768 {
3769 rtx op1 = gen_reg_rtx (SFmode);
3770 expand_float (op1, operands[1], 0);
3771 op1 = convert_to_mode (HFmode, op1, 0);
3772 emit_move_insn (operands[0], op1);
3773 DONE;
3774 }"
3775)
3776
3777(define_expand "floatdihf2"
3778 [(set (match_operand:HF 0 "general_operand" "")
3779 (float:HF (match_operand:DI 1 "general_operand" "")))]
3780 "TARGET_EITHER"
3781 "
3782 {
3783 rtx op1 = gen_reg_rtx (SFmode);
3784 expand_float (op1, operands[1], 0);
3785 op1 = convert_to_mode (HFmode, op1, 0);
3786 emit_move_insn (operands[0], op1);
3787 DONE;
3788 }"
3789)
3790
604f3a0a 3791(define_expand "floatsisf2"
3792 [(set (match_operand:SF 0 "s_register_operand" "")
3793 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3794 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3795 "
a2cd141b 3796 if (TARGET_MAVERICK)
604f3a0a 3797 {
3798 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3799 DONE;
3800 }
3801")
3802
604f3a0a 3803(define_expand "floatsidf2"
3804 [(set (match_operand:DF 0 "s_register_operand" "")
3805 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 3806 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3807 "
a2cd141b 3808 if (TARGET_MAVERICK)
604f3a0a 3809 {
3810 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3811 DONE;
3812 }
3813")
3814
9b8516be 3815(define_expand "fix_trunchfsi2"
3816 [(set (match_operand:SI 0 "general_operand" "")
3817 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3818 "TARGET_EITHER"
3819 "
3820 {
3821 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3822 expand_fix (operands[0], op1, 0);
3823 DONE;
3824 }"
3825)
3826
3827(define_expand "fix_trunchfdi2"
3828 [(set (match_operand:DI 0 "general_operand" "")
3829 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3830 "TARGET_EITHER"
3831 "
3832 {
3833 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3834 expand_fix (operands[0], op1, 0);
3835 DONE;
3836 }"
3837)
3838
604f3a0a 3839(define_expand "fix_truncsfsi2"
3840 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3841 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3842 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3843 "
a2cd141b 3844 if (TARGET_MAVERICK)
604f3a0a 3845 {
3846 if (!cirrus_fp_register (operands[0], SImode))
3847 operands[0] = force_reg (SImode, operands[0]);
3848 if (!cirrus_fp_register (operands[1], SFmode))
3849 operands[1] = force_reg (SFmode, operands[0]);
3850 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3851 DONE;
3852 }
3853")
3854
604f3a0a 3855(define_expand "fix_truncdfsi2"
3856 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3857 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 3858 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3859 "
a2cd141b 3860 if (TARGET_MAVERICK)
604f3a0a 3861 {
3862 if (!cirrus_fp_register (operands[1], DFmode))
3863 operands[1] = force_reg (DFmode, operands[0]);
3864 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3865 DONE;
3866 }
3867")
3868
f544c6d2 3869;; Truncation insns
b11cae9e 3870
604f3a0a 3871(define_expand "truncdfsf2"
3872 [(set (match_operand:SF 0 "s_register_operand" "")
3873 (float_truncate:SF
3874 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3875 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3876 ""
3877)
9b8516be 3878
3879/* DFmode -> HFmode conversions have to go through SFmode. */
3880(define_expand "truncdfhf2"
3881 [(set (match_operand:HF 0 "general_operand" "")
3882 (float_truncate:HF
3883 (match_operand:DF 1 "general_operand" "")))]
3884 "TARGET_EITHER"
3885 "
3886 {
3887 rtx op1;
3888 op1 = convert_to_mode (SFmode, operands[1], 0);
3889 op1 = convert_to_mode (HFmode, op1, 0);
3890 emit_move_insn (operands[0], op1);
3891 DONE;
3892 }"
3893)
b11cae9e 3894\f
9c08d1fa 3895;; Zero and sign extension instructions.
b11cae9e 3896
25f905c2 3897(define_expand "zero_extendsidi2"
3898 [(set (match_operand:DI 0 "s_register_operand" "")
3899 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3900 "TARGET_32BIT"
3901 ""
3902)
3903
3904(define_insn "*arm_zero_extendsidi2"
9c08d1fa 3905 [(set (match_operand:DI 0 "s_register_operand" "=r")
3906 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3907 "TARGET_ARM"
9c08d1fa 3908 "*
0d66636f 3909 if (REGNO (operands[1])
3910 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3911 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3912 return \"mov%?\\t%R0, #0\";
3913 "
3914 [(set_attr "length" "8")
3915 (set_attr "predicable" "yes")]
3916)
9c08d1fa 3917
25f905c2 3918(define_expand "zero_extendqidi2"
3919 [(set (match_operand:DI 0 "s_register_operand" "")
3920 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3921 "TARGET_32BIT"
3922 ""
3923)
3924
3925(define_insn "*arm_zero_extendqidi2"
cffb2a26 3926 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3927 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3928 "TARGET_ARM"
e2348bcb 3929 "@
97499065 3930 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
25f905c2 3931 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3932 [(set_attr "length" "8")
0d66636f 3933 (set_attr "predicable" "yes")
a2cd141b 3934 (set_attr "type" "*,load_byte")
cffb2a26 3935 (set_attr "pool_range" "*,4092")
3936 (set_attr "neg_pool_range" "*,4084")]
3937)
9c08d1fa 3938
25f905c2 3939(define_expand "extendsidi2"
3940 [(set (match_operand:DI 0 "s_register_operand" "")
3941 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3942 "TARGET_32BIT"
3943 ""
3944)
3945
3946(define_insn "*arm_extendsidi2"
9c08d1fa 3947 [(set (match_operand:DI 0 "s_register_operand" "=r")
3948 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3949 "TARGET_ARM"
9c08d1fa 3950 "*
0d66636f 3951 if (REGNO (operands[1])
3952 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3953 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3954 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3955 "
3956 [(set_attr "length" "8")
331beb1a 3957 (set_attr "shift" "1")
0d66636f 3958 (set_attr "predicable" "yes")]
3959)
9c08d1fa 3960
3961(define_expand "zero_extendhisi2"
cffb2a26 3962 [(set (match_dup 2)
0d66636f 3963 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3964 (const_int 16)))
9c08d1fa 3965 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3966 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3967 "TARGET_EITHER"
9c08d1fa 3968 "
cffb2a26 3969 {
25f905c2 3970 if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3971 {
a2cd141b 3972 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3973 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3974 DONE;
cffb2a26 3975 }
cffb2a26 3976
c1a66faf 3977 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3978 {
3979 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3980 DONE;
3981 }
cffb2a26 3982
a2cd141b 3983 if (!s_register_operand (operands[1], HImode))
3984 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3985
a2cd141b 3986 if (arm_arch6)
3987 {
3988 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3989 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3990 DONE;
cffb2a26 3991 }
a2cd141b 3992
3993 operands[1] = gen_lowpart (SImode, operands[1]);
3994 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3995 }"
3996)
3997
25f905c2 3998(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 3999 [(set (match_operand:SI 0 "register_operand" "=l")
4000 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
25f905c2 4001 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4002 "*
4003 rtx mem = XEXP (operands[1], 0);
4004
4005 if (GET_CODE (mem) == CONST)
4006 mem = XEXP (mem, 0);
4007
4008 if (GET_CODE (mem) == LABEL_REF)
4009 return \"ldr\\t%0, %1\";
4010
4011 if (GET_CODE (mem) == PLUS)
f7fbdd4a 4012 {
cffb2a26 4013 rtx a = XEXP (mem, 0);
4014 rtx b = XEXP (mem, 1);
4015
4016 /* This can happen due to bugs in reload. */
4017 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4018 {
4019 rtx ops[2];
4020 ops[0] = operands[0];
4021 ops[1] = a;
4022
4023 output_asm_insn (\"mov %0, %1\", ops);
4024
4025 XEXP (mem, 0) = operands[0];
4026 }
4027
4028 else if ( GET_CODE (a) == LABEL_REF
4029 && GET_CODE (b) == CONST_INT)
4030 return \"ldr\\t%0, %1\";
25f7a26e 4031 }
cffb2a26 4032
4033 return \"ldrh\\t%0, %1\";
4034 "
4035 [(set_attr "length" "4")
a2cd141b 4036 (set_attr "type" "load_byte")
cffb2a26 4037 (set_attr "pool_range" "60")]
4038)
9c08d1fa 4039
25f905c2 4040(define_insn "*thumb1_zero_extendhisi2_v6"
a2cd141b 4041 [(set (match_operand:SI 0 "register_operand" "=l,l")
4042 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4043 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4044 "*
4045 rtx mem;
4046
4047 if (which_alternative == 0)
4048 return \"uxth\\t%0, %1\";
4049
4050 mem = XEXP (operands[1], 0);
4051
4052 if (GET_CODE (mem) == CONST)
4053 mem = XEXP (mem, 0);
4054
4055 if (GET_CODE (mem) == LABEL_REF)
4056 return \"ldr\\t%0, %1\";
4057
4058 if (GET_CODE (mem) == PLUS)
4059 {
4060 rtx a = XEXP (mem, 0);
4061 rtx b = XEXP (mem, 1);
4062
4063 /* This can happen due to bugs in reload. */
4064 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4065 {
4066 rtx ops[2];
4067 ops[0] = operands[0];
4068 ops[1] = a;
4069
4070 output_asm_insn (\"mov %0, %1\", ops);
4071
4072 XEXP (mem, 0) = operands[0];
4073 }
4074
4075 else if ( GET_CODE (a) == LABEL_REF
4076 && GET_CODE (b) == CONST_INT)
4077 return \"ldr\\t%0, %1\";
4078 }
4079
4080 return \"ldrh\\t%0, %1\";
4081 "
4082 [(set_attr "length" "2,4")
4083 (set_attr "type" "alu_shift,load_byte")
4084 (set_attr "pool_range" "*,60")]
4085)
4086
cffb2a26 4087(define_insn "*arm_zero_extendhisi2"
a2cd141b 4088 [(set (match_operand:SI 0 "s_register_operand" "=r")
4089 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4090 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4091 "ldr%(h%)\\t%0, %1"
a2cd141b 4092 [(set_attr "type" "load_byte")
0d66636f 4093 (set_attr "predicable" "yes")
cffb2a26 4094 (set_attr "pool_range" "256")
4095 (set_attr "neg_pool_range" "244")]
4096)
f7fbdd4a 4097
a2cd141b 4098(define_insn "*arm_zero_extendhisi2_v6"
4099 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4100 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4101 "TARGET_ARM && arm_arch6"
4102 "@
4103 uxth%?\\t%0, %1
25f905c2 4104 ldr%(h%)\\t%0, %1"
a2cd141b 4105 [(set_attr "type" "alu_shift,load_byte")
4106 (set_attr "predicable" "yes")
4107 (set_attr "pool_range" "*,256")
4108 (set_attr "neg_pool_range" "*,244")]
4109)
4110
4111(define_insn "*arm_zero_extendhisi2addsi"
4112 [(set (match_operand:SI 0 "s_register_operand" "=r")
4113 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4114 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4115 "TARGET_INT_SIMD"
a2cd141b 4116 "uxtah%?\\t%0, %2, %1"
4117 [(set_attr "type" "alu_shift")
4118 (set_attr "predicable" "yes")]
4119)
4120
87b22bf7 4121(define_expand "zero_extendqisi2"
cffb2a26 4122 [(set (match_operand:SI 0 "s_register_operand" "")
4123 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4124 "TARGET_EITHER"
87b22bf7 4125 "
a2cd141b 4126 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4127 {
cffb2a26 4128 if (TARGET_ARM)
4129 {
215b30b3 4130 emit_insn (gen_andsi3 (operands[0],
4131 gen_lowpart (SImode, operands[1]),
cffb2a26 4132 GEN_INT (255)));
4133 }
4134 else /* TARGET_THUMB */
4135 {
4136 rtx temp = gen_reg_rtx (SImode);
4137 rtx ops[3];
4138
4139 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4140 operands[1] = gen_lowpart (SImode, operands[1]);
4141
4142 ops[0] = temp;
4143 ops[1] = operands[1];
4144 ops[2] = GEN_INT (24);
4145
215b30b3 4146 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4147 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 4148
4149 ops[0] = operands[0];
4150 ops[1] = temp;
4151 ops[2] = GEN_INT (24);
4152
215b30b3 4153 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4154 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 4155 }
87b22bf7 4156 DONE;
4157 }
215b30b3 4158 "
4159)
9c08d1fa 4160
25f905c2 4161(define_insn "*thumb1_zero_extendqisi2"
a2cd141b 4162 [(set (match_operand:SI 0 "register_operand" "=l")
4163 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
25f905c2 4164 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4165 "ldrb\\t%0, %1"
4166 [(set_attr "length" "2")
a2cd141b 4167 (set_attr "type" "load_byte")
cffb2a26 4168 (set_attr "pool_range" "32")]
4169)
4170
25f905c2 4171(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4172 [(set (match_operand:SI 0 "register_operand" "=l,l")
4173 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4174 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4175 "@
4176 uxtb\\t%0, %1
4177 ldrb\\t%0, %1"
4178 [(set_attr "length" "2,2")
4179 (set_attr "type" "alu_shift,load_byte")
4180 (set_attr "pool_range" "*,32")]
4181)
4182
cffb2a26 4183(define_insn "*arm_zero_extendqisi2"
a2cd141b 4184 [(set (match_operand:SI 0 "s_register_operand" "=r")
4185 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4186 "TARGET_ARM && !arm_arch6"
25f905c2 4187 "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4188 [(set_attr "type" "load_byte")
0d66636f 4189 (set_attr "predicable" "yes")
cffb2a26 4190 (set_attr "pool_range" "4096")
4191 (set_attr "neg_pool_range" "4084")]
4192)
87b22bf7 4193
a2cd141b 4194(define_insn "*arm_zero_extendqisi2_v6"
4195 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4196 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4197 "TARGET_ARM && arm_arch6"
4198 "@
25f905c2 4199 uxtb%(%)\\t%0, %1
4200 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4201 [(set_attr "type" "alu_shift,load_byte")
4202 (set_attr "predicable" "yes")
4203 (set_attr "pool_range" "*,4096")
4204 (set_attr "neg_pool_range" "*,4084")]
4205)
4206
4207(define_insn "*arm_zero_extendqisi2addsi"
4208 [(set (match_operand:SI 0 "s_register_operand" "=r")
4209 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4210 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4211 "TARGET_INT_SIMD"
a2cd141b 4212 "uxtab%?\\t%0, %2, %1"
4213 [(set_attr "predicable" "yes")
bcaec148 4214 (set_attr "insn" "xtab")
a2cd141b 4215 (set_attr "type" "alu_shift")]
4216)
4217
87b22bf7 4218(define_split
4219 [(set (match_operand:SI 0 "s_register_operand" "")
4220 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4221 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4222 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4223 [(set (match_dup 2) (match_dup 1))
4224 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4225 ""
4226)
9c08d1fa 4227
8a4d25d6 4228(define_split
4229 [(set (match_operand:SI 0 "s_register_operand" "")
4230 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4231 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4232 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4233 [(set (match_dup 2) (match_dup 1))
4234 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4235 ""
4236)
4237
1c274529 4238(define_code_iterator ior_xor [ior xor])
4239
4240(define_split
4241 [(set (match_operand:SI 0 "s_register_operand" "")
4242 (ior_xor:SI (and:SI (ashift:SI
4243 (match_operand:SI 1 "s_register_operand" "")
4244 (match_operand:SI 2 "const_int_operand" ""))
4245 (match_operand:SI 3 "const_int_operand" ""))
4246 (zero_extend:SI
4247 (match_operator 5 "subreg_lowpart_operator"
4248 [(match_operand:SI 4 "s_register_operand" "")]))))]
4249 "TARGET_32BIT
63787642 4250 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4251 == (GET_MODE_MASK (GET_MODE (operands[5]))
4252 & (GET_MODE_MASK (GET_MODE (operands[5]))
4253 << (INTVAL (operands[2])))))"
4254 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4255 (match_dup 4)))
4256 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4257 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4258)
4259
f7fbdd4a 4260(define_insn "*compareqi_eq0"
bd5b4116 4261 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4262 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4263 (const_int 0)))]
25f905c2 4264 "TARGET_32BIT"
87b22bf7 4265 "tst\\t%0, #255"
cffb2a26 4266 [(set_attr "conds" "set")]
4267)
b11cae9e 4268
b11cae9e 4269(define_expand "extendhisi2"
c8f69309 4270 [(set (match_dup 2)
25f7a26e 4271 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 4272 (const_int 16)))
9c08d1fa 4273 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4274 (ashiftrt:SI (match_dup 2)
4275 (const_int 16)))]
cffb2a26 4276 "TARGET_EITHER"
b11cae9e 4277 "
cffb2a26 4278 {
a2cd141b 4279 if (GET_CODE (operands[1]) == MEM)
cffb2a26 4280 {
25f905c2 4281 if (TARGET_THUMB1)
a2cd141b 4282 {
25f905c2 4283 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4284 DONE;
4285 }
4286 else if (arm_arch4)
4287 {
a2cd141b 4288 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4289 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4290 DONE;
4291 }
cffb2a26 4292 }
7bd8ccc9 4293
c1a66faf 4294 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 4295 {
4296 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4297 DONE;
4298 }
a2cd141b 4299
215b30b3 4300 if (!s_register_operand (operands[1], HImode))
cffb2a26 4301 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 4302
a2cd141b 4303 if (arm_arch6)
cffb2a26 4304 {
25f905c2 4305 if (TARGET_THUMB1)
4306 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4307 else
4308 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4309 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4310
cffb2a26 4311 DONE;
4312 }
a2cd141b 4313
4314 operands[1] = gen_lowpart (SImode, operands[1]);
4315 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4316 }"
4317)
4318
25f905c2 4319(define_insn "thumb1_extendhisi2"
a2cd141b 4320 [(set (match_operand:SI 0 "register_operand" "=l")
4321 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4322 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4323 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4324 "*
4325 {
4326 rtx ops[4];
4327 rtx mem = XEXP (operands[1], 0);
4328
4329 /* This code used to try to use 'V', and fix the address only if it was
4330 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4331 range of QImode offsets, and offsettable_address_p does a QImode
4332 address check. */
4333
4334 if (GET_CODE (mem) == CONST)
4335 mem = XEXP (mem, 0);
4336
4337 if (GET_CODE (mem) == LABEL_REF)
4338 return \"ldr\\t%0, %1\";
4339
4340 if (GET_CODE (mem) == PLUS)
4341 {
4342 rtx a = XEXP (mem, 0);
4343 rtx b = XEXP (mem, 1);
4344
4345 if (GET_CODE (a) == LABEL_REF
4346 && GET_CODE (b) == CONST_INT)
4347 return \"ldr\\t%0, %1\";
4348
4349 if (GET_CODE (b) == REG)
4350 return \"ldrsh\\t%0, %1\";
4351
4352 ops[1] = a;
4353 ops[2] = b;
4354 }
4355 else
4356 {
4357 ops[1] = mem;
4358 ops[2] = const0_rtx;
4359 }
ed29c566 4360
4361 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 4362
4363 ops[0] = operands[0];
4364 ops[3] = operands[2];
4365 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4366 return \"\";
4367 }"
4368 [(set_attr "length" "4")
a2cd141b 4369 (set_attr "type" "load_byte")
cffb2a26 4370 (set_attr "pool_range" "1020")]
4371)
25f7a26e 4372
a2cd141b 4373;; We used to have an early-clobber on the scratch register here.
4374;; However, there's a bug somewhere in reload which means that this
4375;; can be partially ignored during spill allocation if the memory
ed29c566 4376;; address also needs reloading; this causes us to die later on when
a2cd141b 4377;; we try to verify the operands. Fortunately, we don't really need
4378;; the early-clobber: we can always use operand 0 if operand 2
4379;; overlaps the address.
25f905c2 4380(define_insn "*thumb1_extendhisi2_insn_v6"
a2cd141b 4381 [(set (match_operand:SI 0 "register_operand" "=l,l")
4382 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4383 (clobber (match_scratch:SI 2 "=X,l"))]
25f905c2 4384 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4385 "*
4386 {
4387 rtx ops[4];
4388 rtx mem;
4389
4390 if (which_alternative == 0)
4391 return \"sxth\\t%0, %1\";
4392
4393 mem = XEXP (operands[1], 0);
4394
4395 /* This code used to try to use 'V', and fix the address only if it was
4396 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4397 range of QImode offsets, and offsettable_address_p does a QImode
4398 address check. */
4399
4400 if (GET_CODE (mem) == CONST)
4401 mem = XEXP (mem, 0);
4402
4403 if (GET_CODE (mem) == LABEL_REF)
4404 return \"ldr\\t%0, %1\";
4405
4406 if (GET_CODE (mem) == PLUS)
4407 {
4408 rtx a = XEXP (mem, 0);
4409 rtx b = XEXP (mem, 1);
4410
4411 if (GET_CODE (a) == LABEL_REF
4412 && GET_CODE (b) == CONST_INT)
4413 return \"ldr\\t%0, %1\";
4414
4415 if (GET_CODE (b) == REG)
4416 return \"ldrsh\\t%0, %1\";
4417
4418 ops[1] = a;
4419 ops[2] = b;
4420 }
4421 else
4422 {
4423 ops[1] = mem;
4424 ops[2] = const0_rtx;
4425 }
4426
ed29c566 4427 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4428
4429 ops[0] = operands[0];
4430 if (reg_mentioned_p (operands[2], ops[1]))
4431 ops[3] = ops[0];
4432 else
4433 ops[3] = operands[2];
4434 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4435 return \"\";
4436 }"
4437 [(set_attr "length" "2,4")
4438 (set_attr "type" "alu_shift,load_byte")
4439 (set_attr "pool_range" "*,1020")]
4440)
4441
25f905c2 4442;; This pattern will only be used when ldsh is not available
25f7a26e 4443(define_expand "extendhisi2_mem"
eab14235 4444 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4445 (set (match_dup 3)
eab14235 4446 (zero_extend:SI (match_dup 7)))
25f7a26e 4447 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4448 (set (match_operand:SI 0 "" "")
4449 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4450 "TARGET_ARM"
25f7a26e 4451 "
215b30b3 4452 {
4453 rtx mem1, mem2;
4454 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4455
788fcce0 4456 mem1 = change_address (operands[1], QImode, addr);
4457 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4458 operands[0] = gen_lowpart (SImode, operands[0]);
4459 operands[1] = mem1;
4460 operands[2] = gen_reg_rtx (SImode);
4461 operands[3] = gen_reg_rtx (SImode);
4462 operands[6] = gen_reg_rtx (SImode);
4463 operands[7] = mem2;
25f7a26e 4464
215b30b3 4465 if (BYTES_BIG_ENDIAN)
4466 {
4467 operands[4] = operands[2];
4468 operands[5] = operands[3];
4469 }
4470 else
4471 {
4472 operands[4] = operands[3];
4473 operands[5] = operands[2];
4474 }
4475 }"
4476)
b11cae9e 4477
a2cd141b 4478(define_insn "*arm_extendhisi2"
4479 [(set (match_operand:SI 0 "s_register_operand" "=r")
4480 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4481 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4482 "ldr%(sh%)\\t%0, %1"
a2cd141b 4483 [(set_attr "type" "load_byte")
0d66636f 4484 (set_attr "predicable" "yes")
cffb2a26 4485 (set_attr "pool_range" "256")
4486 (set_attr "neg_pool_range" "244")]
4487)
f7fbdd4a 4488
25f905c2 4489;; ??? Check Thumb-2 pool range
a2cd141b 4490(define_insn "*arm_extendhisi2_v6"
4491 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4492 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4493 "TARGET_32BIT && arm_arch6"
a2cd141b 4494 "@
4495 sxth%?\\t%0, %1
25f905c2 4496 ldr%(sh%)\\t%0, %1"
a2cd141b 4497 [(set_attr "type" "alu_shift,load_byte")
4498 (set_attr "predicable" "yes")
4499 (set_attr "pool_range" "*,256")
4500 (set_attr "neg_pool_range" "*,244")]
4501)
4502
4503(define_insn "*arm_extendhisi2addsi"
4504 [(set (match_operand:SI 0 "s_register_operand" "=r")
4505 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4506 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4507 "TARGET_INT_SIMD"
a2cd141b 4508 "sxtah%?\\t%0, %2, %1"
4509)
4510
c8f69309 4511(define_expand "extendqihi2"
4512 [(set (match_dup 2)
bed7d9a5 4513 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4514 (const_int 24)))
9c08d1fa 4515 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4516 (ashiftrt:SI (match_dup 2)
4517 (const_int 24)))]
cffb2a26 4518 "TARGET_ARM"
c8f69309 4519 "
215b30b3 4520 {
4521 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4522 {
4523 emit_insn (gen_rtx_SET (VOIDmode,
4524 operands[0],
4525 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4526 DONE;
4527 }
4528 if (!s_register_operand (operands[1], QImode))
4529 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4530 operands[0] = gen_lowpart (SImode, operands[0]);
4531 operands[1] = gen_lowpart (SImode, operands[1]);
4532 operands[2] = gen_reg_rtx (SImode);
4533 }"
4534)
f7fbdd4a 4535
25f905c2 4536(define_insn "*arm_extendqihi_insn"
b4e8a300 4537 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4538 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4539 "TARGET_ARM && arm_arch4"
25f905c2 4540 "ldr%(sb%)\\t%0, %1"
a2cd141b 4541 [(set_attr "type" "load_byte")
0d66636f 4542 (set_attr "predicable" "yes")
cffb2a26 4543 (set_attr "pool_range" "256")
4544 (set_attr "neg_pool_range" "244")]
4545)
3fc2009e 4546
b11cae9e 4547(define_expand "extendqisi2"
c8f69309 4548 [(set (match_dup 2)
bed7d9a5 4549 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
b11cae9e 4550 (const_int 24)))
9c08d1fa 4551 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4552 (ashiftrt:SI (match_dup 2)
4553 (const_int 24)))]
cffb2a26 4554 "TARGET_EITHER"
b11cae9e 4555 "
cffb2a26 4556 {
a2cd141b 4557 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 4558 {
a2cd141b 4559 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 4560 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4561 DONE;
4562 }
a2cd141b 4563
215b30b3 4564 if (!s_register_operand (operands[1], QImode))
cffb2a26 4565 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 4566
a2cd141b 4567 if (arm_arch6)
4568 {
4569 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4570 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4571 DONE;
cffb2a26 4572 }
a2cd141b 4573
4574 operands[1] = gen_lowpart (SImode, operands[1]);
4575 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4576 }"
4577)
f7fbdd4a 4578
a2cd141b 4579(define_insn "*arm_extendqisi"
4580 [(set (match_operand:SI 0 "s_register_operand" "=r")
bed7d9a5 4581 (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
a2cd141b 4582 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4583 "ldr%(sb%)\\t%0, %1"
a2cd141b 4584 [(set_attr "type" "load_byte")
0d66636f 4585 (set_attr "predicable" "yes")
cffb2a26 4586 (set_attr "pool_range" "256")
4587 (set_attr "neg_pool_range" "244")]
4588)
3fc2009e 4589
a2cd141b 4590(define_insn "*arm_extendqisi_v6"
4591 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4592 (sign_extend:SI
4593 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4594 "TARGET_ARM && arm_arch6"
b4e8a300 4595 "@
4596 sxtb%?\\t%0, %1
25f905c2 4597 ldr%(sb%)\\t%0, %1"
a2cd141b 4598 [(set_attr "type" "alu_shift,load_byte")
4599 (set_attr "predicable" "yes")
a2cd141b 4600 (set_attr "pool_range" "*,256")
4601 (set_attr "neg_pool_range" "*,244")]
4602)
4603
4604(define_insn "*arm_extendqisi2addsi"
4605 [(set (match_operand:SI 0 "s_register_operand" "=r")
4606 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4607 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4608 "TARGET_INT_SIMD"
a2cd141b 4609 "sxtab%?\\t%0, %2, %1"
4610 [(set_attr "type" "alu_shift")
bcaec148 4611 (set_attr "insn" "xtab")
a2cd141b 4612 (set_attr "predicable" "yes")]
4613)
4614
25f905c2 4615(define_insn "*thumb1_extendqisi2"
a2cd141b 4616 [(set (match_operand:SI 0 "register_operand" "=l,l")
4617 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
25f905c2 4618 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4619 "*
4620 {
4621 rtx ops[3];
4622 rtx mem = XEXP (operands[1], 0);
4623
4624 if (GET_CODE (mem) == CONST)
4625 mem = XEXP (mem, 0);
4626
4627 if (GET_CODE (mem) == LABEL_REF)
4628 return \"ldr\\t%0, %1\";
4629
4630 if (GET_CODE (mem) == PLUS
4631 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4632 return \"ldr\\t%0, %1\";
4633
4634 if (which_alternative == 0)
4635 return \"ldrsb\\t%0, %1\";
4636
4637 ops[0] = operands[0];
4638
4639 if (GET_CODE (mem) == PLUS)
4640 {
4641 rtx a = XEXP (mem, 0);
4642 rtx b = XEXP (mem, 1);
4643
4644 ops[1] = a;
4645 ops[2] = b;
4646
4647 if (GET_CODE (a) == REG)
4648 {
4649 if (GET_CODE (b) == REG)
4650 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4651 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 4652 {
4653 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4654 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4655 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4656 }
cffb2a26 4657 else
4658 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4659 }
cffb2a26 4660 else
4661 {
ed29c566 4662 gcc_assert (GET_CODE (b) == REG);
cffb2a26 4663 if (REGNO (b) == REGNO (ops[0]))
215b30b3 4664 {
4665 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4666 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4667 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4668 }
cffb2a26 4669 else
4670 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4671 }
4672 }
4673 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4674 {
215b30b3 4675 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4676 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4677 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 4678 }
4679 else
4680 {
4681 ops[1] = mem;
4682 ops[2] = const0_rtx;
4683
4684 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4685 }
4686 return \"\";
4687 }"
4688 [(set_attr "length" "2,6")
a2cd141b 4689 (set_attr "type" "load_byte,load_byte")
cffb2a26 4690 (set_attr "pool_range" "32,32")]
4691)
4692
25f905c2 4693(define_insn "*thumb1_extendqisi2_v6"
a2cd141b 4694 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4695 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
25f905c2 4696 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4697 "*
4698 {
4699 rtx ops[3];
4700 rtx mem;
4701
4702 if (which_alternative == 0)
4703 return \"sxtb\\t%0, %1\";
4704
4705 mem = XEXP (operands[1], 0);
4706
4707 if (GET_CODE (mem) == CONST)
4708 mem = XEXP (mem, 0);
4709
4710 if (GET_CODE (mem) == LABEL_REF)
4711 return \"ldr\\t%0, %1\";
4712
4713 if (GET_CODE (mem) == PLUS
4714 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4715 return \"ldr\\t%0, %1\";
4716
4717 if (which_alternative == 0)
4718 return \"ldrsb\\t%0, %1\";
4719
4720 ops[0] = operands[0];
4721
4722 if (GET_CODE (mem) == PLUS)
4723 {
4724 rtx a = XEXP (mem, 0);
4725 rtx b = XEXP (mem, 1);
4726
4727 ops[1] = a;
4728 ops[2] = b;
4729
4730 if (GET_CODE (a) == REG)
4731 {
4732 if (GET_CODE (b) == REG)
4733 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4734 else if (REGNO (a) == REGNO (ops[0]))
4735 {
4736 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4737 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4738 }
4739 else
4740 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4741 }
a2cd141b 4742 else
4743 {
ed29c566 4744 gcc_assert (GET_CODE (b) == REG);
a2cd141b 4745 if (REGNO (b) == REGNO (ops[0]))
4746 {
4747 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4748 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4749 }
4750 else
4751 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4752 }
4753 }
4754 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4755 {
4756 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4757 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4758 }
4759 else
4760 {
4761 ops[1] = mem;
4762 ops[2] = const0_rtx;
4763
4764 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4765 }
4766 return \"\";
4767 }"
4768 [(set_attr "length" "2,2,4")
4769 (set_attr "type" "alu_shift,load_byte,load_byte")
4770 (set_attr "pool_range" "*,32,32")]
4771)
4772
caedf871 4773(define_expand "extendsfdf2"
4774 [(set (match_operand:DF 0 "s_register_operand" "")
4775 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4776 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4777 ""
4778)
9b8516be 4779
4780/* HFmode -> DFmode conversions have to go through SFmode. */
4781(define_expand "extendhfdf2"
4782 [(set (match_operand:DF 0 "general_operand" "")
4783 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4784 "TARGET_EITHER"
4785 "
4786 {
4787 rtx op1;
4788 op1 = convert_to_mode (SFmode, operands[1], 0);
4789 op1 = convert_to_mode (DFmode, op1, 0);
4790 emit_insn (gen_movdf (operands[0], op1));
4791 DONE;
4792 }"
4793)
b11cae9e 4794\f
4795;; Move insns (including loads and stores)
4796
4797;; XXX Just some ideas about movti.
9c08d1fa 4798;; I don't think these are a good idea on the arm, there just aren't enough
4799;; registers
b11cae9e 4800;;(define_expand "loadti"
9c08d1fa 4801;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4802;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4803;; "" "")
4804
4805;;(define_expand "storeti"
4806;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4807;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4808;; "" "")
4809
4810;;(define_expand "movti"
4811;; [(set (match_operand:TI 0 "general_operand" "")
4812;; (match_operand:TI 1 "general_operand" ""))]
4813;; ""
4814;; "
4815;;{
4816;; rtx insn;
4817;;
4818;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4819;; operands[1] = copy_to_reg (operands[1]);
4820;; if (GET_CODE (operands[0]) == MEM)
4821;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4822;; else if (GET_CODE (operands[1]) == MEM)
4823;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4824;; else
4825;; FAIL;
4826;;
4827;; emit_insn (insn);
4828;; DONE;
4829;;}")
4830
a2f10574 4831;; Recognize garbage generated above.
b11cae9e 4832
4833;;(define_insn ""
4834;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4835;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4836;; ""
4837;; "*
4838;; {
4839;; register mem = (which_alternative < 3);
0d66636f 4840;; register const char *template;
b11cae9e 4841;;
4842;; operands[mem] = XEXP (operands[mem], 0);
4843;; switch (which_alternative)
4844;; {
4845;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4846;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4847;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4848;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4849;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4850;; case 5: template = \"stmia\\t%0, %M1\"; break;
4851;; }
e2348bcb 4852;; output_asm_insn (template, operands);
4853;; return \"\";
b11cae9e 4854;; }")
4855
cffb2a26 4856(define_expand "movdi"
4857 [(set (match_operand:DI 0 "general_operand" "")
4858 (match_operand:DI 1 "general_operand" ""))]
4859 "TARGET_EITHER"
4860 "
e1ba4a27 4861 if (can_create_pseudo_p ())
cffb2a26 4862 {
b2778788 4863 if (GET_CODE (operands[0]) != REG)
4864 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4865 }
4866 "
4867)
b11cae9e 4868
cffb2a26 4869(define_insn "*arm_movdi"
d51f92df 4870 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4871 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4872 "TARGET_ARM
b2778788 4873 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4874 && !TARGET_IWMMXT
4875 && ( register_operand (operands[0], DImode)
4876 || register_operand (operands[1], DImode))"
b11cae9e 4877 "*
d51f92df 4878 switch (which_alternative)
4879 {
4880 case 0:
4881 case 1:
4882 case 2:
4883 return \"#\";
4884 default:
4885 return output_move_double (operands);
4886 }
cffb2a26 4887 "
359a6e9f 4888 [(set_attr "length" "8,12,16,8,8")
4889 (set_attr "type" "*,*,*,load2,store2")
4890 (set_attr "pool_range" "*,*,*,1020,*")
4891 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4892)
4893
d51f92df 4894(define_split
4895 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4896 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4897 "TARGET_32BIT
d51f92df 4898 && reload_completed
4899 && (arm_const_double_inline_cost (operands[1])
4900 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4901 [(const_int 0)]
4902 "
4903 arm_split_constant (SET, SImode, curr_insn,
4904 INTVAL (gen_lowpart (SImode, operands[1])),
4905 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4906 arm_split_constant (SET, SImode, curr_insn,
4907 INTVAL (gen_highpart_mode (SImode,
4908 GET_MODE (operands[0]),
4909 operands[1])),
4910 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4911 DONE;
4912 "
4913)
4914
e5ba9289 4915; If optimizing for size, or if we have load delay slots, then
4916; we want to split the constant into two separate operations.
4917; In both cases this may split a trivial part into a single data op
4918; leaving a single complex constant to load. We can also get longer
4919; offsets in a LDR which means we get better chances of sharing the pool
4920; entries. Finally, we can normally do a better job of scheduling
4921; LDR instructions than we can with LDM.
4922; This pattern will only match if the one above did not.
4923(define_split
4924 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4925 (match_operand:ANY64 1 "const_double_operand" ""))]
4926 "TARGET_ARM && reload_completed
4927 && arm_const_double_by_parts (operands[1])"
4928 [(set (match_dup 0) (match_dup 1))
4929 (set (match_dup 2) (match_dup 3))]
4930 "
4931 operands[2] = gen_highpart (SImode, operands[0]);
4932 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4933 operands[1]);
4934 operands[0] = gen_lowpart (SImode, operands[0]);
4935 operands[1] = gen_lowpart (SImode, operands[1]);
4936 "
4937)
4938
d51f92df 4939(define_split
4940 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4941 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4942 "TARGET_EITHER && reload_completed"
4943 [(set (match_dup 0) (match_dup 1))
4944 (set (match_dup 2) (match_dup 3))]
4945 "
4946 operands[2] = gen_highpart (SImode, operands[0]);
4947 operands[3] = gen_highpart (SImode, operands[1]);
4948 operands[0] = gen_lowpart (SImode, operands[0]);
4949 operands[1] = gen_lowpart (SImode, operands[1]);
4950
4951 /* Handle a partial overlap. */
4952 if (rtx_equal_p (operands[0], operands[3]))
4953 {
4954 rtx tmp0 = operands[0];
4955 rtx tmp1 = operands[1];
4956
4957 operands[0] = operands[2];
4958 operands[1] = operands[3];
4959 operands[2] = tmp0;
4960 operands[3] = tmp1;
4961 }
4962 "
4963)
4964
a8a3b539 4965;; We can't actually do base+index doubleword loads if the index and
4966;; destination overlap. Split here so that we at least have chance to
4967;; schedule.
4968(define_split
4969 [(set (match_operand:DI 0 "s_register_operand" "")
4970 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4971 (match_operand:SI 2 "s_register_operand" ""))))]
4972 "TARGET_LDRD
4973 && reg_overlap_mentioned_p (operands[0], operands[1])
4974 && reg_overlap_mentioned_p (operands[0], operands[2])"
4975 [(set (match_dup 4)
4976 (plus:SI (match_dup 1)
4977 (match_dup 2)))
4978 (set (match_dup 0)
4979 (mem:DI (match_dup 4)))]
4980 "
4981 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4982 "
4983)
4984
cffb2a26 4985;;; ??? This should have alternatives for constants.
4986;;; ??? This was originally identical to the movdf_insn pattern.
4987;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4988;;; thumb_reorg with a memory reference.
25f905c2 4989(define_insn "*thumb1_movdi_insn"
215b30b3 4990 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4991 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4992 "TARGET_THUMB1
a2cd141b 4993 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4994 && ( register_operand (operands[0], DImode)
4995 || register_operand (operands[1], DImode))"
4996 "*
4997 {
4998 switch (which_alternative)
4999 {
5000 default:
5001 case 0:
5002 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5003 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5004 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5005 case 1:
5006 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5007 case 2:
5008 operands[1] = GEN_INT (- INTVAL (operands[1]));
5009 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5010 case 3:
5011 return \"ldmia\\t%1, {%0, %H0}\";
5012 case 4:
5013 return \"stmia\\t%0, {%1, %H1}\";
5014 case 5:
5015 return thumb_load_double_from_address (operands);
5016 case 6:
1a83b3ff 5017 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5018 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5019 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5020 return \"\";
5021 case 7:
5022 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5023 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5024 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5025 }
5026 }"
5027 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5028 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 5029 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5030)
b11cae9e 5031
9c08d1fa 5032(define_expand "movsi"
5033 [(set (match_operand:SI 0 "general_operand" "")
5034 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5035 "TARGET_EITHER"
9c08d1fa 5036 "
befb0bac 5037 {
e348ff3e 5038 rtx base, offset, tmp;
5039
25f905c2 5040 if (TARGET_32BIT)
9c08d1fa 5041 {
674a8f0b 5042 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5043 if (GET_CODE (operands[0]) == MEM)
5044 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5045 if (arm_general_register_operand (operands[0], SImode)
5046 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5047 && !(const_ok_for_arm (INTVAL (operands[1]))
5048 || const_ok_for_arm (~INTVAL (operands[1]))))
5049 {
96f57e36 5050 arm_split_constant (SET, SImode, NULL_RTX,
5051 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5052 optimize && can_create_pseudo_p ());
cffb2a26 5053 DONE;
5054 }
d0e6a121 5055
5056 if (TARGET_USE_MOVT && !target_word_relocations
5057 && GET_CODE (operands[1]) == SYMBOL_REF
5058 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5059 {
5060 arm_emit_movpair (operands[0], operands[1]);
5061 DONE;
5062 }
cffb2a26 5063 }
25f905c2 5064 else /* TARGET_THUMB1... */
cffb2a26 5065 {
e1ba4a27 5066 if (can_create_pseudo_p ())
cffb2a26 5067 {
5068 if (GET_CODE (operands[0]) != REG)
5069 operands[1] = force_reg (SImode, operands[1]);
5070 }
9c08d1fa 5071 }
f655717d 5072
e348ff3e 5073 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5074 {
5075 split_const (operands[1], &base, &offset);
5076 if (GET_CODE (base) == SYMBOL_REF
5077 && !offset_within_block_p (base, INTVAL (offset)))
5078 {
b308ddcf 5079 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5080 emit_move_insn (tmp, base);
5081 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5082 DONE;
5083 }
5084 }
5085
f655717d 5086 /* Recognize the case where operand[1] is a reference to thread-local
5087 data and load its address to a register. */
5088 if (arm_tls_referenced_p (operands[1]))
5089 {
5090 rtx tmp = operands[1];
5091 rtx addend = NULL;
5092
5093 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5094 {
5095 addend = XEXP (XEXP (tmp, 0), 1);
5096 tmp = XEXP (XEXP (tmp, 0), 0);
5097 }
5098
5099 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5100 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5101
e1ba4a27 5102 tmp = legitimize_tls_address (tmp,
5103 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5104 if (addend)
5105 {
5106 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5107 tmp = force_operand (tmp, operands[0]);
5108 }
5109 operands[1] = tmp;
5110 }
5111 else if (flag_pic
5112 && (CONSTANT_P (operands[1])
5113 || symbol_mentioned_p (operands[1])
5114 || label_mentioned_p (operands[1])))
5115 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5116 (!can_create_pseudo_p ()
5117 ? operands[0]
5118 : 0));
befb0bac 5119 }
215b30b3 5120 "
5121)
9c08d1fa 5122
d0e6a121 5123;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5124;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5125;; so this does not matter.
5126(define_insn "*arm_movt"
5127 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5128 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5129 (match_operand:SI 2 "general_operand" "i")))]
5130 "TARGET_32BIT"
5131 "movt%?\t%0, #:upper16:%c2"
5132 [(set_attr "predicable" "yes")
5133 (set_attr "length" "4")]
5134)
5135
cffb2a26 5136(define_insn "*arm_movsi_insn"
aaa37ad6 5137 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5138 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5139 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5140 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5141 && ( register_operand (operands[0], SImode)
5142 || register_operand (operands[1], SImode))"
f7fbdd4a 5143 "@
aaa37ad6 5144 mov%?\\t%0, %1
f7fbdd4a 5145 mov%?\\t%0, %1
5146 mvn%?\\t%0, #%B1
25f905c2 5147 movw%?\\t%0, %1
f7fbdd4a 5148 ldr%?\\t%0, %1
5149 str%?\\t%1, %0"
aaa37ad6 5150 [(set_attr "type" "*,*,*,*,load1,store1")
0d66636f 5151 (set_attr "predicable" "yes")
aaa37ad6 5152 (set_attr "pool_range" "*,*,*,*,4096,*")
5153 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5154)
87b22bf7 5155
5156(define_split
a2cd141b 5157 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5158 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5159 "TARGET_32BIT
215b30b3 5160 && (!(const_ok_for_arm (INTVAL (operands[1]))
5161 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5162 [(clobber (const_int 0))]
5163 "
96f57e36 5164 arm_split_constant (SET, SImode, NULL_RTX,
5165 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5166 DONE;
215b30b3 5167 "
5168)
9c08d1fa 5169
25f905c2 5170(define_insn "*thumb1_movsi_insn"
aaa37ad6 5171 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5172 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
25f905c2 5173 "TARGET_THUMB1
cffb2a26 5174 && ( register_operand (operands[0], SImode)
5175 || register_operand (operands[1], SImode))"
5176 "@
5177 mov %0, %1
5178 mov %0, %1
5179 #
5180 #
5181 ldmia\\t%1, {%0}
5182 stmia\\t%0, {%1}
5183 ldr\\t%0, %1
5184 str\\t%1, %0
5185 mov\\t%0, %1"
5186 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5187 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 5188 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5189)
5190
5191(define_split
5192 [(set (match_operand:SI 0 "register_operand" "")
5193 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5194 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
cffb2a26 5195 [(set (match_dup 0) (match_dup 1))
5196 (set (match_dup 0) (neg:SI (match_dup 0)))]
5197 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5198)
5199
5200(define_split
5201 [(set (match_operand:SI 0 "register_operand" "")
5202 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5203 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
cffb2a26 5204 [(set (match_dup 0) (match_dup 1))
5205 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5206 "
5207 {
e4aeee53 5208 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5209 unsigned HOST_WIDE_INT mask = 0xff;
5210 int i;
5211
5212 for (i = 0; i < 25; i++)
5213 if ((val & (mask << i)) == val)
5214 break;
5215
f5b3169c 5216 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 5217 if (i == 0)
5218 FAIL;
5219
5220 operands[1] = GEN_INT (val >> i);
5221 operands[2] = GEN_INT (i);
5222 }"
5223)
5224
67336bcf 5225;; When generating pic, we need to load the symbol offset into a register.
5226;; So that the optimizer does not confuse this with a normal symbol load
5227;; we use an unspec. The offset will be loaded from a constant pool entry,
5228;; since that is the only type of relocation we can use.
5229
5230;; The rather odd constraints on the following are to force reload to leave
5231;; the insn alone, and to force the minipool generation pass to then move
5232;; the GOT symbol to memory.
849170fd 5233
b3cd5f55 5234(define_insn "pic_load_addr_32bit"
849170fd 5235 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5236 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5237 "TARGET_32BIT && flag_pic"
67336bcf 5238 "ldr%?\\t%0, %1"
a2cd141b 5239 [(set_attr "type" "load1")
b3cd5f55 5240 (set_attr "pool_range" "4096")
5241 (set (attr "neg_pool_range")
5242 (if_then_else (eq_attr "is_thumb" "no")
5243 (const_int 4084)
5244 (const_int 0)))]
8c4d8060 5245)
5246
25f905c2 5247(define_insn "pic_load_addr_thumb1"
8c4d8060 5248 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5249 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5250 "TARGET_THUMB1 && flag_pic"
8c4d8060 5251 "ldr\\t%0, %1"
a2cd141b 5252 [(set_attr "type" "load1")
8c4d8060 5253 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5254)
849170fd 5255
cffb2a26 5256(define_insn "pic_add_dot_plus_four"
15d5d060 5257 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5258 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5259 (const_int 4)
beef0fb5 5260 (match_operand 2 "" "")]
5261 UNSPEC_PIC_BASE))]
b3cd5f55 5262 "TARGET_THUMB"
cffb2a26 5263 "*
6cdcb15c 5264 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5265 INTVAL (operands[2]));
cffb2a26 5266 return \"add\\t%0, %|pc\";
5267 "
5268 [(set_attr "length" "2")]
5269)
849170fd 5270
5271(define_insn "pic_add_dot_plus_eight"
15d5d060 5272 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5273 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5274 (const_int 8)
beef0fb5 5275 (match_operand 2 "" "")]
5276 UNSPEC_PIC_BASE))]
f655717d 5277 "TARGET_ARM"
c4034607 5278 "*
6cdcb15c 5279 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5280 INTVAL (operands[2]));
15d5d060 5281 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5282 "
0d66636f 5283 [(set_attr "predicable" "yes")]
cffb2a26 5284)
849170fd 5285
f655717d 5286(define_insn "tls_load_dot_plus_eight"
cc071db6 5287 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5288 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5289 (const_int 8)
beef0fb5 5290 (match_operand 2 "" "")]
5291 UNSPEC_PIC_BASE)))]
f655717d 5292 "TARGET_ARM"
5293 "*
6cdcb15c 5294 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5295 INTVAL (operands[2]));
f655717d 5296 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5297 "
5298 [(set_attr "predicable" "yes")]
5299)
5300
5301;; PIC references to local variables can generate pic_add_dot_plus_eight
5302;; followed by a load. These sequences can be crunched down to
5303;; tls_load_dot_plus_eight by a peephole.
5304
5305(define_peephole2
c0c1fba5 5306 [(set (match_operand:SI 0 "register_operand" "")
5307 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5308 (const_int 8)
5309 (match_operand 1 "" "")]
5310 UNSPEC_PIC_BASE))
f655717d 5311 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5312 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5313 [(set (match_dup 2)
5314 (mem:SI (unspec:SI [(match_dup 3)
5315 (const_int 8)
5316 (match_dup 1)]
5317 UNSPEC_PIC_BASE)))]
f655717d 5318 ""
5319)
5320
bac7fc85 5321(define_insn "pic_offset_arm"
5322 [(set (match_operand:SI 0 "register_operand" "=r")
5323 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5324 (unspec:SI [(match_operand:SI 2 "" "X")]
5325 UNSPEC_PIC_OFFSET))))]
5326 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5327 "ldr%?\\t%0, [%1,%2]"
5328 [(set_attr "type" "load1")]
5329)
5330
95373f08 5331(define_expand "builtin_setjmp_receiver"
5332 [(label_ref (match_operand 0 "" ""))]
5333 "flag_pic"
5334 "
5335{
b935b306 5336 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5337 register. */
2cb7d577 5338 if (arm_pic_register != INVALID_REGNUM)
5339 arm_load_pic_register (1UL << 3);
95373f08 5340 DONE;
5341}")
5342
9c08d1fa 5343;; If copying one reg to another we can set the condition codes according to
5344;; its value. Such a move is common after a return from subroutine and the
5345;; result is being tested against zero.
5346
f7fbdd4a 5347(define_insn "*movsi_compare0"
bd5b4116 5348 [(set (reg:CC CC_REGNUM)
cffb2a26 5349 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5350 (const_int 0)))
5351 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5352 (match_dup 1))]
25f905c2 5353 "TARGET_32BIT"
e2348bcb 5354 "@
40dbec34 5355 cmp%?\\t%0, #0
25f905c2 5356 sub%.\\t%0, %1, #0"
cffb2a26 5357 [(set_attr "conds" "set")]
5358)
b11cae9e 5359
b11cae9e 5360;; Subroutine to store a half word from a register into memory.
5361;; Operand 0 is the source register (HImode)
c8f69309 5362;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5363
9c08d1fa 5364;; In both this routine and the next, we must be careful not to spill
01cc3b75 5365;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5366;; can generate unrecognizable rtl.
5367
b11cae9e 5368(define_expand "storehi"
c8f69309 5369 [;; store the low byte
f082f1c4 5370 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5371 ;; extract the high byte
c8f69309 5372 (set (match_dup 2)
5373 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5374 ;; store the high byte
787f8210 5375 (set (match_dup 4) (match_dup 5))]
cffb2a26 5376 "TARGET_ARM"
b11cae9e 5377 "
215b30b3 5378 {
537ffcfc 5379 rtx op1 = operands[1];
5380 rtx addr = XEXP (op1, 0);
215b30b3 5381 enum rtx_code code = GET_CODE (addr);
5382
5383 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5384 || code == MINUS)
537ffcfc 5385 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5386
537ffcfc 5387 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5388 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5389 operands[3] = gen_lowpart (QImode, operands[0]);
5390 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5391 operands[2] = gen_reg_rtx (SImode);
5392 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5393 }"
5394)
b11cae9e 5395
c7597b5d 5396(define_expand "storehi_bigend"
f082f1c4 5397 [(set (match_dup 4) (match_dup 3))
c7597b5d 5398 (set (match_dup 2)
5399 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5400 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5401 "TARGET_ARM"
b11cae9e 5402 "
215b30b3 5403 {
537ffcfc 5404 rtx op1 = operands[1];
5405 rtx addr = XEXP (op1, 0);
215b30b3 5406 enum rtx_code code = GET_CODE (addr);
5407
5408 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5409 || code == MINUS)
537ffcfc 5410 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5411
537ffcfc 5412 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5413 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5414 operands[3] = gen_lowpart (QImode, operands[0]);
5415 operands[0] = gen_lowpart (SImode, operands[0]);
5416 operands[2] = gen_reg_rtx (SImode);
787f8210 5417 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5418 }"
5419)
c7597b5d 5420
5421;; Subroutine to store a half word integer constant into memory.
5422(define_expand "storeinthi"
f082f1c4 5423 [(set (match_operand 0 "" "")
787f8210 5424 (match_operand 1 "" ""))
9e8503e6 5425 (set (match_dup 3) (match_dup 2))]
cffb2a26 5426 "TARGET_ARM"
c7597b5d 5427 "
215b30b3 5428 {
5429 HOST_WIDE_INT value = INTVAL (operands[1]);
5430 rtx addr = XEXP (operands[0], 0);
537ffcfc 5431 rtx op0 = operands[0];
215b30b3 5432 enum rtx_code code = GET_CODE (addr);
c7597b5d 5433
215b30b3 5434 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5435 || code == MINUS)
537ffcfc 5436 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5437
215b30b3 5438 operands[1] = gen_reg_rtx (SImode);
5439 if (BYTES_BIG_ENDIAN)
5440 {
5441 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5442 if ((value & 255) == ((value >> 8) & 255))
5443 operands[2] = operands[1];
5444 else
5445 {
5446 operands[2] = gen_reg_rtx (SImode);
5447 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5448 }
5449 }
5450 else
5451 {
5452 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5453 if ((value & 255) == ((value >> 8) & 255))
5454 operands[2] = operands[1];
5455 else
5456 {
5457 operands[2] = gen_reg_rtx (SImode);
5458 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5459 }
5460 }
c7597b5d 5461
537ffcfc 5462 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5463 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5464 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5465 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5466 }"
5467)
b11cae9e 5468
f7fbdd4a 5469(define_expand "storehi_single_op"
5470 [(set (match_operand:HI 0 "memory_operand" "")
5471 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5472 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5473 "
215b30b3 5474 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5475 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5476 "
5477)
f7fbdd4a 5478
b11cae9e 5479(define_expand "movhi"
5480 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5481 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5482 "TARGET_EITHER"
b11cae9e 5483 "
cffb2a26 5484 if (TARGET_ARM)
b11cae9e 5485 {
e1ba4a27 5486 if (can_create_pseudo_p ())
cffb2a26 5487 {
5488 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5489 {
cffb2a26 5490 if (arm_arch4)
5491 {
5492 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5493 DONE;
5494 }
5495 if (GET_CODE (operands[1]) == CONST_INT)
5496 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5497 else
cffb2a26 5498 {
5499 if (GET_CODE (operands[1]) == MEM)
5500 operands[1] = force_reg (HImode, operands[1]);
5501 if (BYTES_BIG_ENDIAN)
5502 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5503 else
5504 emit_insn (gen_storehi (operands[1], operands[0]));
5505 }
5506 DONE;
b11cae9e 5507 }
cffb2a26 5508 /* Sign extend a constant, and keep it in an SImode reg. */
5509 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5510 {
cffb2a26 5511 rtx reg = gen_reg_rtx (SImode);
5512 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5513
5514 /* If the constant is already valid, leave it alone. */
215b30b3 5515 if (!const_ok_for_arm (val))
cffb2a26 5516 {
5517 /* If setting all the top bits will make the constant
5518 loadable in a single instruction, then set them.
5519 Otherwise, sign extend the number. */
5520
215b30b3 5521 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5522 val |= ~0xffff;
5523 else if (val & 0x8000)
5524 val |= ~0xffff;
5525 }
5526
5527 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5528 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5529 }
e1ba4a27 5530 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5531 && GET_CODE (operands[1]) == MEM)
5532 {
5533 rtx reg = gen_reg_rtx (SImode);
5534
5535 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5536 operands[1] = gen_lowpart (HImode, reg);
5537 }
215b30b3 5538 else if (!arm_arch4)
f7fbdd4a 5539 {
cffb2a26 5540 if (GET_CODE (operands[1]) == MEM)
5541 {
c1a66faf 5542 rtx base;
5543 rtx offset = const0_rtx;
5544 rtx reg = gen_reg_rtx (SImode);
5545
5546 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5547 || (GET_CODE (base) == PLUS
5548 && (GET_CODE (offset = XEXP (base, 1))
5549 == CONST_INT)
5550 && ((INTVAL(offset) & 1) != 1)
5551 && GET_CODE (base = XEXP (base, 0)) == REG))
5552 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5553 {
8deb3959 5554 rtx new_rtx;
c1a66faf 5555
8deb3959 5556 new_rtx = widen_memory_access (operands[1], SImode,
5557 ((INTVAL (offset) & ~3)
5558 - INTVAL (offset)));
5559 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5560 if (((INTVAL (offset) & 2) != 0)
5561 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5562 {
5563 rtx reg2 = gen_reg_rtx (SImode);
5564
5565 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5566 reg = reg2;
5567 }
206ee9a2 5568 }
c1a66faf 5569 else
5570 emit_insn (gen_movhi_bytes (reg, operands[1]));
5571
5572 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5573 }
5574 }
5575 }
674a8f0b 5576 /* Handle loading a large integer during reload. */
cffb2a26 5577 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5578 && !const_ok_for_arm (INTVAL (operands[1]))
5579 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5580 {
5581 /* Writing a constant to memory needs a scratch, which should
5582 be handled with SECONDARY_RELOADs. */
ed29c566 5583 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5584
5585 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5586 emit_insn (gen_movsi (operands[0], operands[1]));
5587 DONE;
5588 }
5589 }
25f905c2 5590 else if (TARGET_THUMB2)
5591 {
5592 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5593 if (can_create_pseudo_p ())
25f905c2 5594 {
5595 if (GET_CODE (operands[0]) != REG)
5596 operands[1] = force_reg (HImode, operands[1]);
5597 /* Zero extend a constant, and keep it in an SImode reg. */
5598 else if (GET_CODE (operands[1]) == CONST_INT)
5599 {
5600 rtx reg = gen_reg_rtx (SImode);
5601 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5602
5603 emit_insn (gen_movsi (reg, GEN_INT (val)));
5604 operands[1] = gen_lowpart (HImode, reg);
5605 }
5606 }
5607 }
5608 else /* TARGET_THUMB1 */
cffb2a26 5609 {
e1ba4a27 5610 if (can_create_pseudo_p ())
cffb2a26 5611 {
6cffc037 5612 if (GET_CODE (operands[1]) == CONST_INT)
5613 {
5614 rtx reg = gen_reg_rtx (SImode);
5615
5616 emit_insn (gen_movsi (reg, operands[1]));
5617 operands[1] = gen_lowpart (HImode, reg);
5618 }
cffb2a26 5619
5620 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5621 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5622 virtual register (also rejected as illegitimate for HImode/QImode)
5623 relative address. */
cffb2a26 5624 /* ??? This should perhaps be fixed elsewhere, for instance, in
5625 fixup_stack_1, by checking for other kinds of invalid addresses,
5626 e.g. a bare reference to a virtual register. This may confuse the
5627 alpha though, which must handle this case differently. */
5628 if (GET_CODE (operands[0]) == MEM
215b30b3 5629 && !memory_address_p (GET_MODE (operands[0]),
5630 XEXP (operands[0], 0)))
537ffcfc 5631 operands[0]
5632 = replace_equiv_address (operands[0],
5633 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5634
5635 if (GET_CODE (operands[1]) == MEM
215b30b3 5636 && !memory_address_p (GET_MODE (operands[1]),
5637 XEXP (operands[1], 0)))
537ffcfc 5638 operands[1]
5639 = replace_equiv_address (operands[1],
5640 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5641
5642 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5643 {
5644 rtx reg = gen_reg_rtx (SImode);
5645
5646 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5647 operands[1] = gen_lowpart (HImode, reg);
5648 }
5649
5650 if (GET_CODE (operands[0]) == MEM)
5651 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5652 }
cffb2a26 5653 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5654 && !satisfies_constraint_I (operands[1]))
cffb2a26 5655 {
6cffc037 5656 /* Handle loading a large integer during reload. */
5657
cffb2a26 5658 /* Writing a constant to memory needs a scratch, which should
5659 be handled with SECONDARY_RELOADs. */
ed29c566 5660 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5661
1a83b3ff 5662 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5663 emit_insn (gen_movsi (operands[0], operands[1]));
5664 DONE;
5665 }
b11cae9e 5666 }
cffb2a26 5667 "
5668)
5669
25f905c2 5670(define_insn "*thumb1_movhi_insn"
a941568e 5671 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5672 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5673 "TARGET_THUMB1
cffb2a26 5674 && ( register_operand (operands[0], HImode)
5675 || register_operand (operands[1], HImode))"
5676 "*
5677 switch (which_alternative)
d79300ac 5678 {
cffb2a26 5679 case 0: return \"add %0, %1, #0\";
5680 case 2: return \"strh %1, %0\";
5681 case 3: return \"mov %0, %1\";
5682 case 4: return \"mov %0, %1\";
5683 case 5: return \"mov %0, %1\";
ed29c566 5684 default: gcc_unreachable ();
cffb2a26 5685 case 1:
5686 /* The stack pointer can end up being taken as an index register.
5687 Catch this case here and deal with it. */
5688 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5689 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5690 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5691 {
5692 rtx ops[2];
5693 ops[0] = operands[0];
5694 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5695
5696 output_asm_insn (\"mov %0, %1\", ops);
5697
5698 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5699
5700 }
5701 return \"ldrh %0, %1\";
5702 }"
5703 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 5704 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 5705)
d79300ac 5706
b11cae9e 5707
25f7a26e 5708(define_expand "movhi_bytes"
eab14235 5709 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5710 (set (match_dup 3)
eab14235 5711 (zero_extend:SI (match_dup 6)))
25f7a26e 5712 (set (match_operand:SI 0 "" "")
5713 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5714 "TARGET_ARM"
25f7a26e 5715 "
215b30b3 5716 {
5717 rtx mem1, mem2;
5718 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5719
788fcce0 5720 mem1 = change_address (operands[1], QImode, addr);
5721 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5722 operands[0] = gen_lowpart (SImode, operands[0]);
5723 operands[1] = mem1;
5724 operands[2] = gen_reg_rtx (SImode);
5725 operands[3] = gen_reg_rtx (SImode);
5726 operands[6] = mem2;
25f7a26e 5727
215b30b3 5728 if (BYTES_BIG_ENDIAN)
5729 {
5730 operands[4] = operands[2];
5731 operands[5] = operands[3];
5732 }
5733 else
5734 {
5735 operands[4] = operands[3];
5736 operands[5] = operands[2];
5737 }
5738 }"
5739)
25f7a26e 5740
c7597b5d 5741(define_expand "movhi_bigend"
5742 [(set (match_dup 2)
5743 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5744 (const_int 16)))
5745 (set (match_dup 3)
5746 (ashiftrt:SI (match_dup 2) (const_int 16)))
5747 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5748 (match_dup 4))]
cffb2a26 5749 "TARGET_ARM"
c7597b5d 5750 "
5751 operands[2] = gen_reg_rtx (SImode);
5752 operands[3] = gen_reg_rtx (SImode);
787f8210 5753 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5754 "
5755)
b11cae9e 5756
a2f10574 5757;; Pattern to recognize insn generated default case above
f7fbdd4a 5758(define_insn "*movhi_insn_arch4"
cffb2a26 5759 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5760 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5761 "TARGET_ARM
5762 && arm_arch4
f7fbdd4a 5763 && (GET_CODE (operands[1]) != CONST_INT
5764 || const_ok_for_arm (INTVAL (operands[1]))
5765 || const_ok_for_arm (~INTVAL (operands[1])))"
5766 "@
5767 mov%?\\t%0, %1\\t%@ movhi
5768 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5769 str%(h%)\\t%1, %0\\t%@ movhi
5770 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5771 [(set_attr "type" "*,*,store1,load1")
0d66636f 5772 (set_attr "predicable" "yes")
cffb2a26 5773 (set_attr "pool_range" "*,*,*,256")
5774 (set_attr "neg_pool_range" "*,*,*,244")]
5775)
f7fbdd4a 5776
f7fbdd4a 5777(define_insn "*movhi_bytes"
25f7a26e 5778 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5779 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5780 "TARGET_ARM"
25f7a26e 5781 "@
5782 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5783 mvn%?\\t%0, #%B1\\t%@ movhi"
5784 [(set_attr "predicable" "yes")]
5785)
25f7a26e 5786
f90b51f1 5787(define_expand "thumb_movhi_clobber"
5788 [(set (match_operand:HI 0 "memory_operand" "")
5789 (match_operand:HI 1 "register_operand" ""))
5790 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5791 "TARGET_THUMB1"
f90b51f1 5792 "
5793 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5794 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5795 {
5796 emit_insn (gen_movhi (operands[0], operands[1]));
5797 DONE;
5798 }
5799 /* XXX Fixme, need to handle other cases here as well. */
5800 gcc_unreachable ();
5801 "
cffb2a26 5802)
5803
bc5c7e08 5804;; We use a DImode scratch because we may occasionally need an additional
5805;; temporary if the address isn't offsettable -- push_reload doesn't seem
5806;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5807(define_expand "reload_outhi"
cffb2a26 5808 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5809 (match_operand:HI 1 "s_register_operand" "r")
5810 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5811 "TARGET_EITHER"
5812 "if (TARGET_ARM)
5813 arm_reload_out_hi (operands);
5814 else
5815 thumb_reload_out_hi (operands);
d3373b54 5816 DONE;
cffb2a26 5817 "
5818)
d3373b54 5819
25f7a26e 5820(define_expand "reload_inhi"
5821 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5822 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5823 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5824 "TARGET_EITHER"
25f7a26e 5825 "
cffb2a26 5826 if (TARGET_ARM)
5827 arm_reload_in_hi (operands);
5828 else
5829 thumb_reload_out_hi (operands);
25f7a26e 5830 DONE;
5831")
5832
9c08d1fa 5833(define_expand "movqi"
5834 [(set (match_operand:QI 0 "general_operand" "")
5835 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5836 "TARGET_EITHER"
9c08d1fa 5837 "
6cffc037 5838 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5839
e1ba4a27 5840 if (can_create_pseudo_p ())
cffb2a26 5841 {
6cffc037 5842 if (GET_CODE (operands[1]) == CONST_INT)
5843 {
5844 rtx reg = gen_reg_rtx (SImode);
5845
03770691 5846 /* For thumb we want an unsigned immediate, then we are more likely
5847 to be able to use a movs insn. */
5848 if (TARGET_THUMB)
5849 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5850
6cffc037 5851 emit_insn (gen_movsi (reg, operands[1]));
5852 operands[1] = gen_lowpart (QImode, reg);
5853 }
cffb2a26 5854
6cffc037 5855 if (TARGET_THUMB)
5856 {
cffb2a26 5857 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5858 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5859 virtual register (also rejected as illegitimate for HImode/QImode)
5860 relative address. */
cffb2a26 5861 /* ??? This should perhaps be fixed elsewhere, for instance, in
5862 fixup_stack_1, by checking for other kinds of invalid addresses,
5863 e.g. a bare reference to a virtual register. This may confuse the
5864 alpha though, which must handle this case differently. */
5865 if (GET_CODE (operands[0]) == MEM
215b30b3 5866 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5867 XEXP (operands[0], 0)))
537ffcfc 5868 operands[0]
5869 = replace_equiv_address (operands[0],
5870 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5871 if (GET_CODE (operands[1]) == MEM
5872 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5873 XEXP (operands[1], 0)))
537ffcfc 5874 operands[1]
5875 = replace_equiv_address (operands[1],
5876 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5877 }
5878
5879 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5880 {
5881 rtx reg = gen_reg_rtx (SImode);
5882
5883 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5884 operands[1] = gen_lowpart (QImode, reg);
5885 }
5886
5887 if (GET_CODE (operands[0]) == MEM)
5888 operands[1] = force_reg (QImode, operands[1]);
5889 }
5890 else if (TARGET_THUMB
5891 && GET_CODE (operands[1]) == CONST_INT
234f6557 5892 && !satisfies_constraint_I (operands[1]))
6cffc037 5893 {
674a8f0b 5894 /* Handle loading a large integer during reload. */
cffb2a26 5895
6cffc037 5896 /* Writing a constant to memory needs a scratch, which should
5897 be handled with SECONDARY_RELOADs. */
5898 gcc_assert (GET_CODE (operands[0]) == REG);
5899
5900 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5901 emit_insn (gen_movsi (operands[0], operands[1]));
5902 DONE;
cffb2a26 5903 }
5904 "
5905)
b11cae9e 5906
9c08d1fa 5907
cffb2a26 5908(define_insn "*arm_movqi_insn"
5909 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5910 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5911 "TARGET_32BIT
cffb2a26 5912 && ( register_operand (operands[0], QImode)
5913 || register_operand (operands[1], QImode))"
5565501b 5914 "@
5915 mov%?\\t%0, %1
5916 mvn%?\\t%0, #%B1
25f905c2 5917 ldr%(b%)\\t%0, %1
5918 str%(b%)\\t%1, %0"
a2cd141b 5919 [(set_attr "type" "*,*,load1,store1")
0d66636f 5920 (set_attr "predicable" "yes")]
cffb2a26 5921)
5922
25f905c2 5923(define_insn "*thumb1_movqi_insn"
cffb2a26 5924 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5925 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5926 "TARGET_THUMB1
cffb2a26 5927 && ( register_operand (operands[0], QImode)
5928 || register_operand (operands[1], QImode))"
5929 "@
5930 add\\t%0, %1, #0
5931 ldrb\\t%0, %1
5932 strb\\t%1, %0
5933 mov\\t%0, %1
5934 mov\\t%0, %1
5935 mov\\t%0, %1"
5936 [(set_attr "length" "2")
a2cd141b 5937 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5938 (set_attr "pool_range" "*,32,*,*,*,*")]
5939)
b11cae9e 5940
9b8516be 5941;; HFmode moves
5942(define_expand "movhf"
5943 [(set (match_operand:HF 0 "general_operand" "")
5944 (match_operand:HF 1 "general_operand" ""))]
5945 "TARGET_EITHER"
5946 "
5947 if (TARGET_32BIT)
5948 {
5949 if (GET_CODE (operands[0]) == MEM)
5950 operands[1] = force_reg (HFmode, operands[1]);
5951 }
5952 else /* TARGET_THUMB1 */
5953 {
5954 if (can_create_pseudo_p ())
5955 {
5956 if (GET_CODE (operands[0]) != REG)
5957 operands[1] = force_reg (HFmode, operands[1]);
5958 }
5959 }
5960 "
5961)
5962
5963(define_insn "*arm32_movhf"
5964 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5965 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 5966 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 5967 && ( s_register_operand (operands[0], HFmode)
5968 || s_register_operand (operands[1], HFmode))"
5969 "*
5970 switch (which_alternative)
5971 {
5972 case 0: /* ARM register from memory */
5973 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5974 case 1: /* memory from ARM register */
5975 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5976 case 2: /* ARM register from ARM register */
5977 return \"mov%?\\t%0, %1\\t%@ __fp16\";
5978 case 3: /* ARM register from constant */
5979 {
5980 REAL_VALUE_TYPE r;
5981 long bits;
5982 rtx ops[4];
5983
5984 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
5985 bits = real_to_target (NULL, &r, HFmode);
5986 ops[0] = operands[0];
5987 ops[1] = GEN_INT (bits);
5988 ops[2] = GEN_INT (bits & 0xff00);
5989 ops[3] = GEN_INT (bits & 0x00ff);
5990
5991 if (arm_arch_thumb2)
5992 output_asm_insn (\"movw%?\\t%0, %1\", ops);
5993 else
5994 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
5995 return \"\";
5996 }
5997 default:
5998 gcc_unreachable ();
5999 }
6000 "
6001 [(set_attr "conds" "unconditional")
6002 (set_attr "type" "load1,store1,*,*")
6003 (set_attr "length" "4,4,4,8")
6004 (set_attr "predicable" "yes")
6005 ]
6006)
6007
6008(define_insn "*thumb1_movhf"
6009 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6010 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6011 "TARGET_THUMB1
6012 && ( s_register_operand (operands[0], HFmode)
6013 || s_register_operand (operands[1], HFmode))"
6014 "*
6015 switch (which_alternative)
6016 {
6017 case 1:
6018 {
6019 rtx addr;
6020 gcc_assert (GET_CODE(operands[1]) == MEM);
6021 addr = XEXP (operands[1], 0);
6022 if (GET_CODE (addr) == LABEL_REF
6023 || (GET_CODE (addr) == CONST
6024 && GET_CODE (XEXP (addr, 0)) == PLUS
6025 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6026 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6027 {
6028 /* Constant pool entry. */
6029 return \"ldr\\t%0, %1\";
6030 }
6031 return \"ldrh\\t%0, %1\";
6032 }
6033 case 2: return \"strh\\t%1, %0\";
6034 default: return \"mov\\t%0, %1\";
6035 }
6036 "
6037 [(set_attr "length" "2")
6038 (set_attr "type" "*,load1,store1,*,*")
6039 (set_attr "pool_range" "*,1020,*,*,*")]
6040)
6041
87b22bf7 6042(define_expand "movsf"
6043 [(set (match_operand:SF 0 "general_operand" "")
6044 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6045 "TARGET_EITHER"
87b22bf7 6046 "
25f905c2 6047 if (TARGET_32BIT)
cffb2a26 6048 {
6049 if (GET_CODE (operands[0]) == MEM)
6050 operands[1] = force_reg (SFmode, operands[1]);
6051 }
25f905c2 6052 else /* TARGET_THUMB1 */
cffb2a26 6053 {
e1ba4a27 6054 if (can_create_pseudo_p ())
cffb2a26 6055 {
6056 if (GET_CODE (operands[0]) != REG)
6057 operands[1] = force_reg (SFmode, operands[1]);
6058 }
6059 }
6060 "
6061)
6062
03d440a6 6063;; Transform a floating-point move of a constant into a core register into
6064;; an SImode operation.
cffb2a26 6065(define_split
03d440a6 6066 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6067 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6068 "TARGET_EITHER
cffb2a26 6069 && reload_completed
6070 && GET_CODE (operands[1]) == CONST_DOUBLE"
6071 [(set (match_dup 2) (match_dup 3))]
6072 "
6073 operands[2] = gen_lowpart (SImode, operands[0]);
6074 operands[3] = gen_lowpart (SImode, operands[1]);
6075 if (operands[2] == 0 || operands[3] == 0)
6076 FAIL;
215b30b3 6077 "
6078)
87b22bf7 6079
cffb2a26 6080(define_insn "*arm_movsf_soft_insn"
6081 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6082 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6083 "TARGET_ARM
6084 && TARGET_SOFT_FLOAT
215b30b3 6085 && (GET_CODE (operands[0]) != MEM
6086 || register_operand (operands[1], SFmode))"
9a1112d7 6087 "@
6088 mov%?\\t%0, %1
6089 ldr%?\\t%0, %1\\t%@ float
6090 str%?\\t%1, %0\\t%@ float"
cffb2a26 6091 [(set_attr "length" "4,4,4")
0d66636f 6092 (set_attr "predicable" "yes")
a2cd141b 6093 (set_attr "type" "*,load1,store1")
cffb2a26 6094 (set_attr "pool_range" "*,4096,*")
6095 (set_attr "neg_pool_range" "*,4084,*")]
6096)
6097
6098;;; ??? This should have alternatives for constants.
25f905c2 6099(define_insn "*thumb1_movsf_insn"
215b30b3 6100 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6101 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6102 "TARGET_THUMB1
cffb2a26 6103 && ( register_operand (operands[0], SFmode)
6104 || register_operand (operands[1], SFmode))"
6105 "@
6106 add\\t%0, %1, #0
6107 ldmia\\t%1, {%0}
6108 stmia\\t%0, {%1}
6109 ldr\\t%0, %1
6110 str\\t%1, %0
6111 mov\\t%0, %1
6112 mov\\t%0, %1"
6113 [(set_attr "length" "2")
a2cd141b 6114 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 6115 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
6116)
9a1112d7 6117
9c08d1fa 6118(define_expand "movdf"
87b22bf7 6119 [(set (match_operand:DF 0 "general_operand" "")
6120 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6121 "TARGET_EITHER"
9c08d1fa 6122 "
25f905c2 6123 if (TARGET_32BIT)
cffb2a26 6124 {
6125 if (GET_CODE (operands[0]) == MEM)
6126 operands[1] = force_reg (DFmode, operands[1]);
6127 }
6128 else /* TARGET_THUMB */
6129 {
e1ba4a27 6130 if (can_create_pseudo_p ())
cffb2a26 6131 {
6132 if (GET_CODE (operands[0]) != REG)
6133 operands[1] = force_reg (DFmode, operands[1]);
6134 }
6135 }
6136 "
6137)
b11cae9e 6138
9c08d1fa 6139;; Reloading a df mode value stored in integer regs to memory can require a
6140;; scratch reg.
6141(define_expand "reload_outdf"
cffb2a26 6142 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6143 (match_operand:DF 1 "s_register_operand" "r")
6144 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6145 "TARGET_32BIT"
87b22bf7 6146 "
215b30b3 6147 {
6148 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6149
215b30b3 6150 if (code == REG)
6151 operands[2] = XEXP (operands[0], 0);
6152 else if (code == POST_INC || code == PRE_DEC)
6153 {
6154 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6155 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6156 emit_insn (gen_movdi (operands[0], operands[1]));
6157 DONE;
6158 }
6159 else if (code == PRE_INC)
6160 {
6161 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6162
215b30b3 6163 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6164 operands[2] = reg;
6165 }
6166 else if (code == POST_DEC)
6167 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6168 else
6169 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6170 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6171
788fcce0 6172 emit_insn (gen_rtx_SET (VOIDmode,
6173 replace_equiv_address (operands[0], operands[2]),
215b30b3 6174 operands[1]));
f7fbdd4a 6175
215b30b3 6176 if (code == POST_DEC)
6177 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6178
6179 DONE;
6180 }"
6181)
9c08d1fa 6182
9a1112d7 6183(define_insn "*movdf_soft_insn"
359a6e9f 6184 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6185 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 6186 "TARGET_ARM && TARGET_SOFT_FLOAT
b2778788 6187 && ( register_operand (operands[0], DFmode)
6188 || register_operand (operands[1], DFmode))"
d51f92df 6189 "*
6190 switch (which_alternative)
6191 {
6192 case 0:
6193 case 1:
6194 case 2:
6195 return \"#\";
6196 default:
6197 return output_move_double (operands);
6198 }
6199 "
359a6e9f 6200 [(set_attr "length" "8,12,16,8,8")
6201 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 6202 (set_attr "pool_range" "1020")
6203 (set_attr "neg_pool_range" "1008")]
cffb2a26 6204)
6205
6206;;; ??? This should have alternatives for constants.
6207;;; ??? This was originally identical to the movdi_insn pattern.
6208;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6209;;; thumb_reorg with a memory reference.
6210(define_insn "*thumb_movdf_insn"
215b30b3 6211 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6212 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6213 "TARGET_THUMB1
cffb2a26 6214 && ( register_operand (operands[0], DFmode)
6215 || register_operand (operands[1], DFmode))"
6216 "*
6217 switch (which_alternative)
6218 {
6219 default:
6220 case 0:
6221 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6222 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6223 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6224 case 1:
6225 return \"ldmia\\t%1, {%0, %H0}\";
6226 case 2:
6227 return \"stmia\\t%0, {%1, %H1}\";
6228 case 3:
6229 return thumb_load_double_from_address (operands);
6230 case 4:
1a83b3ff 6231 operands[2] = gen_rtx_MEM (SImode,
6232 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6233 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6234 return \"\";
6235 case 5:
6236 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6237 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6238 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6239 }
6240 "
6241 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6242 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 6243 (set_attr "pool_range" "*,*,*,1020,*,*")]
6244)
755eb2b4 6245
ccd90aaa 6246(define_expand "movxf"
6247 [(set (match_operand:XF 0 "general_operand" "")
6248 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6249 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6250 "
6251 if (GET_CODE (operands[0]) == MEM)
6252 operands[1] = force_reg (XFmode, operands[1]);
6253 "
6254)
6255
b11cae9e 6256\f
b11cae9e 6257
9c08d1fa 6258;; load- and store-multiple insns
6259;; The arm can load/store any set of registers, provided that they are in
6260;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 6261
9c08d1fa 6262(define_expand "load_multiple"
6263 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6264 (match_operand:SI 1 "" ""))
6265 (use (match_operand:SI 2 "" ""))])]
25f905c2 6266 "TARGET_32BIT"
9580c25f 6267{
6268 HOST_WIDE_INT offset = 0;
6269
bd5b4116 6270 /* Support only fixed point registers. */
9c08d1fa 6271 if (GET_CODE (operands[2]) != CONST_INT
6272 || INTVAL (operands[2]) > 14
6273 || INTVAL (operands[2]) < 2
6274 || GET_CODE (operands[1]) != MEM
6275 || GET_CODE (operands[0]) != REG
bd5b4116 6276 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6277 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6278 FAIL;
6279
6280 operands[3]
f082f1c4 6281 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6282 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 6283 TRUE, FALSE, operands[1], &offset);
6284})
b11cae9e 6285
9c08d1fa 6286;; Load multiple with write-back
6287
2162064c 6288(define_insn "*ldmsi_postinc4"
9c08d1fa 6289 [(match_parallel 0 "load_multiple_operation"
13e9316a 6290 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6291 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6292 (const_int 16)))
6293 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6294 (mem:SI (match_dup 2)))
a0a72ac3 6295 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 6296 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6297 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6298 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6299 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6300 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6301 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6302 "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
a2cd141b 6303 [(set_attr "type" "load4")
2162064c 6304 (set_attr "predicable" "yes")]
6305)
b11cae9e 6306
25f905c2 6307(define_insn "*ldmsi_postinc4_thumb1"
ccd90aaa 6308 [(match_parallel 0 "load_multiple_operation"
6309 [(set (match_operand:SI 1 "s_register_operand" "=l")
6310 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6311 (const_int 16)))
6312 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6313 (mem:SI (match_dup 2)))
6314 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6315 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6316 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6317 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6318 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6319 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6320 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6321 "ldmia\\t%1!, {%3, %4, %5, %6}"
6322 [(set_attr "type" "load4")]
6323)
6324
2162064c 6325(define_insn "*ldmsi_postinc3"
6326 [(match_parallel 0 "load_multiple_operation"
13e9316a 6327 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6328 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6329 (const_int 12)))
6330 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6331 (mem:SI (match_dup 2)))
6332 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6333 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6334 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6335 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
25f905c2 6336 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6337 "ldm%(ia%)\\t%1!, {%3, %4, %5}"
a2cd141b 6338 [(set_attr "type" "load3")
2162064c 6339 (set_attr "predicable" "yes")]
6340)
b11cae9e 6341
2162064c 6342(define_insn "*ldmsi_postinc2"
6343 [(match_parallel 0 "load_multiple_operation"
13e9316a 6344 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6345 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6346 (const_int 8)))
6347 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6348 (mem:SI (match_dup 2)))
6349 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6350 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
25f905c2 6351 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6352 "ldm%(ia%)\\t%1!, {%3, %4}"
a2cd141b 6353 [(set_attr "type" "load2")
0d66636f 6354 (set_attr "predicable" "yes")]
6355)
b11cae9e 6356
9c08d1fa 6357;; Ordinary load multiple
b11cae9e 6358
2162064c 6359(define_insn "*ldmsi4"
9c08d1fa 6360 [(match_parallel 0 "load_multiple_operation"
2162064c 6361 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6362 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6363 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6364 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6365 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6366 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6367 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6368 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
25f905c2 6369 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6370 "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
a2cd141b 6371 [(set_attr "type" "load4")
2162064c 6372 (set_attr "predicable" "yes")]
6373)
9c08d1fa 6374
2162064c 6375(define_insn "*ldmsi3"
6376 [(match_parallel 0 "load_multiple_operation"
6377 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6378 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6379 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6380 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6381 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6382 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
25f905c2 6383 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6384 "ldm%(ia%)\\t%1, {%2, %3, %4}"
a2cd141b 6385 [(set_attr "type" "load3")
2162064c 6386 (set_attr "predicable" "yes")]
6387)
9c08d1fa 6388
2162064c 6389(define_insn "*ldmsi2"
6390 [(match_parallel 0 "load_multiple_operation"
6391 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6392 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6393 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6394 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
25f905c2 6395 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6396 "ldm%(ia%)\\t%1, {%2, %3}"
a2cd141b 6397 [(set_attr "type" "load2")
0d66636f 6398 (set_attr "predicable" "yes")]
6399)
9c08d1fa 6400
6401(define_expand "store_multiple"
6402 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6403 (match_operand:SI 1 "" ""))
6404 (use (match_operand:SI 2 "" ""))])]
25f905c2 6405 "TARGET_32BIT"
9580c25f 6406{
6407 HOST_WIDE_INT offset = 0;
6408
674a8f0b 6409 /* Support only fixed point registers. */
9c08d1fa 6410 if (GET_CODE (operands[2]) != CONST_INT
6411 || INTVAL (operands[2]) > 14
6412 || INTVAL (operands[2]) < 2
6413 || GET_CODE (operands[1]) != REG
6414 || GET_CODE (operands[0]) != MEM
bd5b4116 6415 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6416 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6417 FAIL;
6418
6419 operands[3]
f082f1c4 6420 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6421 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 6422 TRUE, FALSE, operands[0], &offset);
6423})
b11cae9e 6424
9c08d1fa 6425;; Store multiple with write-back
6426
2162064c 6427(define_insn "*stmsi_postinc4"
9c08d1fa 6428 [(match_parallel 0 "store_multiple_operation"
13e9316a 6429 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6430 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6431 (const_int 16)))
a0a72ac3 6432 (set (mem:SI (match_dup 2))
2162064c 6433 (match_operand:SI 3 "arm_hard_register_operand" ""))
6434 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6435 (match_operand:SI 4 "arm_hard_register_operand" ""))
6436 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6437 (match_operand:SI 5 "arm_hard_register_operand" ""))
6438 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6439 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6440 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6441 "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
2162064c 6442 [(set_attr "predicable" "yes")
6443 (set_attr "type" "store4")]
6444)
b11cae9e 6445
25f905c2 6446(define_insn "*stmsi_postinc4_thumb1"
ccd90aaa 6447 [(match_parallel 0 "store_multiple_operation"
6448 [(set (match_operand:SI 1 "s_register_operand" "=l")
6449 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6450 (const_int 16)))
6451 (set (mem:SI (match_dup 2))
6452 (match_operand:SI 3 "arm_hard_register_operand" ""))
6453 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6454 (match_operand:SI 4 "arm_hard_register_operand" ""))
6455 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6456 (match_operand:SI 5 "arm_hard_register_operand" ""))
6457 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6458 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6459 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6460 "stmia\\t%1!, {%3, %4, %5, %6}"
6461 [(set_attr "type" "store4")]
6462)
6463
2162064c 6464(define_insn "*stmsi_postinc3"
6465 [(match_parallel 0 "store_multiple_operation"
13e9316a 6466 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6467 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6468 (const_int 12)))
6469 (set (mem:SI (match_dup 2))
6470 (match_operand:SI 3 "arm_hard_register_operand" ""))
6471 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6472 (match_operand:SI 4 "arm_hard_register_operand" ""))
6473 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6474 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6475 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6476 "stm%(ia%)\\t%1!, {%3, %4, %5}"
2162064c 6477 [(set_attr "predicable" "yes")
6478 (set_attr "type" "store3")]
6479)
9c08d1fa 6480
2162064c 6481(define_insn "*stmsi_postinc2"
6482 [(match_parallel 0 "store_multiple_operation"
13e9316a 6483 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6484 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6485 (const_int 8)))
6486 (set (mem:SI (match_dup 2))
6487 (match_operand:SI 3 "arm_hard_register_operand" ""))
6488 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6489 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6490 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6491 "stm%(ia%)\\t%1!, {%3, %4}"
0d66636f 6492 [(set_attr "predicable" "yes")
2162064c 6493 (set_attr "type" "store2")]
cffb2a26 6494)
9c08d1fa 6495
6496;; Ordinary store multiple
6497
2162064c 6498(define_insn "*stmsi4"
9c08d1fa 6499 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 6500 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 6501 (match_operand:SI 2 "arm_hard_register_operand" ""))
6502 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6503 (match_operand:SI 3 "arm_hard_register_operand" ""))
6504 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6505 (match_operand:SI 4 "arm_hard_register_operand" ""))
6506 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6507 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6508 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6509 "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
2162064c 6510 [(set_attr "predicable" "yes")
6511 (set_attr "type" "store4")]
6512)
9c08d1fa 6513
2162064c 6514(define_insn "*stmsi3"
6515 [(match_parallel 0 "store_multiple_operation"
6516 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6517 (match_operand:SI 2 "arm_hard_register_operand" ""))
6518 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6519 (match_operand:SI 3 "arm_hard_register_operand" ""))
6520 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6521 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6522 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6523 "stm%(ia%)\\t%1, {%2, %3, %4}"
2162064c 6524 [(set_attr "predicable" "yes")
6525 (set_attr "type" "store3")]
6526)
9c08d1fa 6527
2162064c 6528(define_insn "*stmsi2"
6529 [(match_parallel 0 "store_multiple_operation"
6530 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6531 (match_operand:SI 2 "arm_hard_register_operand" ""))
6532 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6533 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
25f905c2 6534 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6535 "stm%(ia%)\\t%1, {%2, %3}"
0d66636f 6536 [(set_attr "predicable" "yes")
2162064c 6537 (set_attr "type" "store2")]
cffb2a26 6538)
9c08d1fa 6539
6540;; Move a block of memory if it is word aligned and MORE than 2 words long.
6541;; We could let this apply for blocks of less than this, but it clobbers so
6542;; many registers that there is then probably a better way.
6543
008c057d 6544(define_expand "movmemqi"
34191dd1 6545 [(match_operand:BLK 0 "general_operand" "")
6546 (match_operand:BLK 1 "general_operand" "")
6547 (match_operand:SI 2 "const_int_operand" "")
6548 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6549 "TARGET_EITHER"
9c08d1fa 6550 "
25f905c2 6551 if (TARGET_32BIT)
cffb2a26 6552 {
008c057d 6553 if (arm_gen_movmemqi (operands))
cffb2a26 6554 DONE;
6555 FAIL;
6556 }
25f905c2 6557 else /* TARGET_THUMB1 */
cffb2a26 6558 {
6559 if ( INTVAL (operands[3]) != 4
6560 || INTVAL (operands[2]) > 48)
6561 FAIL;
6562
008c057d 6563 thumb_expand_movmemqi (operands);
cffb2a26 6564 DONE;
6565 }
6566 "
6567)
6568
2162064c 6569;; Thumb block-move insns
cffb2a26 6570
6571(define_insn "movmem12b"
960f3acf 6572 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6573 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6574 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6575 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6576 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6577 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6578 (set (match_operand:SI 0 "register_operand" "=l")
6579 (plus:SI (match_dup 2) (const_int 12)))
6580 (set (match_operand:SI 1 "register_operand" "=l")
6581 (plus:SI (match_dup 3) (const_int 12)))
6582 (clobber (match_scratch:SI 4 "=&l"))
6583 (clobber (match_scratch:SI 5 "=&l"))
6584 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6585 "TARGET_THUMB1"
cffb2a26 6586 "* return thumb_output_move_mem_multiple (3, operands);"
6587 [(set_attr "length" "4")
215b30b3 6588 ; This isn't entirely accurate... It loads as well, but in terms of
6589 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6590 (set_attr "type" "store3")]
6591)
6592
6593(define_insn "movmem8b"
960f3acf 6594 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6595 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6596 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6597 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6598 (set (match_operand:SI 0 "register_operand" "=l")
6599 (plus:SI (match_dup 2) (const_int 8)))
6600 (set (match_operand:SI 1 "register_operand" "=l")
6601 (plus:SI (match_dup 3) (const_int 8)))
6602 (clobber (match_scratch:SI 4 "=&l"))
6603 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6604 "TARGET_THUMB1"
cffb2a26 6605 "* return thumb_output_move_mem_multiple (2, operands);"
6606 [(set_attr "length" "4")
215b30b3 6607 ; This isn't entirely accurate... It loads as well, but in terms of
6608 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6609 (set_attr "type" "store2")]
6610)
6611
9c08d1fa 6612\f
b11cae9e 6613
341940e8 6614;; Compare & branch insns
8d232dc7 6615;; The range calculations are based as follows:
341940e8 6616;; For forward branches, the address calculation returns the address of
6617;; the next instruction. This is 2 beyond the branch instruction.
6618;; For backward branches, the address calculation returns the address of
6619;; the first instruction in this pattern (cmp). This is 2 before the branch
6620;; instruction for the shortest sequence, and 4 before the branch instruction
6621;; if we have to jump around an unconditional branch.
6622;; To the basic branch range the PC offset must be added (this is +4).
6623;; So for forward branches we have
6624;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6625;; And for backward branches we have
6626;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6627;;
6628;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6629;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6630
aeac46d4 6631(define_expand "cbranchsi4"
6632 [(set (pc) (if_then_else
6633 (match_operator 0 "arm_comparison_operator"
6634 [(match_operand:SI 1 "s_register_operand" "")
6635 (match_operand:SI 2 "nonmemory_operand" "")])
6636 (label_ref (match_operand 3 "" ""))
6637 (pc)))]
74f4459c 6638 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6639 "
74f4459c 6640 if (!TARGET_THUMB1)
6641 {
6642 if (!arm_add_operand (operands[2], SImode))
6643 operands[2] = force_reg (SImode, operands[2]);
6644 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6645 operands[3]));
6646 DONE;
6647 }
25f905c2 6648 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6649 {
6650 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6651 operands[3], operands[0]));
6652 DONE;
6653 }
25f905c2 6654 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6655 operands[2] = force_reg (SImode, operands[2]);
6656 ")
6657
a8e6c15d 6658;; A pattern to recognize a special situation and optimize for it.
6659;; On the thumb, zero-extension from memory is preferrable to sign-extension
6660;; due to the available addressing modes. Hence, convert a signed comparison
6661;; with zero into an unsigned comparison with 127 if possible.
6662(define_expand "cbranchqi4"
6663 [(set (pc) (if_then_else
6664 (match_operator 0 "lt_ge_comparison_operator"
6665 [(match_operand:QI 1 "memory_operand" "")
6666 (match_operand:QI 2 "const0_operand" "")])
6667 (label_ref (match_operand 3 "" ""))
6668 (pc)))]
6669 "TARGET_THUMB1"
6670{
6671 rtx xops[3];
6672 xops[1] = gen_reg_rtx (SImode);
6673 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6674 xops[2] = GEN_INT (127);
6675 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6676 VOIDmode, xops[1], xops[2]);
6677 xops[3] = operands[3];
6678 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6679 DONE;
6680})
6681
74f4459c 6682(define_expand "cbranchsf4"
6683 [(set (pc) (if_then_else
6684 (match_operator 0 "arm_comparison_operator"
6685 [(match_operand:SF 1 "s_register_operand" "")
6686 (match_operand:SF 2 "arm_float_compare_operand" "")])
6687 (label_ref (match_operand 3 "" ""))
6688 (pc)))]
6689 "TARGET_32BIT && TARGET_HARD_FLOAT"
6690 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6691 operands[3])); DONE;"
6692)
6693
6694(define_expand "cbranchdf4"
6695 [(set (pc) (if_then_else
6696 (match_operator 0 "arm_comparison_operator"
6697 [(match_operand:DF 1 "s_register_operand" "")
6698 (match_operand:DF 2 "arm_float_compare_operand" "")])
6699 (label_ref (match_operand 3 "" ""))
6700 (pc)))]
a50d7267 6701 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6702 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6703 operands[3])); DONE;"
6704)
6705
6706;; this uses the Cirrus DI compare instruction
6707(define_expand "cbranchdi4"
6708 [(set (pc) (if_then_else
6709 (match_operator 0 "arm_comparison_operator"
6710 [(match_operand:DI 1 "cirrus_fp_register" "")
6711 (match_operand:DI 2 "cirrus_fp_register" "")])
6712 (label_ref (match_operand 3 "" ""))
6713 (pc)))]
6714 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6715 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6716 operands[3])); DONE;"
6717)
6718
d60047aa 6719(define_insn "cbranchsi4_insn"
aeac46d4 6720 [(set (pc) (if_then_else
6721 (match_operator 0 "arm_comparison_operator"
6722 [(match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 6723 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6724 (label_ref (match_operand 3 "" ""))
6725 (pc)))]
25f905c2 6726 "TARGET_THUMB1"
cffb2a26 6727 "*
d60047aa 6728 rtx t = prev_nonnote_insn (insn);
6729 if (t != NULL_RTX
6730 && INSN_P (t)
6731 && INSN_CODE (t) == CODE_FOR_cbranchsi4_insn)
6732 {
6733 t = XEXP (SET_SRC (PATTERN (t)), 0);
6734 if (!rtx_equal_p (XEXP (t, 0), operands[1])
6735 || !rtx_equal_p (XEXP (t, 1), operands[2]))
6736 t = NULL_RTX;
6737 }
6738 else
6739 t = NULL_RTX;
6740 if (t == NULL_RTX)
6741 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 6742
cffb2a26 6743 switch (get_attr_length (insn))
6744 {
6745 case 4: return \"b%d0\\t%l3\";
6746 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6747 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6748 }
6749 "
6750 [(set (attr "far_jump")
6751 (if_then_else
6752 (eq_attr "length" "8")
6753 (const_string "yes")
6754 (const_string "no")))
6755 (set (attr "length")
6756 (if_then_else
6757 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6758 (le (minus (match_dup 3) (pc)) (const_int 256)))
6759 (const_int 4)
6760 (if_then_else
6761 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6762 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6763 (const_int 6)
6764 (const_int 8))))]
6765)
6766
aeac46d4 6767(define_insn "cbranchsi4_scratch"
6768 [(set (pc) (if_then_else
6769 (match_operator 4 "arm_comparison_operator"
6770 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6771 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6772 (label_ref (match_operand 3 "" ""))
6773 (pc)))
6774 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6775 "TARGET_THUMB1"
aeac46d4 6776 "*
6777 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6778
6779 switch (get_attr_length (insn))
6780 {
6781 case 4: return \"b%d4\\t%l3\";
6782 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6783 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6784 }
6785 "
6786 [(set (attr "far_jump")
6787 (if_then_else
6788 (eq_attr "length" "8")
6789 (const_string "yes")
6790 (const_string "no")))
6791 (set (attr "length")
6792 (if_then_else
6793 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6794 (le (minus (match_dup 3) (pc)) (const_int 256)))
6795 (const_int 4)
6796 (if_then_else
6797 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6798 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6799 (const_int 6)
6800 (const_int 8))))]
6801)
446a1e96 6802
aeac46d4 6803(define_insn "*movsi_cbranchsi4"
6804 [(set (pc)
6805 (if_then_else
6806 (match_operator 3 "arm_comparison_operator"
6807 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6808 (const_int 0)])
6809 (label_ref (match_operand 2 "" ""))
6810 (pc)))
6811 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6812 (match_dup 1))]
25f905c2 6813 "TARGET_THUMB1"
aeac46d4 6814 "*{
6815 if (which_alternative == 0)
6816 output_asm_insn (\"cmp\t%0, #0\", operands);
6817 else if (which_alternative == 1)
6818 output_asm_insn (\"sub\t%0, %1, #0\", operands);
6819 else
6820 {
6821 output_asm_insn (\"cmp\t%1, #0\", operands);
6822 if (which_alternative == 2)
6823 output_asm_insn (\"mov\t%0, %1\", operands);
6824 else
6825 output_asm_insn (\"str\t%1, %0\", operands);
6826 }
6827 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6828 {
6829 case 4: return \"b%d3\\t%l2\";
6830 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6831 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6832 }
6833 }"
6834 [(set (attr "far_jump")
6835 (if_then_else
6836 (ior (and (gt (symbol_ref ("which_alternative"))
6837 (const_int 1))
6838 (eq_attr "length" "8"))
6839 (eq_attr "length" "10"))
6840 (const_string "yes")
6841 (const_string "no")))
6842 (set (attr "length")
6843 (if_then_else
6844 (le (symbol_ref ("which_alternative"))
6845 (const_int 1))
6846 (if_then_else
6847 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6848 (le (minus (match_dup 2) (pc)) (const_int 256)))
6849 (const_int 4)
6850 (if_then_else
6851 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6852 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6853 (const_int 6)
6854 (const_int 8)))
6855 (if_then_else
6856 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6857 (le (minus (match_dup 2) (pc)) (const_int 256)))
6858 (const_int 6)
6859 (if_then_else
6860 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6861 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6862 (const_int 8)
6863 (const_int 10)))))]
6864)
6865
446a1e96 6866(define_peephole2
6867 [(set (match_operand:SI 0 "low_register_operand" "")
6868 (match_operand:SI 1 "low_register_operand" ""))
6869 (set (pc)
6870 (if_then_else (match_operator 2 "arm_comparison_operator"
6871 [(match_dup 1) (const_int 0)])
6872 (label_ref (match_operand 3 "" ""))
6873 (pc)))]
6874 "TARGET_THUMB1"
6875 [(parallel
6876 [(set (pc)
6877 (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6878 (label_ref (match_dup 3))
6879 (pc)))
6880 (set (match_dup 0) (match_dup 1))])]
6881 ""
6882)
6883
6884;; Sigh! This variant shouldn't be needed, but combine often fails to
6885;; merge cases like this because the op1 is a hard register in
6886;; CLASS_LIKELY_SPILLED_P.
6887(define_peephole2
6888 [(set (match_operand:SI 0 "low_register_operand" "")
6889 (match_operand:SI 1 "low_register_operand" ""))
6890 (set (pc)
6891 (if_then_else (match_operator 2 "arm_comparison_operator"
6892 [(match_dup 0) (const_int 0)])
6893 (label_ref (match_operand 3 "" ""))
6894 (pc)))]
6895 "TARGET_THUMB1"
6896 [(parallel
6897 [(set (pc)
6898 (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6899 (label_ref (match_dup 3))
6900 (pc)))
6901 (set (match_dup 0) (match_dup 1))])]
6902 ""
6903)
6904
cffb2a26 6905(define_insn "*negated_cbranchsi4"
6906 [(set (pc)
6907 (if_then_else
aed179ae 6908 (match_operator 0 "equality_operator"
aeac46d4 6909 [(match_operand:SI 1 "s_register_operand" "l")
6910 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6911 (label_ref (match_operand 3 "" ""))
215b30b3 6912 (pc)))]
25f905c2 6913 "TARGET_THUMB1"
cffb2a26 6914 "*
6915 output_asm_insn (\"cmn\\t%1, %2\", operands);
6916 switch (get_attr_length (insn))
6917 {
6918 case 4: return \"b%d0\\t%l3\";
6919 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6920 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6921 }
6922 "
6923 [(set (attr "far_jump")
6924 (if_then_else
6925 (eq_attr "length" "8")
6926 (const_string "yes")
6927 (const_string "no")))
6928 (set (attr "length")
6929 (if_then_else
6930 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6931 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6932 (const_int 4)
6933 (if_then_else
341940e8 6934 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6935 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6936 (const_int 6)
6937 (const_int 8))))]
6938)
6939
58d6528b 6940(define_insn "*tbit_cbranch"
6941 [(set (pc)
6942 (if_then_else
6943 (match_operator 0 "equality_operator"
6944 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6945 (const_int 1)
6946 (match_operand:SI 2 "const_int_operand" "i"))
6947 (const_int 0)])
6948 (label_ref (match_operand 3 "" ""))
6949 (pc)))
6950 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6951 "TARGET_THUMB1"
58d6528b 6952 "*
6953 {
6954 rtx op[3];
6955 op[0] = operands[4];
6956 op[1] = operands[1];
6957 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6958
86efa74d 6959 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6960 switch (get_attr_length (insn))
6961 {
6962 case 4: return \"b%d0\\t%l3\";
6963 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6964 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6965 }
6966 }"
6967 [(set (attr "far_jump")
6968 (if_then_else
6969 (eq_attr "length" "8")
6970 (const_string "yes")
6971 (const_string "no")))
6972 (set (attr "length")
6973 (if_then_else
6974 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6975 (le (minus (match_dup 3) (pc)) (const_int 256)))
6976 (const_int 4)
6977 (if_then_else
6978 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6979 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6980 (const_int 6)
6981 (const_int 8))))]
6982)
6983
6984(define_insn "*tlobits_cbranch"
6985 [(set (pc)
6986 (if_then_else
6987 (match_operator 0 "equality_operator"
6988 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6989 (match_operand:SI 2 "const_int_operand" "i")
6990 (const_int 0))
6991 (const_int 0)])
6992 (label_ref (match_operand 3 "" ""))
6993 (pc)))
6994 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6995 "TARGET_THUMB1"
86efa74d 6996 "*
6997 {
6998 rtx op[3];
6999 op[0] = operands[4];
7000 op[1] = operands[1];
7001 op[2] = GEN_INT (32 - INTVAL (operands[2]));
7002
58d6528b 7003 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7004 switch (get_attr_length (insn))
7005 {
7006 case 4: return \"b%d0\\t%l3\";
7007 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7008 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7009 }
7010 }"
7011 [(set (attr "far_jump")
7012 (if_then_else
7013 (eq_attr "length" "8")
7014 (const_string "yes")
7015 (const_string "no")))
7016 (set (attr "length")
7017 (if_then_else
7018 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7019 (le (minus (match_dup 3) (pc)) (const_int 256)))
7020 (const_int 4)
7021 (if_then_else
7022 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7023 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7024 (const_int 6)
7025 (const_int 8))))]
7026)
7027
aeac46d4 7028(define_insn "*tstsi3_cbranch"
58d6528b 7029 [(set (pc)
7030 (if_then_else
aeac46d4 7031 (match_operator 3 "equality_operator"
7032 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7033 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 7034 (const_int 0)])
aeac46d4 7035 (label_ref (match_operand 2 "" ""))
7036 (pc)))]
25f905c2 7037 "TARGET_THUMB1"
58d6528b 7038 "*
7039 {
aeac46d4 7040 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 7041 switch (get_attr_length (insn))
7042 {
aeac46d4 7043 case 4: return \"b%d3\\t%l2\";
7044 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7045 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 7046 }
7047 }"
7048 [(set (attr "far_jump")
7049 (if_then_else
7050 (eq_attr "length" "8")
7051 (const_string "yes")
7052 (const_string "no")))
7053 (set (attr "length")
7054 (if_then_else
aeac46d4 7055 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7056 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 7057 (const_int 4)
7058 (if_then_else
aeac46d4 7059 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7060 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 7061 (const_int 6)
7062 (const_int 8))))]
7063)
7064
7065(define_insn "*andsi3_cbranch"
7066 [(set (pc)
7067 (if_then_else
7068 (match_operator 5 "equality_operator"
7069 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7070 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7071 (const_int 0)])
7072 (label_ref (match_operand 4 "" ""))
7073 (pc)))
aeac46d4 7074 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7075 (and:SI (match_dup 2) (match_dup 3)))
7076 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7077 "TARGET_THUMB1"
58d6528b 7078 "*
7079 {
7080 if (which_alternative == 0)
7081 output_asm_insn (\"and\\t%0, %3\", operands);
7082 else if (which_alternative == 1)
7083 {
7084 output_asm_insn (\"and\\t%1, %3\", operands);
7085 output_asm_insn (\"mov\\t%0, %1\", operands);
7086 }
7087 else
7088 {
7089 output_asm_insn (\"and\\t%1, %3\", operands);
7090 output_asm_insn (\"str\\t%1, %0\", operands);
7091 }
7092
7093 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7094 {
7095 case 4: return \"b%d5\\t%l4\";
7096 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7097 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7098 }
7099 }"
7100 [(set (attr "far_jump")
7101 (if_then_else
7102 (ior (and (eq (symbol_ref ("which_alternative"))
7103 (const_int 0))
7104 (eq_attr "length" "8"))
7105 (eq_attr "length" "10"))
7106 (const_string "yes")
7107 (const_string "no")))
7108 (set (attr "length")
7109 (if_then_else
7110 (eq (symbol_ref ("which_alternative"))
7111 (const_int 0))
7112 (if_then_else
7113 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7114 (le (minus (match_dup 4) (pc)) (const_int 256)))
7115 (const_int 4)
7116 (if_then_else
7117 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7118 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7119 (const_int 6)
7120 (const_int 8)))
7121 (if_then_else
7122 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7123 (le (minus (match_dup 4) (pc)) (const_int 256)))
7124 (const_int 6)
7125 (if_then_else
7126 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7127 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7128 (const_int 8)
7129 (const_int 10)))))]
7130)
7131
7132(define_insn "*orrsi3_cbranch_scratch"
7133 [(set (pc)
7134 (if_then_else
7135 (match_operator 4 "equality_operator"
7136 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
7137 (match_operand:SI 2 "s_register_operand" "l"))
7138 (const_int 0)])
7139 (label_ref (match_operand 3 "" ""))
7140 (pc)))
7141 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7142 "TARGET_THUMB1"
58d6528b 7143 "*
7144 {
7145 output_asm_insn (\"orr\\t%0, %2\", operands);
7146 switch (get_attr_length (insn))
7147 {
7148 case 4: return \"b%d4\\t%l3\";
7149 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7150 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7151 }
7152 }"
7153 [(set (attr "far_jump")
7154 (if_then_else
7155 (eq_attr "length" "8")
7156 (const_string "yes")
7157 (const_string "no")))
7158 (set (attr "length")
7159 (if_then_else
7160 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7161 (le (minus (match_dup 3) (pc)) (const_int 256)))
7162 (const_int 4)
7163 (if_then_else
7164 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7165 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7166 (const_int 6)
7167 (const_int 8))))]
7168)
7169
7170(define_insn "*orrsi3_cbranch"
7171 [(set (pc)
7172 (if_then_else
7173 (match_operator 5 "equality_operator"
7174 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7175 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7176 (const_int 0)])
7177 (label_ref (match_operand 4 "" ""))
7178 (pc)))
aeac46d4 7179 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7180 (ior:SI (match_dup 2) (match_dup 3)))
7181 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7182 "TARGET_THUMB1"
58d6528b 7183 "*
7184 {
7185 if (which_alternative == 0)
7186 output_asm_insn (\"orr\\t%0, %3\", operands);
7187 else if (which_alternative == 1)
7188 {
7189 output_asm_insn (\"orr\\t%1, %3\", operands);
7190 output_asm_insn (\"mov\\t%0, %1\", operands);
7191 }
7192 else
7193 {
7194 output_asm_insn (\"orr\\t%1, %3\", operands);
7195 output_asm_insn (\"str\\t%1, %0\", operands);
7196 }
7197
7198 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7199 {
7200 case 4: return \"b%d5\\t%l4\";
7201 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7202 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7203 }
7204 }"
7205 [(set (attr "far_jump")
7206 (if_then_else
7207 (ior (and (eq (symbol_ref ("which_alternative"))
7208 (const_int 0))
7209 (eq_attr "length" "8"))
7210 (eq_attr "length" "10"))
7211 (const_string "yes")
7212 (const_string "no")))
7213 (set (attr "length")
7214 (if_then_else
7215 (eq (symbol_ref ("which_alternative"))
7216 (const_int 0))
7217 (if_then_else
7218 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7219 (le (minus (match_dup 4) (pc)) (const_int 256)))
7220 (const_int 4)
7221 (if_then_else
7222 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7223 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7224 (const_int 6)
7225 (const_int 8)))
7226 (if_then_else
7227 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7228 (le (minus (match_dup 4) (pc)) (const_int 256)))
7229 (const_int 6)
7230 (if_then_else
7231 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7232 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7233 (const_int 8)
7234 (const_int 10)))))]
7235)
7236
7237(define_insn "*xorsi3_cbranch_scratch"
7238 [(set (pc)
7239 (if_then_else
7240 (match_operator 4 "equality_operator"
7241 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
7242 (match_operand:SI 2 "s_register_operand" "l"))
7243 (const_int 0)])
7244 (label_ref (match_operand 3 "" ""))
7245 (pc)))
7246 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7247 "TARGET_THUMB1"
58d6528b 7248 "*
7249 {
7250 output_asm_insn (\"eor\\t%0, %2\", operands);
7251 switch (get_attr_length (insn))
7252 {
7253 case 4: return \"b%d4\\t%l3\";
7254 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7255 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7256 }
7257 }"
7258 [(set (attr "far_jump")
7259 (if_then_else
7260 (eq_attr "length" "8")
7261 (const_string "yes")
7262 (const_string "no")))
7263 (set (attr "length")
7264 (if_then_else
7265 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7266 (le (minus (match_dup 3) (pc)) (const_int 256)))
7267 (const_int 4)
7268 (if_then_else
7269 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7270 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7271 (const_int 6)
7272 (const_int 8))))]
7273)
7274
7275(define_insn "*xorsi3_cbranch"
7276 [(set (pc)
7277 (if_then_else
7278 (match_operator 5 "equality_operator"
7279 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7280 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7281 (const_int 0)])
7282 (label_ref (match_operand 4 "" ""))
7283 (pc)))
aeac46d4 7284 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7285 (xor:SI (match_dup 2) (match_dup 3)))
7286 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7287 "TARGET_THUMB1"
58d6528b 7288 "*
7289 {
7290 if (which_alternative == 0)
7291 output_asm_insn (\"eor\\t%0, %3\", operands);
7292 else if (which_alternative == 1)
7293 {
7294 output_asm_insn (\"eor\\t%1, %3\", operands);
7295 output_asm_insn (\"mov\\t%0, %1\", operands);
7296 }
7297 else
7298 {
7299 output_asm_insn (\"eor\\t%1, %3\", operands);
7300 output_asm_insn (\"str\\t%1, %0\", operands);
7301 }
7302
7303 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7304 {
7305 case 4: return \"b%d5\\t%l4\";
7306 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7307 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7308 }
7309 }"
7310 [(set (attr "far_jump")
7311 (if_then_else
7312 (ior (and (eq (symbol_ref ("which_alternative"))
7313 (const_int 0))
7314 (eq_attr "length" "8"))
7315 (eq_attr "length" "10"))
7316 (const_string "yes")
7317 (const_string "no")))
7318 (set (attr "length")
7319 (if_then_else
7320 (eq (symbol_ref ("which_alternative"))
7321 (const_int 0))
7322 (if_then_else
7323 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7324 (le (minus (match_dup 4) (pc)) (const_int 256)))
7325 (const_int 4)
7326 (if_then_else
7327 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7328 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7329 (const_int 6)
7330 (const_int 8)))
7331 (if_then_else
7332 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7333 (le (minus (match_dup 4) (pc)) (const_int 256)))
7334 (const_int 6)
7335 (if_then_else
7336 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7337 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7338 (const_int 8)
7339 (const_int 10)))))]
7340)
7341
aeac46d4 7342(define_insn "*bicsi3_cbranch_scratch"
7343 [(set (pc)
7344 (if_then_else
7345 (match_operator 4 "equality_operator"
7346 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7347 (match_operand:SI 1 "s_register_operand" "0"))
7348 (const_int 0)])
7349 (label_ref (match_operand 3 "" ""))
7350 (pc)))
7351 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7352 "TARGET_THUMB1"
aeac46d4 7353 "*
7354 {
7355 output_asm_insn (\"bic\\t%0, %2\", operands);
7356 switch (get_attr_length (insn))
7357 {
7358 case 4: return \"b%d4\\t%l3\";
7359 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7360 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7361 }
7362 }"
7363 [(set (attr "far_jump")
7364 (if_then_else
7365 (eq_attr "length" "8")
7366 (const_string "yes")
7367 (const_string "no")))
7368 (set (attr "length")
7369 (if_then_else
7370 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7371 (le (minus (match_dup 3) (pc)) (const_int 256)))
7372 (const_int 4)
7373 (if_then_else
7374 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7375 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7376 (const_int 6)
7377 (const_int 8))))]
7378)
7379
7380(define_insn "*bicsi3_cbranch"
7381 [(set (pc)
7382 (if_then_else
7383 (match_operator 5 "equality_operator"
01145ae6 7384 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7385 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 7386 (const_int 0)])
7387 (label_ref (match_operand 4 "" ""))
7388 (pc)))
01145ae6 7389 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 7390 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 7391 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
25f905c2 7392 "TARGET_THUMB1"
aeac46d4 7393 "*
7394 {
7395 if (which_alternative == 0)
7396 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 7397 else if (which_alternative <= 2)
aeac46d4 7398 {
7399 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 7400 /* It's ok if OP0 is a lo-reg, even though the mov will set the
7401 conditions again, since we're only testing for equality. */
aeac46d4 7402 output_asm_insn (\"mov\\t%0, %1\", operands);
7403 }
7404 else
7405 {
7406 output_asm_insn (\"bic\\t%1, %3\", operands);
7407 output_asm_insn (\"str\\t%1, %0\", operands);
7408 }
7409
7410 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7411 {
7412 case 4: return \"b%d5\\t%l4\";
7413 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7414 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7415 }
7416 }"
7417 [(set (attr "far_jump")
7418 (if_then_else
7419 (ior (and (eq (symbol_ref ("which_alternative"))
7420 (const_int 0))
7421 (eq_attr "length" "8"))
7422 (eq_attr "length" "10"))
7423 (const_string "yes")
7424 (const_string "no")))
7425 (set (attr "length")
7426 (if_then_else
7427 (eq (symbol_ref ("which_alternative"))
7428 (const_int 0))
7429 (if_then_else
7430 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7431 (le (minus (match_dup 4) (pc)) (const_int 256)))
7432 (const_int 4)
7433 (if_then_else
7434 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7435 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7436 (const_int 6)
7437 (const_int 8)))
7438 (if_then_else
7439 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7440 (le (minus (match_dup 4) (pc)) (const_int 256)))
7441 (const_int 6)
7442 (if_then_else
7443 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7444 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7445 (const_int 8)
7446 (const_int 10)))))]
7447)
7448
203c488f 7449(define_insn "*cbranchne_decr1"
7450 [(set (pc)
7451 (if_then_else (match_operator 3 "equality_operator"
7452 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7453 (const_int 0)])
7454 (label_ref (match_operand 4 "" ""))
7455 (pc)))
aeac46d4 7456 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7457 (plus:SI (match_dup 2) (const_int -1)))
7458 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7459 "TARGET_THUMB1"
203c488f 7460 "*
7461 {
7462 rtx cond[2];
7463 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7464 ? GEU : LTU),
58d6528b 7465 VOIDmode, operands[2], const1_rtx);
203c488f 7466 cond[1] = operands[4];
7467
7468 if (which_alternative == 0)
7469 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7470 else if (which_alternative == 1)
7471 {
7472 /* We must provide an alternative for a hi reg because reload
7473 cannot handle output reloads on a jump instruction, but we
7474 can't subtract into that. Fortunately a mov from lo to hi
7475 does not clobber the condition codes. */
7476 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7477 output_asm_insn (\"mov\\t%0, %1\", operands);
7478 }
7479 else
7480 {
7481 /* Similarly, but the target is memory. */
7482 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7483 output_asm_insn (\"str\\t%1, %0\", operands);
7484 }
7485
7486 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7487 {
7488 case 4:
8aea555f 7489 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7490 return \"\";
7491 case 6:
8aea555f 7492 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7493 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7494 default:
8aea555f 7495 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7496 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7497 }
7498 }
7499 "
7500 [(set (attr "far_jump")
7501 (if_then_else
7502 (ior (and (eq (symbol_ref ("which_alternative"))
7503 (const_int 0))
7504 (eq_attr "length" "8"))
7505 (eq_attr "length" "10"))
7506 (const_string "yes")
7507 (const_string "no")))
7508 (set_attr_alternative "length"
7509 [
7510 ;; Alternative 0
7511 (if_then_else
7512 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7513 (le (minus (match_dup 4) (pc)) (const_int 256)))
7514 (const_int 4)
7515 (if_then_else
7516 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7517 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7518 (const_int 6)
7519 (const_int 8)))
7520 ;; Alternative 1
7521 (if_then_else
7522 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7523 (le (minus (match_dup 4) (pc)) (const_int 256)))
7524 (const_int 6)
7525 (if_then_else
7526 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7527 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7528 (const_int 8)
7529 (const_int 10)))
7530 ;; Alternative 2
7531 (if_then_else
7532 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7533 (le (minus (match_dup 4) (pc)) (const_int 256)))
7534 (const_int 6)
7535 (if_then_else
7536 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7537 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7538 (const_int 8)
7539 (const_int 10)))
7540 ;; Alternative 3
7541 (if_then_else
7542 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7543 (le (minus (match_dup 4) (pc)) (const_int 256)))
7544 (const_int 6)
7545 (if_then_else
7546 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7547 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7548 (const_int 8)
7549 (const_int 10)))])]
7550)
cffb2a26 7551
58d6528b 7552(define_insn "*addsi3_cbranch"
7553 [(set (pc)
7554 (if_then_else
b0694be0 7555 (match_operator 4 "arm_comparison_operator"
58d6528b 7556 [(plus:SI
956a6170 7557 (match_operand:SI 2 "s_register_operand" "%l,0,*l,1,1,1")
7558 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*l,lIJ,lIJ,lIJ"))
58d6528b 7559 (const_int 0)])
7560 (label_ref (match_operand 5 "" ""))
7561 (pc)))
aeac46d4 7562 (set
7563 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7564 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 7565 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 7566 "TARGET_THUMB1
58d6528b 7567 && (GET_CODE (operands[4]) == EQ
7568 || GET_CODE (operands[4]) == NE
7569 || GET_CODE (operands[4]) == GE
7570 || GET_CODE (operands[4]) == LT)"
7571 "*
7572 {
7573 rtx cond[3];
7574
956a6170 7575 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 7576 cond[1] = operands[2];
7577 cond[2] = operands[3];
7578
7579 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7580 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7581 else
7582 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7583
956a6170 7584 if (which_alternative >= 2
58d6528b 7585 && which_alternative < 4)
7586 output_asm_insn (\"mov\\t%0, %1\", operands);
7587 else if (which_alternative >= 4)
7588 output_asm_insn (\"str\\t%1, %0\", operands);
7589
7590 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7591 {
7592 case 4:
7593 return \"b%d4\\t%l5\";
7594 case 6:
7595 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7596 default:
7597 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7598 }
7599 }
7600 "
7601 [(set (attr "far_jump")
7602 (if_then_else
7603 (ior (and (lt (symbol_ref ("which_alternative"))
7604 (const_int 3))
7605 (eq_attr "length" "8"))
7606 (eq_attr "length" "10"))
7607 (const_string "yes")
7608 (const_string "no")))
7609 (set (attr "length")
7610 (if_then_else
7611 (lt (symbol_ref ("which_alternative"))
7612 (const_int 3))
7613 (if_then_else
7614 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7615 (le (minus (match_dup 5) (pc)) (const_int 256)))
7616 (const_int 4)
7617 (if_then_else
7618 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7619 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7620 (const_int 6)
7621 (const_int 8)))
7622 (if_then_else
7623 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7624 (le (minus (match_dup 5) (pc)) (const_int 256)))
7625 (const_int 6)
7626 (if_then_else
7627 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7628 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7629 (const_int 8)
7630 (const_int 10)))))]
7631)
7632
7633(define_insn "*addsi3_cbranch_scratch"
7634 [(set (pc)
7635 (if_then_else
b0694be0 7636 (match_operator 3 "arm_comparison_operator"
58d6528b 7637 [(plus:SI
7638 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7639 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7640 (const_int 0)])
7641 (label_ref (match_operand 4 "" ""))
7642 (pc)))
7643 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7644 "TARGET_THUMB1
58d6528b 7645 && (GET_CODE (operands[3]) == EQ
7646 || GET_CODE (operands[3]) == NE
7647 || GET_CODE (operands[3]) == GE
7648 || GET_CODE (operands[3]) == LT)"
7649 "*
7650 {
7651 switch (which_alternative)
7652 {
7653 case 0:
7654 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7655 break;
7656 case 1:
7657 output_asm_insn (\"cmn\t%1, %2\", operands);
7658 break;
0f5e9701 7659 case 2:
3a445a04 7660 if (INTVAL (operands[2]) < 0)
7661 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7662 else
7663 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7664 break;
0f5e9701 7665 case 3:
3a445a04 7666 if (INTVAL (operands[2]) < 0)
7667 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7668 else
7669 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7670 break;
7671 }
7672
7673 switch (get_attr_length (insn))
7674 {
7675 case 4:
7676 return \"b%d3\\t%l4\";
7677 case 6:
7678 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7679 default:
7680 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7681 }
7682 }
7683 "
7684 [(set (attr "far_jump")
7685 (if_then_else
7686 (eq_attr "length" "8")
7687 (const_string "yes")
7688 (const_string "no")))
7689 (set (attr "length")
7690 (if_then_else
7691 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7692 (le (minus (match_dup 4) (pc)) (const_int 256)))
7693 (const_int 4)
7694 (if_then_else
7695 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7696 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7697 (const_int 6)
7698 (const_int 8))))]
7699)
7700
7701(define_insn "*subsi3_cbranch"
7702 [(set (pc)
7703 (if_then_else
b0694be0 7704 (match_operator 4 "arm_comparison_operator"
58d6528b 7705 [(minus:SI
7706 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7707 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7708 (const_int 0)])
7709 (label_ref (match_operand 5 "" ""))
7710 (pc)))
aeac46d4 7711 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7712 (minus:SI (match_dup 2) (match_dup 3)))
7713 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7714 "TARGET_THUMB1
58d6528b 7715 && (GET_CODE (operands[4]) == EQ
7716 || GET_CODE (operands[4]) == NE
7717 || GET_CODE (operands[4]) == GE
7718 || GET_CODE (operands[4]) == LT)"
7719 "*
7720 {
7721 if (which_alternative == 0)
7722 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7723 else if (which_alternative == 1)
7724 {
7725 /* We must provide an alternative for a hi reg because reload
7726 cannot handle output reloads on a jump instruction, but we
7727 can't subtract into that. Fortunately a mov from lo to hi
7728 does not clobber the condition codes. */
7729 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7730 output_asm_insn (\"mov\\t%0, %1\", operands);
7731 }
7732 else
7733 {
7734 /* Similarly, but the target is memory. */
7735 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7736 output_asm_insn (\"str\\t%1, %0\", operands);
7737 }
7738
7739 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7740 {
7741 case 4:
7742 return \"b%d4\\t%l5\";
7743 case 6:
7744 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7745 default:
7746 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7747 }
7748 }
7749 "
7750 [(set (attr "far_jump")
7751 (if_then_else
7752 (ior (and (eq (symbol_ref ("which_alternative"))
7753 (const_int 0))
7754 (eq_attr "length" "8"))
7755 (eq_attr "length" "10"))
7756 (const_string "yes")
7757 (const_string "no")))
7758 (set (attr "length")
7759 (if_then_else
7760 (eq (symbol_ref ("which_alternative"))
7761 (const_int 0))
7762 (if_then_else
7763 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7764 (le (minus (match_dup 5) (pc)) (const_int 256)))
7765 (const_int 4)
7766 (if_then_else
7767 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7768 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7769 (const_int 6)
7770 (const_int 8)))
7771 (if_then_else
7772 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7773 (le (minus (match_dup 5) (pc)) (const_int 256)))
7774 (const_int 6)
7775 (if_then_else
7776 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7777 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7778 (const_int 8)
7779 (const_int 10)))))]
7780)
7781
7782(define_insn "*subsi3_cbranch_scratch"
7783 [(set (pc)
7784 (if_then_else
7785 (match_operator 0 "arm_comparison_operator"
7786 [(minus:SI (match_operand:SI 1 "register_operand" "l")
7787 (match_operand:SI 2 "nonmemory_operand" "l"))
7788 (const_int 0)])
7789 (label_ref (match_operand 3 "" ""))
7790 (pc)))]
25f905c2 7791 "TARGET_THUMB1
58d6528b 7792 && (GET_CODE (operands[0]) == EQ
7793 || GET_CODE (operands[0]) == NE
7794 || GET_CODE (operands[0]) == GE
7795 || GET_CODE (operands[0]) == LT)"
7796 "*
7797 output_asm_insn (\"cmp\\t%1, %2\", operands);
7798 switch (get_attr_length (insn))
7799 {
7800 case 4: return \"b%d0\\t%l3\";
7801 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7802 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7803 }
7804 "
7805 [(set (attr "far_jump")
7806 (if_then_else
7807 (eq_attr "length" "8")
7808 (const_string "yes")
7809 (const_string "no")))
7810 (set (attr "length")
7811 (if_then_else
7812 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7813 (le (minus (match_dup 3) (pc)) (const_int 256)))
7814 (const_int 4)
7815 (if_then_else
7816 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7817 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7818 (const_int 6)
7819 (const_int 8))))]
7820)
7821
9c08d1fa 7822;; Comparison and test insns
7823
cffb2a26 7824(define_insn "*arm_cmpsi_insn"
bd5b4116 7825 [(set (reg:CC CC_REGNUM)
aea4c774 7826 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7827 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7828 "TARGET_32BIT"
5565501b 7829 "@
aea4c774 7830 cmp%?\\t%0, %1
7831 cmn%?\\t%0, #%n1"
cffb2a26 7832 [(set_attr "conds" "set")]
7833)
b11cae9e 7834
25f905c2 7835(define_insn "*arm_cmpsi_shiftsi"
bd5b4116 7836 [(set (reg:CC CC_REGNUM)
cffb2a26 7837 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
7838 (match_operator:SI 3 "shift_operator"
aea4c774 7839 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 7840 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
7841 "TARGET_ARM"
aea4c774 7842 "cmp%?\\t%0, %1%S3"
344495ea 7843 [(set_attr "conds" "set")
331beb1a 7844 (set_attr "shift" "1")
a2cd141b 7845 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7846 (const_string "alu_shift")
7847 (const_string "alu_shift_reg")))]
0d66636f 7848)
b11cae9e 7849
25f905c2 7850(define_insn "*arm_cmpsi_shiftsi_swp"
bd5b4116 7851 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7852 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7853 [(match_operand:SI 1 "s_register_operand" "r")
7854 (match_operand:SI 2 "reg_or_int_operand" "rM")])
7855 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7856 "TARGET_ARM"
aea4c774 7857 "cmp%?\\t%0, %1%S3"
344495ea 7858 [(set_attr "conds" "set")
331beb1a 7859 (set_attr "shift" "1")
a2cd141b 7860 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7861 (const_string "alu_shift")
7862 (const_string "alu_shift_reg")))]
0d66636f 7863)
b11cae9e 7864
25f905c2 7865(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7866 [(set (reg:CC_Z CC_REGNUM)
7867 (compare:CC_Z
7868 (neg:SI (match_operator:SI 1 "shift_operator"
7869 [(match_operand:SI 2 "s_register_operand" "r")
7870 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7871 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7872 "TARGET_ARM"
aed179ae 7873 "cmn%?\\t%0, %2%S1"
344495ea 7874 [(set_attr "conds" "set")
aed179ae 7875 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7876 (const_string "alu_shift")
7877 (const_string "alu_shift_reg")))]
0d66636f 7878)
b11cae9e 7879
7d57ec45 7880;; Cirrus SF compare instruction
7881(define_insn "*cirrus_cmpsf"
7882 [(set (reg:CCFP CC_REGNUM)
7883 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7884 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7885 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7886 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7887 [(set_attr "type" "mav_farith")
7d57ec45 7888 (set_attr "cirrus" "compare")]
7889)
7890
7891;; Cirrus DF compare instruction
7892(define_insn "*cirrus_cmpdf"
7893 [(set (reg:CCFP CC_REGNUM)
7894 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7895 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7896 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7897 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7898 [(set_attr "type" "mav_farith")
7d57ec45 7899 (set_attr "cirrus" "compare")]
7900)
7901
7d57ec45 7902(define_insn "*cirrus_cmpdi"
7903 [(set (reg:CC CC_REGNUM)
7904 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7905 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7906 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7907 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7908 [(set_attr "type" "mav_farith")
7d57ec45 7909 (set_attr "cirrus" "compare")]
7910)
7911
9c08d1fa 7912; This insn allows redundant compares to be removed by cse, nothing should
7913; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7914; is deleted later on. The match_dup will match the mode here, so that
7915; mode changes of the condition codes aren't lost by this even though we don't
7916; specify what they are.
7917
8a18b90c 7918(define_insn "*deleted_compare"
9c08d1fa 7919 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7920 "TARGET_32BIT"
40dbec34 7921 "\\t%@ deleted compare"
cffb2a26 7922 [(set_attr "conds" "set")
7923 (set_attr "length" "0")]
7924)
9c08d1fa 7925
7926\f
7927;; Conditional branch insns
7928
74f4459c 7929(define_expand "cbranch_cc"
9c08d1fa 7930 [(set (pc)
74f4459c 7931 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7932 (match_operand 2 "" "")])
7933 (label_ref (match_operand 3 "" ""))
9c08d1fa 7934 (pc)))]
25f905c2 7935 "TARGET_32BIT"
74f4459c 7936 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7937 operands[1], operands[2]);
7938 operands[2] = const0_rtx;"
8fa3ba89 7939)
7940
7941;;
7942;; Patterns to match conditional branch insns.
7943;;
7944
cffb2a26 7945(define_insn "*arm_cond_branch"
9c08d1fa 7946 [(set (pc)
8fa3ba89 7947 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7948 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7949 (label_ref (match_operand 0 "" ""))
7950 (pc)))]
25f905c2 7951 "TARGET_32BIT"
d75350ce 7952 "*
9c08d1fa 7953 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7954 {
7955 arm_ccfsm_state += 2;
7956 return \"\";
7957 }
e2348bcb 7958 return \"b%d1\\t%l0\";
cffb2a26 7959 "
a2cd141b 7960 [(set_attr "conds" "use")
7961 (set_attr "type" "branch")]
cffb2a26 7962)
d75350ce 7963
cffb2a26 7964(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7965 [(set (pc)
8fa3ba89 7966 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7967 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7968 (pc)
7969 (label_ref (match_operand 0 "" ""))))]
25f905c2 7970 "TARGET_32BIT"
d75350ce 7971 "*
9c08d1fa 7972 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7973 {
7974 arm_ccfsm_state += 2;
7975 return \"\";
7976 }
e2348bcb 7977 return \"b%D1\\t%l0\";
cffb2a26 7978 "
a2cd141b 7979 [(set_attr "conds" "use")
7980 (set_attr "type" "branch")]
cffb2a26 7981)
7982
b11cae9e 7983\f
9c08d1fa 7984
7985; scc insns
7986
74f4459c 7987(define_expand "cstore_cc"
7db9af5d 7988 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7989 (match_operator:SI 1 "" [(match_operand 2 "" "")
7990 (match_operand 3 "" "")]))]
25f905c2 7991 "TARGET_32BIT"
74f4459c 7992 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7993 operands[2], operands[3]);
7994 operands[3] = const0_rtx;"
8fa3ba89 7995)
7996
f7fbdd4a 7997(define_insn "*mov_scc"
9c08d1fa 7998 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7999 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 8000 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 8001 "TARGET_ARM"
4d61e570 8002 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 8003 [(set_attr "conds" "use")
8004 (set_attr "length" "8")]
8005)
9c08d1fa 8006
f7fbdd4a 8007(define_insn "*mov_negscc"
9c08d1fa 8008 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8009 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 8010 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 8011 "TARGET_ARM"
4d61e570 8012 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 8013 [(set_attr "conds" "use")
8014 (set_attr "length" "8")]
8015)
9c08d1fa 8016
f7fbdd4a 8017(define_insn "*mov_notscc"
9c08d1fa 8018 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8019 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 8020 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 8021 "TARGET_ARM"
4d61e570 8022 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 8023 [(set_attr "conds" "use")
8024 (set_attr "length" "8")]
8025)
9c08d1fa 8026
595d88b5 8027(define_expand "cstoresi4"
8028 [(set (match_operand:SI 0 "s_register_operand" "")
8029 (match_operator:SI 1 "arm_comparison_operator"
8030 [(match_operand:SI 2 "s_register_operand" "")
8031 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 8032 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 8033 "{
8034 rtx op3, scratch, scratch2;
8035
74f4459c 8036 if (!TARGET_THUMB1)
8037 {
8038 if (!arm_add_operand (operands[3], SImode))
8039 operands[3] = force_reg (SImode, operands[3]);
8040 emit_insn (gen_cstore_cc (operands[0], operands[1],
8041 operands[2], operands[3]));
8042 DONE;
8043 }
8044
595d88b5 8045 if (operands[3] == const0_rtx)
8046 {
8047 switch (GET_CODE (operands[1]))
8048 {
8049 case EQ:
25f905c2 8050 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 8051 break;
8052
8053 case NE:
25f905c2 8054 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 8055 break;
8056
8057 case LE:
8058 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8059 NULL_RTX, 0, OPTAB_WIDEN);
8060 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8061 NULL_RTX, 0, OPTAB_WIDEN);
8062 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8063 operands[0], 1, OPTAB_WIDEN);
8064 break;
8065
8066 case GE:
8067 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8068 NULL_RTX, 1);
8069 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8070 NULL_RTX, 1, OPTAB_WIDEN);
8071 break;
8072
8073 case GT:
8074 scratch = expand_binop (SImode, ashr_optab, operands[2],
8075 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8076 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8077 NULL_RTX, 0, OPTAB_WIDEN);
8078 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8079 0, OPTAB_WIDEN);
8080 break;
8081
8082 /* LT is handled by generic code. No need for unsigned with 0. */
8083 default:
8084 FAIL;
8085 }
8086 DONE;
8087 }
8088
8089 switch (GET_CODE (operands[1]))
8090 {
8091 case EQ:
8092 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8093 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8094 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 8095 break;
8096
8097 case NE:
8098 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8099 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8100 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 8101 break;
8102
8103 case LE:
8104 op3 = force_reg (SImode, operands[3]);
8105
8106 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8107 NULL_RTX, 1, OPTAB_WIDEN);
8108 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8109 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8110 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8111 op3, operands[2]));
8112 break;
8113
8114 case GE:
8115 op3 = operands[3];
25f905c2 8116 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8117 op3 = force_reg (SImode, op3);
8118 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8119 NULL_RTX, 0, OPTAB_WIDEN);
8120 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8121 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 8122 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8123 operands[2], op3));
8124 break;
8125
8126 case LEU:
8127 op3 = force_reg (SImode, operands[3]);
8128 scratch = force_reg (SImode, const0_rtx);
25f905c2 8129 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8130 op3, operands[2]));
8131 break;
8132
8133 case GEU:
8134 op3 = operands[3];
25f905c2 8135 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8136 op3 = force_reg (SImode, op3);
8137 scratch = force_reg (SImode, const0_rtx);
25f905c2 8138 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8139 operands[2], op3));
8140 break;
8141
8142 case LTU:
8143 op3 = operands[3];
25f905c2 8144 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8145 op3 = force_reg (SImode, op3);
8146 scratch = gen_reg_rtx (SImode);
408b7ae5 8147 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 8148 break;
8149
8150 case GTU:
8151 op3 = force_reg (SImode, operands[3]);
8152 scratch = gen_reg_rtx (SImode);
408b7ae5 8153 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 8154 break;
8155
8156 /* No good sequences for GT, LT. */
8157 default:
8158 FAIL;
8159 }
8160 DONE;
8161}")
8162
74f4459c 8163(define_expand "cstoresf4"
8164 [(set (match_operand:SI 0 "s_register_operand" "")
8165 (match_operator:SI 1 "arm_comparison_operator"
8166 [(match_operand:SF 2 "s_register_operand" "")
8167 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8168 "TARGET_32BIT && TARGET_HARD_FLOAT"
8169 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8170 operands[2], operands[3])); DONE;"
8171)
8172
8173(define_expand "cstoredf4"
8174 [(set (match_operand:SI 0 "s_register_operand" "")
8175 (match_operator:SI 1 "arm_comparison_operator"
8176 [(match_operand:DF 2 "s_register_operand" "")
8177 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8178 "TARGET_32BIT && TARGET_HARD_FLOAT"
8179 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8180 operands[2], operands[3])); DONE;"
8181)
8182
8183;; this uses the Cirrus DI compare instruction
8184(define_expand "cstoredi4"
8185 [(set (match_operand:SI 0 "s_register_operand" "")
8186 (match_operator:SI 1 "arm_comparison_operator"
8187 [(match_operand:DI 2 "cirrus_fp_register" "")
8188 (match_operand:DI 3 "cirrus_fp_register" "")]))]
8189 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
8190 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8191 operands[2], operands[3])); DONE;"
8192)
8193
8194
25f905c2 8195(define_expand "cstoresi_eq0_thumb1"
595d88b5 8196 [(parallel
8197 [(set (match_operand:SI 0 "s_register_operand" "")
8198 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8199 (const_int 0)))
8200 (clobber (match_dup:SI 2))])]
25f905c2 8201 "TARGET_THUMB1"
595d88b5 8202 "operands[2] = gen_reg_rtx (SImode);"
8203)
8204
25f905c2 8205(define_expand "cstoresi_ne0_thumb1"
595d88b5 8206 [(parallel
8207 [(set (match_operand:SI 0 "s_register_operand" "")
8208 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8209 (const_int 0)))
8210 (clobber (match_dup:SI 2))])]
25f905c2 8211 "TARGET_THUMB1"
595d88b5 8212 "operands[2] = gen_reg_rtx (SImode);"
8213)
8214
25f905c2 8215(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 8216 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8217 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8218 (const_int 0)))
8219 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 8220 "TARGET_THUMB1"
595d88b5 8221 "@
8222 neg\\t%0, %1\;adc\\t%0, %0, %1
8223 neg\\t%2, %1\;adc\\t%0, %1, %2"
8224 [(set_attr "length" "4")]
8225)
8226
25f905c2 8227(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 8228 [(set (match_operand:SI 0 "s_register_operand" "=l")
8229 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8230 (const_int 0)))
8231 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8232 "TARGET_THUMB1"
595d88b5 8233 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8234 [(set_attr "length" "4")]
8235)
8236
408b7ae5 8237;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 8238(define_insn "cstoresi_nltu_thumb1"
595d88b5 8239 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8240 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8241 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8242 "TARGET_THUMB1"
595d88b5 8243 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8244 [(set_attr "length" "4")]
8245)
8246
408b7ae5 8247(define_insn_and_split "cstoresi_ltu_thumb1"
8248 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8249 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8250 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8251 "TARGET_THUMB1"
8252 "#"
8253 "TARGET_THUMB1"
8254 [(set (match_dup 3)
8255 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8256 (set (match_dup 0) (neg:SI (match_dup 3)))]
8257 "operands[3] = gen_reg_rtx (SImode);"
8258 [(set_attr "length" "4")]
8259)
8260
595d88b5 8261;; Used as part of the expansion of thumb les sequence.
25f905c2 8262(define_insn "thumb1_addsi3_addgeu"
595d88b5 8263 [(set (match_operand:SI 0 "s_register_operand" "=l")
8264 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8265 (match_operand:SI 2 "s_register_operand" "l"))
8266 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8267 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8268 "TARGET_THUMB1"
595d88b5 8269 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8270 [(set_attr "length" "4")]
8271)
8272
9c08d1fa 8273\f
39b5e676 8274;; Conditional move insns
8275
8276(define_expand "movsicc"
8a18b90c 8277 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 8278 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 8279 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8280 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8281 "TARGET_32BIT"
39b5e676 8282 "
215b30b3 8283 {
8284 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8285 rtx ccreg;
8286
8287 if (code == UNEQ || code == LTGT)
8288 FAIL;
39b5e676 8289
74f4459c 8290 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8291 XEXP (operands[1], 1));
29bb088d 8292 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8293 }"
8294)
39b5e676 8295
8296(define_expand "movsfcc"
8a18b90c 8297 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 8298 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8299 (match_operand:SF 2 "s_register_operand" "")
8300 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 8301 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8302 "
215b30b3 8303 {
8304 enum rtx_code code = GET_CODE (operands[1]);
8305 rtx ccreg;
f082f1c4 8306
278b301d 8307 if (code == UNEQ || code == LTGT)
8308 FAIL;
8309
215b30b3 8310 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 8311 Otherwise, ensure it is a valid FP add operand */
8312 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8313 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 8314 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8315
74f4459c 8316 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8317 XEXP (operands[1], 1));
29bb088d 8318 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8319 }"
8320)
39b5e676 8321
8322(define_expand "movdfcc"
8a18b90c 8323 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 8324 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8325 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8326 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 8327 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 8328 "
215b30b3 8329 {
8330 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8331 rtx ccreg;
39b5e676 8332
278b301d 8333 if (code == UNEQ || code == LTGT)
8334 FAIL;
8335
74f4459c 8336 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8337 XEXP (operands[1], 1));
29bb088d 8338 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8339 }"
8340)
39b5e676 8341
8342(define_insn "*movsicc_insn"
f082f1c4 8343 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8344 (if_then_else:SI
8fa3ba89 8345 (match_operator 3 "arm_comparison_operator"
8a18b90c 8346 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8347 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8348 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8349 "TARGET_ARM"
39b5e676 8350 "@
8a18b90c 8351 mov%D3\\t%0, %2
8352 mvn%D3\\t%0, #%B2
f082f1c4 8353 mov%d3\\t%0, %1
8354 mvn%d3\\t%0, #%B1
8a18b90c 8355 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8356 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8357 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8358 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8359 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 8360 (set_attr "conds" "use")]
8361)
39b5e676 8362
39b5e676 8363(define_insn "*movsfcc_soft_insn"
f082f1c4 8364 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8365 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8366 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8367 (match_operand:SF 1 "s_register_operand" "0,r")
8368 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8369 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8370 "@
8371 mov%D3\\t%0, %2
8372 mov%d3\\t%0, %1"
8fa3ba89 8373 [(set_attr "conds" "use")]
8374)
39b5e676 8375
39b5e676 8376\f
9c08d1fa 8377;; Jump and linkage insns
8378
cffb2a26 8379(define_expand "jump"
9c08d1fa 8380 [(set (pc)
8381 (label_ref (match_operand 0 "" "")))]
cffb2a26 8382 "TARGET_EITHER"
9c08d1fa 8383 ""
cffb2a26 8384)
8385
8386(define_insn "*arm_jump"
8387 [(set (pc)
8388 (label_ref (match_operand 0 "" "")))]
25f905c2 8389 "TARGET_32BIT"
9c08d1fa 8390 "*
0d66636f 8391 {
8392 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8393 {
8394 arm_ccfsm_state += 2;
8395 return \"\";
8396 }
8397 return \"b%?\\t%l0\";
8398 }
8399 "
8400 [(set_attr "predicable" "yes")]
8401)
9c08d1fa 8402
cffb2a26 8403(define_insn "*thumb_jump"
8404 [(set (pc)
8405 (label_ref (match_operand 0 "" "")))]
25f905c2 8406 "TARGET_THUMB1"
cffb2a26 8407 "*
8408 if (get_attr_length (insn) == 2)
8409 return \"b\\t%l0\";
8410 return \"bl\\t%l0\\t%@ far jump\";
8411 "
8412 [(set (attr "far_jump")
8413 (if_then_else
8414 (eq_attr "length" "4")
8415 (const_string "yes")
8416 (const_string "no")))
8417 (set (attr "length")
8418 (if_then_else
911ed8af 8419 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8420 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8421 (const_int 2)
8422 (const_int 4)))]
8423)
8424
d3373b54 8425(define_expand "call"
8426 [(parallel [(call (match_operand 0 "memory_operand" "")
8427 (match_operand 1 "general_operand" ""))
cffb2a26 8428 (use (match_operand 2 "" ""))
bd5b4116 8429 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8430 "TARGET_EITHER"
6c4c2133 8431 "
8432 {
bac7fc85 8433 rtx callee, pat;
bbe777ea 8434
bbe777ea 8435 /* In an untyped call, we can get NULL for operand 2. */
8436 if (operands[2] == NULL_RTX)
8437 operands[2] = const0_rtx;
8438
de55252a 8439 /* Decide if we should generate indirect calls by loading the
85c36fd1 8440 32-bit address of the callee into a register before performing the
de55252a 8441 branch and link. */
8442 callee = XEXP (operands[0], 0);
8443 if (GET_CODE (callee) == SYMBOL_REF
8444 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8445 : !REG_P (callee))
bbe777ea 8446 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8447
8448 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8449 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8450 DONE;
6c4c2133 8451 }"
8452)
d3373b54 8453
bac7fc85 8454(define_expand "call_internal"
8455 [(parallel [(call (match_operand 0 "memory_operand" "")
8456 (match_operand 1 "general_operand" ""))
8457 (use (match_operand 2 "" ""))
8458 (clobber (reg:SI LR_REGNUM))])])
8459
f1039640 8460(define_insn "*call_reg_armv5"
d3373b54 8461 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8462 (match_operand 1 "" ""))
8463 (use (match_operand 2 "" ""))
bd5b4116 8464 (clobber (reg:SI LR_REGNUM))]
f1039640 8465 "TARGET_ARM && arm_arch5"
8466 "blx%?\\t%0"
8467 [(set_attr "type" "call")]
8468)
8469
8470(define_insn "*call_reg_arm"
8471 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8472 (match_operand 1 "" ""))
8473 (use (match_operand 2 "" ""))
8474 (clobber (reg:SI LR_REGNUM))]
8475 "TARGET_ARM && !arm_arch5"
9c08d1fa 8476 "*
5565501b 8477 return output_call (operands);
cffb2a26 8478 "
8479 ;; length is worst case, normally it is only two
8480 [(set_attr "length" "12")
8481 (set_attr "type" "call")]
8482)
9c08d1fa 8483
89504fc1 8484
8485;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8486;; considered a function call by the branch predictor of some cores (PR40887).
8487;; Falls back to blx rN (*call_reg_armv5).
8488
f7fbdd4a 8489(define_insn "*call_mem"
a3c63a9d 8490 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8491 (match_operand 1 "" ""))
8492 (use (match_operand 2 "" ""))
bd5b4116 8493 (clobber (reg:SI LR_REGNUM))]
89504fc1 8494 "TARGET_ARM && !arm_arch5"
9c08d1fa 8495 "*
5565501b 8496 return output_call_mem (operands);
cffb2a26 8497 "
8498 [(set_attr "length" "12")
8499 (set_attr "type" "call")]
8500)
8501
25f905c2 8502(define_insn "*call_reg_thumb1_v5"
cffb2a26 8503 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8504 (match_operand 1 "" ""))
8505 (use (match_operand 2 "" ""))
bd5b4116 8506 (clobber (reg:SI LR_REGNUM))]
25f905c2 8507 "TARGET_THUMB1 && arm_arch5"
f1039640 8508 "blx\\t%0"
8509 [(set_attr "length" "2")
8510 (set_attr "type" "call")]
cffb2a26 8511)
8512
25f905c2 8513(define_insn "*call_reg_thumb1"
f1039640 8514 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8515 (match_operand 1 "" ""))
8516 (use (match_operand 2 "" ""))
bd5b4116 8517 (clobber (reg:SI LR_REGNUM))]
25f905c2 8518 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8519 "*
8520 {
150502c9 8521 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8522 return thumb_call_via_reg (operands[0]);
150502c9 8523 else if (operands[1] == const0_rtx)
f1039640 8524 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8525 else if (frame_pointer_needed)
8526 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8527 else
150502c9 8528 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8529 }"
8530 [(set_attr "type" "call")]
8531)
9c08d1fa 8532
d3373b54 8533(define_expand "call_value"
e0698af7 8534 [(parallel [(set (match_operand 0 "" "")
8535 (call (match_operand 1 "memory_operand" "")
8536 (match_operand 2 "general_operand" "")))
cffb2a26 8537 (use (match_operand 3 "" ""))
bd5b4116 8538 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8539 "TARGET_EITHER"
6c4c2133 8540 "
8541 {
bac7fc85 8542 rtx pat, callee;
bbe777ea 8543
8544 /* In an untyped call, we can get NULL for operand 2. */
8545 if (operands[3] == 0)
8546 operands[3] = const0_rtx;
8547
de55252a 8548 /* Decide if we should generate indirect calls by loading the
8549 32-bit address of the callee into a register before performing the
8550 branch and link. */
8551 callee = XEXP (operands[1], 0);
8552 if (GET_CODE (callee) == SYMBOL_REF
8553 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8554 : !REG_P (callee))
78fe751b 8555 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8556
8557 pat = gen_call_value_internal (operands[0], operands[1],
8558 operands[2], operands[3]);
8559 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8560 DONE;
6c4c2133 8561 }"
8562)
d3373b54 8563
bac7fc85 8564(define_expand "call_value_internal"
8565 [(parallel [(set (match_operand 0 "" "")
8566 (call (match_operand 1 "memory_operand" "")
8567 (match_operand 2 "general_operand" "")))
8568 (use (match_operand 3 "" ""))
8569 (clobber (reg:SI LR_REGNUM))])])
8570
f1039640 8571(define_insn "*call_value_reg_armv5"
27ed6835 8572 [(set (match_operand 0 "" "")
755eb2b4 8573 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8574 (match_operand 2 "" "")))
bbe777ea 8575 (use (match_operand 3 "" ""))
bd5b4116 8576 (clobber (reg:SI LR_REGNUM))]
f1039640 8577 "TARGET_ARM && arm_arch5"
8578 "blx%?\\t%1"
8579 [(set_attr "type" "call")]
8580)
8581
8582(define_insn "*call_value_reg_arm"
8583 [(set (match_operand 0 "" "")
8584 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8585 (match_operand 2 "" "")))
8586 (use (match_operand 3 "" ""))
8587 (clobber (reg:SI LR_REGNUM))]
8588 "TARGET_ARM && !arm_arch5"
9c08d1fa 8589 "*
215b30b3 8590 return output_call (&operands[1]);
cffb2a26 8591 "
8592 [(set_attr "length" "12")
8593 (set_attr "type" "call")]
8594)
9c08d1fa 8595
89504fc1 8596;; Note: see *call_mem
8597
f7fbdd4a 8598(define_insn "*call_value_mem"
27ed6835 8599 [(set (match_operand 0 "" "")
a3c63a9d 8600 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8601 (match_operand 2 "" "")))
bbe777ea 8602 (use (match_operand 3 "" ""))
bd5b4116 8603 (clobber (reg:SI LR_REGNUM))]
89504fc1 8604 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8605 "*
215b30b3 8606 return output_call_mem (&operands[1]);
cffb2a26 8607 "
8608 [(set_attr "length" "12")
8609 (set_attr "type" "call")]
8610)
9c08d1fa 8611
25f905c2 8612(define_insn "*call_value_reg_thumb1_v5"
f1039640 8613 [(set (match_operand 0 "" "")
8614 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8615 (match_operand 2 "" "")))
8616 (use (match_operand 3 "" ""))
8617 (clobber (reg:SI LR_REGNUM))]
25f905c2 8618 "TARGET_THUMB1 && arm_arch5"
f1039640 8619 "blx\\t%1"
8620 [(set_attr "length" "2")
8621 (set_attr "type" "call")]
8622)
8623
25f905c2 8624(define_insn "*call_value_reg_thumb1"
f1039640 8625 [(set (match_operand 0 "" "")
8626 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8627 (match_operand 2 "" "")))
8628 (use (match_operand 3 "" ""))
8629 (clobber (reg:SI LR_REGNUM))]
25f905c2 8630 "TARGET_THUMB1 && !arm_arch5"
f1039640 8631 "*
8632 {
150502c9 8633 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8634 return thumb_call_via_reg (operands[1]);
150502c9 8635 else if (operands[2] == const0_rtx)
f1039640 8636 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8637 else if (frame_pointer_needed)
8638 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8639 else
150502c9 8640 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8641 }"
8642 [(set_attr "type" "call")]
8643)
8644
9c08d1fa 8645;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8646;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8647
f7fbdd4a 8648(define_insn "*call_symbol"
27ed6835 8649 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8650 (match_operand 1 "" ""))
bbe777ea 8651 (use (match_operand 2 "" ""))
bd5b4116 8652 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8653 "TARGET_32BIT
cffb2a26 8654 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8655 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8656 "*
8657 {
55c1e470 8658 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8659 }"
cffb2a26 8660 [(set_attr "type" "call")]
8661)
9c08d1fa 8662
f7fbdd4a 8663(define_insn "*call_value_symbol"
ccd90aaa 8664 [(set (match_operand 0 "" "")
27ed6835 8665 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8666 (match_operand:SI 2 "" "")))
bbe777ea 8667 (use (match_operand 3 "" ""))
bd5b4116 8668 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8669 "TARGET_32BIT
cffb2a26 8670 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8671 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8672 "*
8673 {
55c1e470 8674 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8675 }"
cffb2a26 8676 [(set_attr "type" "call")]
8677)
8678
8679(define_insn "*call_insn"
27ed6835 8680 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8681 (match_operand:SI 1 "" ""))
8682 (use (match_operand 2 "" ""))
bd5b4116 8683 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8684 "TARGET_THUMB1
1675c6e9 8685 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8686 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8687 "bl\\t%a0"
8688 [(set_attr "length" "4")
8689 (set_attr "type" "call")]
8690)
8691
8692(define_insn "*call_value_insn"
ccd90aaa 8693 [(set (match_operand 0 "" "")
27ed6835 8694 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8695 (match_operand 2 "" "")))
8696 (use (match_operand 3 "" ""))
bd5b4116 8697 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8698 "TARGET_THUMB1
1675c6e9 8699 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8700 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8701 "bl\\t%a1"
8702 [(set_attr "length" "4")
8703 (set_attr "type" "call")]
8704)
9c08d1fa 8705
1c494086 8706;; We may also be able to do sibcalls for Thumb, but it's much harder...
8707(define_expand "sibcall"
8708 [(parallel [(call (match_operand 0 "memory_operand" "")
8709 (match_operand 1 "general_operand" ""))
2ba80634 8710 (return)
8711 (use (match_operand 2 "" ""))])]
d68c2c10 8712 "TARGET_32BIT"
1c494086 8713 "
8714 {
8715 if (operands[2] == NULL_RTX)
8716 operands[2] = const0_rtx;
1c494086 8717 }"
8718)
8719
8720(define_expand "sibcall_value"
ccd90aaa 8721 [(parallel [(set (match_operand 0 "" "")
1c494086 8722 (call (match_operand 1 "memory_operand" "")
8723 (match_operand 2 "general_operand" "")))
2ba80634 8724 (return)
8725 (use (match_operand 3 "" ""))])]
d68c2c10 8726 "TARGET_32BIT"
1c494086 8727 "
8728 {
8729 if (operands[3] == NULL_RTX)
8730 operands[3] = const0_rtx;
1c494086 8731 }"
8732)
8733
8734(define_insn "*sibcall_insn"
8735 [(call (mem:SI (match_operand:SI 0 "" "X"))
8736 (match_operand 1 "" ""))
2ba80634 8737 (return)
8738 (use (match_operand 2 "" ""))]
d68c2c10 8739 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8740 "*
8741 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8742 "
8743 [(set_attr "type" "call")]
8744)
8745
8746(define_insn "*sibcall_value_insn"
ccd90aaa 8747 [(set (match_operand 0 "" "")
755eb2b4 8748 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8749 (match_operand 2 "" "")))
2ba80634 8750 (return)
8751 (use (match_operand 3 "" ""))]
d68c2c10 8752 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8753 "*
8754 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8755 "
8756 [(set_attr "type" "call")]
8757)
8758
d68c2c10 8759(define_expand "return"
8760 [(return)]
8761 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8762 "")
8763
9c08d1fa 8764;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8765(define_insn "*arm_return"
9c08d1fa 8766 [(return)]
cffb2a26 8767 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8768 "*
9c08d1fa 8769 {
cffb2a26 8770 if (arm_ccfsm_state == 2)
8771 {
8772 arm_ccfsm_state += 2;
8773 return \"\";
8774 }
5db468b7 8775 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8776 }"
a2cd141b 8777 [(set_attr "type" "load1")
755eb2b4 8778 (set_attr "length" "12")
0d66636f 8779 (set_attr "predicable" "yes")]
cffb2a26 8780)
9c08d1fa 8781
f7fbdd4a 8782(define_insn "*cond_return"
9c08d1fa 8783 [(set (pc)
8fa3ba89 8784 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8785 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8786 (return)
8787 (pc)))]
cffb2a26 8788 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8789 "*
8fa3ba89 8790 {
8791 if (arm_ccfsm_state == 2)
8792 {
8793 arm_ccfsm_state += 2;
8794 return \"\";
8795 }
8796 return output_return_instruction (operands[0], TRUE, FALSE);
8797 }"
8798 [(set_attr "conds" "use")
755eb2b4 8799 (set_attr "length" "12")
a2cd141b 8800 (set_attr "type" "load1")]
8fa3ba89 8801)
9c08d1fa 8802
f7fbdd4a 8803(define_insn "*cond_return_inverted"
9c08d1fa 8804 [(set (pc)
8fa3ba89 8805 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8806 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8807 (pc)
8808 (return)))]
cffb2a26 8809 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8810 "*
8fa3ba89 8811 {
8812 if (arm_ccfsm_state == 2)
8813 {
8814 arm_ccfsm_state += 2;
8815 return \"\";
8816 }
8817 return output_return_instruction (operands[0], TRUE, TRUE);
8818 }"
8819 [(set_attr "conds" "use")
37a1317b 8820 (set_attr "length" "12")
a2cd141b 8821 (set_attr "type" "load1")]
8fa3ba89 8822)
9c08d1fa 8823
68121397 8824;; Generate a sequence of instructions to determine if the processor is
8825;; in 26-bit or 32-bit mode, and return the appropriate return address
8826;; mask.
8827
8828(define_expand "return_addr_mask"
8829 [(set (match_dup 1)
8830 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8831 (const_int 0)))
8832 (set (match_operand:SI 0 "s_register_operand" "")
8833 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8834 (const_int -1)
8835 (const_int 67108860)))] ; 0x03fffffc
8836 "TARGET_ARM"
8837 "
62eddbd4 8838 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8839 ")
8840
8841(define_insn "*check_arch2"
8842 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8843 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8844 (const_int 0)))]
8845 "TARGET_ARM"
8846 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8847 [(set_attr "length" "8")
8848 (set_attr "conds" "set")]
8849)
8850
9c08d1fa 8851;; Call subroutine returning any type.
8852
8853(define_expand "untyped_call"
8854 [(parallel [(call (match_operand 0 "" "")
8855 (const_int 0))
8856 (match_operand 1 "" "")
8857 (match_operand 2 "" "")])]
ccd90aaa 8858 "TARGET_EITHER"
9c08d1fa 8859 "
215b30b3 8860 {
8861 int i;
ccd90aaa 8862 rtx par = gen_rtx_PARALLEL (VOIDmode,
8863 rtvec_alloc (XVECLEN (operands[2], 0)));
8864 rtx addr = gen_reg_rtx (Pmode);
8865 rtx mem;
8866 int size = 0;
9c08d1fa 8867
ccd90aaa 8868 emit_move_insn (addr, XEXP (operands[1], 0));
8869 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8870
215b30b3 8871 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8872 {
ccd90aaa 8873 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8874
ccd90aaa 8875 /* Default code only uses r0 as a return value, but we could
8876 be using anything up to 4 registers. */
8877 if (REGNO (src) == R0_REGNUM)
8878 src = gen_rtx_REG (TImode, R0_REGNUM);
8879
8880 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8881 GEN_INT (size));
8882 size += GET_MODE_SIZE (GET_MODE (src));
8883 }
8884
8885 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8886 const0_rtx));
8887
8888 size = 0;
8889
8890 for (i = 0; i < XVECLEN (par, 0); i++)
8891 {
8892 HOST_WIDE_INT offset = 0;
8893 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8894
8895 if (size != 0)
8896 emit_move_insn (addr, plus_constant (addr, size));
8897
8898 mem = change_address (mem, GET_MODE (reg), NULL);
8899 if (REGNO (reg) == R0_REGNUM)
8900 {
8901 /* On thumb we have to use a write-back instruction. */
8902 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8903 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8904 size = TARGET_ARM ? 16 : 0;
8905 }
8906 else
8907 {
8908 emit_move_insn (mem, reg);
8909 size = GET_MODE_SIZE (GET_MODE (reg));
8910 }
215b30b3 8911 }
9c08d1fa 8912
215b30b3 8913 /* The optimizer does not know that the call sets the function value
8914 registers we stored in the result block. We avoid problems by
8915 claiming that all hard registers are used and clobbered at this
8916 point. */
8917 emit_insn (gen_blockage ());
8918
8919 DONE;
8920 }"
8921)
9c08d1fa 8922
ccd90aaa 8923(define_expand "untyped_return"
8924 [(match_operand:BLK 0 "memory_operand" "")
8925 (match_operand 1 "" "")]
8926 "TARGET_EITHER"
8927 "
8928 {
8929 int i;
8930 rtx addr = gen_reg_rtx (Pmode);
8931 rtx mem;
8932 int size = 0;
8933
8934 emit_move_insn (addr, XEXP (operands[0], 0));
8935 mem = change_address (operands[0], BLKmode, addr);
8936
8937 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8938 {
8939 HOST_WIDE_INT offset = 0;
8940 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8941
8942 if (size != 0)
8943 emit_move_insn (addr, plus_constant (addr, size));
8944
8945 mem = change_address (mem, GET_MODE (reg), NULL);
8946 if (REGNO (reg) == R0_REGNUM)
8947 {
8948 /* On thumb we have to use a write-back instruction. */
8949 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8950 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8951 size = TARGET_ARM ? 16 : 0;
8952 }
8953 else
8954 {
8955 emit_move_insn (reg, mem);
8956 size = GET_MODE_SIZE (GET_MODE (reg));
8957 }
8958 }
8959
8960 /* Emit USE insns before the return. */
8961 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8962 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8963
8964 /* Construct the return. */
8965 expand_naked_return ();
8966
8967 DONE;
8968 }"
8969)
8970
9c08d1fa 8971;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8972;; all of memory. This blocks insns from being moved across this point.
8973
8974(define_insn "blockage"
e1159bbe 8975 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8976 "TARGET_EITHER"
9c08d1fa 8977 ""
cffb2a26 8978 [(set_attr "length" "0")
8979 (set_attr "type" "block")]
8980)
9c08d1fa 8981
f7fbdd4a 8982(define_expand "casesi"
8983 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8984 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8985 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8986 (match_operand:SI 3 "" "") ; table label
8987 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8988 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8989 "
215b30b3 8990 {
e6ac8414 8991 enum insn_code code;
215b30b3 8992 if (operands[1] != const0_rtx)
8993 {
e6ac8414 8994 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8995
215b30b3 8996 emit_insn (gen_addsi3 (reg, operands[0],
8997 GEN_INT (-INTVAL (operands[1]))));
8998 operands[0] = reg;
8999 }
9c08d1fa 9000
25f905c2 9001 if (TARGET_ARM)
e6ac8414 9002 code = CODE_FOR_arm_casesi_internal;
3db2019b 9003 else if (TARGET_THUMB1)
e6ac8414 9004 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 9005 else if (flag_pic)
e6ac8414 9006 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 9007 else
e6ac8414 9008 code = CODE_FOR_thumb2_casesi_internal;
9009
9010 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
9011 operands[2] = force_reg (SImode, operands[2]);
9012
9013 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
9014 operands[3], operands[4]));
215b30b3 9015 DONE;
9016 }"
9017)
f7fbdd4a 9018
f082f1c4 9019;; The USE in this pattern is needed to tell flow analysis that this is
9020;; a CASESI insn. It has no other purpose.
25f905c2 9021(define_insn "arm_casesi_internal"
f082f1c4 9022 [(parallel [(set (pc)
9023 (if_then_else
9024 (leu (match_operand:SI 0 "s_register_operand" "r")
9025 (match_operand:SI 1 "arm_rhs_operand" "rI"))
9026 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9027 (label_ref (match_operand 2 "" ""))))
9028 (label_ref (match_operand 3 "" ""))))
bd5b4116 9029 (clobber (reg:CC CC_REGNUM))
f082f1c4 9030 (use (label_ref (match_dup 2)))])]
cffb2a26 9031 "TARGET_ARM"
f7fbdd4a 9032 "*
0d66636f 9033 if (flag_pic)
9034 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
9035 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
9036 "
9037 [(set_attr "conds" "clob")
9038 (set_attr "length" "12")]
9039)
9c08d1fa 9040
e6ac8414 9041(define_expand "thumb1_casesi_internal_pic"
9042 [(match_operand:SI 0 "s_register_operand" "")
9043 (match_operand:SI 1 "thumb1_cmp_operand" "")
9044 (match_operand 2 "" "")
9045 (match_operand 3 "" "")]
3db2019b 9046 "TARGET_THUMB1"
e6ac8414 9047 {
9048 rtx reg0;
9049 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9050 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9051 operands[3]));
9052 reg0 = gen_rtx_REG (SImode, 0);
9053 emit_move_insn (reg0, operands[0]);
9054 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9055 DONE;
9056 }
9057)
9058
9059(define_insn "thumb1_casesi_dispatch"
9060 [(parallel [(set (pc) (unspec [(reg:SI 0)
9061 (label_ref (match_operand 0 "" ""))
9062;; (label_ref (match_operand 1 "" ""))
9063]
9064 UNSPEC_THUMB1_CASESI))
9065 (clobber (reg:SI IP_REGNUM))
9066 (clobber (reg:SI LR_REGNUM))])]
3db2019b 9067 "TARGET_THUMB1"
e6ac8414 9068 "* return thumb1_output_casesi(operands);"
9069 [(set_attr "length" "4")]
9070)
9071
cffb2a26 9072(define_expand "indirect_jump"
9c08d1fa 9073 [(set (pc)
cffb2a26 9074 (match_operand:SI 0 "s_register_operand" ""))]
9075 "TARGET_EITHER"
25f905c2 9076 "
9077 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
9078 address and use bx. */
9079 if (TARGET_THUMB2)
9080 {
9081 rtx tmp;
9082 tmp = gen_reg_rtx (SImode);
9083 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9084 operands[0] = tmp;
9085 }
9086 "
cffb2a26 9087)
9088
f1039640 9089;; NB Never uses BX.
cffb2a26 9090(define_insn "*arm_indirect_jump"
9091 [(set (pc)
9092 (match_operand:SI 0 "s_register_operand" "r"))]
9093 "TARGET_ARM"
9094 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 9095 [(set_attr "predicable" "yes")]
cffb2a26 9096)
9c08d1fa 9097
f7fbdd4a 9098(define_insn "*load_indirect_jump"
9c08d1fa 9099 [(set (pc)
9100 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 9101 "TARGET_ARM"
9102 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 9103 [(set_attr "type" "load1")
61a2d04c 9104 (set_attr "pool_range" "4096")
9105 (set_attr "neg_pool_range" "4084")
0d66636f 9106 (set_attr "predicable" "yes")]
cffb2a26 9107)
9108
f1039640 9109;; NB Never uses BX.
25f905c2 9110(define_insn "*thumb1_indirect_jump"
cffb2a26 9111 [(set (pc)
9112 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 9113 "TARGET_THUMB1"
cffb2a26 9114 "mov\\tpc, %0"
9115 [(set_attr "conds" "clob")
9116 (set_attr "length" "2")]
9117)
9118
9c08d1fa 9119\f
9120;; Misc insns
9121
9122(define_insn "nop"
9123 [(const_int 0)]
cffb2a26 9124 "TARGET_EITHER"
9125 "*
25f905c2 9126 if (TARGET_UNIFIED_ASM)
9127 return \"nop\";
cffb2a26 9128 if (TARGET_ARM)
9129 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9130 return \"mov\\tr8, r8\";
9131 "
9132 [(set (attr "length")
9133 (if_then_else (eq_attr "is_thumb" "yes")
9134 (const_int 2)
9135 (const_int 4)))]
9136)
9137
9c08d1fa 9138\f
9139;; Patterns to allow combination of arithmetic, cond code and shifts
9140
f7fbdd4a 9141(define_insn "*arith_shiftsi"
9c08d1fa 9142 [(set (match_operand:SI 0 "s_register_operand" "=r")
9143 (match_operator:SI 1 "shiftable_operator"
9144 [(match_operator:SI 3 "shift_operator"
9145 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9146 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9147 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 9148 "TARGET_ARM"
6c4c2133 9149 "%i1%?\\t%0, %2, %4%S3"
344495ea 9150 [(set_attr "predicable" "yes")
331beb1a 9151 (set_attr "shift" "4")
a2cd141b 9152 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9153 (const_string "alu_shift")
9154 (const_string "alu_shift_reg")))]
6c4c2133 9155)
9c08d1fa 9156
d7863cfe 9157(define_split
9158 [(set (match_operand:SI 0 "s_register_operand" "")
9159 (match_operator:SI 1 "shiftable_operator"
9160 [(match_operator:SI 2 "shiftable_operator"
9161 [(match_operator:SI 3 "shift_operator"
9162 [(match_operand:SI 4 "s_register_operand" "")
9163 (match_operand:SI 5 "reg_or_int_operand" "")])
9164 (match_operand:SI 6 "s_register_operand" "")])
9165 (match_operand:SI 7 "arm_rhs_operand" "")]))
9166 (clobber (match_operand:SI 8 "s_register_operand" ""))]
9167 "TARGET_ARM"
9168 [(set (match_dup 8)
9169 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9170 (match_dup 6)]))
9171 (set (match_dup 0)
9172 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9173 "")
9174
f7fbdd4a 9175(define_insn "*arith_shiftsi_compare0"
bd5b4116 9176 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 9177 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9178 [(match_operator:SI 3 "shift_operator"
9179 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9180 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9181 (match_operand:SI 2 "s_register_operand" "r")])
9182 (const_int 0)))
9183 (set (match_operand:SI 0 "s_register_operand" "=r")
9184 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9185 (match_dup 2)]))]
cffb2a26 9186 "TARGET_ARM"
25f905c2 9187 "%i1%.\\t%0, %2, %4%S3"
344495ea 9188 [(set_attr "conds" "set")
331beb1a 9189 (set_attr "shift" "4")
a2cd141b 9190 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9191 (const_string "alu_shift")
9192 (const_string "alu_shift_reg")))]
0d66636f 9193)
9c08d1fa 9194
f7fbdd4a 9195(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9196 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 9197 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9198 [(match_operator:SI 3 "shift_operator"
9199 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9200 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9201 (match_operand:SI 2 "s_register_operand" "r")])
9202 (const_int 0)))
9203 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 9204 "TARGET_ARM"
25f905c2 9205 "%i1%.\\t%0, %2, %4%S3"
344495ea 9206 [(set_attr "conds" "set")
331beb1a 9207 (set_attr "shift" "4")
a2cd141b 9208 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9209 (const_string "alu_shift")
9210 (const_string "alu_shift_reg")))]
0d66636f 9211)
9c08d1fa 9212
f7fbdd4a 9213(define_insn "*sub_shiftsi"
9c08d1fa 9214 [(set (match_operand:SI 0 "s_register_operand" "=r")
9215 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9216 (match_operator:SI 2 "shift_operator"
9217 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9218 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 9219 "TARGET_ARM"
6c4c2133 9220 "sub%?\\t%0, %1, %3%S2"
344495ea 9221 [(set_attr "predicable" "yes")
331beb1a 9222 (set_attr "shift" "3")
a2cd141b 9223 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9224 (const_string "alu_shift")
9225 (const_string "alu_shift_reg")))]
6c4c2133 9226)
9c08d1fa 9227
f7fbdd4a 9228(define_insn "*sub_shiftsi_compare0"
bd5b4116 9229 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9230 (compare:CC_NOOV
9231 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9232 (match_operator:SI 2 "shift_operator"
9233 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9234 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 9235 (const_int 0)))
9c08d1fa 9236 (set (match_operand:SI 0 "s_register_operand" "=r")
9237 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9238 (match_dup 4)])))]
cffb2a26 9239 "TARGET_ARM"
25f905c2 9240 "sub%.\\t%0, %1, %3%S2"
344495ea 9241 [(set_attr "conds" "set")
a2cd141b 9242 (set_attr "shift" "3")
9243 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9244 (const_string "alu_shift")
9245 (const_string "alu_shift_reg")))]
0d66636f 9246)
9c08d1fa 9247
f7fbdd4a 9248(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9249 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9250 (compare:CC_NOOV
9251 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9252 (match_operator:SI 2 "shift_operator"
9253 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9254 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 9255 (const_int 0)))
9c08d1fa 9256 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 9257 "TARGET_ARM"
25f905c2 9258 "sub%.\\t%0, %1, %3%S2"
344495ea 9259 [(set_attr "conds" "set")
a2cd141b 9260 (set_attr "shift" "3")
9261 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9262 (const_string "alu_shift")
9263 (const_string "alu_shift_reg")))]
0d66636f 9264)
9c08d1fa 9265
9c08d1fa 9266\f
9267
f7fbdd4a 9268(define_insn "*and_scc"
9c08d1fa 9269 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9270 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9271 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9272 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9273 "TARGET_ARM"
e2348bcb 9274 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9275 [(set_attr "conds" "use")
9276 (set_attr "length" "8")]
9277)
9c08d1fa 9278
f7fbdd4a 9279(define_insn "*ior_scc"
9c08d1fa 9280 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9281 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9282 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9283 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9284 "TARGET_ARM"
e2348bcb 9285 "@
899850b0 9286 orr%d2\\t%0, %1, #1
9287 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9288 [(set_attr "conds" "use")
9289 (set_attr "length" "4,8")]
9290)
9c08d1fa 9291
f7fbdd4a 9292(define_insn "*compare_scc"
5565501b 9293 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9294 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9295 [(match_operand:SI 2 "s_register_operand" "r,r")
9296 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9297 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9298 "TARGET_ARM"
9c08d1fa 9299 "*
601f584c 9300 if (operands[3] == const0_rtx)
9301 {
9302 if (GET_CODE (operands[1]) == LT)
9303 return \"mov\\t%0, %2, lsr #31\";
9304
9305 if (GET_CODE (operands[1]) == GE)
9306 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 9307
601f584c 9308 if (GET_CODE (operands[1]) == EQ)
9309 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9310 }
e2348bcb 9311
8fa3ba89 9312 if (GET_CODE (operands[1]) == NE)
9313 {
9314 if (which_alternative == 1)
9315 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9316 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9317 }
9318 if (which_alternative == 1)
9319 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9320 else
9321 output_asm_insn (\"cmp\\t%2, %3\", operands);
9322 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9323 "
9324 [(set_attr "conds" "clob")
9325 (set_attr "length" "12")]
9326)
9c08d1fa 9327
f7fbdd4a 9328(define_insn "*cond_move"
9c08d1fa 9329 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9330 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9331 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9332 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9333 (const_int 0)])
9334 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9335 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9336 "TARGET_ARM"
9c08d1fa 9337 "*
8fa3ba89 9338 if (GET_CODE (operands[3]) == NE)
9339 {
9340 if (which_alternative != 1)
9341 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9342 if (which_alternative != 0)
9343 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9344 return \"\";
9345 }
9346 if (which_alternative != 0)
9347 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9348 if (which_alternative != 1)
9349 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9350 return \"\";
9351 "
9352 [(set_attr "conds" "use")
9353 (set_attr "length" "4,4,8")]
9354)
9c08d1fa 9355
f7fbdd4a 9356(define_insn "*cond_arith"
9c08d1fa 9357 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9358 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9359 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9360 [(match_operand:SI 2 "s_register_operand" "r,r")
9361 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9362 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9363 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9364 "TARGET_ARM"
9c08d1fa 9365 "*
8fa3ba89 9366 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9367 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9368
8fa3ba89 9369 output_asm_insn (\"cmp\\t%2, %3\", operands);
9370 if (GET_CODE (operands[5]) == AND)
9371 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9372 else if (GET_CODE (operands[5]) == MINUS)
9373 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9374 else if (which_alternative != 0)
9375 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9376 return \"%i5%d4\\t%0, %1, #1\";
9377 "
9378 [(set_attr "conds" "clob")
9379 (set_attr "length" "12")]
9380)
9c08d1fa 9381
f7fbdd4a 9382(define_insn "*cond_sub"
9c08d1fa 9383 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9384 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9385 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9386 [(match_operand:SI 2 "s_register_operand" "r,r")
9387 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9388 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9389 "TARGET_ARM"
9c08d1fa 9390 "*
8fa3ba89 9391 output_asm_insn (\"cmp\\t%2, %3\", operands);
9392 if (which_alternative != 0)
9393 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9394 return \"sub%d4\\t%0, %1, #1\";
9395 "
9396 [(set_attr "conds" "clob")
9397 (set_attr "length" "8,12")]
9398)
9c08d1fa 9399
25f905c2 9400;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 9401(define_insn "*cmp_ite0"
cffb2a26 9402 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9403 (compare
9404 (if_then_else:SI
8fa3ba89 9405 (match_operator 4 "arm_comparison_operator"
aea4c774 9406 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9407 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9408 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9409 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9410 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9411 (const_int 0))
9412 (const_int 0)))]
cffb2a26 9413 "TARGET_ARM"
9c08d1fa 9414 "*
aea4c774 9415 {
8fa3ba89 9416 static const char * const opcodes[4][2] =
9417 {
9418 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9419 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9420 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9421 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9422 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9423 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9424 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9425 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9426 };
9427 int swap =
9428 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9429
9430 return opcodes[which_alternative][swap];
9431 }"
9432 [(set_attr "conds" "set")
9433 (set_attr "length" "8")]
9434)
9c08d1fa 9435
aea4c774 9436(define_insn "*cmp_ite1"
cffb2a26 9437 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9438 (compare
9439 (if_then_else:SI
8fa3ba89 9440 (match_operator 4 "arm_comparison_operator"
aea4c774 9441 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 9442 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9443 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9444 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 9445 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 9446 (const_int 1))
9447 (const_int 0)))]
cffb2a26 9448 "TARGET_ARM"
9c08d1fa 9449 "*
9c08d1fa 9450 {
215b30b3 9451 static const char * const opcodes[4][2] =
9452 {
9453 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9454 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9455 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9456 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9457 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9458 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9459 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9460 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9461 };
9462 int swap =
9463 comparison_dominates_p (GET_CODE (operands[5]),
9464 reverse_condition (GET_CODE (operands[4])));
9465
9466 return opcodes[which_alternative][swap];
9467 }"
8fa3ba89 9468 [(set_attr "conds" "set")
9469 (set_attr "length" "8")]
9470)
9c08d1fa 9471
f6c53574 9472(define_insn "*cmp_and"
9473 [(set (match_operand 6 "dominant_cc_register" "")
9474 (compare
9475 (and:SI
9476 (match_operator 4 "arm_comparison_operator"
9477 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9478 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9479 (match_operator:SI 5 "arm_comparison_operator"
9480 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9481 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9482 (const_int 0)))]
9483 "TARGET_ARM"
9484 "*
9485 {
35823b64 9486 static const char *const opcodes[4][2] =
f6c53574 9487 {
9488 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9489 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9490 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9491 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9492 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9493 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9494 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9495 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9496 };
9497 int swap =
9498 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9499
9500 return opcodes[which_alternative][swap];
9501 }"
9502 [(set_attr "conds" "set")
9503 (set_attr "predicable" "no")
9504 (set_attr "length" "8")]
9505)
9506
9507(define_insn "*cmp_ior"
9508 [(set (match_operand 6 "dominant_cc_register" "")
9509 (compare
9510 (ior:SI
9511 (match_operator 4 "arm_comparison_operator"
9512 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9513 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9514 (match_operator:SI 5 "arm_comparison_operator"
9515 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9516 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9517 (const_int 0)))]
9518 "TARGET_ARM"
9519 "*
9520{
35823b64 9521 static const char *const opcodes[4][2] =
f6c53574 9522 {
9523 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9524 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9525 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9526 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9527 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9528 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9529 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9530 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9531 };
9532 int swap =
9533 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9534
9535 return opcodes[which_alternative][swap];
9536}
9537"
9538 [(set_attr "conds" "set")
9539 (set_attr "length" "8")]
9540)
9541
3c5afce6 9542(define_insn_and_split "*ior_scc_scc"
9543 [(set (match_operand:SI 0 "s_register_operand" "=r")
9544 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9545 [(match_operand:SI 1 "s_register_operand" "r")
9546 (match_operand:SI 2 "arm_add_operand" "rIL")])
9547 (match_operator:SI 6 "arm_comparison_operator"
9548 [(match_operand:SI 4 "s_register_operand" "r")
9549 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9550 (clobber (reg:CC CC_REGNUM))]
9551 "TARGET_ARM
9552 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9553 != CCmode)"
9554 "#"
9555 "TARGET_ARM && reload_completed"
9556 [(set (match_dup 7)
9557 (compare
9558 (ior:SI
9559 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9560 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9561 (const_int 0)))
9562 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9563 "operands[7]
9564 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9565 DOM_CC_X_OR_Y),
601f584c 9566 CC_REGNUM);"
9567 [(set_attr "conds" "clob")
9568 (set_attr "length" "16")])
9569
9570; If the above pattern is followed by a CMP insn, then the compare is
9571; redundant, since we can rework the conditional instruction that follows.
9572(define_insn_and_split "*ior_scc_scc_cmp"
9573 [(set (match_operand 0 "dominant_cc_register" "")
9574 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9575 [(match_operand:SI 1 "s_register_operand" "r")
9576 (match_operand:SI 2 "arm_add_operand" "rIL")])
9577 (match_operator:SI 6 "arm_comparison_operator"
9578 [(match_operand:SI 4 "s_register_operand" "r")
9579 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9580 (const_int 0)))
9581 (set (match_operand:SI 7 "s_register_operand" "=r")
9582 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9583 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9584 "TARGET_ARM"
9585 "#"
9586 "TARGET_ARM && reload_completed"
9587 [(set (match_dup 0)
9588 (compare
9589 (ior:SI
9590 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9591 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9592 (const_int 0)))
9593 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9594 ""
9595 [(set_attr "conds" "set")
9596 (set_attr "length" "16")])
3c5afce6 9597
9598(define_insn_and_split "*and_scc_scc"
9599 [(set (match_operand:SI 0 "s_register_operand" "=r")
9600 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9601 [(match_operand:SI 1 "s_register_operand" "r")
9602 (match_operand:SI 2 "arm_add_operand" "rIL")])
9603 (match_operator:SI 6 "arm_comparison_operator"
9604 [(match_operand:SI 4 "s_register_operand" "r")
9605 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9606 (clobber (reg:CC CC_REGNUM))]
9607 "TARGET_ARM
9608 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9609 != CCmode)"
9610 "#"
601f584c 9611 "TARGET_ARM && reload_completed
9612 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9613 != CCmode)"
3c5afce6 9614 [(set (match_dup 7)
9615 (compare
9616 (and:SI
9617 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9618 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9619 (const_int 0)))
9620 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9621 "operands[7]
9622 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9623 DOM_CC_X_AND_Y),
601f584c 9624 CC_REGNUM);"
9625 [(set_attr "conds" "clob")
9626 (set_attr "length" "16")])
9627
9628; If the above pattern is followed by a CMP insn, then the compare is
9629; redundant, since we can rework the conditional instruction that follows.
9630(define_insn_and_split "*and_scc_scc_cmp"
9631 [(set (match_operand 0 "dominant_cc_register" "")
9632 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9633 [(match_operand:SI 1 "s_register_operand" "r")
9634 (match_operand:SI 2 "arm_add_operand" "rIL")])
9635 (match_operator:SI 6 "arm_comparison_operator"
9636 [(match_operand:SI 4 "s_register_operand" "r")
9637 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9638 (const_int 0)))
9639 (set (match_operand:SI 7 "s_register_operand" "=r")
9640 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9641 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9642 "TARGET_ARM"
9643 "#"
9644 "TARGET_ARM && reload_completed"
9645 [(set (match_dup 0)
9646 (compare
9647 (and:SI
9648 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9649 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9650 (const_int 0)))
9651 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9652 ""
9653 [(set_attr "conds" "set")
9654 (set_attr "length" "16")])
9655
9656;; If there is no dominance in the comparison, then we can still save an
9657;; instruction in the AND case, since we can know that the second compare
9658;; need only zero the value if false (if true, then the value is already
9659;; correct).
9660(define_insn_and_split "*and_scc_scc_nodom"
9661 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9662 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9663 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9664 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9665 (match_operator:SI 6 "arm_comparison_operator"
9666 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9667 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9668 (clobber (reg:CC CC_REGNUM))]
9669 "TARGET_ARM
9670 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9671 == CCmode)"
9672 "#"
9673 "TARGET_ARM && reload_completed"
9674 [(parallel [(set (match_dup 0)
9675 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9676 (clobber (reg:CC CC_REGNUM))])
9677 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9678 (set (match_dup 0)
9679 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9680 (match_dup 0)
9681 (const_int 0)))]
9682 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9683 operands[4], operands[5]),
9684 CC_REGNUM);
9685 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9686 operands[5]);"
9687 [(set_attr "conds" "clob")
9688 (set_attr "length" "20")])
3c5afce6 9689
3a0bdee0 9690(define_split
9691 [(set (reg:CC_NOOV CC_REGNUM)
9692 (compare:CC_NOOV (ior:SI
9693 (and:SI (match_operand:SI 0 "s_register_operand" "")
9694 (const_int 1))
b0694be0 9695 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9696 [(match_operand:SI 2 "s_register_operand" "")
9697 (match_operand:SI 3 "arm_add_operand" "")]))
9698 (const_int 0)))
9699 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9700 "TARGET_ARM"
9701 [(set (match_dup 4)
9702 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9703 (match_dup 0)))
9704 (set (reg:CC_NOOV CC_REGNUM)
9705 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9706 (const_int 0)))]
9707 "")
9708
9709(define_split
9710 [(set (reg:CC_NOOV CC_REGNUM)
9711 (compare:CC_NOOV (ior:SI
b0694be0 9712 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9713 [(match_operand:SI 2 "s_register_operand" "")
9714 (match_operand:SI 3 "arm_add_operand" "")])
9715 (and:SI (match_operand:SI 0 "s_register_operand" "")
9716 (const_int 1)))
9717 (const_int 0)))
9718 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9719 "TARGET_ARM"
9720 [(set (match_dup 4)
9721 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9722 (match_dup 0)))
9723 (set (reg:CC_NOOV CC_REGNUM)
9724 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9725 (const_int 0)))]
9726 "")
25f905c2 9727;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9728
f7fbdd4a 9729(define_insn "*negscc"
9c08d1fa 9730 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9731 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9732 [(match_operand:SI 1 "s_register_operand" "r")
9733 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9734 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9735 "TARGET_ARM"
9c08d1fa 9736 "*
2ca2ec2e 9737 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9738 return \"mov\\t%0, %1, asr #31\";
9739
9c08d1fa 9740 if (GET_CODE (operands[3]) == NE)
e2348bcb 9741 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9742
e2348bcb 9743 output_asm_insn (\"cmp\\t%1, %2\", operands);
9744 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9745 return \"mvn%d3\\t%0, #0\";
215b30b3 9746 "
8fa3ba89 9747 [(set_attr "conds" "clob")
9748 (set_attr "length" "12")]
9749)
9c08d1fa 9750
9751(define_insn "movcond"
9752 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9753 (if_then_else:SI
8fa3ba89 9754 (match_operator 5 "arm_comparison_operator"
5565501b 9755 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9756 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9757 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9758 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9759 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9760 "TARGET_ARM"
9c08d1fa 9761 "*
9762 if (GET_CODE (operands[5]) == LT
9763 && (operands[4] == const0_rtx))
9764 {
5565501b 9765 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9766 {
9c08d1fa 9767 if (operands[2] == const0_rtx)
e2348bcb 9768 return \"and\\t%0, %1, %3, asr #31\";
9769 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9770 }
9771 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9772 {
9c08d1fa 9773 if (operands[1] == const0_rtx)
e2348bcb 9774 return \"bic\\t%0, %2, %3, asr #31\";
9775 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9776 }
9777 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9778 are constants. */
9c08d1fa 9779 }
e2348bcb 9780
9c08d1fa 9781 if (GET_CODE (operands[5]) == GE
9782 && (operands[4] == const0_rtx))
9783 {
9784 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9785 {
9c08d1fa 9786 if (operands[2] == const0_rtx)
e2348bcb 9787 return \"bic\\t%0, %1, %3, asr #31\";
9788 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9789 }
9790 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9791 {
9c08d1fa 9792 if (operands[1] == const0_rtx)
e2348bcb 9793 return \"and\\t%0, %2, %3, asr #31\";
9794 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9795 }
9796 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9797 are constants. */
9c08d1fa 9798 }
9799 if (GET_CODE (operands[4]) == CONST_INT
9800 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9801 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9802 else
e2348bcb 9803 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9804 if (which_alternative != 0)
e2348bcb 9805 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9806 if (which_alternative != 1)
e2348bcb 9807 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9808 return \"\";
215b30b3 9809 "
8fa3ba89 9810 [(set_attr "conds" "clob")
9811 (set_attr "length" "8,8,12")]
9812)
9c08d1fa 9813
25f905c2 9814;; ??? The patterns below need checking for Thumb-2 usefulness.
9815
8a18b90c 9816(define_insn "*ifcompare_plus_move"
9817 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9818 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9819 [(match_operand:SI 4 "s_register_operand" "r,r")
9820 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9821 (plus:SI
9822 (match_operand:SI 2 "s_register_operand" "r,r")
9823 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9824 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9825 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9826 "TARGET_ARM"
8a18b90c 9827 "#"
8fa3ba89 9828 [(set_attr "conds" "clob")
9829 (set_attr "length" "8,12")]
9830)
8a18b90c 9831
9832(define_insn "*if_plus_move"
129a2fe4 9833 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9834 (if_then_else:SI
8fa3ba89 9835 (match_operator 4 "arm_comparison_operator"
8a18b90c 9836 [(match_operand 5 "cc_register" "") (const_int 0)])
9837 (plus:SI
129a2fe4 9838 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9839 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9840 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9841 "TARGET_ARM"
8a18b90c 9842 "@
9843 add%d4\\t%0, %2, %3
9844 sub%d4\\t%0, %2, #%n3
9845 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9846 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9847 [(set_attr "conds" "use")
9848 (set_attr "length" "4,4,8,8")
9849 (set_attr "type" "*,*,*,*")]
9850)
8a18b90c 9851
9852(define_insn "*ifcompare_move_plus"
5565501b 9853 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9854 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9855 [(match_operand:SI 4 "s_register_operand" "r,r")
9856 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9857 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9858 (plus:SI
9859 (match_operand:SI 2 "s_register_operand" "r,r")
9860 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9861 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9862 "TARGET_ARM"
8a18b90c 9863 "#"
8fa3ba89 9864 [(set_attr "conds" "clob")
9865 (set_attr "length" "8,12")]
9866)
8a18b90c 9867
9868(define_insn "*if_move_plus"
129a2fe4 9869 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9870 (if_then_else:SI
8fa3ba89 9871 (match_operator 4 "arm_comparison_operator"
8a18b90c 9872 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9873 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9874 (plus:SI
129a2fe4 9875 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9876 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9877 "TARGET_ARM"
8a18b90c 9878 "@
9879 add%D4\\t%0, %2, %3
9880 sub%D4\\t%0, %2, #%n3
9881 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9882 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9883 [(set_attr "conds" "use")
9884 (set_attr "length" "4,4,8,8")
9885 (set_attr "type" "*,*,*,*")]
9886)
8a18b90c 9887
9888(define_insn "*ifcompare_arith_arith"
9889 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9890 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9891 [(match_operand:SI 5 "s_register_operand" "r")
9892 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9893 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9894 [(match_operand:SI 1 "s_register_operand" "r")
9895 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9896 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9897 [(match_operand:SI 3 "s_register_operand" "r")
9898 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9899 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9900 "TARGET_ARM"
8a18b90c 9901 "#"
8fa3ba89 9902 [(set_attr "conds" "clob")
9903 (set_attr "length" "12")]
9904)
9c08d1fa 9905
8a18b90c 9906(define_insn "*if_arith_arith"
9907 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9908 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9909 [(match_operand 8 "cc_register" "") (const_int 0)])
9910 (match_operator:SI 6 "shiftable_operator"
9911 [(match_operand:SI 1 "s_register_operand" "r")
9912 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9913 (match_operator:SI 7 "shiftable_operator"
9914 [(match_operand:SI 3 "s_register_operand" "r")
9915 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9916 "TARGET_ARM"
8a18b90c 9917 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9918 [(set_attr "conds" "use")
9919 (set_attr "length" "8")]
9920)
8a18b90c 9921
f7fbdd4a 9922(define_insn "*ifcompare_arith_move"
9c08d1fa 9923 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9924 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9925 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9926 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9927 (match_operator:SI 7 "shiftable_operator"
9928 [(match_operand:SI 4 "s_register_operand" "r,r")
9929 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9930 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9931 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9932 "TARGET_ARM"
9c08d1fa 9933 "*
9c08d1fa 9934 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9935 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9936 everything is in registers then we can do this in two instructions. */
9c08d1fa 9937 if (operands[3] == const0_rtx
9938 && GET_CODE (operands[7]) != AND
9939 && GET_CODE (operands[5]) == REG
9940 && GET_CODE (operands[1]) == REG
9941 && REGNO (operands[1]) == REGNO (operands[4])
9942 && REGNO (operands[4]) != REGNO (operands[0]))
9943 {
9944 if (GET_CODE (operands[6]) == LT)
40dbec34 9945 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9946 else if (GET_CODE (operands[6]) == GE)
40dbec34 9947 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9948 }
9949 if (GET_CODE (operands[3]) == CONST_INT
9950 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9951 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9952 else
e2348bcb 9953 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9954 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9955 if (which_alternative != 0)
129a2fe4 9956 return \"mov%D6\\t%0, %1\";
9c08d1fa 9957 return \"\";
215b30b3 9958 "
8fa3ba89 9959 [(set_attr "conds" "clob")
9960 (set_attr "length" "8,12")]
9961)
9c08d1fa 9962
8a18b90c 9963(define_insn "*if_arith_move"
129a2fe4 9964 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9965 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9966 [(match_operand 6 "cc_register" "") (const_int 0)])
9967 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9968 [(match_operand:SI 2 "s_register_operand" "r,r")
9969 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9970 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9971 "TARGET_ARM"
8a18b90c 9972 "@
9973 %I5%d4\\t%0, %2, %3
129a2fe4 9974 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9975 [(set_attr "conds" "use")
9976 (set_attr "length" "4,8")
9977 (set_attr "type" "*,*")]
9978)
8a18b90c 9979
f7fbdd4a 9980(define_insn "*ifcompare_move_arith"
9c08d1fa 9981 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9982 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9983 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9984 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9985 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9986 (match_operator:SI 7 "shiftable_operator"
9987 [(match_operand:SI 2 "s_register_operand" "r,r")
9988 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9989 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9990 "TARGET_ARM"
9c08d1fa 9991 "*
9c08d1fa 9992 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9993 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9994 everything is in registers then we can do this in two instructions */
9995 if (operands[5] == const0_rtx
9996 && GET_CODE (operands[7]) != AND
9997 && GET_CODE (operands[3]) == REG
9998 && GET_CODE (operands[1]) == REG
9999 && REGNO (operands[1]) == REGNO (operands[2])
10000 && REGNO (operands[2]) != REGNO (operands[0]))
10001 {
10002 if (GET_CODE (operands[6]) == GE)
40dbec34 10003 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10004 else if (GET_CODE (operands[6]) == LT)
40dbec34 10005 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10006 }
40dbec34 10007
9c08d1fa 10008 if (GET_CODE (operands[5]) == CONST_INT
10009 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10010 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10011 else
e2348bcb 10012 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10013
9c08d1fa 10014 if (which_alternative != 0)
129a2fe4 10015 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10016 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10017 "
8fa3ba89 10018 [(set_attr "conds" "clob")
10019 (set_attr "length" "8,12")]
10020)
9c08d1fa 10021
8a18b90c 10022(define_insn "*if_move_arith"
129a2fe4 10023 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10024 (if_then_else:SI
8fa3ba89 10025 (match_operator 4 "arm_comparison_operator"
8a18b90c 10026 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10027 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10028 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10029 [(match_operand:SI 2 "s_register_operand" "r,r")
10030 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10031 "TARGET_ARM"
8a18b90c 10032 "@
10033 %I5%D4\\t%0, %2, %3
129a2fe4 10034 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10035 [(set_attr "conds" "use")
10036 (set_attr "length" "4,8")
10037 (set_attr "type" "*,*")]
10038)
8a18b90c 10039
10040(define_insn "*ifcompare_move_not"
9c08d1fa 10041 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10042 (if_then_else:SI
8fa3ba89 10043 (match_operator 5 "arm_comparison_operator"
8a18b90c 10044 [(match_operand:SI 3 "s_register_operand" "r,r")
10045 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10046 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10047 (not:SI
10048 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10049 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10050 "TARGET_ARM"
8a18b90c 10051 "#"
8fa3ba89 10052 [(set_attr "conds" "clob")
10053 (set_attr "length" "8,12")]
10054)
9c08d1fa 10055
8a18b90c 10056(define_insn "*if_move_not"
10057 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10058 (if_then_else:SI
8fa3ba89 10059 (match_operator 4 "arm_comparison_operator"
8a18b90c 10060 [(match_operand 3 "cc_register" "") (const_int 0)])
10061 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10062 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10063 "TARGET_ARM"
8a18b90c 10064 "@
10065 mvn%D4\\t%0, %2
10066 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10067 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10068 [(set_attr "conds" "use")
10069 (set_attr "length" "4,8,8")]
10070)
8a18b90c 10071
10072(define_insn "*ifcompare_not_move"
9c08d1fa 10073 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10074 (if_then_else:SI
8fa3ba89 10075 (match_operator 5 "arm_comparison_operator"
8a18b90c 10076 [(match_operand:SI 3 "s_register_operand" "r,r")
10077 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10078 (not:SI
10079 (match_operand:SI 2 "s_register_operand" "r,r"))
10080 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10081 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10082 "TARGET_ARM"
8a18b90c 10083 "#"
8fa3ba89 10084 [(set_attr "conds" "clob")
10085 (set_attr "length" "8,12")]
10086)
9c08d1fa 10087
8a18b90c 10088(define_insn "*if_not_move"
10089 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10090 (if_then_else:SI
8fa3ba89 10091 (match_operator 4 "arm_comparison_operator"
8a18b90c 10092 [(match_operand 3 "cc_register" "") (const_int 0)])
10093 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10094 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10095 "TARGET_ARM"
8a18b90c 10096 "@
10097 mvn%d4\\t%0, %2
10098 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10099 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10100 [(set_attr "conds" "use")
10101 (set_attr "length" "4,8,8")]
10102)
8a18b90c 10103
10104(define_insn "*ifcompare_shift_move"
9c08d1fa 10105 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10106 (if_then_else:SI
8fa3ba89 10107 (match_operator 6 "arm_comparison_operator"
8a18b90c 10108 [(match_operand:SI 4 "s_register_operand" "r,r")
10109 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10110 (match_operator:SI 7 "shift_operator"
10111 [(match_operand:SI 2 "s_register_operand" "r,r")
10112 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10113 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10114 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10115 "TARGET_ARM"
9c08d1fa 10116 "#"
8fa3ba89 10117 [(set_attr "conds" "clob")
10118 (set_attr "length" "8,12")]
10119)
9c08d1fa 10120
8a18b90c 10121(define_insn "*if_shift_move"
10122 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10123 (if_then_else:SI
8fa3ba89 10124 (match_operator 5 "arm_comparison_operator"
8a18b90c 10125 [(match_operand 6 "cc_register" "") (const_int 0)])
10126 (match_operator:SI 4 "shift_operator"
10127 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10128 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10129 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10130 "TARGET_ARM"
5565501b 10131 "@
8a18b90c 10132 mov%d5\\t%0, %2%S4
10133 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10134 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10135 [(set_attr "conds" "use")
331beb1a 10136 (set_attr "shift" "2")
a2cd141b 10137 (set_attr "length" "4,8,8")
10138 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10139 (const_string "alu_shift")
10140 (const_string "alu_shift_reg")))]
8fa3ba89 10141)
5565501b 10142
8a18b90c 10143(define_insn "*ifcompare_move_shift"
10144 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10145 (if_then_else:SI
8fa3ba89 10146 (match_operator 6 "arm_comparison_operator"
8a18b90c 10147 [(match_operand:SI 4 "s_register_operand" "r,r")
10148 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10149 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10150 (match_operator:SI 7 "shift_operator"
8a18b90c 10151 [(match_operand:SI 2 "s_register_operand" "r,r")
10152 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10153 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10154 "TARGET_ARM"
8a18b90c 10155 "#"
8fa3ba89 10156 [(set_attr "conds" "clob")
10157 (set_attr "length" "8,12")]
10158)
5565501b 10159
8a18b90c 10160(define_insn "*if_move_shift"
10161 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10162 (if_then_else:SI
8fa3ba89 10163 (match_operator 5 "arm_comparison_operator"
8a18b90c 10164 [(match_operand 6 "cc_register" "") (const_int 0)])
10165 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10166 (match_operator:SI 4 "shift_operator"
10167 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10168 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10169 "TARGET_ARM"
5565501b 10170 "@
8a18b90c 10171 mov%D5\\t%0, %2%S4
10172 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10173 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10174 [(set_attr "conds" "use")
331beb1a 10175 (set_attr "shift" "2")
a2cd141b 10176 (set_attr "length" "4,8,8")
10177 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10178 (const_string "alu_shift")
10179 (const_string "alu_shift_reg")))]
8fa3ba89 10180)
9c08d1fa 10181
f7fbdd4a 10182(define_insn "*ifcompare_shift_shift"
8a18b90c 10183 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10184 (if_then_else:SI
8fa3ba89 10185 (match_operator 7 "arm_comparison_operator"
8a18b90c 10186 [(match_operand:SI 5 "s_register_operand" "r")
10187 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10188 (match_operator:SI 8 "shift_operator"
8a18b90c 10189 [(match_operand:SI 1 "s_register_operand" "r")
10190 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10191 (match_operator:SI 9 "shift_operator"
8a18b90c 10192 [(match_operand:SI 3 "s_register_operand" "r")
10193 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10194 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10195 "TARGET_ARM"
8a18b90c 10196 "#"
8fa3ba89 10197 [(set_attr "conds" "clob")
10198 (set_attr "length" "12")]
10199)
9c08d1fa 10200
8a18b90c 10201(define_insn "*if_shift_shift"
10202 [(set (match_operand:SI 0 "s_register_operand" "=r")
10203 (if_then_else:SI
8fa3ba89 10204 (match_operator 5 "arm_comparison_operator"
8a18b90c 10205 [(match_operand 8 "cc_register" "") (const_int 0)])
10206 (match_operator:SI 6 "shift_operator"
10207 [(match_operand:SI 1 "s_register_operand" "r")
10208 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10209 (match_operator:SI 7 "shift_operator"
10210 [(match_operand:SI 3 "s_register_operand" "r")
10211 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10212 "TARGET_ARM"
8a18b90c 10213 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10214 [(set_attr "conds" "use")
331beb1a 10215 (set_attr "shift" "1")
a2cd141b 10216 (set_attr "length" "8")
10217 (set (attr "type") (if_then_else
10218 (and (match_operand 2 "const_int_operand" "")
10219 (match_operand 4 "const_int_operand" ""))
10220 (const_string "alu_shift")
10221 (const_string "alu_shift_reg")))]
8fa3ba89 10222)
8a18b90c 10223
f7fbdd4a 10224(define_insn "*ifcompare_not_arith"
8a18b90c 10225 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10226 (if_then_else:SI
8fa3ba89 10227 (match_operator 6 "arm_comparison_operator"
8a18b90c 10228 [(match_operand:SI 4 "s_register_operand" "r")
10229 (match_operand:SI 5 "arm_add_operand" "rIL")])
10230 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10231 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10232 [(match_operand:SI 2 "s_register_operand" "r")
10233 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10234 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10235 "TARGET_ARM"
8a18b90c 10236 "#"
8fa3ba89 10237 [(set_attr "conds" "clob")
10238 (set_attr "length" "12")]
10239)
9c08d1fa 10240
8a18b90c 10241(define_insn "*if_not_arith"
10242 [(set (match_operand:SI 0 "s_register_operand" "=r")
10243 (if_then_else:SI
8fa3ba89 10244 (match_operator 5 "arm_comparison_operator"
8a18b90c 10245 [(match_operand 4 "cc_register" "") (const_int 0)])
10246 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10247 (match_operator:SI 6 "shiftable_operator"
10248 [(match_operand:SI 2 "s_register_operand" "r")
10249 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10250 "TARGET_ARM"
8a18b90c 10251 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10252 [(set_attr "conds" "use")
10253 (set_attr "length" "8")]
10254)
8a18b90c 10255
10256(define_insn "*ifcompare_arith_not"
10257 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10258 (if_then_else:SI
8fa3ba89 10259 (match_operator 6 "arm_comparison_operator"
8a18b90c 10260 [(match_operand:SI 4 "s_register_operand" "r")
10261 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10262 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10263 [(match_operand:SI 2 "s_register_operand" "r")
10264 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10265 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10266 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10267 "TARGET_ARM"
8a18b90c 10268 "#"
8fa3ba89 10269 [(set_attr "conds" "clob")
10270 (set_attr "length" "12")]
10271)
9c08d1fa 10272
8a18b90c 10273(define_insn "*if_arith_not"
10274 [(set (match_operand:SI 0 "s_register_operand" "=r")
10275 (if_then_else:SI
8fa3ba89 10276 (match_operator 5 "arm_comparison_operator"
8a18b90c 10277 [(match_operand 4 "cc_register" "") (const_int 0)])
10278 (match_operator:SI 6 "shiftable_operator"
10279 [(match_operand:SI 2 "s_register_operand" "r")
10280 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10281 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10282 "TARGET_ARM"
8a18b90c 10283 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10284 [(set_attr "conds" "use")
10285 (set_attr "length" "8")]
10286)
8a18b90c 10287
f7fbdd4a 10288(define_insn "*ifcompare_neg_move"
8a18b90c 10289 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10290 (if_then_else:SI
8fa3ba89 10291 (match_operator 5 "arm_comparison_operator"
8a18b90c 10292 [(match_operand:SI 3 "s_register_operand" "r,r")
10293 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10294 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10295 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10296 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10297 "TARGET_ARM"
8a18b90c 10298 "#"
8fa3ba89 10299 [(set_attr "conds" "clob")
10300 (set_attr "length" "8,12")]
10301)
8a18b90c 10302
10303(define_insn "*if_neg_move"
10304 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10305 (if_then_else:SI
8fa3ba89 10306 (match_operator 4 "arm_comparison_operator"
8a18b90c 10307 [(match_operand 3 "cc_register" "") (const_int 0)])
10308 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10309 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10310 "TARGET_ARM"
8a18b90c 10311 "@
10312 rsb%d4\\t%0, %2, #0
10313 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10314 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10315 [(set_attr "conds" "use")
10316 (set_attr "length" "4,8,8")]
10317)
9c08d1fa 10318
f7fbdd4a 10319(define_insn "*ifcompare_move_neg"
8a18b90c 10320 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10321 (if_then_else:SI
8fa3ba89 10322 (match_operator 5 "arm_comparison_operator"
8a18b90c 10323 [(match_operand:SI 3 "s_register_operand" "r,r")
10324 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10325 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10326 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10327 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10328 "TARGET_ARM"
8a18b90c 10329 "#"
8fa3ba89 10330 [(set_attr "conds" "clob")
10331 (set_attr "length" "8,12")]
10332)
8a18b90c 10333
10334(define_insn "*if_move_neg"
10335 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10336 (if_then_else:SI
8fa3ba89 10337 (match_operator 4 "arm_comparison_operator"
8a18b90c 10338 [(match_operand 3 "cc_register" "") (const_int 0)])
10339 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10340 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10341 "TARGET_ARM"
8a18b90c 10342 "@
10343 rsb%D4\\t%0, %2, #0
10344 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10345 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10346 [(set_attr "conds" "use")
10347 (set_attr "length" "4,8,8")]
10348)
9c08d1fa 10349
f7fbdd4a 10350(define_insn "*arith_adjacentmem"
9c08d1fa 10351 [(set (match_operand:SI 0 "s_register_operand" "=r")
10352 (match_operator:SI 1 "shiftable_operator"
10353 [(match_operand:SI 2 "memory_operand" "m")
10354 (match_operand:SI 3 "memory_operand" "m")]))
10355 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10356 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10357 "*
215b30b3 10358 {
10359 rtx ldm[3];
10360 rtx arith[4];
94dee231 10361 rtx base_reg;
10362 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10363
215b30b3 10364 if (REGNO (operands[0]) > REGNO (operands[4]))
10365 {
10366 ldm[1] = operands[4];
10367 ldm[2] = operands[0];
10368 }
10369 else
10370 {
10371 ldm[1] = operands[0];
10372 ldm[2] = operands[4];
10373 }
94dee231 10374
10375 base_reg = XEXP (operands[2], 0);
10376
10377 if (!REG_P (base_reg))
10378 {
10379 val1 = INTVAL (XEXP (base_reg, 1));
10380 base_reg = XEXP (base_reg, 0);
10381 }
10382
10383 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10384 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10385
215b30b3 10386 arith[0] = operands[0];
10387 arith[3] = operands[1];
94dee231 10388
215b30b3 10389 if (val1 < val2)
10390 {
10391 arith[1] = ldm[1];
10392 arith[2] = ldm[2];
10393 }
10394 else
10395 {
10396 arith[1] = ldm[2];
10397 arith[2] = ldm[1];
10398 }
94dee231 10399
10400 ldm[0] = base_reg;
10401 if (val1 !=0 && val2 != 0)
215b30b3 10402 {
cdb1295a 10403 rtx ops[3];
10404
94dee231 10405 if (val1 == 4 || val2 == 4)
10406 /* Other val must be 8, since we know they are adjacent and neither
10407 is zero. */
25f905c2 10408 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10409 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10410 {
94dee231 10411 ldm[0] = ops[0] = operands[4];
10412 ops[1] = base_reg;
10413 ops[2] = GEN_INT (val1);
10414 output_add_immediate (ops);
10415 if (val1 < val2)
25f905c2 10416 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10417 else
25f905c2 10418 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10419 }
cdb1295a 10420 else
10421 {
10422 /* Offset is out of range for a single add, so use two ldr. */
10423 ops[0] = ldm[1];
10424 ops[1] = base_reg;
10425 ops[2] = GEN_INT (val1);
10426 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10427 ops[0] = ldm[2];
10428 ops[2] = GEN_INT (val2);
10429 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10430 }
215b30b3 10431 }
94dee231 10432 else if (val1 != 0)
215b30b3 10433 {
215b30b3 10434 if (val1 < val2)
25f905c2 10435 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10436 else
25f905c2 10437 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10438 }
10439 else
10440 {
215b30b3 10441 if (val1 < val2)
25f905c2 10442 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10443 else
25f905c2 10444 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10445 }
10446 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10447 return \"\";
10448 }"
10449 [(set_attr "length" "12")
10450 (set_attr "predicable" "yes")
a2cd141b 10451 (set_attr "type" "load1")]
215b30b3 10452)
9c08d1fa 10453
9c08d1fa 10454; This pattern is never tried by combine, so do it as a peephole
10455
a0f94409 10456(define_peephole2
372575c7 10457 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10458 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10459 (set (reg:CC CC_REGNUM)
aea4c774 10460 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10461 "TARGET_ARM"
a0f94409 10462 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10463 (set (match_dup 0) (match_dup 1))])]
10464 ""
0d66636f 10465)
9c08d1fa 10466
675d848d 10467; Peepholes to spot possible load- and store-multiples, if the ordering is
10468; reversed, check that the memory references aren't volatile.
9c08d1fa 10469
10470(define_peephole
aaa37ad6 10471 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10472 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10473 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10474 (match_operand:SI 5 "memory_operand" "m"))
aaa37ad6 10475 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10476 (match_operand:SI 6 "memory_operand" "m"))
aaa37ad6 10477 (set (match_operand:SI 3 "s_register_operand" "=rk")
aea4c774 10478 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 10479 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10480 "*
10481 return emit_ldm_seq (operands, 4);
215b30b3 10482 "
10483)
9c08d1fa 10484
10485(define_peephole
aaa37ad6 10486 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10487 (match_operand:SI 3 "memory_operand" "m"))
aaa37ad6 10488 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10489 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10490 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10491 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 10492 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10493 "*
10494 return emit_ldm_seq (operands, 3);
215b30b3 10495 "
10496)
9c08d1fa 10497
10498(define_peephole
aaa37ad6 10499 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10500 (match_operand:SI 2 "memory_operand" "m"))
aaa37ad6 10501 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10502 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 10503 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10504 "*
10505 return emit_ldm_seq (operands, 2);
215b30b3 10506 "
10507)
9c08d1fa 10508
10509(define_peephole
aea4c774 10510 [(set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10511 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10512 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10513 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10514 (set (match_operand:SI 6 "memory_operand" "=m")
aaa37ad6 10515 (match_operand:SI 2 "s_register_operand" "rk"))
aea4c774 10516 (set (match_operand:SI 7 "memory_operand" "=m")
aaa37ad6 10517 (match_operand:SI 3 "s_register_operand" "rk"))]
cffb2a26 10518 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10519 "*
10520 return emit_stm_seq (operands, 4);
215b30b3 10521 "
10522)
9c08d1fa 10523
10524(define_peephole
aea4c774 10525 [(set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10526 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10527 (set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10528 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10529 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10530 (match_operand:SI 2 "s_register_operand" "rk"))]
cffb2a26 10531 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10532 "*
10533 return emit_stm_seq (operands, 3);
215b30b3 10534 "
10535)
9c08d1fa 10536
10537(define_peephole
aea4c774 10538 [(set (match_operand:SI 2 "memory_operand" "=m")
aaa37ad6 10539 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10540 (set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10541 (match_operand:SI 1 "s_register_operand" "rk"))]
cffb2a26 10542 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10543 "*
10544 return emit_stm_seq (operands, 2);
215b30b3 10545 "
10546)
9c08d1fa 10547
9c08d1fa 10548(define_split
10549 [(set (match_operand:SI 0 "s_register_operand" "")
10550 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10551 (const_int 0))
8fa3ba89 10552 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10553 [(match_operand:SI 3 "s_register_operand" "")
10554 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10555 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10556 "TARGET_ARM"
9c08d1fa 10557 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10558 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10559 (match_dup 5)))]
215b30b3 10560 ""
10561)
9c08d1fa 10562
aea4c774 10563;; This split can be used because CC_Z mode implies that the following
10564;; branch will be an equality, or an unsigned inequality, so the sign
10565;; extension is not needed.
9c08d1fa 10566
aea4c774 10567(define_split
bd5b4116 10568 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10569 (compare:CC_Z
10570 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10571 (const_int 24))
aea4c774 10572 (match_operand 1 "const_int_operand" "")))
10573 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10574 "TARGET_ARM
10575 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10576 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10577 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10578 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10579 "
9c08d1fa 10580 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10581 "
10582)
25f905c2 10583;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10584
87b22bf7 10585(define_expand "prologue"
10586 [(clobber (const_int 0))]
cffb2a26 10587 "TARGET_EITHER"
25f905c2 10588 "if (TARGET_32BIT)
cffb2a26 10589 arm_expand_prologue ();
10590 else
25f905c2 10591 thumb1_expand_prologue ();
87b22bf7 10592 DONE;
cffb2a26 10593 "
10594)
87b22bf7 10595
56d27660 10596(define_expand "epilogue"
4c44712e 10597 [(clobber (const_int 0))]
cffb2a26 10598 "TARGET_EITHER"
56d27660 10599 "
18d50ae6 10600 if (crtl->calls_eh_return)
4c44712e 10601 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10602 if (TARGET_THUMB1)
10603 thumb1_expand_epilogue ();
cffb2a26 10604 else if (USE_RETURN_INSN (FALSE))
56d27660 10605 {
10606 emit_jump_insn (gen_return ());
10607 DONE;
10608 }
cffb2a26 10609 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10610 gen_rtvec (1,
10611 gen_rtx_RETURN (VOIDmode)),
e1159bbe 10612 VUNSPEC_EPILOGUE));
cffb2a26 10613 DONE;
10614 "
10615)
56d27660 10616
ef5651d0 10617;; Note - although unspec_volatile's USE all hard registers,
10618;; USEs are ignored after relaod has completed. Thus we need
10619;; to add an unspec of the link register to ensure that flow
10620;; does not think that it is unused by the sibcall branch that
10621;; will replace the standard function epilogue.
1c494086 10622(define_insn "sibcall_epilogue"
ef5651d0 10623 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10624 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10625 "TARGET_32BIT"
1c494086 10626 "*
ffc9d00c 10627 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10628 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10629 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10630 "
10631;; Length is absolute worst case
10632 [(set_attr "length" "44")
defc47cf 10633 (set_attr "type" "block")
10634 ;; We don't clobber the conditions, but the potential length of this
10635 ;; operation is sufficient to make conditionalizing the sequence
10636 ;; unlikely to be profitable.
10637 (set_attr "conds" "clob")]
1c494086 10638)
10639
cffb2a26 10640(define_insn "*epilogue_insns"
e1159bbe 10641 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10642 "TARGET_EITHER"
56d27660 10643 "*
25f905c2 10644 if (TARGET_32BIT)
ffc9d00c 10645 return arm_output_epilogue (NULL);
25f905c2 10646 else /* TARGET_THUMB1 */
cffb2a26 10647 return thumb_unexpanded_epilogue ();
10648 "
215b30b3 10649 ; Length is absolute worst case
cffb2a26 10650 [(set_attr "length" "44")
defc47cf 10651 (set_attr "type" "block")
10652 ;; We don't clobber the conditions, but the potential length of this
10653 ;; operation is sufficient to make conditionalizing the sequence
10654 ;; unlikely to be profitable.
10655 (set_attr "conds" "clob")]
cffb2a26 10656)
10657
10658(define_expand "eh_epilogue"
7db9af5d 10659 [(use (match_operand:SI 0 "register_operand" ""))
10660 (use (match_operand:SI 1 "register_operand" ""))
10661 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10662 "TARGET_EITHER"
10663 "
215b30b3 10664 {
10665 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10666 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10667 {
10668 rtx ra = gen_rtx_REG (Pmode, 2);
10669
10670 emit_move_insn (ra, operands[2]);
10671 operands[2] = ra;
10672 }
5cf3595a 10673 /* This is a hack -- we may have crystalized the function type too
10674 early. */
10675 cfun->machine->func_type = 0;
215b30b3 10676 }"
10677)
56d27660 10678
9c08d1fa 10679;; This split is only used during output to reduce the number of patterns
10680;; that need assembler instructions adding to them. We allowed the setting
10681;; of the conditions to be implicit during rtl generation so that
10682;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10683;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10684;; up again here.
10685
25f905c2 10686;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10687;; conditional execution sufficient?
10688
9c08d1fa 10689(define_split
10690 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10691 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10692 [(match_operand 2 "" "") (match_operand 3 "" "")])
10693 (match_dup 0)
10694 (match_operand 4 "" "")))
bd5b4116 10695 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10696 "TARGET_ARM && reload_completed"
8fa3ba89 10697 [(set (match_dup 5) (match_dup 6))
10698 (cond_exec (match_dup 7)
10699 (set (match_dup 0) (match_dup 4)))]
10700 "
10701 {
10702 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10703 operands[2], operands[3]);
10704 enum rtx_code rc = GET_CODE (operands[1]);
10705
bd5b4116 10706 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10707 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10708 if (mode == CCFPmode || mode == CCFPEmode)
10709 rc = reverse_condition_maybe_unordered (rc);
10710 else
10711 rc = reverse_condition (rc);
10712
10713 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10714 }"
10715)
10716
10717(define_split
10718 [(set (match_operand:SI 0 "s_register_operand" "")
10719 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10720 [(match_operand 2 "" "") (match_operand 3 "" "")])
10721 (match_operand 4 "" "")
10722 (match_dup 0)))
bd5b4116 10723 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10724 "TARGET_ARM && reload_completed"
8fa3ba89 10725 [(set (match_dup 5) (match_dup 6))
10726 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10727 (set (match_dup 0) (match_dup 4)))]
10728 "
10729 {
10730 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10731 operands[2], operands[3]);
10732
bd5b4116 10733 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10734 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10735 }"
10736)
10737
10738(define_split
10739 [(set (match_operand:SI 0 "s_register_operand" "")
10740 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10741 [(match_operand 2 "" "") (match_operand 3 "" "")])
10742 (match_operand 4 "" "")
10743 (match_operand 5 "" "")))
bd5b4116 10744 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10745 "TARGET_ARM && reload_completed"
8fa3ba89 10746 [(set (match_dup 6) (match_dup 7))
10747 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10748 (set (match_dup 0) (match_dup 4)))
10749 (cond_exec (match_dup 8)
10750 (set (match_dup 0) (match_dup 5)))]
10751 "
10752 {
10753 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10754 operands[2], operands[3]);
10755 enum rtx_code rc = GET_CODE (operands[1]);
10756
bd5b4116 10757 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10758 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10759 if (mode == CCFPmode || mode == CCFPEmode)
10760 rc = reverse_condition_maybe_unordered (rc);
10761 else
10762 rc = reverse_condition (rc);
10763
10764 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10765 }"
10766)
10767
cffb2a26 10768(define_split
10769 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10770 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10771 [(match_operand:SI 2 "s_register_operand" "")
10772 (match_operand:SI 3 "arm_add_operand" "")])
10773 (match_operand:SI 4 "arm_rhs_operand" "")
10774 (not:SI
10775 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10776 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10777 "TARGET_ARM && reload_completed"
cffb2a26 10778 [(set (match_dup 6) (match_dup 7))
f6c53574 10779 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10780 (set (match_dup 0) (match_dup 4)))
10781 (cond_exec (match_dup 8)
10782 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10783 "
215b30b3 10784 {
10785 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10786 operands[2], operands[3]);
f6c53574 10787 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10788
bd5b4116 10789 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10790 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10791 if (mode == CCFPmode || mode == CCFPEmode)
10792 rc = reverse_condition_maybe_unordered (rc);
10793 else
10794 rc = reverse_condition (rc);
10795
10796 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10797 }"
10798)
cffb2a26 10799
10800(define_insn "*cond_move_not"
10801 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10802 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10803 [(match_operand 3 "cc_register" "") (const_int 0)])
10804 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10805 (not:SI
10806 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10807 "TARGET_ARM"
10808 "@
10809 mvn%D4\\t%0, %2
10810 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10811 [(set_attr "conds" "use")
10812 (set_attr "length" "4,8")]
10813)
cffb2a26 10814
9c08d1fa 10815;; The next two patterns occur when an AND operation is followed by a
10816;; scc insn sequence
10817
f7fbdd4a 10818(define_insn "*sign_extract_onebit"
9c08d1fa 10819 [(set (match_operand:SI 0 "s_register_operand" "=r")
10820 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10821 (const_int 1)
ed750274 10822 (match_operand:SI 2 "const_int_operand" "n")))
10823 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10824 "TARGET_ARM"
9c08d1fa 10825 "*
0d66636f 10826 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10827 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10828 return \"mvnne\\t%0, #0\";
10829 "
10830 [(set_attr "conds" "clob")
10831 (set_attr "length" "8")]
10832)
9c08d1fa 10833
f7fbdd4a 10834(define_insn "*not_signextract_onebit"
9c08d1fa 10835 [(set (match_operand:SI 0 "s_register_operand" "=r")
10836 (not:SI
10837 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10838 (const_int 1)
ed750274 10839 (match_operand:SI 2 "const_int_operand" "n"))))
10840 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10841 "TARGET_ARM"
9c08d1fa 10842 "*
0d66636f 10843 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10844 output_asm_insn (\"tst\\t%1, %2\", operands);
10845 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10846 return \"movne\\t%0, #0\";
10847 "
10848 [(set_attr "conds" "clob")
10849 (set_attr "length" "12")]
10850)
25f905c2 10851;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10852
0d66636f 10853;; Push multiple registers to the stack. Registers are in parallel (use ...)
10854;; expressions. For simplicity, the first register is also in the unspec
10855;; part.
f7fbdd4a 10856(define_insn "*push_multi"
87b22bf7 10857 [(match_parallel 2 "multi_register_push"
10858 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10859 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10860 UNSPEC_PUSH_MULT))])]
25f905c2 10861 "TARGET_32BIT"
87b22bf7 10862 "*
215b30b3 10863 {
10864 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10865
215b30b3 10866 /* For the StrongARM at least it is faster to
25f905c2 10867 use STR to store only a single register.
542d5028 10868 In Thumb mode always use push, and the assembler will pick
10869 something appropriate. */
25f905c2 10870 if (num_saves == 1 && TARGET_ARM)
215b30b3 10871 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10872 else
10873 {
10874 int i;
10875 char pattern[100];
ed593f11 10876
25f905c2 10877 if (TARGET_ARM)
10878 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10879 else
10880 strcpy (pattern, \"push\\t{%1\");
215b30b3 10881
6079f055 10882 for (i = 1; i < num_saves; i++)
215b30b3 10883 {
10884 strcat (pattern, \", %|\");
10885 strcat (pattern,
10886 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10887 }
10888
10889 strcat (pattern, \"}\");
10890 output_asm_insn (pattern, operands);
10891 }
10892
10893 return \"\";
10894 }"
10895 [(set_attr "type" "store4")]
10896)
f7fbdd4a 10897
4c58c898 10898(define_insn "stack_tie"
10899 [(set (mem:BLK (scratch))
aaa37ad6 10900 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10901 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10902 UNSPEC_PRLG_STK))]
10903 ""
10904 ""
10905 [(set_attr "length" "0")]
10906)
10907
3398e91d 10908;; Similarly for the floating point registers
7b1d2fc4 10909(define_insn "*push_fp_multi"
10910 [(match_parallel 2 "multi_register_push"
10911 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10912 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10913 UNSPEC_PUSH_MULT))])]
25f905c2 10914 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10915 "*
215b30b3 10916 {
10917 char pattern[100];
7b1d2fc4 10918
215b30b3 10919 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10920 output_asm_insn (pattern, operands);
10921 return \"\";
10922 }"
10923 [(set_attr "type" "f_store")]
10924)
7b1d2fc4 10925
f7fbdd4a 10926;; Special patterns for dealing with the constant pool
10927
cffb2a26 10928(define_insn "align_4"
e1159bbe 10929 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10930 "TARGET_EITHER"
f7fbdd4a 10931 "*
cffb2a26 10932 assemble_align (32);
f7fbdd4a 10933 return \"\";
cffb2a26 10934 "
10935)
f7fbdd4a 10936
755eb2b4 10937(define_insn "align_8"
10938 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10939 "TARGET_EITHER"
755eb2b4 10940 "*
10941 assemble_align (64);
10942 return \"\";
10943 "
10944)
10945
cffb2a26 10946(define_insn "consttable_end"
e1159bbe 10947 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10948 "TARGET_EITHER"
f7fbdd4a 10949 "*
cffb2a26 10950 making_const_table = FALSE;
f7fbdd4a 10951 return \"\";
cffb2a26 10952 "
10953)
f7fbdd4a 10954
cffb2a26 10955(define_insn "consttable_1"
e1159bbe 10956 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10957 "TARGET_THUMB1"
f7fbdd4a 10958 "*
cffb2a26 10959 making_const_table = TRUE;
09d688ff 10960 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10961 assemble_zeros (3);
f7fbdd4a 10962 return \"\";
cffb2a26 10963 "
10964 [(set_attr "length" "4")]
10965)
f7fbdd4a 10966
cffb2a26 10967(define_insn "consttable_2"
e1159bbe 10968 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10969 "TARGET_THUMB1"
f7fbdd4a 10970 "*
cffb2a26 10971 making_const_table = TRUE;
9b8516be 10972 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10973 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10974 assemble_zeros (2);
f7fbdd4a 10975 return \"\";
cffb2a26 10976 "
10977 [(set_attr "length" "4")]
10978)
10979
10980(define_insn "consttable_4"
e1159bbe 10981 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10982 "TARGET_EITHER"
10983 "*
10984 {
9b8516be 10985 rtx x = operands[0];
cffb2a26 10986 making_const_table = TRUE;
9b8516be 10987 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10988 {
10989 case MODE_FLOAT:
9b8516be 10990 if (GET_MODE (x) == HFmode)
10991 arm_emit_fp16_const (x);
10992 else
10993 {
10994 REAL_VALUE_TYPE r;
10995 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10996 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10997 }
10998 break;
cffb2a26 10999 default:
7b04c5d5 11000 /* XXX: Sometimes gcc does something really dumb and ends up with
11001 a HIGH in a constant pool entry, usually because it's trying to
11002 load into a VFP register. We know this will always be used in
11003 combination with a LO_SUM which ignores the high bits, so just
11004 strip off the HIGH. */
11005 if (GET_CODE (x) == HIGH)
11006 x = XEXP (x, 0);
9b8516be 11007 assemble_integer (x, 4, BITS_PER_WORD, 1);
11008 mark_symbol_refs_as_used (x);
cffb2a26 11009 break;
11010 }
11011 return \"\";
11012 }"
11013 [(set_attr "length" "4")]
11014)
11015
11016(define_insn "consttable_8"
e1159bbe 11017 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11018 "TARGET_EITHER"
11019 "*
11020 {
11021 making_const_table = TRUE;
11022 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11023 {
11024 case MODE_FLOAT:
11025 {
badfe841 11026 REAL_VALUE_TYPE r;
11027 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11028 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 11029 break;
11030 }
11031 default:
09d688ff 11032 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11033 break;
11034 }
11035 return \"\";
11036 }"
11037 [(set_attr "length" "8")]
11038)
11039
d98a3884 11040(define_insn "consttable_16"
11041 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11042 "TARGET_EITHER"
11043 "*
11044 {
11045 making_const_table = TRUE;
11046 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11047 {
11048 case MODE_FLOAT:
11049 {
11050 REAL_VALUE_TYPE r;
11051 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11052 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11053 break;
11054 }
11055 default:
11056 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11057 break;
11058 }
11059 return \"\";
11060 }"
11061 [(set_attr "length" "16")]
11062)
11063
cffb2a26 11064;; Miscellaneous Thumb patterns
11065
fd957ef3 11066(define_expand "tablejump"
7db9af5d 11067 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 11068 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 11069 "TARGET_THUMB1"
fd957ef3 11070 "
11071 if (flag_pic)
11072 {
11073 /* Hopefully, CSE will eliminate this copy. */
11074 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11075 rtx reg2 = gen_reg_rtx (SImode);
11076
11077 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11078 operands[0] = reg2;
11079 }
11080 "
11081)
11082
f1039640 11083;; NB never uses BX.
25f905c2 11084(define_insn "*thumb1_tablejump"
cffb2a26 11085 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11086 (use (label_ref (match_operand 1 "" "")))]
25f905c2 11087 "TARGET_THUMB1"
fd957ef3 11088 "mov\\t%|pc, %0"
cffb2a26 11089 [(set_attr "length" "2")]
11090)
0d66636f 11091
331beb1a 11092;; V5 Instructions,
11093
8f4be2be 11094(define_insn "clzsi2"
11095 [(set (match_operand:SI 0 "s_register_operand" "=r")
11096 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11097 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11098 "clz%?\\t%0, %1"
bcaec148 11099 [(set_attr "predicable" "yes")
11100 (set_attr "insn" "clz")])
331beb1a 11101
099ad98b 11102(define_insn "rbitsi2"
11103 [(set (match_operand:SI 0 "s_register_operand" "=r")
11104 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11105 "TARGET_32BIT && arm_arch_thumb2"
11106 "rbit%?\\t%0, %1"
11107 [(set_attr "predicable" "yes")
11108 (set_attr "insn" "clz")])
11109
11110(define_expand "ctzsi2"
11111 [(set (match_operand:SI 0 "s_register_operand" "")
11112 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
11113 "TARGET_32BIT && arm_arch_thumb2"
11114 "
30191172 11115 {
11116 rtx tmp = gen_reg_rtx (SImode);
11117 emit_insn (gen_rbitsi2 (tmp, operands[1]));
11118 emit_insn (gen_clzsi2 (operands[0], tmp));
11119 }
099ad98b 11120 DONE;
11121 "
11122)
11123
e1159bbe 11124;; V5E instructions.
331beb1a 11125
11126(define_insn "prefetch"
f4e79814 11127 [(prefetch (match_operand:SI 0 "address_operand" "p")
11128 (match_operand:SI 1 "" "")
11129 (match_operand:SI 2 "" ""))]
25f905c2 11130 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 11131 "pld\\t%a0")
331beb1a 11132
0d66636f 11133;; General predication pattern
11134
11135(define_cond_exec
11136 [(match_operator 0 "arm_comparison_operator"
11137 [(match_operand 1 "cc_register" "")
11138 (const_int 0)])]
25f905c2 11139 "TARGET_32BIT"
0d66636f 11140 ""
11141)
11142
063a05c7 11143(define_insn "prologue_use"
11144 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11145 ""
11146 "%@ %0 needed for prologue"
02cfc9c9 11147 [(set_attr "length" "0")]
063a05c7 11148)
7db9af5d 11149
4c44712e 11150
11151;; Patterns for exception handling
11152
11153(define_expand "eh_return"
11154 [(use (match_operand 0 "general_operand" ""))]
11155 "TARGET_EITHER"
11156 "
11157 {
25f905c2 11158 if (TARGET_32BIT)
4c44712e 11159 emit_insn (gen_arm_eh_return (operands[0]));
11160 else
11161 emit_insn (gen_thumb_eh_return (operands[0]));
11162 DONE;
11163 }"
11164)
11165
11166;; We can't expand this before we know where the link register is stored.
11167(define_insn_and_split "arm_eh_return"
11168 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11169 VUNSPEC_EH_RETURN)
11170 (clobber (match_scratch:SI 1 "=&r"))]
11171 "TARGET_ARM"
11172 "#"
11173 "&& reload_completed"
11174 [(const_int 0)]
11175 "
11176 {
11177 arm_set_return_address (operands[0], operands[1]);
11178 DONE;
11179 }"
11180)
11181
11182(define_insn_and_split "thumb_eh_return"
11183 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11184 VUNSPEC_EH_RETURN)
11185 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 11186 "TARGET_THUMB1"
4c44712e 11187 "#"
11188 "&& reload_completed"
11189 [(const_int 0)]
11190 "
11191 {
11192 thumb_set_return_address (operands[0], operands[1]);
11193 DONE;
11194 }"
11195)
11196
f655717d 11197\f
11198;; TLS support
11199
11200(define_insn "load_tp_hard"
11201 [(set (match_operand:SI 0 "register_operand" "=r")
11202 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11203 "TARGET_HARD_TP"
11204 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11205 [(set_attr "predicable" "yes")]
11206)
11207
11208;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11209(define_insn "load_tp_soft"
11210 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11211 (clobber (reg:SI LR_REGNUM))
11212 (clobber (reg:SI IP_REGNUM))
11213 (clobber (reg:CC CC_REGNUM))]
11214 "TARGET_SOFT_TP"
11215 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11216 [(set_attr "conds" "clob")]
11217)
11218
eca5c984 11219(define_insn "*arm_movtas_ze"
11220 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11221 (const_int 16)
11222 (const_int 16))
11223 (match_operand:SI 1 "const_int_operand" ""))]
11224 "TARGET_32BIT"
11225 "movt%?\t%0, %c1"
11226 [(set_attr "predicable" "yes")
11227 (set_attr "length" "4")]
11228)
11229
ff82f757 11230(define_insn "arm_rev"
11231 [(set (match_operand:SI 0 "s_register_operand" "=r")
11232 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11233 "TARGET_EITHER && arm_arch6"
11234 "rev\t%0, %1"
11235 [(set (attr "length")
11236 (if_then_else (eq_attr "is_thumb" "yes")
11237 (const_int 2)
11238 (const_int 4)))]
11239)
11240
11241(define_expand "arm_legacy_rev"
11242 [(set (match_operand:SI 2 "s_register_operand" "")
11243 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11244 (const_int 16))
11245 (match_dup 1)))
11246 (set (match_dup 2)
11247 (lshiftrt:SI (match_dup 2)
11248 (const_int 8)))
11249 (set (match_operand:SI 3 "s_register_operand" "")
11250 (rotatert:SI (match_dup 1)
11251 (const_int 8)))
11252 (set (match_dup 2)
11253 (and:SI (match_dup 2)
11254 (const_int -65281)))
11255 (set (match_operand:SI 0 "s_register_operand" "")
11256 (xor:SI (match_dup 3)
11257 (match_dup 2)))]
11258 "TARGET_32BIT"
11259 ""
11260)
11261
11262;; Reuse temporaries to keep register pressure down.
11263(define_expand "thumb_legacy_rev"
11264 [(set (match_operand:SI 2 "s_register_operand" "")
11265 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11266 (const_int 24)))
11267 (set (match_operand:SI 3 "s_register_operand" "")
11268 (lshiftrt:SI (match_dup 1)
11269 (const_int 24)))
11270 (set (match_dup 3)
11271 (ior:SI (match_dup 3)
11272 (match_dup 2)))
11273 (set (match_operand:SI 4 "s_register_operand" "")
11274 (const_int 16))
11275 (set (match_operand:SI 5 "s_register_operand" "")
11276 (rotatert:SI (match_dup 1)
11277 (match_dup 4)))
11278 (set (match_dup 2)
11279 (ashift:SI (match_dup 5)
11280 (const_int 24)))
11281 (set (match_dup 5)
11282 (lshiftrt:SI (match_dup 5)
11283 (const_int 24)))
11284 (set (match_dup 5)
11285 (ior:SI (match_dup 5)
11286 (match_dup 2)))
11287 (set (match_dup 5)
11288 (rotatert:SI (match_dup 5)
11289 (match_dup 4)))
11290 (set (match_operand:SI 0 "s_register_operand" "")
11291 (ior:SI (match_dup 5)
11292 (match_dup 3)))]
11293 "TARGET_THUMB"
11294 ""
11295)
11296
11297(define_expand "bswapsi2"
11298 [(set (match_operand:SI 0 "s_register_operand" "=r")
11299 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11300"TARGET_EITHER"
11301"
11302 if (!arm_arch6)
11303 {
11304 if (!optimize_size)
11305 {
11306 rtx op2 = gen_reg_rtx (SImode);
11307 rtx op3 = gen_reg_rtx (SImode);
11308
11309 if (TARGET_THUMB)
11310 {
11311 rtx op4 = gen_reg_rtx (SImode);
11312 rtx op5 = gen_reg_rtx (SImode);
11313
11314 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11315 op2, op3, op4, op5));
11316 }
11317 else
11318 {
11319 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11320 op2, op3));
11321 }
11322
11323 DONE;
11324 }
11325 else
11326 FAIL;
11327 }
11328 "
11329)
11330
7db9af5d 11331;; Load the FPA co-processor patterns
11332(include "fpa.md")
11333;; Load the Maverick co-processor patterns
11334(include "cirrus.md")
d98a3884 11335;; Vector bits common to IWMMXT and Neon
11336(include "vec-common.md")
755eb2b4 11337;; Load the Intel Wireless Multimedia Extension patterns
11338(include "iwmmxt.md")
a2cd141b 11339;; Load the VFP co-processor patterns
11340(include "vfp.md")
25f905c2 11341;; Thumb-2 patterns
11342(include "thumb2.md")
d98a3884 11343;; Neon patterns
11344(include "neon.md")
a2cd141b 11345