]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* config/i386/predicates.md (call_register_no_elim_operand):
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
cfaf579d 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
934a1e72 4;; Free Software Foundation, Inc.
b11cae9e 5;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 6;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 7;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 8
acf6ed70 9;; This file is part of GCC.
b11cae9e 10
acf6ed70 11;; GCC is free software; you can redistribute it and/or modify it
12;; under the terms of the GNU General Public License as published
038d1e19 13;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 14;; option) any later version.
b11cae9e 15
acf6ed70 16;; GCC is distributed in the hope that it will be useful, but WITHOUT
17;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19;; License for more details.
b11cae9e 20
21;; You should have received a copy of the GNU General Public License
038d1e19 22;; along with GCC; see the file COPYING3. If not see
23;; <http://www.gnu.org/licenses/>.
b11cae9e 24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
9c08d1fa 27\f
e1159bbe 28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
ccd90aaa 33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
e1159bbe 35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
ccd90aaa 39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
e1159bbe 51
9c08d1fa 52;; UNSPEC Usage:
8a18b90c 53;; Note: sin and cos are no-longer used.
d98a3884 54;; Unspec constants for Neon are defined in neon.md.
e1159bbe 55
56(define_constants
57 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
58 ; operand 0 is the result,
59 ; operand 1 the parameter.
60 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
61 ; operand 0 is the result,
62 ; operand 1 the parameter.
63 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
64 ; operand 0 is the first register,
65 ; subsequent registers are in parallel (use ...)
66 ; expressions.
67 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
68 ; usage, that is, we will add the pic_register
69 ; value to it before trying to dereference it.
c0c1fba5 70 (UNSPEC_PIC_BASE 4) ; Add PC and all but the last operand together,
71 ; The last operand is the number of a PIC_LABEL
72 ; that points at the containing instruction.
2c96dc5a 73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
e1159bbe 74 ; being scheduled before the stack adjustment insn.
063a05c7 75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
79 ; register to "use".
68121397 80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
8d232dc7 81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
f655717d 93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
6cdcb15c 94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95 ; instruction stream.
2c2d2f40 96 (UNSPEC_STACK_ALIGN 22) ; Doubleword aligned stack pointer. Used to
25f905c2 97 ; generate correct unwind information.
2c2d2f40 98 (UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
bac7fc85 99 ; correctly for PIC usage.
c0c1fba5 100 (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
101 ; a given symbolic address.
e6ac8414 102 (UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
099ad98b 103 (UNSPEC_RBIT 26) ; rbit operation.
e1159bbe 104 ]
105)
106
215b30b3 107;; UNSPEC_VOLATILE Usage:
e1159bbe 108
109(define_constants
110 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
111 ; insn in the code.
112 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
113 ; instruction epilogue sequence that isn't expanded
114 ; into normal RTL. Used for both normal and sibcall
115 ; epilogues.
116 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
117 ; for inlined constants.
118 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
119 ; table.
120 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
121 ; an 8-bit object.
122 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
123 ; a 16-bit object.
124 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
125 ; a 32-bit object.
126 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
127 ; a 64-bit object.
d98a3884 128 (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
129 ; a 128-bit object.
130 (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
131 (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
132 (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
133 (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
134 (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
135 (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 136 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 137 ; handling.
e1159bbe 138 ]
139)
b11cae9e 140\f
e1159bbe 141;;---------------------------------------------------------------------------
9c08d1fa 142;; Attributes
143
215b30b3 144; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
145; generating ARM code. This is used to control the length of some insn
146; patterns that share the same RTL in both ARM and Thumb code.
1c494086 147(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 148
215b30b3 149; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
150; scheduling decisions for the load unit and the multiplier.
74a71f7d 151(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
9c08d1fa 152
5ecb8da7 153; IS_XSCALE is set to 'yes' when compiling for XScale.
154(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
155
331beb1a 156;; Operand number of an input operand that is shifted. Zero if the
157;; given instruction does not shift one of its input operands.
331beb1a 158(define_attr "shift" "" (const_int 0))
159
3d91c5d6 160; Floating Point Unit. If we only have floating point emulation, then there
161; is no point in scheduling the floating point insns. (Well, for best
162; performance we should try and group them together).
4fea7d65 163(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 164 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 165
094e994f 166; LENGTH of an instruction (in bytes)
167(define_attr "length" "" (const_int 4))
9c08d1fa 168
56d27660 169; POOL_RANGE is how far away from a constant pool entry that this insn
170; can be placed. If the distance is zero, then this insn will never
171; reference the pool.
cffb2a26 172; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
173; before its address.
56d27660 174(define_attr "pool_range" "" (const_int 0))
cffb2a26 175(define_attr "neg_pool_range" "" (const_int 0))
56d27660 176
215b30b3 177; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 178; If such an insn references the pool, then we have no way of knowing how,
179; so use the most conservative value for pool_range.
9c08d1fa 180(define_asm_attributes
4d7a8451 181 [(set_attr "conds" "clob")
182 (set_attr "length" "4")
183 (set_attr "pool_range" "250")])
9c08d1fa 184
a2cd141b 185;; The instruction used to implement a particular pattern. This
186;; information is used by pipeline descriptions to provide accurate
187;; scheduling information.
188
189(define_attr "insn"
934a1e72 190 "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 191 (const_string "other"))
192
9c08d1fa 193; TYPE attribute is used to detect floating point instructions which, if
194; running on a co-processor can run in parallel with other, basic instructions
195; If write-buffer scheduling is enabled then it can also be used in the
196; scheduling of writes.
197
198; Classification of each insn
607978a1 199; Note: vfp.md has different meanings for some of these, and some further
200; types as well. See that file for details.
a2cd141b 201; alu any alu instruction that doesn't hit memory or fp
202; regs or have a shifted source operand
203; alu_shift any data instruction that doesn't hit memory or fp
204; regs, but has a source operand shifted by a constant
205; alu_shift_reg any data instruction that doesn't hit memory or fp
206; regs, but has a source operand shifted by a register value
f7fbdd4a 207; mult a multiply instruction
9c08d1fa 208; block blockage insn, this blocks all functional units
209; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 210; fdivd DFmode floating point division
211; fdivs SFmode floating point division
212; fmul Floating point multiply
213; ffmul Fast floating point multiply
214; farith Floating point arithmetic (4 cycle)
215; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 216; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 217; even on a machine with an fpa.
9c08d1fa 218; f_load a floating point load from memory
219; f_store a floating point store to memory
9aff9709 220; f_load[sd] single/double load from memory
221; f_store[sd] single/double store to memory
c0e1af52 222; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 223; f_mem_r a transfer of a floating point register to a real reg via mem
224; r_mem_f the reverse of f_mem_r
225; f_2_r fast transfer float to arm (no memory needed)
226; r_2_f fast transfer arm to float
c0e1af52 227; f_cvt convert floating<->integral
a2cd141b 228; branch a branch
9c08d1fa 229; call a subroutine call
a2cd141b 230; load_byte load byte(s) from memory to arm registers
231; load1 load 1 word from memory to arm registers
232; load2 load 2 words from memory to arm registers
233; load3 load 3 words from memory to arm registers
234; load4 load 4 words from memory to arm registers
235; store store 1 word to memory from arm registers
9c08d1fa 236; store2 store 2 words
237; store3 store 3 words
a2cd141b 238; store4 store 4 (or more) words
2c6c7d8b 239; Additions for Cirrus Maverick co-processor:
240; mav_farith Floating point arithmetic (4 cycle)
241; mav_dmult Double multiplies (7 cycle)
9c08d1fa 242;
bcaec148 243
9c08d1fa 244(define_attr "type"
e3879fd0 245 "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 246 (if_then_else
247 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
248 (const_string "mult")
249 (const_string "alu")))
9c08d1fa 250
9888ad6d 251; Load scheduling, set from the arm_ld_sched variable
457275b6 252; initialized by arm_override_options()
9888ad6d 253(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 254
c52acdd2 255;; Classification of NEON instructions for scheduling purposes.
256;; Do not set this attribute and the "type" attribute together in
257;; any one instruction pattern.
258(define_attr "neon_type"
259 "neon_int_1,\
260 neon_int_2,\
261 neon_int_3,\
262 neon_int_4,\
263 neon_int_5,\
264 neon_vqneg_vqabs,\
265 neon_vmov,\
266 neon_vaba,\
267 neon_vsma,\
268 neon_vaba_qqq,\
269 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
270 neon_mul_qqq_8_16_32_ddd_32,\
271 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
272 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
273 neon_mla_qqq_8_16,\
274 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
275 neon_mla_qqq_32_qqd_32_scalar,\
276 neon_mul_ddd_16_scalar_32_16_long_scalar,\
277 neon_mul_qqd_32_scalar,\
278 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
279 neon_shift_1,\
280 neon_shift_2,\
281 neon_shift_3,\
282 neon_vshl_ddd,\
283 neon_vqshl_vrshl_vqrshl_qqq,\
284 neon_vsra_vrsra,\
285 neon_fp_vadd_ddd_vabs_dd,\
286 neon_fp_vadd_qqq_vabs_qq,\
287 neon_fp_vsum,\
288 neon_fp_vmul_ddd,\
289 neon_fp_vmul_qqd,\
290 neon_fp_vmla_ddd,\
291 neon_fp_vmla_qqq,\
292 neon_fp_vmla_ddd_scalar,\
293 neon_fp_vmla_qqq_scalar,\
294 neon_fp_vrecps_vrsqrts_ddd,\
295 neon_fp_vrecps_vrsqrts_qqq,\
296 neon_bp_simple,\
297 neon_bp_2cycle,\
298 neon_bp_3cycle,\
299 neon_ldr,\
300 neon_str,\
301 neon_vld1_1_2_regs,\
302 neon_vld1_3_4_regs,\
303 neon_vld2_2_regs_vld1_vld2_all_lanes,\
304 neon_vld2_4_regs,\
305 neon_vld3_vld4,\
306 neon_vst1_1_2_regs_vst2_2_regs,\
307 neon_vst1_3_4_regs,\
308 neon_vst2_4_regs_vst3_vst4,\
309 neon_vst3_vst4,\
310 neon_vld1_vld2_lane,\
311 neon_vld3_vld4_lane,\
312 neon_vst1_vst2_lane,\
313 neon_vst3_vst4_lane,\
314 neon_vld3_vld4_all_lanes,\
315 neon_mcr,\
316 neon_mcr_2_mcrr,\
317 neon_mrc,\
318 neon_mrrc,\
319 neon_ldm_2,\
320 neon_stm_2,\
321 none"
322 (const_string "none"))
323
f7fbdd4a 324; condition codes: this one is used by final_prescan_insn to speed up
325; conditionalizing instructions. It saves having to scan the rtl to see if
326; it uses or alters the condition codes.
215b30b3 327;
f7fbdd4a 328; USE means that the condition codes are used by the insn in the process of
215b30b3 329; outputting code, this means (at present) that we can't use the insn in
330; inlined branches
331;
f7fbdd4a 332; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 333; well defined manner.
334;
f7fbdd4a 335; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 336; they are altered at all
337;
c52acdd2 338; UNCONDITIONAL means the instions can not be conditionally executed.
339;
f7fbdd4a 340; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 341; output of this insn
f7fbdd4a 342
b0694be0 343(define_attr "conds" "use,set,clob,unconditional,nocond"
f7fbdd4a 344 (if_then_else (eq_attr "type" "call")
c1a66faf 345 (const_string "clob")
c52acdd2 346 (if_then_else (eq_attr "neon_type" "none")
347 (const_string "nocond")
348 (const_string "unconditional"))))
f7fbdd4a 349
215b30b3 350; Predicable means that the insn can be conditionally executed based on
351; an automatically added predicate (additional patterns are generated by
352; gen...). We default to 'no' because no Thumb patterns match this rule
353; and not all ARM patterns do.
0d66636f 354(define_attr "predicable" "no,yes" (const_string "no"))
355
129a2fe4 356; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
357; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 358; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 359; affect the schedule).
74a71f7d 360(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 361
215b30b3 362; WRITE_CONFLICT implies that a read following an unrelated write is likely
363; to stall the processor. Used with model_wbuf above.
9c08d1fa 364(define_attr "write_conflict" "no,yes"
365 (if_then_else (eq_attr "type"
a2cd141b 366 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 367 (const_string "yes")
368 (const_string "no")))
369
215b30b3 370; Classify the insns into those that take one cycle and those that take more
371; than one on the main cpu execution unit.
f7fbdd4a 372(define_attr "core_cycles" "single,multi"
373 (if_then_else (eq_attr "type"
a2cd141b 374 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 375 (const_string "single")
376 (const_string "multi")))
377
cffb2a26 378;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 379;; distant label. Only applicable to Thumb code.
cffb2a26 380(define_attr "far_jump" "yes,no" (const_string "no"))
381
d51f92df 382
25f905c2 383;; The number of machine instructions this pattern expands to.
384;; Used for Thumb-2 conditional execution.
385(define_attr "ce_count" "" (const_int 1))
386
d51f92df 387;;---------------------------------------------------------------------------
fd781bb2 388;; Mode iterators
d51f92df 389
390; A list of modes that are exactly 64 bits in size. We use this to expand
391; some splits that are the same for all modes when operating on ARM
392; registers.
fd781bb2 393(define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
d51f92df 394
03770691 395;; The integer modes up to word size
396(define_mode_iterator QHSI [QI HI SI])
397
d51f92df 398;;---------------------------------------------------------------------------
399;; Predicates
400
9c9db025 401(include "predicates.md")
234f6557 402(include "constraints.md")
9c9db025 403
a2cd141b 404;;---------------------------------------------------------------------------
405;; Pipeline descriptions
215b30b3 406
06469f9e 407;; Processor type. This is created automatically from arm-cores.def.
408(include "arm-tune.md")
331beb1a 409
e3879fd0 410(define_attr "tune_cortexr4" "yes,no"
411 (const (if_then_else
412 (eq_attr "tune" "cortexr4,cortexr4f")
413 (const_string "yes")
414 (const_string "no"))))
415
a2cd141b 416;; True if the generic scheduling description should be used.
417
418(define_attr "generic_sched" "yes,no"
4d5cb40d 419 (const (if_then_else
036068af 420 (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
e3879fd0 421 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 422 (const_string "no")
423 (const_string "yes"))))
424
c0e1af52 425(define_attr "generic_vfp" "yes,no"
426 (const (if_then_else
427 (and (eq_attr "fpu" "vfp")
036068af 428 (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
e3879fd0 429 (eq_attr "tune_cortexr4" "no"))
c0e1af52 430 (const_string "yes")
431 (const_string "no"))))
432
a2cd141b 433(include "arm-generic.md")
434(include "arm926ejs.md")
c0e1af52 435(include "arm1020e.md")
a2cd141b 436(include "arm1026ejs.md")
437(include "arm1136jfs.md")
bcaec148 438(include "cortex-a8.md")
036068af 439(include "cortex-a9.md")
934a1e72 440(include "cortex-r4.md")
e3879fd0 441(include "cortex-r4f.md")
55e3ada8 442(include "vfp11.md")
3586df96 443
9c08d1fa 444\f
215b30b3 445;;---------------------------------------------------------------------------
e1159bbe 446;; Insn patterns
447;;
a0f94409 448;; Addition insns.
215b30b3 449
9c08d1fa 450;; Note: For DImode insns, there is normally no reason why operands should
451;; not be in the same register, what we don't want is for something being
452;; written to partially overlap something that is an input.
7d57ec45 453;; Cirrus 64bit additions should not be split because we have a native
454;; 64bit addition instructions.
9c08d1fa 455
cffb2a26 456(define_expand "adddi3"
457 [(parallel
215b30b3 458 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 459 (plus:DI (match_operand:DI 1 "s_register_operand" "")
460 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 461 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 462 "TARGET_EITHER"
463 "
a2cd141b 464 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 465 {
466 if (!cirrus_fp_register (operands[0], DImode))
467 operands[0] = force_reg (DImode, operands[0]);
468 if (!cirrus_fp_register (operands[1], DImode))
469 operands[1] = force_reg (DImode, operands[1]);
470 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
471 DONE;
472 }
473
25f905c2 474 if (TARGET_THUMB1)
cffb2a26 475 {
476 if (GET_CODE (operands[1]) != REG)
bc5a93af 477 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 478 if (GET_CODE (operands[2]) != REG)
bc5a93af 479 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 480 }
481 "
482)
483
25f905c2 484(define_insn "*thumb1_adddi3"
cffb2a26 485 [(set (match_operand:DI 0 "register_operand" "=l")
486 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 487 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 488 (clobber (reg:CC CC_REGNUM))
cffb2a26 489 ]
25f905c2 490 "TARGET_THUMB1"
cffb2a26 491 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
492 [(set_attr "length" "4")]
493)
494
a0f94409 495(define_insn_and_split "*arm_adddi3"
cffb2a26 496 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 497 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
498 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 499 (clobber (reg:CC CC_REGNUM))]
25f905c2 500 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 501 "#"
25f905c2 502 "TARGET_32BIT && reload_completed"
a0f94409 503 [(parallel [(set (reg:CC_C CC_REGNUM)
504 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
505 (match_dup 1)))
506 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
507 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
508 (plus:SI (match_dup 4) (match_dup 5))))]
509 "
510 {
511 operands[3] = gen_highpart (SImode, operands[0]);
512 operands[0] = gen_lowpart (SImode, operands[0]);
513 operands[4] = gen_highpart (SImode, operands[1]);
514 operands[1] = gen_lowpart (SImode, operands[1]);
515 operands[5] = gen_highpart (SImode, operands[2]);
516 operands[2] = gen_lowpart (SImode, operands[2]);
517 }"
cffb2a26 518 [(set_attr "conds" "clob")
519 (set_attr "length" "8")]
520)
9c08d1fa 521
a0f94409 522(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 523 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
524 (plus:DI (sign_extend:DI
97499065 525 (match_operand:SI 2 "s_register_operand" "r,r"))
526 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 527 (clobber (reg:CC CC_REGNUM))]
25f905c2 528 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 529 "#"
25f905c2 530 "TARGET_32BIT && reload_completed"
a0f94409 531 [(parallel [(set (reg:CC_C CC_REGNUM)
532 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
533 (match_dup 1)))
534 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
535 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
536 (plus:SI (ashiftrt:SI (match_dup 2)
537 (const_int 31))
538 (match_dup 4))))]
539 "
540 {
541 operands[3] = gen_highpart (SImode, operands[0]);
542 operands[0] = gen_lowpart (SImode, operands[0]);
543 operands[4] = gen_highpart (SImode, operands[1]);
544 operands[1] = gen_lowpart (SImode, operands[1]);
545 operands[2] = gen_lowpart (SImode, operands[2]);
546 }"
215b30b3 547 [(set_attr "conds" "clob")
548 (set_attr "length" "8")]
549)
9c08d1fa 550
a0f94409 551(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 552 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
553 (plus:DI (zero_extend:DI
97499065 554 (match_operand:SI 2 "s_register_operand" "r,r"))
555 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 556 (clobber (reg:CC CC_REGNUM))]
25f905c2 557 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 558 "#"
25f905c2 559 "TARGET_32BIT && reload_completed"
a0f94409 560 [(parallel [(set (reg:CC_C CC_REGNUM)
561 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
562 (match_dup 1)))
563 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
564 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
565 (plus:SI (match_dup 4) (const_int 0))))]
566 "
567 {
568 operands[3] = gen_highpart (SImode, operands[0]);
569 operands[0] = gen_lowpart (SImode, operands[0]);
570 operands[4] = gen_highpart (SImode, operands[1]);
571 operands[1] = gen_lowpart (SImode, operands[1]);
572 operands[2] = gen_lowpart (SImode, operands[2]);
573 }"
cffb2a26 574 [(set_attr "conds" "clob")
575 (set_attr "length" "8")]
576)
b11cae9e 577
87b22bf7 578(define_expand "addsi3"
cffb2a26 579 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 580 (plus:SI (match_operand:SI 1 "s_register_operand" "")
581 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 582 "TARGET_EITHER"
87b22bf7 583 "
25f905c2 584 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 585 {
96f57e36 586 arm_split_constant (PLUS, SImode, NULL_RTX,
587 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 588 optimize && can_create_pseudo_p ());
87b22bf7 589 DONE;
590 }
cffb2a26 591 "
592)
87b22bf7 593
5bd751ff 594; If there is a scratch available, this will be faster than synthesizing the
a0f94409 595; addition.
596(define_peephole2
597 [(match_scratch:SI 3 "r")
372575c7 598 (set (match_operand:SI 0 "arm_general_register_operand" "")
599 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 600 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 601 "TARGET_32BIT &&
a0f94409 602 !(const_ok_for_arm (INTVAL (operands[2]))
603 || const_ok_for_arm (-INTVAL (operands[2])))
604 && const_ok_for_arm (~INTVAL (operands[2]))"
605 [(set (match_dup 3) (match_dup 2))
606 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
607 ""
608)
87b22bf7 609
2f02c19f 610;; The r/r/k alternative is required when reloading the address
611;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
612;; put the duplicated register first, and not try the commutative version.
a0f94409 613(define_insn_and_split "*arm_addsi3"
2f02c19f 614 [(set (match_operand:SI 0 "s_register_operand" "=r, !k, r,r, !k,r")
615 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
616 (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
25f905c2 617 "TARGET_32BIT"
5565501b 618 "@
619 add%?\\t%0, %1, %2
aaa37ad6 620 add%?\\t%0, %1, %2
2f02c19f 621 add%?\\t%0, %2, %1
aaa37ad6 622 sub%?\\t%0, %1, #%n2
87b22bf7 623 sub%?\\t%0, %1, #%n2
624 #"
a3ffc315 625 "TARGET_32BIT
626 && GET_CODE (operands[2]) == CONST_INT
a0f94409 627 && !(const_ok_for_arm (INTVAL (operands[2]))
a3ffc315 628 || const_ok_for_arm (-INTVAL (operands[2])))
629 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 630 [(clobber (const_int 0))]
631 "
96f57e36 632 arm_split_constant (PLUS, SImode, curr_insn,
633 INTVAL (operands[2]), operands[0],
a0f94409 634 operands[1], 0);
635 DONE;
636 "
2f02c19f 637 [(set_attr "length" "4,4,4,4,4,16")
0d66636f 638 (set_attr "predicable" "yes")]
cffb2a26 639)
640
641;; Register group 'k' is a single register group containing only the stack
642;; register. Trying to reload it will always fail catastrophically,
643;; so never allow those alternatives to match if reloading is needed.
644
0bdb6455 645(define_insn_and_split "*thumb1_addsi3"
646 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
647 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
648 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
25f905c2 649 "TARGET_THUMB1"
cffb2a26 650 "*
0d66636f 651 static const char * const asms[] =
cffb2a26 652 {
653 \"add\\t%0, %0, %2\",
654 \"sub\\t%0, %0, #%n2\",
655 \"add\\t%0, %1, %2\",
656 \"add\\t%0, %0, %2\",
657 \"add\\t%0, %0, %2\",
658 \"add\\t%0, %1, %2\",
0bdb6455 659 \"add\\t%0, %1, %2\",
660 \"#\",
661 \"#\"
cffb2a26 662 };
663 if ((which_alternative == 2 || which_alternative == 6)
664 && GET_CODE (operands[2]) == CONST_INT
665 && INTVAL (operands[2]) < 0)
666 return \"sub\\t%0, %1, #%n2\";
667 return asms[which_alternative];
668 "
0bdb6455 669 "&& reload_completed && CONST_INT_P (operands[2])
670 && operands[1] != stack_pointer_rtx
671 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
672 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
673 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
674 {
675 HOST_WIDE_INT offset = INTVAL (operands[2]);
676 if (offset > 255)
677 offset = 255;
678 else if (offset < -255)
679 offset = -255;
680
681 operands[3] = GEN_INT (offset);
682 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
683 }
684 [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
cffb2a26 685)
686
687;; Reloading and elimination of the frame pointer can
688;; sometimes cause this optimization to be missed.
a0f94409 689(define_peephole2
372575c7 690 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 691 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 692 (set (match_dup 0)
372575c7 693 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 694 "TARGET_THUMB1
cffb2a26 695 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
696 && (INTVAL (operands[1]) & 3) == 0"
372575c7 697 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 698 ""
cffb2a26 699)
b11cae9e 700
25f905c2 701;; ??? Make Thumb-2 variants which prefer low regs
f7fbdd4a 702(define_insn "*addsi3_compare0"
bd5b4116 703 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 704 (compare:CC_NOOV
215b30b3 705 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
706 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 707 (const_int 0)))
708 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 709 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 710 "TARGET_32BIT"
5565501b 711 "@
25f905c2 712 add%.\\t%0, %1, %2
713 sub%.\\t%0, %1, #%n2"
cffb2a26 714 [(set_attr "conds" "set")]
715)
9c08d1fa 716
aea4c774 717(define_insn "*addsi3_compare0_scratch"
bd5b4116 718 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 719 (compare:CC_NOOV
215b30b3 720 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
721 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 722 (const_int 0)))]
25f905c2 723 "TARGET_32BIT"
cffb2a26 724 "@
725 cmn%?\\t%0, %1
726 cmp%?\\t%0, #%n1"
0d66636f 727 [(set_attr "conds" "set")]
728)
cffb2a26 729
aed179ae 730(define_insn "*compare_negsi_si"
731 [(set (reg:CC_Z CC_REGNUM)
732 (compare:CC_Z
733 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
734 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 735 "TARGET_32BIT"
aed179ae 736 "cmn%?\\t%1, %0"
0d66636f 737 [(set_attr "conds" "set")]
738)
aea4c774 739
203c488f 740;; This is the canonicalization of addsi3_compare0_for_combiner when the
741;; addend is a constant.
742(define_insn "*cmpsi2_addneg"
743 [(set (reg:CC CC_REGNUM)
744 (compare:CC
745 (match_operand:SI 1 "s_register_operand" "r,r")
746 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
747 (set (match_operand:SI 0 "s_register_operand" "=r,r")
748 (plus:SI (match_dup 1)
749 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
25f905c2 750 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 751 "@
25f905c2 752 sub%.\\t%0, %1, %2
753 add%.\\t%0, %1, #%n2"
203c488f 754 [(set_attr "conds" "set")]
755)
756
757;; Convert the sequence
758;; sub rd, rn, #1
759;; cmn rd, #1 (equivalent to cmp rd, #-1)
760;; bne dest
761;; into
762;; subs rd, rn, #1
763;; bcs dest ((unsigned)rn >= 1)
764;; similarly for the beq variant using bcc.
765;; This is a common looping idiom (while (n--))
766(define_peephole2
372575c7 767 [(set (match_operand:SI 0 "arm_general_register_operand" "")
768 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 769 (const_int -1)))
770 (set (match_operand 2 "cc_register" "")
771 (compare (match_dup 0) (const_int -1)))
772 (set (pc)
773 (if_then_else (match_operator 3 "equality_operator"
774 [(match_dup 2) (const_int 0)])
775 (match_operand 4 "" "")
776 (match_operand 5 "" "")))]
25f905c2 777 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 778 [(parallel[
779 (set (match_dup 2)
780 (compare:CC
781 (match_dup 1) (const_int 1)))
782 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
783 (set (pc)
784 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
785 (match_dup 4)
786 (match_dup 5)))]
787 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
788 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
789 ? GEU : LTU),
790 VOIDmode,
791 operands[2], const0_rtx);"
792)
793
ebcc79bc 794;; The next four insns work because they compare the result with one of
795;; the operands, and we know that the use of the condition code is
796;; either GEU or LTU, so we can use the carry flag from the addition
797;; instead of doing the compare a second time.
798(define_insn "*addsi3_compare_op1"
bd5b4116 799 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 800 (compare:CC_C
801 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
802 (match_operand:SI 2 "arm_add_operand" "rI,L"))
803 (match_dup 1)))
804 (set (match_operand:SI 0 "s_register_operand" "=r,r")
805 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 806 "TARGET_32BIT"
ebcc79bc 807 "@
25f905c2 808 add%.\\t%0, %1, %2
809 sub%.\\t%0, %1, #%n2"
0d66636f 810 [(set_attr "conds" "set")]
811)
ebcc79bc 812
813(define_insn "*addsi3_compare_op2"
bd5b4116 814 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 815 (compare:CC_C
816 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
817 (match_operand:SI 2 "arm_add_operand" "rI,L"))
818 (match_dup 2)))
5565501b 819 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 820 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 821 "TARGET_32BIT"
5565501b 822 "@
25f905c2 823 add%.\\t%0, %1, %2
824 sub%.\\t%0, %1, #%n2"
0d66636f 825 [(set_attr "conds" "set")]
826)
9c08d1fa 827
ebcc79bc 828(define_insn "*compare_addsi2_op0"
bd5b4116 829 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 830 (compare:CC_C
831 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
832 (match_operand:SI 1 "arm_add_operand" "rI,L"))
833 (match_dup 0)))]
25f905c2 834 "TARGET_32BIT"
ebcc79bc 835 "@
836 cmn%?\\t%0, %1
837 cmp%?\\t%0, #%n1"
0d66636f 838 [(set_attr "conds" "set")]
839)
ebcc79bc 840
841(define_insn "*compare_addsi2_op1"
bd5b4116 842 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 843 (compare:CC_C
844 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
845 (match_operand:SI 1 "arm_add_operand" "rI,L"))
846 (match_dup 1)))]
25f905c2 847 "TARGET_32BIT"
ebcc79bc 848 "@
849 cmn%?\\t%0, %1
850 cmp%?\\t%0, #%n1"
0d66636f 851 [(set_attr "conds" "set")]
852)
ebcc79bc 853
854(define_insn "*addsi3_carryin"
855 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 856 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 857 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
858 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
25f905c2 859 "TARGET_32BIT"
ebcc79bc 860 "adc%?\\t%0, %1, %2"
cffb2a26 861 [(set_attr "conds" "use")]
862)
ebcc79bc 863
33782ec7 864(define_insn "*addsi3_carryin_shift"
7b63a8dd 865 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 866 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 867 (plus:SI
868 (match_operator:SI 2 "shift_operator"
7b63a8dd 869 [(match_operand:SI 3 "s_register_operand" "r")
870 (match_operand:SI 4 "reg_or_int_operand" "rM")])
871 (match_operand:SI 1 "s_register_operand" "r"))))]
25f905c2 872 "TARGET_32BIT"
33782ec7 873 "adc%?\\t%0, %1, %3%S2"
a2cd141b 874 [(set_attr "conds" "use")
875 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
876 (const_string "alu_shift")
877 (const_string "alu_shift_reg")))]
33782ec7 878)
879
ebcc79bc 880(define_insn "*addsi3_carryin_alt1"
881 [(set (match_operand:SI 0 "s_register_operand" "=r")
882 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
883 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 884 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
25f905c2 885 "TARGET_32BIT"
ebcc79bc 886 "adc%?\\t%0, %1, %2"
cffb2a26 887 [(set_attr "conds" "use")]
888)
ebcc79bc 889
890(define_insn "*addsi3_carryin_alt2"
891 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 892 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 893 (match_operand:SI 1 "s_register_operand" "r"))
894 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 895 "TARGET_32BIT"
ebcc79bc 896 "adc%?\\t%0, %1, %2"
0d66636f 897 [(set_attr "conds" "use")]
898)
ebcc79bc 899
900(define_insn "*addsi3_carryin_alt3"
901 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 902 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 903 (match_operand:SI 2 "arm_rhs_operand" "rI"))
904 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 905 "TARGET_32BIT"
ebcc79bc 906 "adc%?\\t%0, %1, %2"
cffb2a26 907 [(set_attr "conds" "use")]
908)
ebcc79bc 909
25f905c2 910(define_expand "incscc"
911 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
912 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
913 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
914 (match_operand:SI 1 "s_register_operand" "0,?r")))]
915 "TARGET_32BIT"
916 ""
917)
918
919(define_insn "*arm_incscc"
9c08d1fa 920 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 921 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 922 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 923 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 924 "TARGET_ARM"
5565501b 925 "@
926 add%d2\\t%0, %1, #1
927 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 928 [(set_attr "conds" "use")
215b30b3 929 (set_attr "length" "4,8")]
930)
9c08d1fa 931
d795fb69 932; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
933(define_split
934 [(set (match_operand:SI 0 "s_register_operand" "")
935 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
936 (match_operand:SI 2 "s_register_operand" ""))
937 (const_int -1)))
938 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 939 "TARGET_32BIT"
d795fb69 940 [(set (match_dup 3) (match_dup 1))
941 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
942 "
943 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
944")
945
604f3a0a 946(define_expand "addsf3"
947 [(set (match_operand:SF 0 "s_register_operand" "")
948 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 949 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 950 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 951 "
a2cd141b 952 if (TARGET_MAVERICK
604f3a0a 953 && !cirrus_fp_register (operands[2], SFmode))
954 operands[2] = force_reg (SFmode, operands[2]);
955")
956
604f3a0a 957(define_expand "adddf3"
958 [(set (match_operand:DF 0 "s_register_operand" "")
959 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 960 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 961 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 962 "
a2cd141b 963 if (TARGET_MAVERICK
604f3a0a 964 && !cirrus_fp_register (operands[2], DFmode))
965 operands[2] = force_reg (DFmode, operands[2]);
966")
967
cffb2a26 968(define_expand "subdi3"
969 [(parallel
970 [(set (match_operand:DI 0 "s_register_operand" "")
971 (minus:DI (match_operand:DI 1 "s_register_operand" "")
972 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 973 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 974 "TARGET_EITHER"
975 "
a2cd141b 976 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 977 && TARGET_32BIT
7d57ec45 978 && cirrus_fp_register (operands[0], DImode)
979 && cirrus_fp_register (operands[1], DImode))
980 {
981 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
982 DONE;
983 }
984
25f905c2 985 if (TARGET_THUMB1)
cffb2a26 986 {
987 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 988 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 989 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 990 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 991 }
992 "
993)
994
995(define_insn "*arm_subdi3"
996 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 997 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
998 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 999 (clobber (reg:CC CC_REGNUM))]
25f905c2 1000 "TARGET_32BIT"
97499065 1001 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1002 [(set_attr "conds" "clob")
1003 (set_attr "length" "8")]
1004)
1005
1006(define_insn "*thumb_subdi3"
1007 [(set (match_operand:DI 0 "register_operand" "=l")
1008 (minus:DI (match_operand:DI 1 "register_operand" "0")
1009 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1010 (clobber (reg:CC CC_REGNUM))]
25f905c2 1011 "TARGET_THUMB1"
cffb2a26 1012 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1013 [(set_attr "length" "4")]
1014)
9c08d1fa 1015
f7fbdd4a 1016(define_insn "*subdi_di_zesidi"
cffb2a26 1017 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1018 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 1019 (zero_extend:DI
cffb2a26 1020 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1021 (clobber (reg:CC CC_REGNUM))]
25f905c2 1022 "TARGET_32BIT"
97499065 1023 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1024 [(set_attr "conds" "clob")
1025 (set_attr "length" "8")]
1026)
9c08d1fa 1027
f7fbdd4a 1028(define_insn "*subdi_di_sesidi"
cffb2a26 1029 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1030 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 1031 (sign_extend:DI
cffb2a26 1032 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1033 (clobber (reg:CC CC_REGNUM))]
25f905c2 1034 "TARGET_32BIT"
97499065 1035 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1036 [(set_attr "conds" "clob")
1037 (set_attr "length" "8")]
1038)
9c08d1fa 1039
f7fbdd4a 1040(define_insn "*subdi_zesidi_di"
cffb2a26 1041 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1042 (minus:DI (zero_extend:DI
cffb2a26 1043 (match_operand:SI 2 "s_register_operand" "r,r"))
1044 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 1045 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1046 "TARGET_ARM"
97499065 1047 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1048 [(set_attr "conds" "clob")
1049 (set_attr "length" "8")]
1050)
9c08d1fa 1051
f7fbdd4a 1052(define_insn "*subdi_sesidi_di"
cffb2a26 1053 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1054 (minus:DI (sign_extend:DI
cffb2a26 1055 (match_operand:SI 2 "s_register_operand" "r,r"))
1056 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 1057 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1058 "TARGET_ARM"
97499065 1059 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1060 [(set_attr "conds" "clob")
1061 (set_attr "length" "8")]
1062)
9c08d1fa 1063
f7fbdd4a 1064(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1065 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1066 (minus:DI (zero_extend:DI
cffb2a26 1067 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1068 (zero_extend:DI
cffb2a26 1069 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1070 (clobber (reg:CC CC_REGNUM))]
25f905c2 1071 "TARGET_32BIT"
1072 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1073 [(set_attr "conds" "clob")
1074 (set_attr "length" "8")]
1075)
b11cae9e 1076
87b22bf7 1077(define_expand "subsi3"
cffb2a26 1078 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1079 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1080 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1081 "TARGET_EITHER"
87b22bf7 1082 "
1083 if (GET_CODE (operands[1]) == CONST_INT)
1084 {
25f905c2 1085 if (TARGET_32BIT)
cffb2a26 1086 {
96f57e36 1087 arm_split_constant (MINUS, SImode, NULL_RTX,
1088 INTVAL (operands[1]), operands[0],
e1ba4a27 1089 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1090 DONE;
1091 }
25f905c2 1092 else /* TARGET_THUMB1 */
cffb2a26 1093 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1094 }
cffb2a26 1095 "
1096)
87b22bf7 1097
25f905c2 1098(define_insn "*thumb1_subsi3_insn"
cffb2a26 1099 [(set (match_operand:SI 0 "register_operand" "=l")
1100 (minus:SI (match_operand:SI 1 "register_operand" "l")
1101 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1102 "TARGET_THUMB1"
cffb2a26 1103 "sub\\t%0, %1, %2"
1104 [(set_attr "length" "2")]
1105)
1106
25f905c2 1107; ??? Check Thumb-2 split length
a0f94409 1108(define_insn_and_split "*arm_subsi3_insn"
aaa37ad6 1109 [(set (match_operand:SI 0 "s_register_operand" "=r,rk,r")
1110 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n")
1111 (match_operand:SI 2 "s_register_operand" "r, r, r")))]
25f905c2 1112 "TARGET_32BIT"
e2348bcb 1113 "@
87b22bf7 1114 rsb%?\\t%0, %2, %1
aaa37ad6 1115 sub%?\\t%0, %1, %2
87b22bf7 1116 #"
25f905c2 1117 "TARGET_32BIT
a0f94409 1118 && GET_CODE (operands[1]) == CONST_INT
1119 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 1120 [(clobber (const_int 0))]
1121 "
96f57e36 1122 arm_split_constant (MINUS, SImode, curr_insn,
1123 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1124 DONE;
cffb2a26 1125 "
aaa37ad6 1126 [(set_attr "length" "4,4,16")
a0f94409 1127 (set_attr "predicable" "yes")]
1128)
1129
1130(define_peephole2
1131 [(match_scratch:SI 3 "r")
372575c7 1132 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1133 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1134 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1135 "TARGET_32BIT
a0f94409 1136 && !const_ok_for_arm (INTVAL (operands[1]))
1137 && const_ok_for_arm (~INTVAL (operands[1]))"
1138 [(set (match_dup 3) (match_dup 1))
1139 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1140 ""
cffb2a26 1141)
b11cae9e 1142
f7fbdd4a 1143(define_insn "*subsi3_compare0"
bd5b4116 1144 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1145 (compare:CC_NOOV
1146 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1147 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1148 (const_int 0)))
9c08d1fa 1149 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1150 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1151 "TARGET_32BIT"
e2348bcb 1152 "@
25f905c2 1153 sub%.\\t%0, %1, %2
1154 rsb%.\\t%0, %2, %1"
cffb2a26 1155 [(set_attr "conds" "set")]
1156)
9c08d1fa 1157
25f905c2 1158(define_expand "decscc"
1159 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1160 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1161 (match_operator:SI 2 "arm_comparison_operator"
1162 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1163 "TARGET_32BIT"
1164 ""
1165)
1166
1167(define_insn "*arm_decscc"
cffb2a26 1168 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1169 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1170 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1171 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1172 "TARGET_ARM"
e2348bcb 1173 "@
215b30b3 1174 sub%d2\\t%0, %1, #1
1175 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1176 [(set_attr "conds" "use")
1177 (set_attr "length" "*,8")]
1178)
9c08d1fa 1179
604f3a0a 1180(define_expand "subsf3"
1181 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1182 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1183 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1184 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1185 "
a2cd141b 1186 if (TARGET_MAVERICK)
604f3a0a 1187 {
1188 if (!cirrus_fp_register (operands[1], SFmode))
1189 operands[1] = force_reg (SFmode, operands[1]);
1190 if (!cirrus_fp_register (operands[2], SFmode))
1191 operands[2] = force_reg (SFmode, operands[2]);
1192 }
1193")
1194
604f3a0a 1195(define_expand "subdf3"
1196 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1197 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1198 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1199 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1200 "
a2cd141b 1201 if (TARGET_MAVERICK)
604f3a0a 1202 {
1203 if (!cirrus_fp_register (operands[1], DFmode))
1204 operands[1] = force_reg (DFmode, operands[1]);
1205 if (!cirrus_fp_register (operands[2], DFmode))
1206 operands[2] = force_reg (DFmode, operands[2]);
1207 }
1208")
1209
b11cae9e 1210\f
1211;; Multiplication insns
1212
cffb2a26 1213(define_expand "mulsi3"
1214 [(set (match_operand:SI 0 "s_register_operand" "")
1215 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1216 (match_operand:SI 1 "s_register_operand" "")))]
1217 "TARGET_EITHER"
1218 ""
1219)
1220
9c08d1fa 1221;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1222(define_insn "*arm_mulsi3"
1223 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1224 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1225 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
58d7d654 1226 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1227 "mul%?\\t%0, %2, %1"
a2cd141b 1228 [(set_attr "insn" "mul")
0d66636f 1229 (set_attr "predicable" "yes")]
cffb2a26 1230)
1231
58d7d654 1232(define_insn "*arm_mulsi3_v6"
1233 [(set (match_operand:SI 0 "s_register_operand" "=r")
1234 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1235 (match_operand:SI 2 "s_register_operand" "r")))]
1236 "TARGET_32BIT && arm_arch6"
1237 "mul%?\\t%0, %1, %2"
1238 [(set_attr "insn" "mul")
1239 (set_attr "predicable" "yes")]
1240)
1241
215b30b3 1242; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1243; 1 and 2; are the same, because reload will make operand 0 match
1244; operand 1 without realizing that this conflicts with operand 2. We fix
1245; this by adding another alternative to match this case, and then `reload'
1246; it ourselves. This alternative must come first.
cffb2a26 1247(define_insn "*thumb_mulsi3"
1248 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1249 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1250 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1251 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1252 "*
1253 if (which_alternative < 2)
20c4e896 1254 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1255 else
20c4e896 1256 return \"mul\\t%0, %2\";
cffb2a26 1257 "
1258 [(set_attr "length" "4,4,2")
a2cd141b 1259 (set_attr "insn" "mul")]
cffb2a26 1260)
b11cae9e 1261
58d7d654 1262(define_insn "*thumb_mulsi3_v6"
1263 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1264 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1265 (match_operand:SI 2 "register_operand" "l,0,0")))]
1266 "TARGET_THUMB1 && arm_arch6"
1267 "@
1268 mul\\t%0, %2
1269 mul\\t%0, %1
1270 mul\\t%0, %1"
1271 [(set_attr "length" "2")
1272 (set_attr "insn" "mul")]
1273)
1274
f7fbdd4a 1275(define_insn "*mulsi3_compare0"
bd5b4116 1276 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1277 (compare:CC_NOOV (mult:SI
1278 (match_operand:SI 2 "s_register_operand" "r,r")
1279 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1280 (const_int 0)))
1281 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1282 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1283 "TARGET_ARM && !arm_arch6"
1284 "mul%.\\t%0, %2, %1"
1285 [(set_attr "conds" "set")
1286 (set_attr "insn" "muls")]
1287)
1288
1289(define_insn "*mulsi3_compare0_v6"
1290 [(set (reg:CC_NOOV CC_REGNUM)
1291 (compare:CC_NOOV (mult:SI
1292 (match_operand:SI 2 "s_register_operand" "r")
1293 (match_operand:SI 1 "s_register_operand" "r"))
1294 (const_int 0)))
1295 (set (match_operand:SI 0 "s_register_operand" "=r")
1296 (mult:SI (match_dup 2) (match_dup 1)))]
1297 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1298 "mul%.\\t%0, %2, %1"
cffb2a26 1299 [(set_attr "conds" "set")
a2cd141b 1300 (set_attr "insn" "muls")]
cffb2a26 1301)
9c08d1fa 1302
f7fbdd4a 1303(define_insn "*mulsi_compare0_scratch"
bd5b4116 1304 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1305 (compare:CC_NOOV (mult:SI
1306 (match_operand:SI 2 "s_register_operand" "r,r")
1307 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1308 (const_int 0)))
1309 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1310 "TARGET_ARM && !arm_arch6"
1311 "mul%.\\t%0, %2, %1"
1312 [(set_attr "conds" "set")
1313 (set_attr "insn" "muls")]
1314)
1315
1316(define_insn "*mulsi_compare0_scratch_v6"
1317 [(set (reg:CC_NOOV CC_REGNUM)
1318 (compare:CC_NOOV (mult:SI
1319 (match_operand:SI 2 "s_register_operand" "r")
1320 (match_operand:SI 1 "s_register_operand" "r"))
1321 (const_int 0)))
1322 (clobber (match_scratch:SI 0 "=r"))]
1323 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1324 "mul%.\\t%0, %2, %1"
cffb2a26 1325 [(set_attr "conds" "set")
a2cd141b 1326 (set_attr "insn" "muls")]
cffb2a26 1327)
9c08d1fa 1328
b11cae9e 1329;; Unnamed templates to match MLA instruction.
1330
f7fbdd4a 1331(define_insn "*mulsi3addsi"
9c08d1fa 1332 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1333 (plus:SI
9c08d1fa 1334 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1335 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1336 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
58d7d654 1337 "TARGET_32BIT && !arm_arch6"
1338 "mla%?\\t%0, %2, %1, %3"
1339 [(set_attr "insn" "mla")
1340 (set_attr "predicable" "yes")]
1341)
1342
1343(define_insn "*mulsi3addsi_v6"
1344 [(set (match_operand:SI 0 "s_register_operand" "=r")
1345 (plus:SI
1346 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1347 (match_operand:SI 1 "s_register_operand" "r"))
1348 (match_operand:SI 3 "s_register_operand" "r")))]
1349 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1350 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1351 [(set_attr "insn" "mla")
0d66636f 1352 (set_attr "predicable" "yes")]
1353)
b11cae9e 1354
f7fbdd4a 1355(define_insn "*mulsi3addsi_compare0"
bd5b4116 1356 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1357 (compare:CC_NOOV
1358 (plus:SI (mult:SI
1359 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1360 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1361 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1362 (const_int 0)))
9c08d1fa 1363 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1364 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1365 (match_dup 3)))]
58d7d654 1366 "TARGET_ARM && arm_arch6"
1367 "mla%.\\t%0, %2, %1, %3"
1368 [(set_attr "conds" "set")
1369 (set_attr "insn" "mlas")]
1370)
1371
1372(define_insn "*mulsi3addsi_compare0_v6"
1373 [(set (reg:CC_NOOV CC_REGNUM)
1374 (compare:CC_NOOV
1375 (plus:SI (mult:SI
1376 (match_operand:SI 2 "s_register_operand" "r")
1377 (match_operand:SI 1 "s_register_operand" "r"))
1378 (match_operand:SI 3 "s_register_operand" "r"))
1379 (const_int 0)))
1380 (set (match_operand:SI 0 "s_register_operand" "=r")
1381 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1382 (match_dup 3)))]
1383 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1384 "mla%.\\t%0, %2, %1, %3"
0d66636f 1385 [(set_attr "conds" "set")
a2cd141b 1386 (set_attr "insn" "mlas")]
0d66636f 1387)
9c08d1fa 1388
f7fbdd4a 1389(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1390 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1391 (compare:CC_NOOV
1392 (plus:SI (mult:SI
1393 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1394 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1395 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1396 (const_int 0)))
9c08d1fa 1397 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1398 "TARGET_ARM && !arm_arch6"
1399 "mla%.\\t%0, %2, %1, %3"
1400 [(set_attr "conds" "set")
1401 (set_attr "insn" "mlas")]
1402)
1403
1404(define_insn "*mulsi3addsi_compare0_scratch_v6"
1405 [(set (reg:CC_NOOV CC_REGNUM)
1406 (compare:CC_NOOV
1407 (plus:SI (mult:SI
1408 (match_operand:SI 2 "s_register_operand" "r")
1409 (match_operand:SI 1 "s_register_operand" "r"))
1410 (match_operand:SI 3 "s_register_operand" "r"))
1411 (const_int 0)))
1412 (clobber (match_scratch:SI 0 "=r"))]
1413 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1414 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1415 [(set_attr "conds" "set")
a2cd141b 1416 (set_attr "insn" "mlas")]
cffb2a26 1417)
f7fbdd4a 1418
89545238 1419(define_insn "*mulsi3subsi"
1420 [(set (match_operand:SI 0 "s_register_operand" "=r")
1421 (minus:SI
1422 (match_operand:SI 3 "s_register_operand" "r")
1423 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1424 (match_operand:SI 1 "s_register_operand" "r"))))]
1425 "TARGET_32BIT && arm_arch_thumb2"
1426 "mls%?\\t%0, %2, %1, %3"
1427 [(set_attr "insn" "mla")
1428 (set_attr "predicable" "yes")]
1429)
1430
efee20da 1431;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1432
1433(define_insn "*mulsidi3adddi"
fe8dbf85 1434 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1435 (plus:DI
215b30b3 1436 (mult:DI
fe8dbf85 1437 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1438 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1439 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1440 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1441 "smlal%?\\t%Q0, %R0, %3, %2"
1442 [(set_attr "insn" "smlal")
1443 (set_attr "predicable" "yes")]
1444)
1445
1446(define_insn "*mulsidi3adddi_v6"
1447 [(set (match_operand:DI 0 "s_register_operand" "=r")
1448 (plus:DI
1449 (mult:DI
1450 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1451 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1452 (match_operand:DI 1 "s_register_operand" "0")))]
1453 "TARGET_32BIT && arm_arch6"
fe8dbf85 1454 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1455 [(set_attr "insn" "smlal")
0d66636f 1456 (set_attr "predicable" "yes")]
1457)
82b85d08 1458
957788b0 1459;; 32x32->64 widening multiply.
1460;; As with mulsi3, the only difference between the v3-5 and v6+
1461;; versions of these patterns is the requirement that the output not
1462;; overlap the inputs, but that still means we have to have a named
1463;; expander and two different starred insns.
1464
1465(define_expand "mulsidi3"
1466 [(set (match_operand:DI 0 "s_register_operand" "")
1467 (mult:DI
1468 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1469 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1470 "TARGET_32BIT && arm_arch3m"
1471 ""
1472)
1473
1474(define_insn "*mulsidi3_nov6"
f7fbdd4a 1475 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1476 (mult:DI
1477 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1478 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1479 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1480 "smull%?\\t%Q0, %R0, %1, %2"
1481 [(set_attr "insn" "smull")
1482 (set_attr "predicable" "yes")]
1483)
1484
957788b0 1485(define_insn "*mulsidi3_v6"
58d7d654 1486 [(set (match_operand:DI 0 "s_register_operand" "=r")
1487 (mult:DI
1488 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1489 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1490 "TARGET_32BIT && arm_arch6"
97499065 1491 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1492 [(set_attr "insn" "smull")
0d66636f 1493 (set_attr "predicable" "yes")]
1494)
f7fbdd4a 1495
957788b0 1496(define_expand "umulsidi3"
1497 [(set (match_operand:DI 0 "s_register_operand" "")
1498 (mult:DI
1499 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1500 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1501 "TARGET_32BIT && arm_arch3m"
1502 ""
1503)
1504
1505(define_insn "*umulsidi3_nov6"
f7fbdd4a 1506 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1507 (mult:DI
1508 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1509 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1510 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1511 "umull%?\\t%Q0, %R0, %1, %2"
1512 [(set_attr "insn" "umull")
1513 (set_attr "predicable" "yes")]
1514)
1515
957788b0 1516(define_insn "*umulsidi3_v6"
58d7d654 1517 [(set (match_operand:DI 0 "s_register_operand" "=r")
1518 (mult:DI
1519 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1520 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1521 "TARGET_32BIT && arm_arch6"
97499065 1522 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1523 [(set_attr "insn" "umull")
0d66636f 1524 (set_attr "predicable" "yes")]
1525)
b11cae9e 1526
efee20da 1527;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1528
1529(define_insn "*umulsidi3adddi"
8ead09f9 1530 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1531 (plus:DI
215b30b3 1532 (mult:DI
fe8dbf85 1533 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1534 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1535 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1536 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1537 "umlal%?\\t%Q0, %R0, %3, %2"
1538 [(set_attr "insn" "umlal")
1539 (set_attr "predicable" "yes")]
1540)
1541
1542(define_insn "*umulsidi3adddi_v6"
1543 [(set (match_operand:DI 0 "s_register_operand" "=r")
1544 (plus:DI
1545 (mult:DI
1546 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1547 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1548 (match_operand:DI 1 "s_register_operand" "0")))]
1549 "TARGET_32BIT && arm_arch6"
fe8dbf85 1550 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1551 [(set_attr "insn" "umlal")
0d66636f 1552 (set_attr "predicable" "yes")]
1553)
82b85d08 1554
957788b0 1555(define_expand "smulsi3_highpart"
1556 [(parallel
1557 [(set (match_operand:SI 0 "s_register_operand" "")
1558 (truncate:SI
1559 (lshiftrt:DI
1560 (mult:DI
1561 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1562 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1563 (const_int 32))))
1564 (clobber (match_scratch:SI 3 ""))])]
1565 "TARGET_32BIT && arm_arch3m"
1566 ""
1567)
1568
1569(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1570 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1571 (truncate:SI
1572 (lshiftrt:DI
215b30b3 1573 (mult:DI
1574 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1575 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1576 (const_int 32))))
1577 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1578 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1579 "smull%?\\t%3, %0, %2, %1"
1580 [(set_attr "insn" "smull")
1581 (set_attr "predicable" "yes")]
1582)
1583
957788b0 1584(define_insn "*smulsi3_highpart_v6"
58d7d654 1585 [(set (match_operand:SI 0 "s_register_operand" "=r")
1586 (truncate:SI
1587 (lshiftrt:DI
1588 (mult:DI
1589 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1590 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1591 (const_int 32))))
1592 (clobber (match_scratch:SI 3 "=r"))]
1593 "TARGET_32BIT && arm_arch6"
f082f1c4 1594 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1595 [(set_attr "insn" "smull")
0d66636f 1596 (set_attr "predicable" "yes")]
cffb2a26 1597)
f082f1c4 1598
957788b0 1599(define_expand "umulsi3_highpart"
1600 [(parallel
1601 [(set (match_operand:SI 0 "s_register_operand" "")
1602 (truncate:SI
1603 (lshiftrt:DI
1604 (mult:DI
1605 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1606 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1607 (const_int 32))))
1608 (clobber (match_scratch:SI 3 ""))])]
1609 "TARGET_32BIT && arm_arch3m"
1610 ""
1611)
1612
1613(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1614 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1615 (truncate:SI
1616 (lshiftrt:DI
215b30b3 1617 (mult:DI
1618 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1619 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1620 (const_int 32))))
1621 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1622 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1623 "umull%?\\t%3, %0, %2, %1"
1624 [(set_attr "insn" "umull")
1625 (set_attr "predicable" "yes")]
1626)
1627
957788b0 1628(define_insn "*umulsi3_highpart_v6"
58d7d654 1629 [(set (match_operand:SI 0 "s_register_operand" "=r")
1630 (truncate:SI
1631 (lshiftrt:DI
1632 (mult:DI
1633 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1634 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1635 (const_int 32))))
1636 (clobber (match_scratch:SI 3 "=r"))]
1637 "TARGET_32BIT && arm_arch6"
f082f1c4 1638 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1639 [(set_attr "insn" "umull")
0d66636f 1640 (set_attr "predicable" "yes")]
cffb2a26 1641)
f082f1c4 1642
331beb1a 1643(define_insn "mulhisi3"
1644 [(set (match_operand:SI 0 "s_register_operand" "=r")
1645 (mult:SI (sign_extend:SI
1646 (match_operand:HI 1 "s_register_operand" "%r"))
1647 (sign_extend:SI
1648 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1649 "TARGET_DSP_MULTIPLY"
61a2d04c 1650 "smulbb%?\\t%0, %1, %2"
a2cd141b 1651 [(set_attr "insn" "smulxy")
fec538d9 1652 (set_attr "predicable" "yes")]
1653)
1654
1655(define_insn "*mulhisi3tb"
1656 [(set (match_operand:SI 0 "s_register_operand" "=r")
1657 (mult:SI (ashiftrt:SI
1658 (match_operand:SI 1 "s_register_operand" "r")
1659 (const_int 16))
1660 (sign_extend:SI
1661 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1662 "TARGET_DSP_MULTIPLY"
fec538d9 1663 "smultb%?\\t%0, %1, %2"
a2cd141b 1664 [(set_attr "insn" "smulxy")
fec538d9 1665 (set_attr "predicable" "yes")]
1666)
1667
1668(define_insn "*mulhisi3bt"
1669 [(set (match_operand:SI 0 "s_register_operand" "=r")
1670 (mult:SI (sign_extend:SI
1671 (match_operand:HI 1 "s_register_operand" "r"))
1672 (ashiftrt:SI
1673 (match_operand:SI 2 "s_register_operand" "r")
1674 (const_int 16))))]
25f905c2 1675 "TARGET_DSP_MULTIPLY"
fec538d9 1676 "smulbt%?\\t%0, %1, %2"
a2cd141b 1677 [(set_attr "insn" "smulxy")
fec538d9 1678 (set_attr "predicable" "yes")]
1679)
1680
1681(define_insn "*mulhisi3tt"
1682 [(set (match_operand:SI 0 "s_register_operand" "=r")
1683 (mult:SI (ashiftrt:SI
1684 (match_operand:SI 1 "s_register_operand" "r")
1685 (const_int 16))
1686 (ashiftrt:SI
1687 (match_operand:SI 2 "s_register_operand" "r")
1688 (const_int 16))))]
25f905c2 1689 "TARGET_DSP_MULTIPLY"
fec538d9 1690 "smultt%?\\t%0, %1, %2"
a2cd141b 1691 [(set_attr "insn" "smulxy")
fec538d9 1692 (set_attr "predicable" "yes")]
331beb1a 1693)
1694
1695(define_insn "*mulhisi3addsi"
1696 [(set (match_operand:SI 0 "s_register_operand" "=r")
1697 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1698 (mult:SI (sign_extend:SI
1699 (match_operand:HI 2 "s_register_operand" "%r"))
1700 (sign_extend:SI
1701 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1702 "TARGET_DSP_MULTIPLY"
61a2d04c 1703 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1704 [(set_attr "insn" "smlaxy")
fec538d9 1705 (set_attr "predicable" "yes")]
331beb1a 1706)
1707
1708(define_insn "*mulhidi3adddi"
1709 [(set (match_operand:DI 0 "s_register_operand" "=r")
1710 (plus:DI
1711 (match_operand:DI 1 "s_register_operand" "0")
1712 (mult:DI (sign_extend:DI
1713 (match_operand:HI 2 "s_register_operand" "%r"))
1714 (sign_extend:DI
1715 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1716 "TARGET_DSP_MULTIPLY"
331beb1a 1717 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1718 [(set_attr "insn" "smlalxy")
fec538d9 1719 (set_attr "predicable" "yes")])
331beb1a 1720
604f3a0a 1721(define_expand "mulsf3"
1722 [(set (match_operand:SF 0 "s_register_operand" "")
1723 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1724 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1725 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1726 "
a2cd141b 1727 if (TARGET_MAVERICK
604f3a0a 1728 && !cirrus_fp_register (operands[2], SFmode))
1729 operands[2] = force_reg (SFmode, operands[2]);
1730")
1731
604f3a0a 1732(define_expand "muldf3"
1733 [(set (match_operand:DF 0 "s_register_operand" "")
1734 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1735 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1736 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1737 "
a2cd141b 1738 if (TARGET_MAVERICK
604f3a0a 1739 && !cirrus_fp_register (operands[2], DFmode))
1740 operands[2] = force_reg (DFmode, operands[2]);
1741")
b11cae9e 1742\f
1743;; Division insns
1744
7db9af5d 1745(define_expand "divsf3"
1746 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1747 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1748 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1749 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1750 "")
9c08d1fa 1751
7db9af5d 1752(define_expand "divdf3"
1753 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1754 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1755 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1756 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1757 "")
b11cae9e 1758\f
1759;; Modulo insns
1760
7db9af5d 1761(define_expand "modsf3"
1762 [(set (match_operand:SF 0 "s_register_operand" "")
1763 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1764 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1765 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1766 "")
9c08d1fa 1767
7db9af5d 1768(define_expand "moddf3"
1769 [(set (match_operand:DF 0 "s_register_operand" "")
1770 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1771 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1772 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1773 "")
b11cae9e 1774\f
1775;; Boolean and,ior,xor insns
1776
f6ebffac 1777;; Split up double word logical operations
1778
1779;; Split up simple DImode logical operations. Simply perform the logical
1780;; operation on the upper and lower halves of the registers.
1781(define_split
1782 [(set (match_operand:DI 0 "s_register_operand" "")
1783 (match_operator:DI 6 "logical_binary_operator"
1784 [(match_operand:DI 1 "s_register_operand" "")
1785 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1786 "TARGET_32BIT && reload_completed
1787 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1788 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1789 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1790 "
215b30b3 1791 {
1792 operands[3] = gen_highpart (SImode, operands[0]);
1793 operands[0] = gen_lowpart (SImode, operands[0]);
1794 operands[4] = gen_highpart (SImode, operands[1]);
1795 operands[1] = gen_lowpart (SImode, operands[1]);
1796 operands[5] = gen_highpart (SImode, operands[2]);
1797 operands[2] = gen_lowpart (SImode, operands[2]);
1798 }"
1799)
f6ebffac 1800
f6ebffac 1801(define_split
1802 [(set (match_operand:DI 0 "s_register_operand" "")
1803 (match_operator:DI 6 "logical_binary_operator"
1804 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1805 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1806 "TARGET_32BIT && reload_completed"
f6ebffac 1807 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1808 (set (match_dup 3) (match_op_dup:SI 6
1809 [(ashiftrt:SI (match_dup 2) (const_int 31))
1810 (match_dup 4)]))]
1811 "
215b30b3 1812 {
1813 operands[3] = gen_highpart (SImode, operands[0]);
1814 operands[0] = gen_lowpart (SImode, operands[0]);
1815 operands[4] = gen_highpart (SImode, operands[1]);
1816 operands[1] = gen_lowpart (SImode, operands[1]);
1817 operands[5] = gen_highpart (SImode, operands[2]);
1818 operands[2] = gen_lowpart (SImode, operands[2]);
1819 }"
1820)
f6ebffac 1821
f6ebffac 1822;; The zero extend of operand 2 means we can just copy the high part of
1823;; operand1 into operand0.
1824(define_split
1825 [(set (match_operand:DI 0 "s_register_operand" "")
1826 (ior:DI
1827 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1828 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1829 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1830 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1831 (set (match_dup 3) (match_dup 4))]
1832 "
215b30b3 1833 {
1834 operands[4] = gen_highpart (SImode, operands[1]);
1835 operands[3] = gen_highpart (SImode, operands[0]);
1836 operands[0] = gen_lowpart (SImode, operands[0]);
1837 operands[1] = gen_lowpart (SImode, operands[1]);
1838 }"
1839)
f6ebffac 1840
1841;; The zero extend of operand 2 means we can just copy the high part of
1842;; operand1 into operand0.
1843(define_split
1844 [(set (match_operand:DI 0 "s_register_operand" "")
1845 (xor:DI
1846 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1847 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1848 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1849 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1850 (set (match_dup 3) (match_dup 4))]
1851 "
215b30b3 1852 {
1853 operands[4] = gen_highpart (SImode, operands[1]);
1854 operands[3] = gen_highpart (SImode, operands[0]);
1855 operands[0] = gen_lowpart (SImode, operands[0]);
1856 operands[1] = gen_lowpart (SImode, operands[1]);
1857 }"
1858)
f6ebffac 1859
b11cae9e 1860(define_insn "anddi3"
cffb2a26 1861 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1862 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1863 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 1864 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 1865 "#"
215b30b3 1866 [(set_attr "length" "8")]
1867)
b11cae9e 1868
a0f94409 1869(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1870 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1871 (and:DI (zero_extend:DI
1872 (match_operand:SI 2 "s_register_operand" "r,r"))
1873 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1874 "TARGET_32BIT"
f6ebffac 1875 "#"
25f905c2 1876 "TARGET_32BIT && reload_completed"
a0f94409 1877 ; The zero extend of operand 2 clears the high word of the output
1878 ; operand.
1879 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1880 (set (match_dup 3) (const_int 0))]
1881 "
1882 {
1883 operands[3] = gen_highpart (SImode, operands[0]);
1884 operands[0] = gen_lowpart (SImode, operands[0]);
1885 operands[1] = gen_lowpart (SImode, operands[1]);
1886 }"
215b30b3 1887 [(set_attr "length" "8")]
1888)
b11cae9e 1889
f7fbdd4a 1890(define_insn "*anddi_sesdi_di"
cffb2a26 1891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1892 (and:DI (sign_extend:DI
1893 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1894 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1895 "TARGET_32BIT"
f6ebffac 1896 "#"
cffb2a26 1897 [(set_attr "length" "8")]
1898)
b11cae9e 1899
87b22bf7 1900(define_expand "andsi3"
cffb2a26 1901 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1902 (and:SI (match_operand:SI 1 "s_register_operand" "")
1903 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1904 "TARGET_EITHER"
87b22bf7 1905 "
25f905c2 1906 if (TARGET_32BIT)
87b22bf7 1907 {
cffb2a26 1908 if (GET_CODE (operands[2]) == CONST_INT)
1909 {
96f57e36 1910 arm_split_constant (AND, SImode, NULL_RTX,
1911 INTVAL (operands[2]), operands[0],
e1ba4a27 1912 operands[1], optimize && can_create_pseudo_p ());
615caa51 1913
cffb2a26 1914 DONE;
1915 }
87b22bf7 1916 }
25f905c2 1917 else /* TARGET_THUMB1 */
cffb2a26 1918 {
1919 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 1920 {
1921 rtx tmp = force_reg (SImode, operands[2]);
1922 if (rtx_equal_p (operands[0], operands[1]))
1923 operands[2] = tmp;
1924 else
1925 {
1926 operands[2] = operands[1];
1927 operands[1] = tmp;
1928 }
1929 }
cffb2a26 1930 else
1931 {
1932 int i;
1933
215b30b3 1934 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1935 {
215b30b3 1936 operands[2] = force_reg (SImode,
1937 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1938
1939 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1940
1941 DONE;
1942 }
87b22bf7 1943
cffb2a26 1944 for (i = 9; i <= 31; i++)
1945 {
1946 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1947 {
1948 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1949 const0_rtx));
1950 DONE;
1951 }
215b30b3 1952 else if ((((HOST_WIDE_INT) 1) << i) - 1
1953 == ~INTVAL (operands[2]))
cffb2a26 1954 {
1955 rtx shift = GEN_INT (i);
1956 rtx reg = gen_reg_rtx (SImode);
1957
1958 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1959 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1960
1961 DONE;
1962 }
1963 }
1964
1965 operands[2] = force_reg (SImode, operands[2]);
1966 }
215b30b3 1967 }
1968 "
cffb2a26 1969)
1970
25f905c2 1971; ??? Check split length for Thumb-2
a0f94409 1972(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1973 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1974 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1975 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 1976 "TARGET_32BIT"
5565501b 1977 "@
1978 and%?\\t%0, %1, %2
87b22bf7 1979 bic%?\\t%0, %1, #%B2
1980 #"
25f905c2 1981 "TARGET_32BIT
a0f94409 1982 && GET_CODE (operands[2]) == CONST_INT
1983 && !(const_ok_for_arm (INTVAL (operands[2]))
1984 || const_ok_for_arm (~INTVAL (operands[2])))"
1985 [(clobber (const_int 0))]
1986 "
96f57e36 1987 arm_split_constant (AND, SImode, curr_insn,
1988 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1989 DONE;
1990 "
0d66636f 1991 [(set_attr "length" "4,4,16")
1992 (set_attr "predicable" "yes")]
cffb2a26 1993)
1994
25f905c2 1995(define_insn "*thumb1_andsi3_insn"
cffb2a26 1996 [(set (match_operand:SI 0 "register_operand" "=l")
1997 (and:SI (match_operand:SI 1 "register_operand" "%0")
1998 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1999 "TARGET_THUMB1"
cffb2a26 2000 "and\\t%0, %0, %2"
2001 [(set_attr "length" "2")]
2002)
87b22bf7 2003
f7fbdd4a 2004(define_insn "*andsi3_compare0"
bd5b4116 2005 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2006 (compare:CC_NOOV
2007 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2008 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2009 (const_int 0)))
cffb2a26 2010 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2011 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2012 "TARGET_32BIT"
5565501b 2013 "@
25f905c2 2014 and%.\\t%0, %1, %2
2015 bic%.\\t%0, %1, #%B2"
cffb2a26 2016 [(set_attr "conds" "set")]
2017)
9c08d1fa 2018
f7fbdd4a 2019(define_insn "*andsi3_compare0_scratch"
bd5b4116 2020 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2021 (compare:CC_NOOV
2022 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2023 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2024 (const_int 0)))
dd193d7c 2025 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2026 "TARGET_32BIT"
5565501b 2027 "@
2028 tst%?\\t%0, %1
25f905c2 2029 bic%.\\t%2, %0, #%B1"
0d66636f 2030 [(set_attr "conds" "set")]
2031)
9c08d1fa 2032
f7fbdd4a 2033(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2034 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2035 (compare:CC_NOOV (zero_extract:SI
2036 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2037 (match_operand 1 "const_int_operand" "n")
2038 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2039 (const_int 0)))]
25f905c2 2040 "TARGET_32BIT
cffb2a26 2041 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2042 && INTVAL (operands[1]) > 0
2043 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2044 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2045 "*
5c49a439 2046 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2047 << INTVAL (operands[2]));
40dbec34 2048 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2049 return \"\";
0d66636f 2050 "
2051 [(set_attr "conds" "set")]
2052)
9c08d1fa 2053
f4462328 2054(define_insn_and_split "*ne_zeroextractsi"
c4034607 2055 [(set (match_operand:SI 0 "s_register_operand" "=r")
2056 (ne:SI (zero_extract:SI
2057 (match_operand:SI 1 "s_register_operand" "r")
2058 (match_operand:SI 2 "const_int_operand" "n")
2059 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2060 (const_int 0)))
2061 (clobber (reg:CC CC_REGNUM))]
25f905c2 2062 "TARGET_32BIT
cffb2a26 2063 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2064 && INTVAL (operands[2]) > 0
2065 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2066 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2067 "#"
25f905c2 2068 "TARGET_32BIT
f4462328 2069 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2070 && INTVAL (operands[2]) > 0
2071 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2072 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2073 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2074 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2075 (const_int 0)))
2076 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2077 (set (match_dup 0)
2078 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2079 (match_dup 0) (const_int 1)))]
2080 "
2081 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2082 << INTVAL (operands[3]));
2083 "
2084 [(set_attr "conds" "clob")
25f905c2 2085 (set (attr "length")
2086 (if_then_else (eq_attr "is_thumb" "yes")
2087 (const_int 12)
2088 (const_int 8)))]
f4462328 2089)
2090
2091(define_insn_and_split "*ne_zeroextractsi_shifted"
2092 [(set (match_operand:SI 0 "s_register_operand" "=r")
2093 (ne:SI (zero_extract:SI
2094 (match_operand:SI 1 "s_register_operand" "r")
2095 (match_operand:SI 2 "const_int_operand" "n")
2096 (const_int 0))
2097 (const_int 0)))
2098 (clobber (reg:CC CC_REGNUM))]
2099 "TARGET_ARM"
2100 "#"
2101 "TARGET_ARM"
2102 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2103 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2104 (const_int 0)))
2105 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2106 (set (match_dup 0)
2107 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2108 (match_dup 0) (const_int 1)))]
2109 "
2110 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2111 "
2112 [(set_attr "conds" "clob")
2113 (set_attr "length" "8")]
2114)
2115
2116(define_insn_and_split "*ite_ne_zeroextractsi"
2117 [(set (match_operand:SI 0 "s_register_operand" "=r")
2118 (if_then_else:SI (ne (zero_extract:SI
2119 (match_operand:SI 1 "s_register_operand" "r")
2120 (match_operand:SI 2 "const_int_operand" "n")
2121 (match_operand:SI 3 "const_int_operand" "n"))
2122 (const_int 0))
2123 (match_operand:SI 4 "arm_not_operand" "rIK")
2124 (const_int 0)))
2125 (clobber (reg:CC CC_REGNUM))]
2126 "TARGET_ARM
2127 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2128 && INTVAL (operands[2]) > 0
2129 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2130 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2131 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2132 "#"
2133 "TARGET_ARM
2134 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2135 && INTVAL (operands[2]) > 0
2136 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2137 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2138 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2139 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2140 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2141 (const_int 0)))
2142 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2143 (set (match_dup 0)
2144 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2145 (match_dup 0) (match_dup 4)))]
2146 "
c4034607 2147 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2148 << INTVAL (operands[3]));
2149 "
2150 [(set_attr "conds" "clob")
2151 (set_attr "length" "8")]
2152)
2153
2154(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2155 [(set (match_operand:SI 0 "s_register_operand" "=r")
2156 (if_then_else:SI (ne (zero_extract:SI
2157 (match_operand:SI 1 "s_register_operand" "r")
2158 (match_operand:SI 2 "const_int_operand" "n")
2159 (const_int 0))
2160 (const_int 0))
2161 (match_operand:SI 3 "arm_not_operand" "rIK")
2162 (const_int 0)))
2163 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2164 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2165 "#"
f8d7bf2f 2166 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2167 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2168 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2169 (const_int 0)))
2170 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2171 (set (match_dup 0)
2172 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2173 (match_dup 0) (match_dup 3)))]
2174 "
2175 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2176 "
2177 [(set_attr "conds" "clob")
215b30b3 2178 (set_attr "length" "8")]
2179)
9c08d1fa 2180
58d6528b 2181(define_split
2182 [(set (match_operand:SI 0 "s_register_operand" "")
2183 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2184 (match_operand:SI 2 "const_int_operand" "")
2185 (match_operand:SI 3 "const_int_operand" "")))
2186 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2187 "TARGET_THUMB1"
58d6528b 2188 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2189 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2190 "{
2191 HOST_WIDE_INT temp = INTVAL (operands[2]);
2192
2193 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2194 operands[3] = GEN_INT (32 - temp);
2195 }"
2196)
2197
25f905c2 2198;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2199(define_split
2200 [(set (match_operand:SI 0 "s_register_operand" "")
2201 (match_operator:SI 1 "shiftable_operator"
2202 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2203 (match_operand:SI 3 "const_int_operand" "")
2204 (match_operand:SI 4 "const_int_operand" ""))
2205 (match_operand:SI 5 "s_register_operand" "")]))
2206 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2207 "TARGET_ARM"
2208 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2209 (set (match_dup 0)
2210 (match_op_dup 1
2211 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2212 (match_dup 5)]))]
2213 "{
2214 HOST_WIDE_INT temp = INTVAL (operands[3]);
2215
2216 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2217 operands[4] = GEN_INT (32 - temp);
2218 }"
2219)
2220
58d6528b 2221(define_split
2222 [(set (match_operand:SI 0 "s_register_operand" "")
2223 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2224 (match_operand:SI 2 "const_int_operand" "")
2225 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2226 "TARGET_THUMB1"
58d6528b 2227 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2228 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2229 "{
2230 HOST_WIDE_INT temp = INTVAL (operands[2]);
2231
2232 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2233 operands[3] = GEN_INT (32 - temp);
2234 }"
2235)
2236
d7863cfe 2237(define_split
2238 [(set (match_operand:SI 0 "s_register_operand" "")
2239 (match_operator:SI 1 "shiftable_operator"
2240 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2241 (match_operand:SI 3 "const_int_operand" "")
2242 (match_operand:SI 4 "const_int_operand" ""))
2243 (match_operand:SI 5 "s_register_operand" "")]))
2244 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2245 "TARGET_ARM"
2246 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2247 (set (match_dup 0)
2248 (match_op_dup 1
2249 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2250 (match_dup 5)]))]
2251 "{
2252 HOST_WIDE_INT temp = INTVAL (operands[3]);
2253
2254 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2255 operands[4] = GEN_INT (32 - temp);
2256 }"
2257)
2258
a42059fd 2259;;; ??? This pattern is bogus. If operand3 has bits outside the range
2260;;; represented by the bitfield, then this will produce incorrect results.
2261;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2262;;; which have a real bit-field insert instruction, the truncation happens
2263;;; in the bit-field insert instruction itself. Since arm does not have a
2264;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2265;;; the value before we insert. This loses some of the advantage of having
2266;;; this insv pattern, so this pattern needs to be reevalutated.
2267
8a18b90c 2268(define_expand "insv"
2269 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2270 (match_operand:SI 1 "general_operand" "")
2271 (match_operand:SI 2 "general_operand" ""))
19335226 2272 (match_operand:SI 3 "reg_or_int_operand" ""))]
8b054d5a 2273 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2274 "
215b30b3 2275 {
2276 int start_bit = INTVAL (operands[2]);
2277 int width = INTVAL (operands[1]);
2278 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2279 rtx target, subtarget;
2280
8b054d5a 2281 if (arm_arch_thumb2)
2282 {
2283 bool use_bfi = TRUE;
2284
2285 if (GET_CODE (operands[3]) == CONST_INT)
2286 {
2287 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2288
2289 if (val == 0)
2290 {
2291 emit_insn (gen_insv_zero (operands[0], operands[1],
2292 operands[2]));
2293 DONE;
2294 }
2295
2296 /* See if the set can be done with a single orr instruction. */
2297 if (val == mask && const_ok_for_arm (val << start_bit))
2298 use_bfi = FALSE;
2299 }
2300
2301 if (use_bfi)
2302 {
2303 if (GET_CODE (operands[3]) != REG)
2304 operands[3] = force_reg (SImode, operands[3]);
2305
2306 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2307 operands[3]));
2308 DONE;
2309 }
2310 }
2311
3f8fde42 2312 target = copy_rtx (operands[0]);
215b30b3 2313 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2314 subreg as the final target. */
2315 if (GET_CODE (target) == SUBREG)
2316 {
2317 subtarget = gen_reg_rtx (SImode);
2318 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2319 < GET_MODE_SIZE (SImode))
2320 target = SUBREG_REG (target);
2321 }
2322 else
2323 subtarget = target;
8a18b90c 2324
215b30b3 2325 if (GET_CODE (operands[3]) == CONST_INT)
2326 {
2327 /* Since we are inserting a known constant, we may be able to
2328 reduce the number of bits that we have to clear so that
2329 the mask becomes simple. */
2330 /* ??? This code does not check to see if the new mask is actually
2331 simpler. It may not be. */
2332 rtx op1 = gen_reg_rtx (SImode);
2333 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2334 start of this pattern. */
2335 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2336 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2337
c5b3a71b 2338 emit_insn (gen_andsi3 (op1, operands[0],
2339 gen_int_mode (~mask2, SImode)));
215b30b3 2340 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2341 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2342 }
2343 else if (start_bit == 0
2344 && !(const_ok_for_arm (mask)
2345 || const_ok_for_arm (~mask)))
2346 {
2347 /* A Trick, since we are setting the bottom bits in the word,
2348 we can shift operand[3] up, operand[0] down, OR them together
2349 and rotate the result back again. This takes 3 insns, and
5910bb95 2350 the third might be mergeable into another op. */
215b30b3 2351 /* The shift up copes with the possibility that operand[3] is
2352 wider than the bitfield. */
2353 rtx op0 = gen_reg_rtx (SImode);
2354 rtx op1 = gen_reg_rtx (SImode);
2355
2356 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2357 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2358 emit_insn (gen_iorsi3 (op1, op1, op0));
2359 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2360 }
2361 else if ((width + start_bit == 32)
2362 && !(const_ok_for_arm (mask)
2363 || const_ok_for_arm (~mask)))
2364 {
2365 /* Similar trick, but slightly less efficient. */
8a18b90c 2366
215b30b3 2367 rtx op0 = gen_reg_rtx (SImode);
2368 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2369
215b30b3 2370 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2371 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2372 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2373 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2374 }
2375 else
2376 {
c5b3a71b 2377 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2378 rtx op1 = gen_reg_rtx (SImode);
2379 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2380
215b30b3 2381 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2382 {
2383 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2384
215b30b3 2385 emit_insn (gen_movsi (tmp, op0));
2386 op0 = tmp;
2387 }
8a18b90c 2388
215b30b3 2389 /* Mask out any bits in operand[3] that are not needed. */
2390 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2391
215b30b3 2392 if (GET_CODE (op0) == CONST_INT
2393 && (const_ok_for_arm (mask << start_bit)
2394 || const_ok_for_arm (~(mask << start_bit))))
2395 {
c5b3a71b 2396 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2397 emit_insn (gen_andsi3 (op2, operands[0], op0));
2398 }
2399 else
2400 {
2401 if (GET_CODE (op0) == CONST_INT)
2402 {
2403 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2404
215b30b3 2405 emit_insn (gen_movsi (tmp, op0));
2406 op0 = tmp;
2407 }
2408
2409 if (start_bit != 0)
2410 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2411
215b30b3 2412 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2413 }
8a18b90c 2414
215b30b3 2415 if (start_bit != 0)
2416 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2417
215b30b3 2418 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2419 }
f082f1c4 2420
215b30b3 2421 if (subtarget != target)
2422 {
2423 /* If TARGET is still a SUBREG, then it must be wider than a word,
2424 so we must be careful only to set the subword we were asked to. */
2425 if (GET_CODE (target) == SUBREG)
2426 emit_move_insn (target, subtarget);
2427 else
2428 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2429 }
8a18b90c 2430
215b30b3 2431 DONE;
2432 }"
2433)
8a18b90c 2434
8b054d5a 2435(define_insn "insv_zero"
2436 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2437 (match_operand:SI 1 "const_int_operand" "M")
2438 (match_operand:SI 2 "const_int_operand" "M"))
2439 (const_int 0))]
2440 "arm_arch_thumb2"
2441 "bfc%?\t%0, %2, %1"
2442 [(set_attr "length" "4")
2443 (set_attr "predicable" "yes")]
2444)
2445
2446(define_insn "insv_t2"
2447 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2448 (match_operand:SI 1 "const_int_operand" "M")
2449 (match_operand:SI 2 "const_int_operand" "M"))
2450 (match_operand:SI 3 "s_register_operand" "r"))]
2451 "arm_arch_thumb2"
2452 "bfi%?\t%0, %3, %2, %1"
2453 [(set_attr "length" "4")
2454 (set_attr "predicable" "yes")]
2455)
2456
215b30b3 2457; constants for op 2 will never be given to these patterns.
a0f94409 2458(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2459 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 2460 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2461 (match_operand:DI 2 "s_register_operand" "0,r")))]
25f905c2 2462 "TARGET_32BIT"
f6ebffac 2463 "#"
25f905c2 2464 "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2465 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2466 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2467 "
2468 {
2469 operands[3] = gen_highpart (SImode, operands[0]);
2470 operands[0] = gen_lowpart (SImode, operands[0]);
2471 operands[4] = gen_highpart (SImode, operands[1]);
2472 operands[1] = gen_lowpart (SImode, operands[1]);
2473 operands[5] = gen_highpart (SImode, operands[2]);
2474 operands[2] = gen_lowpart (SImode, operands[2]);
2475 }"
0d66636f 2476 [(set_attr "length" "8")
2477 (set_attr "predicable" "yes")]
2478)
9c08d1fa 2479
a0f94409 2480(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2481 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2482 (and:DI (not:DI (zero_extend:DI
2483 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2484 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2485 "TARGET_32BIT"
e2348bcb 2486 "@
97499065 2487 bic%?\\t%Q0, %Q1, %2
f6ebffac 2488 #"
a0f94409 2489 ; (not (zero_extend ...)) allows us to just copy the high word from
2490 ; operand1 to operand0.
25f905c2 2491 "TARGET_32BIT
a0f94409 2492 && reload_completed
2493 && operands[0] != operands[1]"
5a097f7d 2494 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2495 (set (match_dup 3) (match_dup 4))]
2496 "
2497 {
2498 operands[3] = gen_highpart (SImode, operands[0]);
2499 operands[0] = gen_lowpart (SImode, operands[0]);
2500 operands[4] = gen_highpart (SImode, operands[1]);
2501 operands[1] = gen_lowpart (SImode, operands[1]);
2502 }"
0d66636f 2503 [(set_attr "length" "4,8")
2504 (set_attr "predicable" "yes")]
2505)
9c08d1fa 2506
a0f94409 2507(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2508 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2509 (and:DI (not:DI (sign_extend:DI
2510 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2511 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2512 "TARGET_32BIT"
f6ebffac 2513 "#"
25f905c2 2514 "TARGET_32BIT && reload_completed"
5a097f7d 2515 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2516 (set (match_dup 3) (and:SI (not:SI
2517 (ashiftrt:SI (match_dup 2) (const_int 31)))
2518 (match_dup 4)))]
2519 "
2520 {
2521 operands[3] = gen_highpart (SImode, operands[0]);
2522 operands[0] = gen_lowpart (SImode, operands[0]);
2523 operands[4] = gen_highpart (SImode, operands[1]);
2524 operands[1] = gen_lowpart (SImode, operands[1]);
2525 }"
0d66636f 2526 [(set_attr "length" "8")
2527 (set_attr "predicable" "yes")]
2528)
9c08d1fa 2529
8a18b90c 2530(define_insn "andsi_notsi_si"
9c08d1fa 2531 [(set (match_operand:SI 0 "s_register_operand" "=r")
2532 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2533 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2534 "TARGET_32BIT"
0d66636f 2535 "bic%?\\t%0, %1, %2"
2536 [(set_attr "predicable" "yes")]
2537)
b11cae9e 2538
cffb2a26 2539(define_insn "bicsi3"
2540 [(set (match_operand:SI 0 "register_operand" "=l")
2541 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2542 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2543 "TARGET_THUMB1"
cffb2a26 2544 "bic\\t%0, %0, %1"
2545 [(set_attr "length" "2")]
2546)
2547
8a18b90c 2548(define_insn "andsi_not_shiftsi_si"
a2cd141b 2549 [(set (match_operand:SI 0 "s_register_operand" "=r")
2550 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2551 [(match_operand:SI 2 "s_register_operand" "r")
2552 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2553 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2554 "TARGET_ARM"
6c4c2133 2555 "bic%?\\t%0, %1, %2%S4"
344495ea 2556 [(set_attr "predicable" "yes")
331beb1a 2557 (set_attr "shift" "2")
a2cd141b 2558 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2559 (const_string "alu_shift")
2560 (const_string "alu_shift_reg")))]
6c4c2133 2561)
8a18b90c 2562
f7fbdd4a 2563(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2564 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2565 (compare:CC_NOOV
2566 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2567 (match_operand:SI 1 "s_register_operand" "r"))
2568 (const_int 0)))
9c08d1fa 2569 (set (match_operand:SI 0 "s_register_operand" "=r")
2570 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2571 "TARGET_32BIT"
2572 "bic%.\\t%0, %1, %2"
0d66636f 2573 [(set_attr "conds" "set")]
2574)
9c08d1fa 2575
f7fbdd4a 2576(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2577 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2578 (compare:CC_NOOV
2579 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2580 (match_operand:SI 1 "s_register_operand" "r"))
2581 (const_int 0)))
9c08d1fa 2582 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2583 "TARGET_32BIT"
2584 "bic%.\\t%0, %1, %2"
0d66636f 2585 [(set_attr "conds" "set")]
2586)
9c08d1fa 2587
2588(define_insn "iordi3"
cffb2a26 2589 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2590 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2591 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2592 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 2593 "#"
0d66636f 2594 [(set_attr "length" "8")
2595 (set_attr "predicable" "yes")]
cffb2a26 2596)
9c08d1fa 2597
f7fbdd4a 2598(define_insn "*iordi_zesidi_di"
9c08d1fa 2599 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2600 (ior:DI (zero_extend:DI
2601 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2602 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2603 "TARGET_32BIT"
e2348bcb 2604 "@
97499065 2605 orr%?\\t%Q0, %Q1, %2
f6ebffac 2606 #"
0d66636f 2607 [(set_attr "length" "4,8")
2608 (set_attr "predicable" "yes")]
cffb2a26 2609)
9c08d1fa 2610
f7fbdd4a 2611(define_insn "*iordi_sesidi_di"
9c08d1fa 2612 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2613 (ior:DI (sign_extend:DI
2614 (match_operand:SI 2 "s_register_operand" "r,r"))
2615 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2616 "TARGET_32BIT"
f6ebffac 2617 "#"
0d66636f 2618 [(set_attr "length" "8")
2619 (set_attr "predicable" "yes")]
cffb2a26 2620)
9c08d1fa 2621
87b22bf7 2622(define_expand "iorsi3"
cffb2a26 2623 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2624 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2625 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2626 "TARGET_EITHER"
87b22bf7 2627 "
2628 if (GET_CODE (operands[2]) == CONST_INT)
2629 {
25f905c2 2630 if (TARGET_32BIT)
cffb2a26 2631 {
96f57e36 2632 arm_split_constant (IOR, SImode, NULL_RTX,
2633 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2634 optimize && can_create_pseudo_p ());
cffb2a26 2635 DONE;
2636 }
25f905c2 2637 else /* TARGET_THUMB1 */
923ffadb 2638 {
2639 rtx tmp = force_reg (SImode, operands[2]);
2640 if (rtx_equal_p (operands[0], operands[1]))
2641 operands[2] = tmp;
2642 else
2643 {
2644 operands[2] = operands[1];
2645 operands[1] = tmp;
2646 }
2647 }
87b22bf7 2648 }
cffb2a26 2649 "
2650)
87b22bf7 2651
a0f94409 2652(define_insn_and_split "*arm_iorsi3"
cffb2a26 2653 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2654 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2655 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
90560cad 2656 "TARGET_ARM"
87b22bf7 2657 "@
2658 orr%?\\t%0, %1, %2
2659 #"
90560cad 2660 "TARGET_ARM
a0f94409 2661 && GET_CODE (operands[2]) == CONST_INT
2662 && !const_ok_for_arm (INTVAL (operands[2]))"
2663 [(clobber (const_int 0))]
2664 "
96f57e36 2665 arm_split_constant (IOR, SImode, curr_insn,
2666 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2667 DONE;
2668 "
0d66636f 2669 [(set_attr "length" "4,16")
2670 (set_attr "predicable" "yes")]
cffb2a26 2671)
2672
25f905c2 2673(define_insn "*thumb1_iorsi3"
cffb2a26 2674 [(set (match_operand:SI 0 "register_operand" "=l")
2675 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2676 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2677 "TARGET_THUMB1"
cffb2a26 2678 "orr\\t%0, %0, %2"
2679 [(set_attr "length" "2")]
2680)
9c08d1fa 2681
a0f94409 2682(define_peephole2
2683 [(match_scratch:SI 3 "r")
372575c7 2684 (set (match_operand:SI 0 "arm_general_register_operand" "")
2685 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2686 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2687 "TARGET_ARM
a0f94409 2688 && !const_ok_for_arm (INTVAL (operands[2]))
2689 && const_ok_for_arm (~INTVAL (operands[2]))"
2690 [(set (match_dup 3) (match_dup 2))
2691 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2692 ""
215b30b3 2693)
a0f94409 2694
f7fbdd4a 2695(define_insn "*iorsi3_compare0"
bd5b4116 2696 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2697 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2698 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2699 (const_int 0)))
2700 (set (match_operand:SI 0 "s_register_operand" "=r")
2701 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2702 "TARGET_32BIT"
2703 "orr%.\\t%0, %1, %2"
cffb2a26 2704 [(set_attr "conds" "set")]
2705)
9c08d1fa 2706
f7fbdd4a 2707(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2708 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2709 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2710 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2711 (const_int 0)))
2712 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2713 "TARGET_32BIT"
2714 "orr%.\\t%0, %1, %2"
0d66636f 2715 [(set_attr "conds" "set")]
2716)
9c08d1fa 2717
2718(define_insn "xordi3"
cffb2a26 2719 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2720 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2721 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2722 "TARGET_32BIT && !TARGET_IWMMXT"
f6ebffac 2723 "#"
0d66636f 2724 [(set_attr "length" "8")
2725 (set_attr "predicable" "yes")]
cffb2a26 2726)
9c08d1fa 2727
f7fbdd4a 2728(define_insn "*xordi_zesidi_di"
9c08d1fa 2729 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2730 (xor:DI (zero_extend:DI
2731 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2732 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2733 "TARGET_32BIT"
e2348bcb 2734 "@
97499065 2735 eor%?\\t%Q0, %Q1, %2
f6ebffac 2736 #"
0d66636f 2737 [(set_attr "length" "4,8")
2738 (set_attr "predicable" "yes")]
cffb2a26 2739)
9c08d1fa 2740
f7fbdd4a 2741(define_insn "*xordi_sesidi_di"
9c08d1fa 2742 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2743 (xor:DI (sign_extend:DI
2744 (match_operand:SI 2 "s_register_operand" "r,r"))
2745 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2746 "TARGET_32BIT"
f6ebffac 2747 "#"
0d66636f 2748 [(set_attr "length" "8")
2749 (set_attr "predicable" "yes")]
cffb2a26 2750)
9c08d1fa 2751
cffb2a26 2752(define_expand "xorsi3"
2753 [(set (match_operand:SI 0 "s_register_operand" "")
2754 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 2755 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2756 "TARGET_EITHER"
923ffadb 2757 "if (GET_CODE (operands[2]) == CONST_INT)
2758 {
2759 if (TARGET_32BIT)
2760 {
2761 arm_split_constant (XOR, SImode, NULL_RTX,
2762 INTVAL (operands[2]), operands[0], operands[1],
2763 optimize && can_create_pseudo_p ());
2764 DONE;
2765 }
2766 else /* TARGET_THUMB1 */
2767 {
2768 rtx tmp = force_reg (SImode, operands[2]);
2769 if (rtx_equal_p (operands[0], operands[1]))
2770 operands[2] = tmp;
2771 else
2772 {
2773 operands[2] = operands[1];
2774 operands[1] = tmp;
2775 }
2776 }
2777 }"
cffb2a26 2778)
2779
2780(define_insn "*arm_xorsi3"
2781 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2782 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2783 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2784 "TARGET_32BIT"
cffb2a26 2785 "eor%?\\t%0, %1, %2"
0d66636f 2786 [(set_attr "predicable" "yes")]
cffb2a26 2787)
2788
25f905c2 2789(define_insn "*thumb1_xorsi3"
cffb2a26 2790 [(set (match_operand:SI 0 "register_operand" "=l")
2791 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2792 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2793 "TARGET_THUMB1"
cffb2a26 2794 "eor\\t%0, %0, %2"
2795 [(set_attr "length" "2")]
2796)
9c08d1fa 2797
f7fbdd4a 2798(define_insn "*xorsi3_compare0"
bd5b4116 2799 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2800 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2801 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2802 (const_int 0)))
2803 (set (match_operand:SI 0 "s_register_operand" "=r")
2804 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2805 "TARGET_32BIT"
2806 "eor%.\\t%0, %1, %2"
0d66636f 2807 [(set_attr "conds" "set")]
2808)
9c08d1fa 2809
f7fbdd4a 2810(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2811 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2812 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2813 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2814 (const_int 0)))]
25f905c2 2815 "TARGET_32BIT"
40dbec34 2816 "teq%?\\t%0, %1"
cffb2a26 2817 [(set_attr "conds" "set")]
2818)
9c08d1fa 2819
215b30b3 2820; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2821; (NOT D) we can sometimes merge the final NOT into one of the following
2822; insns.
9c08d1fa 2823
2824(define_split
a058e94a 2825 [(set (match_operand:SI 0 "s_register_operand" "")
2826 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2827 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2828 (match_operand:SI 3 "arm_rhs_operand" "")))
2829 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2830 "TARGET_32BIT"
9c08d1fa 2831 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2832 (not:SI (match_dup 3))))
2833 (set (match_dup 0) (not:SI (match_dup 4)))]
2834 ""
2835)
2836
f7fbdd4a 2837(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2838 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2839 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2840 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2841 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2842 "TARGET_32BIT"
40dbec34 2843 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2844 [(set_attr "length" "8")
25f905c2 2845 (set_attr "ce_count" "2")
0d66636f 2846 (set_attr "predicable" "yes")]
cffb2a26 2847)
9c08d1fa 2848
25f905c2 2849; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2850; insns are available?
d7863cfe 2851(define_split
2852 [(set (match_operand:SI 0 "s_register_operand" "")
2853 (match_operator:SI 1 "logical_binary_operator"
2854 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2855 (match_operand:SI 3 "const_int_operand" "")
2856 (match_operand:SI 4 "const_int_operand" ""))
2857 (match_operator:SI 9 "logical_binary_operator"
2858 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2859 (match_operand:SI 6 "const_int_operand" ""))
2860 (match_operand:SI 7 "s_register_operand" "")])]))
2861 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2862 "TARGET_32BIT
d7863cfe 2863 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2864 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2865 [(set (match_dup 8)
2866 (match_op_dup 1
2867 [(ashift:SI (match_dup 2) (match_dup 4))
2868 (match_dup 5)]))
2869 (set (match_dup 0)
2870 (match_op_dup 1
2871 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2872 (match_dup 7)]))]
2873 "
2874 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2875")
2876
2877(define_split
2878 [(set (match_operand:SI 0 "s_register_operand" "")
2879 (match_operator:SI 1 "logical_binary_operator"
2880 [(match_operator:SI 9 "logical_binary_operator"
2881 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2882 (match_operand:SI 6 "const_int_operand" ""))
2883 (match_operand:SI 7 "s_register_operand" "")])
2884 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2885 (match_operand:SI 3 "const_int_operand" "")
2886 (match_operand:SI 4 "const_int_operand" ""))]))
2887 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2888 "TARGET_32BIT
d7863cfe 2889 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2890 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2891 [(set (match_dup 8)
2892 (match_op_dup 1
2893 [(ashift:SI (match_dup 2) (match_dup 4))
2894 (match_dup 5)]))
2895 (set (match_dup 0)
2896 (match_op_dup 1
2897 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2898 (match_dup 7)]))]
2899 "
2900 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2901")
2902
2903(define_split
2904 [(set (match_operand:SI 0 "s_register_operand" "")
2905 (match_operator:SI 1 "logical_binary_operator"
2906 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2907 (match_operand:SI 3 "const_int_operand" "")
2908 (match_operand:SI 4 "const_int_operand" ""))
2909 (match_operator:SI 9 "logical_binary_operator"
2910 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2911 (match_operand:SI 6 "const_int_operand" ""))
2912 (match_operand:SI 7 "s_register_operand" "")])]))
2913 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2914 "TARGET_32BIT
d7863cfe 2915 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2916 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2917 [(set (match_dup 8)
2918 (match_op_dup 1
2919 [(ashift:SI (match_dup 2) (match_dup 4))
2920 (match_dup 5)]))
2921 (set (match_dup 0)
2922 (match_op_dup 1
2923 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2924 (match_dup 7)]))]
2925 "
2926 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2927")
2928
2929(define_split
2930 [(set (match_operand:SI 0 "s_register_operand" "")
2931 (match_operator:SI 1 "logical_binary_operator"
2932 [(match_operator:SI 9 "logical_binary_operator"
2933 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2934 (match_operand:SI 6 "const_int_operand" ""))
2935 (match_operand:SI 7 "s_register_operand" "")])
2936 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2937 (match_operand:SI 3 "const_int_operand" "")
2938 (match_operand:SI 4 "const_int_operand" ""))]))
2939 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2940 "TARGET_32BIT
d7863cfe 2941 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2942 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2943 [(set (match_dup 8)
2944 (match_op_dup 1
2945 [(ashift:SI (match_dup 2) (match_dup 4))
2946 (match_dup 5)]))
2947 (set (match_dup 0)
2948 (match_op_dup 1
2949 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2950 (match_dup 7)]))]
2951 "
2952 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2953")
9c08d1fa 2954\f
2955
2956;; Minimum and maximum insns
2957
8b9dc177 2958(define_expand "smaxsi3"
2959 [(parallel [
2960 (set (match_operand:SI 0 "s_register_operand" "")
2961 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2962 (match_operand:SI 2 "arm_rhs_operand" "")))
2963 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2964 "TARGET_32BIT"
8b9dc177 2965 "
8774928b 2966 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 2967 {
2968 /* No need for a clobber of the condition code register here. */
2969 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2970 gen_rtx_SMAX (SImode, operands[1],
2971 operands[2])));
2972 DONE;
2973 }
2974")
2975
2976(define_insn "*smax_0"
2977 [(set (match_operand:SI 0 "s_register_operand" "=r")
2978 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2979 (const_int 0)))]
25f905c2 2980 "TARGET_32BIT"
8b9dc177 2981 "bic%?\\t%0, %1, %1, asr #31"
2982 [(set_attr "predicable" "yes")]
2983)
2984
8774928b 2985(define_insn "*smax_m1"
2986 [(set (match_operand:SI 0 "s_register_operand" "=r")
2987 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2988 (const_int -1)))]
25f905c2 2989 "TARGET_32BIT"
8774928b 2990 "orr%?\\t%0, %1, %1, asr #31"
2991 [(set_attr "predicable" "yes")]
2992)
2993
25f905c2 2994(define_insn "*arm_smax_insn"
8b9dc177 2995 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2996 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2997 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 2998 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2999 "TARGET_ARM"
e2348bcb 3000 "@
3001 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3002 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3003 [(set_attr "conds" "clob")
8b9dc177 3004 (set_attr "length" "8,12")]
cffb2a26 3005)
9c08d1fa 3006
8b9dc177 3007(define_expand "sminsi3"
3008 [(parallel [
3009 (set (match_operand:SI 0 "s_register_operand" "")
3010 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3011 (match_operand:SI 2 "arm_rhs_operand" "")))
3012 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3013 "TARGET_32BIT"
8b9dc177 3014 "
3015 if (operands[2] == const0_rtx)
3016 {
3017 /* No need for a clobber of the condition code register here. */
3018 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3019 gen_rtx_SMIN (SImode, operands[1],
3020 operands[2])));
3021 DONE;
3022 }
3023")
3024
3025(define_insn "*smin_0"
3026 [(set (match_operand:SI 0 "s_register_operand" "=r")
3027 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3028 (const_int 0)))]
25f905c2 3029 "TARGET_32BIT"
8b9dc177 3030 "and%?\\t%0, %1, %1, asr #31"
3031 [(set_attr "predicable" "yes")]
3032)
3033
25f905c2 3034(define_insn "*arm_smin_insn"
8b9dc177 3035 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3036 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3037 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3038 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3039 "TARGET_ARM"
e2348bcb 3040 "@
3041 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3042 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3043 [(set_attr "conds" "clob")
8b9dc177 3044 (set_attr "length" "8,12")]
0d66636f 3045)
9c08d1fa 3046
25f905c2 3047(define_expand "umaxsi3"
3048 [(parallel [
3049 (set (match_operand:SI 0 "s_register_operand" "")
3050 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3051 (match_operand:SI 2 "arm_rhs_operand" "")))
3052 (clobber (reg:CC CC_REGNUM))])]
3053 "TARGET_32BIT"
3054 ""
3055)
3056
3057(define_insn "*arm_umaxsi3"
9c08d1fa 3058 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3059 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3060 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3061 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3062 "TARGET_ARM"
e2348bcb 3063 "@
3064 cmp\\t%1, %2\;movcc\\t%0, %2
3065 cmp\\t%1, %2\;movcs\\t%0, %1
3066 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3067 [(set_attr "conds" "clob")
3068 (set_attr "length" "8,8,12")]
3069)
9c08d1fa 3070
25f905c2 3071(define_expand "uminsi3"
3072 [(parallel [
3073 (set (match_operand:SI 0 "s_register_operand" "")
3074 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3075 (match_operand:SI 2 "arm_rhs_operand" "")))
3076 (clobber (reg:CC CC_REGNUM))])]
3077 "TARGET_32BIT"
3078 ""
3079)
3080
3081(define_insn "*arm_uminsi3"
9c08d1fa 3082 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3083 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3084 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3085 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3086 "TARGET_ARM"
e2348bcb 3087 "@
3088 cmp\\t%1, %2\;movcs\\t%0, %2
3089 cmp\\t%1, %2\;movcc\\t%0, %1
3090 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3091 [(set_attr "conds" "clob")
3092 (set_attr "length" "8,8,12")]
3093)
9c08d1fa 3094
8a18b90c 3095(define_insn "*store_minmaxsi"
9c08d1fa 3096 [(set (match_operand:SI 0 "memory_operand" "=m")
3097 (match_operator:SI 3 "minmax_operator"
3098 [(match_operand:SI 1 "s_register_operand" "r")
3099 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3100 (clobber (reg:CC CC_REGNUM))]
25f905c2 3101 "TARGET_32BIT"
9c08d1fa 3102 "*
dc55b8a9 3103 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3104 operands[1], operands[2]);
e2348bcb 3105 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3106 if (TARGET_THUMB2)
3107 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3108 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3109 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3110 return \"\";
0d66636f 3111 "
3112 [(set_attr "conds" "clob")
25f905c2 3113 (set (attr "length")
3114 (if_then_else (eq_attr "is_thumb" "yes")
3115 (const_int 14)
3116 (const_int 12)))
0d66636f 3117 (set_attr "type" "store1")]
3118)
9c08d1fa 3119
8a18b90c 3120; Reject the frame pointer in operand[1], since reloading this after
3121; it has been eliminated can cause carnage.
f7fbdd4a 3122(define_insn "*minmax_arithsi"
9c08d1fa 3123 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3124 (match_operator:SI 4 "shiftable_operator"
3125 [(match_operator:SI 5 "minmax_operator"
3126 [(match_operand:SI 2 "s_register_operand" "r,r")
3127 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3128 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3129 (clobber (reg:CC CC_REGNUM))]
25f905c2 3130 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3131 "*
0d66636f 3132 {
3133 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3134 bool need_else;
3135
3136 if (which_alternative != 0 || operands[3] != const0_rtx
3137 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3138 need_else = true;
3139 else
3140 need_else = false;
0d66636f 3141
dc55b8a9 3142 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3143 operands[2], operands[3]);
0d66636f 3144 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3145 if (TARGET_THUMB2)
3146 {
3147 if (need_else)
3148 output_asm_insn (\"ite\\t%d5\", operands);
3149 else
3150 output_asm_insn (\"it\\t%d5\", operands);
3151 }
0d66636f 3152 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3153 if (need_else)
0d66636f 3154 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3155 return \"\";
215b30b3 3156 }"
0d66636f 3157 [(set_attr "conds" "clob")
25f905c2 3158 (set (attr "length")
3159 (if_then_else (eq_attr "is_thumb" "yes")
3160 (const_int 14)
3161 (const_int 12)))]
0d66636f 3162)
9c08d1fa 3163
b11cae9e 3164\f
3165;; Shift and rotation insns
3166
a2cd141b 3167(define_expand "ashldi3"
3168 [(set (match_operand:DI 0 "s_register_operand" "")
3169 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3170 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3171 "TARGET_32BIT"
a2cd141b 3172 "
3173 if (GET_CODE (operands[2]) == CONST_INT)
3174 {
3175 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3176 {
3177 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3178 DONE;
3179 }
3180 /* Ideally we shouldn't fail here if we could know that operands[1]
3181 ends up already living in an iwmmxt register. Otherwise it's
3182 cheaper to have the alternate code being generated than moving
1d60d981 3183 values to iwmmxt regs and back. */
a2cd141b 3184 FAIL;
3185 }
3186 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3187 FAIL;
3188 "
3189)
3190
3191(define_insn "arm_ashldi3_1bit"
3192 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3193 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3194 (const_int 1)))
3195 (clobber (reg:CC CC_REGNUM))]
25f905c2 3196 "TARGET_32BIT"
a2cd141b 3197 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3198 [(set_attr "conds" "clob")
3199 (set_attr "length" "8")]
3200)
3201
87b22bf7 3202(define_expand "ashlsi3"
cffb2a26 3203 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3204 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3205 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3206 "TARGET_EITHER"
87b22bf7 3207 "
3208 if (GET_CODE (operands[2]) == CONST_INT
3209 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3210 {
3211 emit_insn (gen_movsi (operands[0], const0_rtx));
3212 DONE;
3213 }
cffb2a26 3214 "
3215)
3216
25f905c2 3217(define_insn "*thumb1_ashlsi3"
cffb2a26 3218 [(set (match_operand:SI 0 "register_operand" "=l,l")
3219 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3220 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3221 "TARGET_THUMB1"
cffb2a26 3222 "lsl\\t%0, %1, %2"
3223 [(set_attr "length" "2")]
3224)
b11cae9e 3225
a2cd141b 3226(define_expand "ashrdi3"
3227 [(set (match_operand:DI 0 "s_register_operand" "")
3228 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3229 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3230 "TARGET_32BIT"
a2cd141b 3231 "
3232 if (GET_CODE (operands[2]) == CONST_INT)
3233 {
3234 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3235 {
3236 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3237 DONE;
3238 }
3239 /* Ideally we shouldn't fail here if we could know that operands[1]
3240 ends up already living in an iwmmxt register. Otherwise it's
3241 cheaper to have the alternate code being generated than moving
1d60d981 3242 values to iwmmxt regs and back. */
a2cd141b 3243 FAIL;
3244 }
3245 else if (!TARGET_REALLY_IWMMXT)
3246 FAIL;
3247 "
3248)
3249
3250(define_insn "arm_ashrdi3_1bit"
3251 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3252 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3253 (const_int 1)))
3254 (clobber (reg:CC CC_REGNUM))]
25f905c2 3255 "TARGET_32BIT"
a2cd141b 3256 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3257 [(set_attr "conds" "clob")
3258 (set_attr "length" "8")]
3259)
3260
87b22bf7 3261(define_expand "ashrsi3"
cffb2a26 3262 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3263 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3264 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3265 "TARGET_EITHER"
87b22bf7 3266 "
3267 if (GET_CODE (operands[2]) == CONST_INT
3268 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3269 operands[2] = GEN_INT (31);
cffb2a26 3270 "
3271)
3272
25f905c2 3273(define_insn "*thumb1_ashrsi3"
cffb2a26 3274 [(set (match_operand:SI 0 "register_operand" "=l,l")
3275 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3276 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3277 "TARGET_THUMB1"
cffb2a26 3278 "asr\\t%0, %1, %2"
3279 [(set_attr "length" "2")]
3280)
b11cae9e 3281
a2cd141b 3282(define_expand "lshrdi3"
3283 [(set (match_operand:DI 0 "s_register_operand" "")
3284 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3285 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3286 "TARGET_32BIT"
a2cd141b 3287 "
3288 if (GET_CODE (operands[2]) == CONST_INT)
3289 {
3290 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3291 {
3292 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3293 DONE;
3294 }
3295 /* Ideally we shouldn't fail here if we could know that operands[1]
3296 ends up already living in an iwmmxt register. Otherwise it's
3297 cheaper to have the alternate code being generated than moving
1d60d981 3298 values to iwmmxt regs and back. */
a2cd141b 3299 FAIL;
3300 }
3301 else if (!TARGET_REALLY_IWMMXT)
3302 FAIL;
3303 "
3304)
3305
3306(define_insn "arm_lshrdi3_1bit"
3307 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3308 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3309 (const_int 1)))
3310 (clobber (reg:CC CC_REGNUM))]
25f905c2 3311 "TARGET_32BIT"
a2cd141b 3312 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3313 [(set_attr "conds" "clob")
3314 (set_attr "length" "8")]
3315)
3316
87b22bf7 3317(define_expand "lshrsi3"
cffb2a26 3318 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3319 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3320 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3321 "TARGET_EITHER"
87b22bf7 3322 "
3323 if (GET_CODE (operands[2]) == CONST_INT
3324 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3325 {
3326 emit_insn (gen_movsi (operands[0], const0_rtx));
3327 DONE;
3328 }
cffb2a26 3329 "
3330)
3331
25f905c2 3332(define_insn "*thumb1_lshrsi3"
cffb2a26 3333 [(set (match_operand:SI 0 "register_operand" "=l,l")
3334 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3335 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3336 "TARGET_THUMB1"
cffb2a26 3337 "lsr\\t%0, %1, %2"
3338 [(set_attr "length" "2")]
3339)
b11cae9e 3340
87b22bf7 3341(define_expand "rotlsi3"
cffb2a26 3342 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3343 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3344 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3345 "TARGET_32BIT"
87b22bf7 3346 "
3347 if (GET_CODE (operands[2]) == CONST_INT)
3348 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3349 else
b11cae9e 3350 {
87b22bf7 3351 rtx reg = gen_reg_rtx (SImode);
3352 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3353 operands[2] = reg;
b11cae9e 3354 }
cffb2a26 3355 "
3356)
9c08d1fa 3357
87b22bf7 3358(define_expand "rotrsi3"
cffb2a26 3359 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3360 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3361 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3362 "TARGET_EITHER"
87b22bf7 3363 "
25f905c2 3364 if (TARGET_32BIT)
cffb2a26 3365 {
3366 if (GET_CODE (operands[2]) == CONST_INT
3367 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3368 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3369 }
25f905c2 3370 else /* TARGET_THUMB1 */
cffb2a26 3371 {
3372 if (GET_CODE (operands [2]) == CONST_INT)
3373 operands [2] = force_reg (SImode, operands[2]);
3374 }
3375 "
3376)
87b22bf7 3377
25f905c2 3378(define_insn "*thumb1_rotrsi3"
cffb2a26 3379 [(set (match_operand:SI 0 "register_operand" "=l")
3380 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3381 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3382 "TARGET_THUMB1"
cffb2a26 3383 "ror\\t%0, %0, %2"
3384 [(set_attr "length" "2")]
3385)
3386
3387(define_insn "*arm_shiftsi3"
3388 [(set (match_operand:SI 0 "s_register_operand" "=r")
3389 (match_operator:SI 3 "shift_operator"
3390 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3391 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3392 "TARGET_32BIT"
3393 "* return arm_output_shift(operands, 0);"
344495ea 3394 [(set_attr "predicable" "yes")
331beb1a 3395 (set_attr "shift" "1")
a2cd141b 3396 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3397 (const_string "alu_shift")
3398 (const_string "alu_shift_reg")))]
6c4c2133 3399)
87b22bf7 3400
f7fbdd4a 3401(define_insn "*shiftsi3_compare0"
bd5b4116 3402 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3403 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3404 [(match_operand:SI 1 "s_register_operand" "r")
3405 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3406 (const_int 0)))
3407 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3408 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3409 "TARGET_32BIT"
3410 "* return arm_output_shift(operands, 1);"
344495ea 3411 [(set_attr "conds" "set")
331beb1a 3412 (set_attr "shift" "1")
a2cd141b 3413 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3414 (const_string "alu_shift")
3415 (const_string "alu_shift_reg")))]
0d66636f 3416)
9c08d1fa 3417
f7fbdd4a 3418(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3419 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3420 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3421 [(match_operand:SI 1 "s_register_operand" "r")
3422 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3423 (const_int 0)))
3424 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3425 "TARGET_32BIT"
3426 "* return arm_output_shift(operands, 1);"
344495ea 3427 [(set_attr "conds" "set")
a2cd141b 3428 (set_attr "shift" "1")]
0d66636f 3429)
9c08d1fa 3430
25f905c2 3431(define_insn "*arm_notsi_shiftsi"
9c08d1fa 3432 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3433 (not:SI (match_operator:SI 3 "shift_operator"
3434 [(match_operand:SI 1 "s_register_operand" "r")
3435 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 3436 "TARGET_ARM"
6c4c2133 3437 "mvn%?\\t%0, %1%S3"
344495ea 3438 [(set_attr "predicable" "yes")
331beb1a 3439 (set_attr "shift" "1")
a2cd141b 3440 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3441 (const_string "alu_shift")
3442 (const_string "alu_shift_reg")))]
0d66636f 3443)
9c08d1fa 3444
25f905c2 3445(define_insn "*arm_notsi_shiftsi_compare0"
bd5b4116 3446 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3447 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3448 [(match_operand:SI 1 "s_register_operand" "r")
3449 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3450 (const_int 0)))
3451 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3452 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 3453 "TARGET_ARM"
25f905c2 3454 "mvn%.\\t%0, %1%S3"
344495ea 3455 [(set_attr "conds" "set")
331beb1a 3456 (set_attr "shift" "1")
a2cd141b 3457 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3458 (const_string "alu_shift")
3459 (const_string "alu_shift_reg")))]
0d66636f 3460)
9c08d1fa 3461
25f905c2 3462(define_insn "*arm_not_shiftsi_compare0_scratch"
bd5b4116 3463 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3464 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3465 [(match_operand:SI 1 "s_register_operand" "r")
3466 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3467 (const_int 0)))
3468 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3469 "TARGET_ARM"
25f905c2 3470 "mvn%.\\t%0, %1%S3"
344495ea 3471 [(set_attr "conds" "set")
331beb1a 3472 (set_attr "shift" "1")
a2cd141b 3473 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3474 (const_string "alu_shift")
3475 (const_string "alu_shift_reg")))]
0d66636f 3476)
9c08d1fa 3477
cffb2a26 3478;; We don't really have extzv, but defining this using shifts helps
3479;; to reduce register pressure later on.
3480
3481(define_expand "extzv"
3482 [(set (match_dup 4)
3483 (ashift:SI (match_operand:SI 1 "register_operand" "")
3484 (match_operand:SI 2 "const_int_operand" "")))
3485 (set (match_operand:SI 0 "register_operand" "")
3486 (lshiftrt:SI (match_dup 4)
215b30b3 3487 (match_operand:SI 3 "const_int_operand" "")))]
8b054d5a 3488 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3489 "
3490 {
3491 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3492 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3493
8b054d5a 3494 if (arm_arch_thumb2)
3495 {
3496 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3497 operands[3]));
3498 DONE;
3499 }
3500
cffb2a26 3501 operands[3] = GEN_INT (rshift);
3502
3503 if (lshift == 0)
3504 {
3505 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3506 DONE;
3507 }
3508
3509 operands[2] = GEN_INT (lshift);
3510 operands[4] = gen_reg_rtx (SImode);
215b30b3 3511 }"
cffb2a26 3512)
3513
8b054d5a 3514(define_insn "extv"
3515 [(set (match_operand:SI 0 "s_register_operand" "=r")
3516 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3517 (match_operand:SI 2 "const_int_operand" "M")
3518 (match_operand:SI 3 "const_int_operand" "M")))]
3519 "arm_arch_thumb2"
3520 "sbfx%?\t%0, %1, %3, %2"
3521 [(set_attr "length" "4")
3522 (set_attr "predicable" "yes")]
3523)
3524
3525(define_insn "extzv_t2"
3526 [(set (match_operand:SI 0 "s_register_operand" "=r")
3527 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3528 (match_operand:SI 2 "const_int_operand" "M")
3529 (match_operand:SI 3 "const_int_operand" "M")))]
3530 "arm_arch_thumb2"
3531 "ubfx%?\t%0, %1, %3, %2"
3532 [(set_attr "length" "4")
3533 (set_attr "predicable" "yes")]
3534)
3535
b11cae9e 3536\f
3537;; Unary arithmetic insns
3538
cffb2a26 3539(define_expand "negdi2"
3540 [(parallel
3541 [(set (match_operand:DI 0 "s_register_operand" "")
3542 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3543 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3544 "TARGET_EITHER"
3545 "
25f905c2 3546 if (TARGET_THUMB1)
cffb2a26 3547 {
3548 if (GET_CODE (operands[1]) != REG)
6edd680c 3549 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 3550 }
215b30b3 3551 "
cffb2a26 3552)
3553
3554;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3555;; The second alternative is to allow the common case of a *full* overlap.
3556(define_insn "*arm_negdi2"
3557 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3558 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 3559 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3560 "TARGET_ARM"
97499065 3561 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3562 [(set_attr "conds" "clob")
3563 (set_attr "length" "8")]
3564)
b11cae9e 3565
25f905c2 3566(define_insn "*thumb1_negdi2"
cffb2a26 3567 [(set (match_operand:DI 0 "register_operand" "=&l")
3568 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3569 (clobber (reg:CC CC_REGNUM))]
25f905c2 3570 "TARGET_THUMB1"
cffb2a26 3571 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3572 [(set_attr "length" "6")]
3573)
3574
3575(define_expand "negsi2"
3576 [(set (match_operand:SI 0 "s_register_operand" "")
3577 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3578 "TARGET_EITHER"
b11cae9e 3579 ""
cffb2a26 3580)
3581
3582(define_insn "*arm_negsi2"
3583 [(set (match_operand:SI 0 "s_register_operand" "=r")
3584 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3585 "TARGET_32BIT"
cffb2a26 3586 "rsb%?\\t%0, %1, #0"
0d66636f 3587 [(set_attr "predicable" "yes")]
cffb2a26 3588)
3589
25f905c2 3590(define_insn "*thumb1_negsi2"
cffb2a26 3591 [(set (match_operand:SI 0 "register_operand" "=l")
3592 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3593 "TARGET_THUMB1"
cffb2a26 3594 "neg\\t%0, %1"
3595 [(set_attr "length" "2")]
3596)
b11cae9e 3597
604f3a0a 3598(define_expand "negsf2"
3599 [(set (match_operand:SF 0 "s_register_operand" "")
3600 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3601 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3602 ""
3603)
3604
3605(define_expand "negdf2"
3606 [(set (match_operand:DF 0 "s_register_operand" "")
3607 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3608 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 3609 "")
3610
9c08d1fa 3611;; abssi2 doesn't really clobber the condition codes if a different register
3612;; is being set. To keep things simple, assume during rtl manipulations that
3613;; it does, but tell the final scan operator the truth. Similarly for
3614;; (neg (abs...))
3615
604f3a0a 3616(define_expand "abssi2"
3617 [(parallel
3618 [(set (match_operand:SI 0 "s_register_operand" "")
3619 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3620 (clobber (match_dup 2))])]
3621 "TARGET_EITHER"
3622 "
25f905c2 3623 if (TARGET_THUMB1)
ba156559 3624 operands[2] = gen_rtx_SCRATCH (SImode);
3625 else
3626 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3627")
604f3a0a 3628
7d57ec45 3629(define_insn "*arm_abssi2"
ba156559 3630 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3631 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3632 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3633 "TARGET_ARM"
e2348bcb 3634 "@
3635 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3636 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3637 [(set_attr "conds" "clob,*")
331beb1a 3638 (set_attr "shift" "1")
0d66636f 3639 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3640 (set_attr "length" "8")]
3641)
9c08d1fa 3642
25f905c2 3643(define_insn_and_split "*thumb1_abssi2"
ba156559 3644 [(set (match_operand:SI 0 "s_register_operand" "=l")
3645 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3646 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3647 "TARGET_THUMB1"
ba156559 3648 "#"
25f905c2 3649 "TARGET_THUMB1 && reload_completed"
ba156559 3650 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3651 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3652 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3653 ""
3654 [(set_attr "length" "6")]
3655)
3656
3657(define_insn "*arm_neg_abssi2"
9c08d1fa 3658 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3659 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3660 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3661 "TARGET_ARM"
e2348bcb 3662 "@
3663 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3664 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3665 [(set_attr "conds" "clob,*")
331beb1a 3666 (set_attr "shift" "1")
0d66636f 3667 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3668 (set_attr "length" "8")]
3669)
b11cae9e 3670
25f905c2 3671(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3672 [(set (match_operand:SI 0 "s_register_operand" "=l")
3673 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3674 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3675 "TARGET_THUMB1"
ba156559 3676 "#"
25f905c2 3677 "TARGET_THUMB1 && reload_completed"
ba156559 3678 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3679 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3680 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3681 ""
3682 [(set_attr "length" "6")]
3683)
3684
604f3a0a 3685(define_expand "abssf2"
3686 [(set (match_operand:SF 0 "s_register_operand" "")
3687 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3688 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3689 "")
3690
604f3a0a 3691(define_expand "absdf2"
3692 [(set (match_operand:DF 0 "s_register_operand" "")
3693 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3694 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3695 "")
3696
7db9af5d 3697(define_expand "sqrtsf2"
3698 [(set (match_operand:SF 0 "s_register_operand" "")
3699 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3700 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3701 "")
9c08d1fa 3702
7db9af5d 3703(define_expand "sqrtdf2"
3704 [(set (match_operand:DF 0 "s_register_operand" "")
3705 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3706 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 3707 "")
9c08d1fa 3708
a0f94409 3709(define_insn_and_split "one_cmpldi2"
9c08d1fa 3710 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3711 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 3712 "TARGET_32BIT"
f6ebffac 3713 "#"
25f905c2 3714 "TARGET_32BIT && reload_completed"
a0f94409 3715 [(set (match_dup 0) (not:SI (match_dup 1)))
3716 (set (match_dup 2) (not:SI (match_dup 3)))]
3717 "
3718 {
3719 operands[2] = gen_highpart (SImode, operands[0]);
3720 operands[0] = gen_lowpart (SImode, operands[0]);
3721 operands[3] = gen_highpart (SImode, operands[1]);
3722 operands[1] = gen_lowpart (SImode, operands[1]);
3723 }"
0d66636f 3724 [(set_attr "length" "8")
3725 (set_attr "predicable" "yes")]
cffb2a26 3726)
b11cae9e 3727
cffb2a26 3728(define_expand "one_cmplsi2"
3729 [(set (match_operand:SI 0 "s_register_operand" "")
3730 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3731 "TARGET_EITHER"
b11cae9e 3732 ""
cffb2a26 3733)
3734
3735(define_insn "*arm_one_cmplsi2"
3736 [(set (match_operand:SI 0 "s_register_operand" "=r")
3737 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3738 "TARGET_32BIT"
cffb2a26 3739 "mvn%?\\t%0, %1"
0d66636f 3740 [(set_attr "predicable" "yes")]
cffb2a26 3741)
3742
25f905c2 3743(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3744 [(set (match_operand:SI 0 "register_operand" "=l")
3745 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3746 "TARGET_THUMB1"
cffb2a26 3747 "mvn\\t%0, %1"
3748 [(set_attr "length" "2")]
3749)
9c08d1fa 3750
f7fbdd4a 3751(define_insn "*notsi_compare0"
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 (set (match_operand:SI 0 "s_register_operand" "=r")
3756 (not:SI (match_dup 1)))]
25f905c2 3757 "TARGET_32BIT"
3758 "mvn%.\\t%0, %1"
cffb2a26 3759 [(set_attr "conds" "set")]
3760)
9c08d1fa 3761
f7fbdd4a 3762(define_insn "*notsi_compare0_scratch"
bd5b4116 3763 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3764 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3765 (const_int 0)))
3766 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3767 "TARGET_32BIT"
3768 "mvn%.\\t%0, %1"
cffb2a26 3769 [(set_attr "conds" "set")]
3770)
b11cae9e 3771\f
3772;; Fixed <--> Floating conversion insns
3773
9b8516be 3774(define_expand "floatsihf2"
3775 [(set (match_operand:HF 0 "general_operand" "")
3776 (float:HF (match_operand:SI 1 "general_operand" "")))]
3777 "TARGET_EITHER"
3778 "
3779 {
3780 rtx op1 = gen_reg_rtx (SFmode);
3781 expand_float (op1, operands[1], 0);
3782 op1 = convert_to_mode (HFmode, op1, 0);
3783 emit_move_insn (operands[0], op1);
3784 DONE;
3785 }"
3786)
3787
3788(define_expand "floatdihf2"
3789 [(set (match_operand:HF 0 "general_operand" "")
3790 (float:HF (match_operand:DI 1 "general_operand" "")))]
3791 "TARGET_EITHER"
3792 "
3793 {
3794 rtx op1 = gen_reg_rtx (SFmode);
3795 expand_float (op1, operands[1], 0);
3796 op1 = convert_to_mode (HFmode, op1, 0);
3797 emit_move_insn (operands[0], op1);
3798 DONE;
3799 }"
3800)
3801
604f3a0a 3802(define_expand "floatsisf2"
3803 [(set (match_operand:SF 0 "s_register_operand" "")
3804 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3805 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3806 "
a2cd141b 3807 if (TARGET_MAVERICK)
604f3a0a 3808 {
3809 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3810 DONE;
3811 }
3812")
3813
604f3a0a 3814(define_expand "floatsidf2"
3815 [(set (match_operand:DF 0 "s_register_operand" "")
3816 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 3817 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3818 "
a2cd141b 3819 if (TARGET_MAVERICK)
604f3a0a 3820 {
3821 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3822 DONE;
3823 }
3824")
3825
9b8516be 3826(define_expand "fix_trunchfsi2"
3827 [(set (match_operand:SI 0 "general_operand" "")
3828 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3829 "TARGET_EITHER"
3830 "
3831 {
3832 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3833 expand_fix (operands[0], op1, 0);
3834 DONE;
3835 }"
3836)
3837
3838(define_expand "fix_trunchfdi2"
3839 [(set (match_operand:DI 0 "general_operand" "")
3840 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
3841 "TARGET_EITHER"
3842 "
3843 {
3844 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3845 expand_fix (operands[0], op1, 0);
3846 DONE;
3847 }"
3848)
3849
604f3a0a 3850(define_expand "fix_truncsfsi2"
3851 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3852 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3853 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3854 "
a2cd141b 3855 if (TARGET_MAVERICK)
604f3a0a 3856 {
3857 if (!cirrus_fp_register (operands[0], SImode))
3858 operands[0] = force_reg (SImode, operands[0]);
3859 if (!cirrus_fp_register (operands[1], SFmode))
3860 operands[1] = force_reg (SFmode, operands[0]);
3861 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3862 DONE;
3863 }
3864")
3865
604f3a0a 3866(define_expand "fix_truncdfsi2"
3867 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3868 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 3869 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3870 "
a2cd141b 3871 if (TARGET_MAVERICK)
604f3a0a 3872 {
3873 if (!cirrus_fp_register (operands[1], DFmode))
3874 operands[1] = force_reg (DFmode, operands[0]);
3875 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3876 DONE;
3877 }
3878")
3879
f544c6d2 3880;; Truncation insns
b11cae9e 3881
604f3a0a 3882(define_expand "truncdfsf2"
3883 [(set (match_operand:SF 0 "s_register_operand" "")
3884 (float_truncate:SF
3885 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 3886 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 3887 ""
3888)
9b8516be 3889
3890/* DFmode -> HFmode conversions have to go through SFmode. */
3891(define_expand "truncdfhf2"
3892 [(set (match_operand:HF 0 "general_operand" "")
3893 (float_truncate:HF
3894 (match_operand:DF 1 "general_operand" "")))]
3895 "TARGET_EITHER"
3896 "
3897 {
3898 rtx op1;
3899 op1 = convert_to_mode (SFmode, operands[1], 0);
3900 op1 = convert_to_mode (HFmode, op1, 0);
3901 emit_move_insn (operands[0], op1);
3902 DONE;
3903 }"
3904)
b11cae9e 3905\f
9c08d1fa 3906;; Zero and sign extension instructions.
b11cae9e 3907
25f905c2 3908(define_expand "zero_extendsidi2"
3909 [(set (match_operand:DI 0 "s_register_operand" "")
3910 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3911 "TARGET_32BIT"
3912 ""
3913)
3914
3915(define_insn "*arm_zero_extendsidi2"
9c08d1fa 3916 [(set (match_operand:DI 0 "s_register_operand" "=r")
3917 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3918 "TARGET_ARM"
9c08d1fa 3919 "*
0d66636f 3920 if (REGNO (operands[1])
3921 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3922 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3923 return \"mov%?\\t%R0, #0\";
3924 "
3925 [(set_attr "length" "8")
3926 (set_attr "predicable" "yes")]
3927)
9c08d1fa 3928
25f905c2 3929(define_expand "zero_extendqidi2"
3930 [(set (match_operand:DI 0 "s_register_operand" "")
3931 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3932 "TARGET_32BIT"
3933 ""
3934)
3935
3936(define_insn "*arm_zero_extendqidi2"
cffb2a26 3937 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3938 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3939 "TARGET_ARM"
e2348bcb 3940 "@
97499065 3941 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
25f905c2 3942 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3943 [(set_attr "length" "8")
0d66636f 3944 (set_attr "predicable" "yes")
a2cd141b 3945 (set_attr "type" "*,load_byte")
cffb2a26 3946 (set_attr "pool_range" "*,4092")
3947 (set_attr "neg_pool_range" "*,4084")]
3948)
9c08d1fa 3949
25f905c2 3950(define_expand "extendsidi2"
3951 [(set (match_operand:DI 0 "s_register_operand" "")
3952 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3953 "TARGET_32BIT"
3954 ""
3955)
3956
3957(define_insn "*arm_extendsidi2"
9c08d1fa 3958 [(set (match_operand:DI 0 "s_register_operand" "=r")
3959 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3960 "TARGET_ARM"
9c08d1fa 3961 "*
0d66636f 3962 if (REGNO (operands[1])
3963 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3964 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3965 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3966 "
3967 [(set_attr "length" "8")
331beb1a 3968 (set_attr "shift" "1")
0d66636f 3969 (set_attr "predicable" "yes")]
3970)
9c08d1fa 3971
3972(define_expand "zero_extendhisi2"
cffb2a26 3973 [(set (match_dup 2)
0d66636f 3974 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3975 (const_int 16)))
9c08d1fa 3976 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3977 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3978 "TARGET_EITHER"
9c08d1fa 3979 "
cffb2a26 3980 {
25f905c2 3981 if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3982 {
a2cd141b 3983 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3984 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3985 DONE;
cffb2a26 3986 }
cffb2a26 3987
c1a66faf 3988 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3989 {
3990 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3991 DONE;
3992 }
cffb2a26 3993
a2cd141b 3994 if (!s_register_operand (operands[1], HImode))
3995 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3996
a2cd141b 3997 if (arm_arch6)
3998 {
3999 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4000 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4001 DONE;
cffb2a26 4002 }
a2cd141b 4003
4004 operands[1] = gen_lowpart (SImode, operands[1]);
4005 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4006 }"
4007)
4008
25f905c2 4009(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4010 [(set (match_operand:SI 0 "register_operand" "=l")
4011 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
25f905c2 4012 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4013 "*
4014 rtx mem = XEXP (operands[1], 0);
4015
4016 if (GET_CODE (mem) == CONST)
4017 mem = XEXP (mem, 0);
4018
4019 if (GET_CODE (mem) == LABEL_REF)
4020 return \"ldr\\t%0, %1\";
4021
4022 if (GET_CODE (mem) == PLUS)
f7fbdd4a 4023 {
cffb2a26 4024 rtx a = XEXP (mem, 0);
4025 rtx b = XEXP (mem, 1);
4026
4027 /* This can happen due to bugs in reload. */
4028 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4029 {
4030 rtx ops[2];
4031 ops[0] = operands[0];
4032 ops[1] = a;
4033
4034 output_asm_insn (\"mov %0, %1\", ops);
4035
4036 XEXP (mem, 0) = operands[0];
4037 }
4038
4039 else if ( GET_CODE (a) == LABEL_REF
4040 && GET_CODE (b) == CONST_INT)
4041 return \"ldr\\t%0, %1\";
25f7a26e 4042 }
cffb2a26 4043
4044 return \"ldrh\\t%0, %1\";
4045 "
4046 [(set_attr "length" "4")
a2cd141b 4047 (set_attr "type" "load_byte")
cffb2a26 4048 (set_attr "pool_range" "60")]
4049)
9c08d1fa 4050
25f905c2 4051(define_insn "*thumb1_zero_extendhisi2_v6"
a2cd141b 4052 [(set (match_operand:SI 0 "register_operand" "=l,l")
4053 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4054 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4055 "*
4056 rtx mem;
4057
4058 if (which_alternative == 0)
4059 return \"uxth\\t%0, %1\";
4060
4061 mem = XEXP (operands[1], 0);
4062
4063 if (GET_CODE (mem) == CONST)
4064 mem = XEXP (mem, 0);
4065
4066 if (GET_CODE (mem) == LABEL_REF)
4067 return \"ldr\\t%0, %1\";
4068
4069 if (GET_CODE (mem) == PLUS)
4070 {
4071 rtx a = XEXP (mem, 0);
4072 rtx b = XEXP (mem, 1);
4073
4074 /* This can happen due to bugs in reload. */
4075 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4076 {
4077 rtx ops[2];
4078 ops[0] = operands[0];
4079 ops[1] = a;
4080
4081 output_asm_insn (\"mov %0, %1\", ops);
4082
4083 XEXP (mem, 0) = operands[0];
4084 }
4085
4086 else if ( GET_CODE (a) == LABEL_REF
4087 && GET_CODE (b) == CONST_INT)
4088 return \"ldr\\t%0, %1\";
4089 }
4090
4091 return \"ldrh\\t%0, %1\";
4092 "
4093 [(set_attr "length" "2,4")
4094 (set_attr "type" "alu_shift,load_byte")
4095 (set_attr "pool_range" "*,60")]
4096)
4097
cffb2a26 4098(define_insn "*arm_zero_extendhisi2"
a2cd141b 4099 [(set (match_operand:SI 0 "s_register_operand" "=r")
4100 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4101 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4102 "ldr%(h%)\\t%0, %1"
a2cd141b 4103 [(set_attr "type" "load_byte")
0d66636f 4104 (set_attr "predicable" "yes")
cffb2a26 4105 (set_attr "pool_range" "256")
4106 (set_attr "neg_pool_range" "244")]
4107)
f7fbdd4a 4108
a2cd141b 4109(define_insn "*arm_zero_extendhisi2_v6"
4110 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4111 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4112 "TARGET_ARM && arm_arch6"
4113 "@
4114 uxth%?\\t%0, %1
25f905c2 4115 ldr%(h%)\\t%0, %1"
a2cd141b 4116 [(set_attr "type" "alu_shift,load_byte")
4117 (set_attr "predicable" "yes")
4118 (set_attr "pool_range" "*,256")
4119 (set_attr "neg_pool_range" "*,244")]
4120)
4121
4122(define_insn "*arm_zero_extendhisi2addsi"
4123 [(set (match_operand:SI 0 "s_register_operand" "=r")
4124 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4125 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4126 "TARGET_INT_SIMD"
a2cd141b 4127 "uxtah%?\\t%0, %2, %1"
4128 [(set_attr "type" "alu_shift")
4129 (set_attr "predicable" "yes")]
4130)
4131
87b22bf7 4132(define_expand "zero_extendqisi2"
cffb2a26 4133 [(set (match_operand:SI 0 "s_register_operand" "")
4134 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4135 "TARGET_EITHER"
87b22bf7 4136 "
a2cd141b 4137 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4138 {
cffb2a26 4139 if (TARGET_ARM)
4140 {
215b30b3 4141 emit_insn (gen_andsi3 (operands[0],
4142 gen_lowpart (SImode, operands[1]),
cffb2a26 4143 GEN_INT (255)));
4144 }
4145 else /* TARGET_THUMB */
4146 {
4147 rtx temp = gen_reg_rtx (SImode);
4148 rtx ops[3];
4149
4150 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4151 operands[1] = gen_lowpart (SImode, operands[1]);
4152
4153 ops[0] = temp;
4154 ops[1] = operands[1];
4155 ops[2] = GEN_INT (24);
4156
215b30b3 4157 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4158 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 4159
4160 ops[0] = operands[0];
4161 ops[1] = temp;
4162 ops[2] = GEN_INT (24);
4163
215b30b3 4164 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4165 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 4166 }
87b22bf7 4167 DONE;
4168 }
215b30b3 4169 "
4170)
9c08d1fa 4171
25f905c2 4172(define_insn "*thumb1_zero_extendqisi2"
a2cd141b 4173 [(set (match_operand:SI 0 "register_operand" "=l")
4174 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
25f905c2 4175 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4176 "ldrb\\t%0, %1"
4177 [(set_attr "length" "2")
a2cd141b 4178 (set_attr "type" "load_byte")
cffb2a26 4179 (set_attr "pool_range" "32")]
4180)
4181
25f905c2 4182(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4183 [(set (match_operand:SI 0 "register_operand" "=l,l")
4184 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4185 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4186 "@
4187 uxtb\\t%0, %1
4188 ldrb\\t%0, %1"
4189 [(set_attr "length" "2,2")
4190 (set_attr "type" "alu_shift,load_byte")
4191 (set_attr "pool_range" "*,32")]
4192)
4193
cffb2a26 4194(define_insn "*arm_zero_extendqisi2"
a2cd141b 4195 [(set (match_operand:SI 0 "s_register_operand" "=r")
4196 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4197 "TARGET_ARM && !arm_arch6"
25f905c2 4198 "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4199 [(set_attr "type" "load_byte")
0d66636f 4200 (set_attr "predicable" "yes")
cffb2a26 4201 (set_attr "pool_range" "4096")
4202 (set_attr "neg_pool_range" "4084")]
4203)
87b22bf7 4204
a2cd141b 4205(define_insn "*arm_zero_extendqisi2_v6"
4206 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4207 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4208 "TARGET_ARM && arm_arch6"
4209 "@
25f905c2 4210 uxtb%(%)\\t%0, %1
4211 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4212 [(set_attr "type" "alu_shift,load_byte")
4213 (set_attr "predicable" "yes")
4214 (set_attr "pool_range" "*,4096")
4215 (set_attr "neg_pool_range" "*,4084")]
4216)
4217
4218(define_insn "*arm_zero_extendqisi2addsi"
4219 [(set (match_operand:SI 0 "s_register_operand" "=r")
4220 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4221 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4222 "TARGET_INT_SIMD"
a2cd141b 4223 "uxtab%?\\t%0, %2, %1"
4224 [(set_attr "predicable" "yes")
bcaec148 4225 (set_attr "insn" "xtab")
a2cd141b 4226 (set_attr "type" "alu_shift")]
4227)
4228
87b22bf7 4229(define_split
4230 [(set (match_operand:SI 0 "s_register_operand" "")
4231 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4232 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4233 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4234 [(set (match_dup 2) (match_dup 1))
4235 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4236 ""
4237)
9c08d1fa 4238
8a4d25d6 4239(define_split
4240 [(set (match_operand:SI 0 "s_register_operand" "")
4241 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4242 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4243 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4244 [(set (match_dup 2) (match_dup 1))
4245 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4246 ""
4247)
4248
1c274529 4249(define_code_iterator ior_xor [ior xor])
4250
4251(define_split
4252 [(set (match_operand:SI 0 "s_register_operand" "")
4253 (ior_xor:SI (and:SI (ashift:SI
4254 (match_operand:SI 1 "s_register_operand" "")
4255 (match_operand:SI 2 "const_int_operand" ""))
4256 (match_operand:SI 3 "const_int_operand" ""))
4257 (zero_extend:SI
4258 (match_operator 5 "subreg_lowpart_operator"
4259 [(match_operand:SI 4 "s_register_operand" "")]))))]
4260 "TARGET_32BIT
63787642 4261 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4262 == (GET_MODE_MASK (GET_MODE (operands[5]))
4263 & (GET_MODE_MASK (GET_MODE (operands[5]))
4264 << (INTVAL (operands[2])))))"
4265 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4266 (match_dup 4)))
4267 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4268 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4269)
4270
f7fbdd4a 4271(define_insn "*compareqi_eq0"
bd5b4116 4272 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4273 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4274 (const_int 0)))]
25f905c2 4275 "TARGET_32BIT"
87b22bf7 4276 "tst\\t%0, #255"
cffb2a26 4277 [(set_attr "conds" "set")]
4278)
b11cae9e 4279
b11cae9e 4280(define_expand "extendhisi2"
c8f69309 4281 [(set (match_dup 2)
25f7a26e 4282 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 4283 (const_int 16)))
9c08d1fa 4284 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4285 (ashiftrt:SI (match_dup 2)
4286 (const_int 16)))]
cffb2a26 4287 "TARGET_EITHER"
b11cae9e 4288 "
cffb2a26 4289 {
a2cd141b 4290 if (GET_CODE (operands[1]) == MEM)
cffb2a26 4291 {
25f905c2 4292 if (TARGET_THUMB1)
a2cd141b 4293 {
25f905c2 4294 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4295 DONE;
4296 }
4297 else if (arm_arch4)
4298 {
a2cd141b 4299 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4300 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4301 DONE;
4302 }
cffb2a26 4303 }
7bd8ccc9 4304
c1a66faf 4305 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 4306 {
4307 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4308 DONE;
4309 }
a2cd141b 4310
215b30b3 4311 if (!s_register_operand (operands[1], HImode))
cffb2a26 4312 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 4313
a2cd141b 4314 if (arm_arch6)
cffb2a26 4315 {
25f905c2 4316 if (TARGET_THUMB1)
4317 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 4318 else
4319 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4320 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4321
cffb2a26 4322 DONE;
4323 }
a2cd141b 4324
4325 operands[1] = gen_lowpart (SImode, operands[1]);
4326 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4327 }"
4328)
4329
25f905c2 4330(define_insn "thumb1_extendhisi2"
a2cd141b 4331 [(set (match_operand:SI 0 "register_operand" "=l")
4332 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4333 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4334 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4335 "*
4336 {
4337 rtx ops[4];
4338 rtx mem = XEXP (operands[1], 0);
4339
4340 /* This code used to try to use 'V', and fix the address only if it was
4341 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4342 range of QImode offsets, and offsettable_address_p does a QImode
4343 address check. */
4344
4345 if (GET_CODE (mem) == CONST)
4346 mem = XEXP (mem, 0);
4347
4348 if (GET_CODE (mem) == LABEL_REF)
4349 return \"ldr\\t%0, %1\";
4350
4351 if (GET_CODE (mem) == PLUS)
4352 {
4353 rtx a = XEXP (mem, 0);
4354 rtx b = XEXP (mem, 1);
4355
4356 if (GET_CODE (a) == LABEL_REF
4357 && GET_CODE (b) == CONST_INT)
4358 return \"ldr\\t%0, %1\";
4359
4360 if (GET_CODE (b) == REG)
4361 return \"ldrsh\\t%0, %1\";
4362
4363 ops[1] = a;
4364 ops[2] = b;
4365 }
4366 else
4367 {
4368 ops[1] = mem;
4369 ops[2] = const0_rtx;
4370 }
ed29c566 4371
4372 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 4373
4374 ops[0] = operands[0];
4375 ops[3] = operands[2];
4376 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4377 return \"\";
4378 }"
4379 [(set_attr "length" "4")
a2cd141b 4380 (set_attr "type" "load_byte")
cffb2a26 4381 (set_attr "pool_range" "1020")]
4382)
25f7a26e 4383
a2cd141b 4384;; We used to have an early-clobber on the scratch register here.
4385;; However, there's a bug somewhere in reload which means that this
4386;; can be partially ignored during spill allocation if the memory
ed29c566 4387;; address also needs reloading; this causes us to die later on when
a2cd141b 4388;; we try to verify the operands. Fortunately, we don't really need
4389;; the early-clobber: we can always use operand 0 if operand 2
4390;; overlaps the address.
25f905c2 4391(define_insn "*thumb1_extendhisi2_insn_v6"
a2cd141b 4392 [(set (match_operand:SI 0 "register_operand" "=l,l")
4393 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4394 (clobber (match_scratch:SI 2 "=X,l"))]
25f905c2 4395 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4396 "*
4397 {
4398 rtx ops[4];
4399 rtx mem;
4400
4401 if (which_alternative == 0)
4402 return \"sxth\\t%0, %1\";
4403
4404 mem = XEXP (operands[1], 0);
4405
4406 /* This code used to try to use 'V', and fix the address only if it was
4407 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4408 range of QImode offsets, and offsettable_address_p does a QImode
4409 address check. */
4410
4411 if (GET_CODE (mem) == CONST)
4412 mem = XEXP (mem, 0);
4413
4414 if (GET_CODE (mem) == LABEL_REF)
4415 return \"ldr\\t%0, %1\";
4416
4417 if (GET_CODE (mem) == PLUS)
4418 {
4419 rtx a = XEXP (mem, 0);
4420 rtx b = XEXP (mem, 1);
4421
4422 if (GET_CODE (a) == LABEL_REF
4423 && GET_CODE (b) == CONST_INT)
4424 return \"ldr\\t%0, %1\";
4425
4426 if (GET_CODE (b) == REG)
4427 return \"ldrsh\\t%0, %1\";
4428
4429 ops[1] = a;
4430 ops[2] = b;
4431 }
4432 else
4433 {
4434 ops[1] = mem;
4435 ops[2] = const0_rtx;
4436 }
4437
ed29c566 4438 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4439
4440 ops[0] = operands[0];
4441 if (reg_mentioned_p (operands[2], ops[1]))
4442 ops[3] = ops[0];
4443 else
4444 ops[3] = operands[2];
4445 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4446 return \"\";
4447 }"
4448 [(set_attr "length" "2,4")
4449 (set_attr "type" "alu_shift,load_byte")
4450 (set_attr "pool_range" "*,1020")]
4451)
4452
25f905c2 4453;; This pattern will only be used when ldsh is not available
25f7a26e 4454(define_expand "extendhisi2_mem"
eab14235 4455 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4456 (set (match_dup 3)
eab14235 4457 (zero_extend:SI (match_dup 7)))
25f7a26e 4458 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4459 (set (match_operand:SI 0 "" "")
4460 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4461 "TARGET_ARM"
25f7a26e 4462 "
215b30b3 4463 {
4464 rtx mem1, mem2;
4465 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4466
788fcce0 4467 mem1 = change_address (operands[1], QImode, addr);
4468 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4469 operands[0] = gen_lowpart (SImode, operands[0]);
4470 operands[1] = mem1;
4471 operands[2] = gen_reg_rtx (SImode);
4472 operands[3] = gen_reg_rtx (SImode);
4473 operands[6] = gen_reg_rtx (SImode);
4474 operands[7] = mem2;
25f7a26e 4475
215b30b3 4476 if (BYTES_BIG_ENDIAN)
4477 {
4478 operands[4] = operands[2];
4479 operands[5] = operands[3];
4480 }
4481 else
4482 {
4483 operands[4] = operands[3];
4484 operands[5] = operands[2];
4485 }
4486 }"
4487)
b11cae9e 4488
a2cd141b 4489(define_insn "*arm_extendhisi2"
4490 [(set (match_operand:SI 0 "s_register_operand" "=r")
4491 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4492 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4493 "ldr%(sh%)\\t%0, %1"
a2cd141b 4494 [(set_attr "type" "load_byte")
0d66636f 4495 (set_attr "predicable" "yes")
cffb2a26 4496 (set_attr "pool_range" "256")
4497 (set_attr "neg_pool_range" "244")]
4498)
f7fbdd4a 4499
25f905c2 4500;; ??? Check Thumb-2 pool range
a2cd141b 4501(define_insn "*arm_extendhisi2_v6"
4502 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4503 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4504 "TARGET_32BIT && arm_arch6"
a2cd141b 4505 "@
4506 sxth%?\\t%0, %1
25f905c2 4507 ldr%(sh%)\\t%0, %1"
a2cd141b 4508 [(set_attr "type" "alu_shift,load_byte")
4509 (set_attr "predicable" "yes")
4510 (set_attr "pool_range" "*,256")
4511 (set_attr "neg_pool_range" "*,244")]
4512)
4513
4514(define_insn "*arm_extendhisi2addsi"
4515 [(set (match_operand:SI 0 "s_register_operand" "=r")
4516 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4517 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4518 "TARGET_INT_SIMD"
a2cd141b 4519 "sxtah%?\\t%0, %2, %1"
4520)
4521
c8f69309 4522(define_expand "extendqihi2"
4523 [(set (match_dup 2)
bed7d9a5 4524 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4525 (const_int 24)))
9c08d1fa 4526 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4527 (ashiftrt:SI (match_dup 2)
4528 (const_int 24)))]
cffb2a26 4529 "TARGET_ARM"
c8f69309 4530 "
215b30b3 4531 {
4532 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4533 {
4534 emit_insn (gen_rtx_SET (VOIDmode,
4535 operands[0],
4536 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4537 DONE;
4538 }
4539 if (!s_register_operand (operands[1], QImode))
4540 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4541 operands[0] = gen_lowpart (SImode, operands[0]);
4542 operands[1] = gen_lowpart (SImode, operands[1]);
4543 operands[2] = gen_reg_rtx (SImode);
4544 }"
4545)
f7fbdd4a 4546
25f905c2 4547(define_insn "*arm_extendqihi_insn"
b4e8a300 4548 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4549 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4550 "TARGET_ARM && arm_arch4"
25f905c2 4551 "ldr%(sb%)\\t%0, %1"
a2cd141b 4552 [(set_attr "type" "load_byte")
0d66636f 4553 (set_attr "predicable" "yes")
cffb2a26 4554 (set_attr "pool_range" "256")
4555 (set_attr "neg_pool_range" "244")]
4556)
3fc2009e 4557
b11cae9e 4558(define_expand "extendqisi2"
c8f69309 4559 [(set (match_dup 2)
bed7d9a5 4560 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
b11cae9e 4561 (const_int 24)))
9c08d1fa 4562 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4563 (ashiftrt:SI (match_dup 2)
4564 (const_int 24)))]
cffb2a26 4565 "TARGET_EITHER"
b11cae9e 4566 "
cffb2a26 4567 {
a2cd141b 4568 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 4569 {
a2cd141b 4570 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 4571 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4572 DONE;
4573 }
a2cd141b 4574
215b30b3 4575 if (!s_register_operand (operands[1], QImode))
cffb2a26 4576 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 4577
a2cd141b 4578 if (arm_arch6)
4579 {
4580 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4581 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4582 DONE;
cffb2a26 4583 }
a2cd141b 4584
4585 operands[1] = gen_lowpart (SImode, operands[1]);
4586 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4587 }"
4588)
f7fbdd4a 4589
a2cd141b 4590(define_insn "*arm_extendqisi"
4591 [(set (match_operand:SI 0 "s_register_operand" "=r")
bed7d9a5 4592 (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
a2cd141b 4593 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4594 "ldr%(sb%)\\t%0, %1"
a2cd141b 4595 [(set_attr "type" "load_byte")
0d66636f 4596 (set_attr "predicable" "yes")
cffb2a26 4597 (set_attr "pool_range" "256")
4598 (set_attr "neg_pool_range" "244")]
4599)
3fc2009e 4600
a2cd141b 4601(define_insn "*arm_extendqisi_v6"
4602 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4603 (sign_extend:SI
4604 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4605 "TARGET_ARM && arm_arch6"
b4e8a300 4606 "@
4607 sxtb%?\\t%0, %1
25f905c2 4608 ldr%(sb%)\\t%0, %1"
a2cd141b 4609 [(set_attr "type" "alu_shift,load_byte")
4610 (set_attr "predicable" "yes")
a2cd141b 4611 (set_attr "pool_range" "*,256")
4612 (set_attr "neg_pool_range" "*,244")]
4613)
4614
4615(define_insn "*arm_extendqisi2addsi"
4616 [(set (match_operand:SI 0 "s_register_operand" "=r")
4617 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4618 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4619 "TARGET_INT_SIMD"
a2cd141b 4620 "sxtab%?\\t%0, %2, %1"
4621 [(set_attr "type" "alu_shift")
bcaec148 4622 (set_attr "insn" "xtab")
a2cd141b 4623 (set_attr "predicable" "yes")]
4624)
4625
25f905c2 4626(define_insn "*thumb1_extendqisi2"
a2cd141b 4627 [(set (match_operand:SI 0 "register_operand" "=l,l")
4628 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
25f905c2 4629 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4630 "*
4631 {
4632 rtx ops[3];
4633 rtx mem = XEXP (operands[1], 0);
4634
4635 if (GET_CODE (mem) == CONST)
4636 mem = XEXP (mem, 0);
4637
4638 if (GET_CODE (mem) == LABEL_REF)
4639 return \"ldr\\t%0, %1\";
4640
4641 if (GET_CODE (mem) == PLUS
4642 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4643 return \"ldr\\t%0, %1\";
4644
4645 if (which_alternative == 0)
4646 return \"ldrsb\\t%0, %1\";
4647
4648 ops[0] = operands[0];
4649
4650 if (GET_CODE (mem) == PLUS)
4651 {
4652 rtx a = XEXP (mem, 0);
4653 rtx b = XEXP (mem, 1);
4654
4655 ops[1] = a;
4656 ops[2] = b;
4657
4658 if (GET_CODE (a) == REG)
4659 {
4660 if (GET_CODE (b) == REG)
4661 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4662 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 4663 {
4664 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4665 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4666 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4667 }
cffb2a26 4668 else
4669 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4670 }
cffb2a26 4671 else
4672 {
ed29c566 4673 gcc_assert (GET_CODE (b) == REG);
cffb2a26 4674 if (REGNO (b) == REGNO (ops[0]))
215b30b3 4675 {
4676 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4677 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4678 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4679 }
cffb2a26 4680 else
4681 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4682 }
4683 }
4684 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4685 {
215b30b3 4686 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4687 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4688 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 4689 }
4690 else
4691 {
4692 ops[1] = mem;
4693 ops[2] = const0_rtx;
4694
4695 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4696 }
4697 return \"\";
4698 }"
4699 [(set_attr "length" "2,6")
a2cd141b 4700 (set_attr "type" "load_byte,load_byte")
cffb2a26 4701 (set_attr "pool_range" "32,32")]
4702)
4703
25f905c2 4704(define_insn "*thumb1_extendqisi2_v6"
a2cd141b 4705 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4706 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
25f905c2 4707 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4708 "*
4709 {
4710 rtx ops[3];
4711 rtx mem;
4712
4713 if (which_alternative == 0)
4714 return \"sxtb\\t%0, %1\";
4715
4716 mem = XEXP (operands[1], 0);
4717
4718 if (GET_CODE (mem) == CONST)
4719 mem = XEXP (mem, 0);
4720
4721 if (GET_CODE (mem) == LABEL_REF)
4722 return \"ldr\\t%0, %1\";
4723
4724 if (GET_CODE (mem) == PLUS
4725 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4726 return \"ldr\\t%0, %1\";
4727
4728 if (which_alternative == 0)
4729 return \"ldrsb\\t%0, %1\";
4730
4731 ops[0] = operands[0];
4732
4733 if (GET_CODE (mem) == PLUS)
4734 {
4735 rtx a = XEXP (mem, 0);
4736 rtx b = XEXP (mem, 1);
4737
4738 ops[1] = a;
4739 ops[2] = b;
4740
4741 if (GET_CODE (a) == REG)
4742 {
4743 if (GET_CODE (b) == REG)
4744 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4745 else if (REGNO (a) == REGNO (ops[0]))
4746 {
4747 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", 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 }
a2cd141b 4753 else
4754 {
ed29c566 4755 gcc_assert (GET_CODE (b) == REG);
a2cd141b 4756 if (REGNO (b) == REGNO (ops[0]))
4757 {
4758 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4759 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4760 }
4761 else
4762 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4763 }
4764 }
4765 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4766 {
4767 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4768 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4769 }
4770 else
4771 {
4772 ops[1] = mem;
4773 ops[2] = const0_rtx;
4774
4775 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4776 }
4777 return \"\";
4778 }"
4779 [(set_attr "length" "2,2,4")
4780 (set_attr "type" "alu_shift,load_byte,load_byte")
4781 (set_attr "pool_range" "*,32,32")]
4782)
4783
caedf871 4784(define_expand "extendsfdf2"
4785 [(set (match_operand:DF 0 "s_register_operand" "")
4786 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 4787 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4788 ""
4789)
9b8516be 4790
4791/* HFmode -> DFmode conversions have to go through SFmode. */
4792(define_expand "extendhfdf2"
4793 [(set (match_operand:DF 0 "general_operand" "")
4794 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4795 "TARGET_EITHER"
4796 "
4797 {
4798 rtx op1;
4799 op1 = convert_to_mode (SFmode, operands[1], 0);
4800 op1 = convert_to_mode (DFmode, op1, 0);
4801 emit_insn (gen_movdf (operands[0], op1));
4802 DONE;
4803 }"
4804)
b11cae9e 4805\f
4806;; Move insns (including loads and stores)
4807
4808;; XXX Just some ideas about movti.
9c08d1fa 4809;; I don't think these are a good idea on the arm, there just aren't enough
4810;; registers
b11cae9e 4811;;(define_expand "loadti"
9c08d1fa 4812;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4813;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4814;; "" "")
4815
4816;;(define_expand "storeti"
4817;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4818;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4819;; "" "")
4820
4821;;(define_expand "movti"
4822;; [(set (match_operand:TI 0 "general_operand" "")
4823;; (match_operand:TI 1 "general_operand" ""))]
4824;; ""
4825;; "
4826;;{
4827;; rtx insn;
4828;;
4829;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4830;; operands[1] = copy_to_reg (operands[1]);
4831;; if (GET_CODE (operands[0]) == MEM)
4832;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4833;; else if (GET_CODE (operands[1]) == MEM)
4834;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4835;; else
4836;; FAIL;
4837;;
4838;; emit_insn (insn);
4839;; DONE;
4840;;}")
4841
a2f10574 4842;; Recognize garbage generated above.
b11cae9e 4843
4844;;(define_insn ""
4845;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4846;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4847;; ""
4848;; "*
4849;; {
4850;; register mem = (which_alternative < 3);
0d66636f 4851;; register const char *template;
b11cae9e 4852;;
4853;; operands[mem] = XEXP (operands[mem], 0);
4854;; switch (which_alternative)
4855;; {
4856;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4857;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4858;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4859;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4860;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4861;; case 5: template = \"stmia\\t%0, %M1\"; break;
4862;; }
e2348bcb 4863;; output_asm_insn (template, operands);
4864;; return \"\";
b11cae9e 4865;; }")
4866
cffb2a26 4867(define_expand "movdi"
4868 [(set (match_operand:DI 0 "general_operand" "")
4869 (match_operand:DI 1 "general_operand" ""))]
4870 "TARGET_EITHER"
4871 "
e1ba4a27 4872 if (can_create_pseudo_p ())
cffb2a26 4873 {
b2778788 4874 if (GET_CODE (operands[0]) != REG)
4875 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4876 }
4877 "
4878)
b11cae9e 4879
cffb2a26 4880(define_insn "*arm_movdi"
d51f92df 4881 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4882 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4883 "TARGET_ARM
b2778788 4884 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4885 && !TARGET_IWMMXT
4886 && ( register_operand (operands[0], DImode)
4887 || register_operand (operands[1], DImode))"
b11cae9e 4888 "*
d51f92df 4889 switch (which_alternative)
4890 {
4891 case 0:
4892 case 1:
4893 case 2:
4894 return \"#\";
4895 default:
4896 return output_move_double (operands);
4897 }
cffb2a26 4898 "
359a6e9f 4899 [(set_attr "length" "8,12,16,8,8")
4900 (set_attr "type" "*,*,*,load2,store2")
4901 (set_attr "pool_range" "*,*,*,1020,*")
4902 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4903)
4904
d51f92df 4905(define_split
4906 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4907 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4908 "TARGET_32BIT
d51f92df 4909 && reload_completed
4910 && (arm_const_double_inline_cost (operands[1])
4911 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4912 [(const_int 0)]
4913 "
4914 arm_split_constant (SET, SImode, curr_insn,
4915 INTVAL (gen_lowpart (SImode, operands[1])),
4916 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4917 arm_split_constant (SET, SImode, curr_insn,
4918 INTVAL (gen_highpart_mode (SImode,
4919 GET_MODE (operands[0]),
4920 operands[1])),
4921 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4922 DONE;
4923 "
4924)
4925
e5ba9289 4926; If optimizing for size, or if we have load delay slots, then
4927; we want to split the constant into two separate operations.
4928; In both cases this may split a trivial part into a single data op
4929; leaving a single complex constant to load. We can also get longer
4930; offsets in a LDR which means we get better chances of sharing the pool
4931; entries. Finally, we can normally do a better job of scheduling
4932; LDR instructions than we can with LDM.
4933; This pattern will only match if the one above did not.
4934(define_split
4935 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4936 (match_operand:ANY64 1 "const_double_operand" ""))]
4937 "TARGET_ARM && reload_completed
4938 && arm_const_double_by_parts (operands[1])"
4939 [(set (match_dup 0) (match_dup 1))
4940 (set (match_dup 2) (match_dup 3))]
4941 "
4942 operands[2] = gen_highpart (SImode, operands[0]);
4943 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4944 operands[1]);
4945 operands[0] = gen_lowpart (SImode, operands[0]);
4946 operands[1] = gen_lowpart (SImode, operands[1]);
4947 "
4948)
4949
d51f92df 4950(define_split
4951 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4952 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4953 "TARGET_EITHER && reload_completed"
4954 [(set (match_dup 0) (match_dup 1))
4955 (set (match_dup 2) (match_dup 3))]
4956 "
4957 operands[2] = gen_highpart (SImode, operands[0]);
4958 operands[3] = gen_highpart (SImode, operands[1]);
4959 operands[0] = gen_lowpart (SImode, operands[0]);
4960 operands[1] = gen_lowpart (SImode, operands[1]);
4961
4962 /* Handle a partial overlap. */
4963 if (rtx_equal_p (operands[0], operands[3]))
4964 {
4965 rtx tmp0 = operands[0];
4966 rtx tmp1 = operands[1];
4967
4968 operands[0] = operands[2];
4969 operands[1] = operands[3];
4970 operands[2] = tmp0;
4971 operands[3] = tmp1;
4972 }
4973 "
4974)
4975
a8a3b539 4976;; We can't actually do base+index doubleword loads if the index and
4977;; destination overlap. Split here so that we at least have chance to
4978;; schedule.
4979(define_split
4980 [(set (match_operand:DI 0 "s_register_operand" "")
4981 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4982 (match_operand:SI 2 "s_register_operand" ""))))]
4983 "TARGET_LDRD
4984 && reg_overlap_mentioned_p (operands[0], operands[1])
4985 && reg_overlap_mentioned_p (operands[0], operands[2])"
4986 [(set (match_dup 4)
4987 (plus:SI (match_dup 1)
4988 (match_dup 2)))
4989 (set (match_dup 0)
4990 (mem:DI (match_dup 4)))]
4991 "
4992 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4993 "
4994)
4995
cffb2a26 4996;;; ??? This should have alternatives for constants.
4997;;; ??? This was originally identical to the movdf_insn pattern.
4998;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4999;;; thumb_reorg with a memory reference.
25f905c2 5000(define_insn "*thumb1_movdi_insn"
215b30b3 5001 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5002 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 5003 "TARGET_THUMB1
a2cd141b 5004 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 5005 && ( register_operand (operands[0], DImode)
5006 || register_operand (operands[1], DImode))"
5007 "*
5008 {
5009 switch (which_alternative)
5010 {
5011 default:
5012 case 0:
5013 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5014 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5015 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5016 case 1:
5017 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5018 case 2:
5019 operands[1] = GEN_INT (- INTVAL (operands[1]));
5020 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5021 case 3:
5022 return \"ldmia\\t%1, {%0, %H0}\";
5023 case 4:
5024 return \"stmia\\t%0, {%1, %H1}\";
5025 case 5:
5026 return thumb_load_double_from_address (operands);
5027 case 6:
1a83b3ff 5028 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5029 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5030 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5031 return \"\";
5032 case 7:
5033 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5034 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5035 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5036 }
5037 }"
5038 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5039 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 5040 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5041)
b11cae9e 5042
9c08d1fa 5043(define_expand "movsi"
5044 [(set (match_operand:SI 0 "general_operand" "")
5045 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5046 "TARGET_EITHER"
9c08d1fa 5047 "
befb0bac 5048 {
e348ff3e 5049 rtx base, offset, tmp;
5050
25f905c2 5051 if (TARGET_32BIT)
9c08d1fa 5052 {
674a8f0b 5053 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5054 if (GET_CODE (operands[0]) == MEM)
5055 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5056 if (arm_general_register_operand (operands[0], SImode)
5057 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5058 && !(const_ok_for_arm (INTVAL (operands[1]))
5059 || const_ok_for_arm (~INTVAL (operands[1]))))
5060 {
96f57e36 5061 arm_split_constant (SET, SImode, NULL_RTX,
5062 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5063 optimize && can_create_pseudo_p ());
cffb2a26 5064 DONE;
5065 }
d0e6a121 5066
5067 if (TARGET_USE_MOVT && !target_word_relocations
5068 && GET_CODE (operands[1]) == SYMBOL_REF
5069 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5070 {
5071 arm_emit_movpair (operands[0], operands[1]);
5072 DONE;
5073 }
cffb2a26 5074 }
25f905c2 5075 else /* TARGET_THUMB1... */
cffb2a26 5076 {
e1ba4a27 5077 if (can_create_pseudo_p ())
cffb2a26 5078 {
5079 if (GET_CODE (operands[0]) != REG)
5080 operands[1] = force_reg (SImode, operands[1]);
5081 }
9c08d1fa 5082 }
f655717d 5083
e348ff3e 5084 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5085 {
5086 split_const (operands[1], &base, &offset);
5087 if (GET_CODE (base) == SYMBOL_REF
5088 && !offset_within_block_p (base, INTVAL (offset)))
5089 {
b308ddcf 5090 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5091 emit_move_insn (tmp, base);
5092 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5093 DONE;
5094 }
5095 }
5096
f655717d 5097 /* Recognize the case where operand[1] is a reference to thread-local
5098 data and load its address to a register. */
5099 if (arm_tls_referenced_p (operands[1]))
5100 {
5101 rtx tmp = operands[1];
5102 rtx addend = NULL;
5103
5104 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5105 {
5106 addend = XEXP (XEXP (tmp, 0), 1);
5107 tmp = XEXP (XEXP (tmp, 0), 0);
5108 }
5109
5110 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5111 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5112
e1ba4a27 5113 tmp = legitimize_tls_address (tmp,
5114 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5115 if (addend)
5116 {
5117 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5118 tmp = force_operand (tmp, operands[0]);
5119 }
5120 operands[1] = tmp;
5121 }
5122 else if (flag_pic
5123 && (CONSTANT_P (operands[1])
5124 || symbol_mentioned_p (operands[1])
5125 || label_mentioned_p (operands[1])))
5126 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5127 (!can_create_pseudo_p ()
5128 ? operands[0]
5129 : 0));
befb0bac 5130 }
215b30b3 5131 "
5132)
9c08d1fa 5133
d0e6a121 5134;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5135;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5136;; so this does not matter.
5137(define_insn "*arm_movt"
5138 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5139 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5140 (match_operand:SI 2 "general_operand" "i")))]
5141 "TARGET_32BIT"
5142 "movt%?\t%0, #:upper16:%c2"
5143 [(set_attr "predicable" "yes")
5144 (set_attr "length" "4")]
5145)
5146
cffb2a26 5147(define_insn "*arm_movsi_insn"
aaa37ad6 5148 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5149 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5150 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5151 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5152 && ( register_operand (operands[0], SImode)
5153 || register_operand (operands[1], SImode))"
f7fbdd4a 5154 "@
aaa37ad6 5155 mov%?\\t%0, %1
f7fbdd4a 5156 mov%?\\t%0, %1
5157 mvn%?\\t%0, #%B1
25f905c2 5158 movw%?\\t%0, %1
f7fbdd4a 5159 ldr%?\\t%0, %1
5160 str%?\\t%1, %0"
aaa37ad6 5161 [(set_attr "type" "*,*,*,*,load1,store1")
0d66636f 5162 (set_attr "predicable" "yes")
aaa37ad6 5163 (set_attr "pool_range" "*,*,*,*,4096,*")
5164 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5165)
87b22bf7 5166
5167(define_split
a2cd141b 5168 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5169 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5170 "TARGET_32BIT
215b30b3 5171 && (!(const_ok_for_arm (INTVAL (operands[1]))
5172 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5173 [(clobber (const_int 0))]
5174 "
96f57e36 5175 arm_split_constant (SET, SImode, NULL_RTX,
5176 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5177 DONE;
215b30b3 5178 "
5179)
9c08d1fa 5180
25f905c2 5181(define_insn "*thumb1_movsi_insn"
aaa37ad6 5182 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5183 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
25f905c2 5184 "TARGET_THUMB1
cffb2a26 5185 && ( register_operand (operands[0], SImode)
5186 || register_operand (operands[1], SImode))"
5187 "@
5188 mov %0, %1
5189 mov %0, %1
5190 #
5191 #
5192 ldmia\\t%1, {%0}
5193 stmia\\t%0, {%1}
5194 ldr\\t%0, %1
5195 str\\t%1, %0
5196 mov\\t%0, %1"
5197 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5198 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 5199 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5200)
5201
5202(define_split
5203 [(set (match_operand:SI 0 "register_operand" "")
5204 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5205 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
cffb2a26 5206 [(set (match_dup 0) (match_dup 1))
5207 (set (match_dup 0) (neg:SI (match_dup 0)))]
5208 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5209)
5210
5211(define_split
5212 [(set (match_operand:SI 0 "register_operand" "")
5213 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5214 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
cffb2a26 5215 [(set (match_dup 0) (match_dup 1))
5216 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5217 "
5218 {
e4aeee53 5219 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5220 unsigned HOST_WIDE_INT mask = 0xff;
5221 int i;
5222
5223 for (i = 0; i < 25; i++)
5224 if ((val & (mask << i)) == val)
5225 break;
5226
f5b3169c 5227 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 5228 if (i == 0)
5229 FAIL;
5230
5231 operands[1] = GEN_INT (val >> i);
5232 operands[2] = GEN_INT (i);
5233 }"
5234)
5235
67336bcf 5236;; When generating pic, we need to load the symbol offset into a register.
5237;; So that the optimizer does not confuse this with a normal symbol load
5238;; we use an unspec. The offset will be loaded from a constant pool entry,
5239;; since that is the only type of relocation we can use.
5240
5241;; The rather odd constraints on the following are to force reload to leave
5242;; the insn alone, and to force the minipool generation pass to then move
5243;; the GOT symbol to memory.
849170fd 5244
8c4d8060 5245(define_insn "pic_load_addr_arm"
849170fd 5246 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5247 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 5248 "TARGET_ARM && flag_pic"
67336bcf 5249 "ldr%?\\t%0, %1"
a2cd141b 5250 [(set_attr "type" "load1")
8c4d8060 5251 (set (attr "pool_range") (const_int 4096))
5252 (set (attr "neg_pool_range") (const_int 4084))]
5253)
5254
25f905c2 5255(define_insn "pic_load_addr_thumb1"
8c4d8060 5256 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5257 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5258 "TARGET_THUMB1 && flag_pic"
8c4d8060 5259 "ldr\\t%0, %1"
a2cd141b 5260 [(set_attr "type" "load1")
8c4d8060 5261 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5262)
849170fd 5263
cffb2a26 5264(define_insn "pic_add_dot_plus_four"
15d5d060 5265 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5266 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5267 (const_int 4)
beef0fb5 5268 (match_operand 2 "" "")]
5269 UNSPEC_PIC_BASE))]
25f905c2 5270 "TARGET_THUMB1"
cffb2a26 5271 "*
6cdcb15c 5272 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5273 INTVAL (operands[2]));
cffb2a26 5274 return \"add\\t%0, %|pc\";
5275 "
5276 [(set_attr "length" "2")]
5277)
849170fd 5278
5279(define_insn "pic_add_dot_plus_eight"
15d5d060 5280 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5281 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5282 (const_int 8)
beef0fb5 5283 (match_operand 2 "" "")]
5284 UNSPEC_PIC_BASE))]
f655717d 5285 "TARGET_ARM"
c4034607 5286 "*
6cdcb15c 5287 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5288 INTVAL (operands[2]));
15d5d060 5289 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5290 "
0d66636f 5291 [(set_attr "predicable" "yes")]
cffb2a26 5292)
849170fd 5293
f655717d 5294(define_insn "tls_load_dot_plus_eight"
5295 [(set (match_operand:SI 0 "register_operand" "+r")
c0c1fba5 5296 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5297 (const_int 8)
beef0fb5 5298 (match_operand 2 "" "")]
5299 UNSPEC_PIC_BASE)))]
f655717d 5300 "TARGET_ARM"
5301 "*
6cdcb15c 5302 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5303 INTVAL (operands[2]));
f655717d 5304 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5305 "
5306 [(set_attr "predicable" "yes")]
5307)
5308
5309;; PIC references to local variables can generate pic_add_dot_plus_eight
5310;; followed by a load. These sequences can be crunched down to
5311;; tls_load_dot_plus_eight by a peephole.
5312
5313(define_peephole2
c0c1fba5 5314 [(set (match_operand:SI 0 "register_operand" "")
5315 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5316 (const_int 8)
5317 (match_operand 1 "" "")]
5318 UNSPEC_PIC_BASE))
f655717d 5319 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5320 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5321 [(set (match_dup 2)
5322 (mem:SI (unspec:SI [(match_dup 3)
5323 (const_int 8)
5324 (match_dup 1)]
5325 UNSPEC_PIC_BASE)))]
f655717d 5326 ""
5327)
5328
bac7fc85 5329(define_insn "pic_offset_arm"
5330 [(set (match_operand:SI 0 "register_operand" "=r")
5331 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5332 (unspec:SI [(match_operand:SI 2 "" "X")]
5333 UNSPEC_PIC_OFFSET))))]
5334 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5335 "ldr%?\\t%0, [%1,%2]"
5336 [(set_attr "type" "load1")]
5337)
5338
95373f08 5339(define_expand "builtin_setjmp_receiver"
5340 [(label_ref (match_operand 0 "" ""))]
5341 "flag_pic"
5342 "
5343{
b935b306 5344 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5345 register. */
2cb7d577 5346 if (arm_pic_register != INVALID_REGNUM)
5347 arm_load_pic_register (1UL << 3);
95373f08 5348 DONE;
5349}")
5350
9c08d1fa 5351;; If copying one reg to another we can set the condition codes according to
5352;; its value. Such a move is common after a return from subroutine and the
5353;; result is being tested against zero.
5354
f7fbdd4a 5355(define_insn "*movsi_compare0"
bd5b4116 5356 [(set (reg:CC CC_REGNUM)
cffb2a26 5357 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5358 (const_int 0)))
5359 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5360 (match_dup 1))]
25f905c2 5361 "TARGET_32BIT"
e2348bcb 5362 "@
40dbec34 5363 cmp%?\\t%0, #0
25f905c2 5364 sub%.\\t%0, %1, #0"
cffb2a26 5365 [(set_attr "conds" "set")]
5366)
b11cae9e 5367
b11cae9e 5368;; Subroutine to store a half word from a register into memory.
5369;; Operand 0 is the source register (HImode)
c8f69309 5370;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5371
9c08d1fa 5372;; In both this routine and the next, we must be careful not to spill
01cc3b75 5373;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5374;; can generate unrecognizable rtl.
5375
b11cae9e 5376(define_expand "storehi"
c8f69309 5377 [;; store the low byte
f082f1c4 5378 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5379 ;; extract the high byte
c8f69309 5380 (set (match_dup 2)
5381 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5382 ;; store the high byte
787f8210 5383 (set (match_dup 4) (match_dup 5))]
cffb2a26 5384 "TARGET_ARM"
b11cae9e 5385 "
215b30b3 5386 {
537ffcfc 5387 rtx op1 = operands[1];
5388 rtx addr = XEXP (op1, 0);
215b30b3 5389 enum rtx_code code = GET_CODE (addr);
5390
5391 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5392 || code == MINUS)
537ffcfc 5393 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5394
537ffcfc 5395 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5396 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5397 operands[3] = gen_lowpart (QImode, operands[0]);
5398 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5399 operands[2] = gen_reg_rtx (SImode);
5400 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5401 }"
5402)
b11cae9e 5403
c7597b5d 5404(define_expand "storehi_bigend"
f082f1c4 5405 [(set (match_dup 4) (match_dup 3))
c7597b5d 5406 (set (match_dup 2)
5407 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5408 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5409 "TARGET_ARM"
b11cae9e 5410 "
215b30b3 5411 {
537ffcfc 5412 rtx op1 = operands[1];
5413 rtx addr = XEXP (op1, 0);
215b30b3 5414 enum rtx_code code = GET_CODE (addr);
5415
5416 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5417 || code == MINUS)
537ffcfc 5418 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5419
537ffcfc 5420 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5421 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5422 operands[3] = gen_lowpart (QImode, operands[0]);
5423 operands[0] = gen_lowpart (SImode, operands[0]);
5424 operands[2] = gen_reg_rtx (SImode);
787f8210 5425 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5426 }"
5427)
c7597b5d 5428
5429;; Subroutine to store a half word integer constant into memory.
5430(define_expand "storeinthi"
f082f1c4 5431 [(set (match_operand 0 "" "")
787f8210 5432 (match_operand 1 "" ""))
9e8503e6 5433 (set (match_dup 3) (match_dup 2))]
cffb2a26 5434 "TARGET_ARM"
c7597b5d 5435 "
215b30b3 5436 {
5437 HOST_WIDE_INT value = INTVAL (operands[1]);
5438 rtx addr = XEXP (operands[0], 0);
537ffcfc 5439 rtx op0 = operands[0];
215b30b3 5440 enum rtx_code code = GET_CODE (addr);
c7597b5d 5441
215b30b3 5442 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5443 || code == MINUS)
537ffcfc 5444 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5445
215b30b3 5446 operands[1] = gen_reg_rtx (SImode);
5447 if (BYTES_BIG_ENDIAN)
5448 {
5449 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5450 if ((value & 255) == ((value >> 8) & 255))
5451 operands[2] = operands[1];
5452 else
5453 {
5454 operands[2] = gen_reg_rtx (SImode);
5455 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5456 }
5457 }
5458 else
5459 {
5460 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5461 if ((value & 255) == ((value >> 8) & 255))
5462 operands[2] = operands[1];
5463 else
5464 {
5465 operands[2] = gen_reg_rtx (SImode);
5466 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5467 }
5468 }
c7597b5d 5469
537ffcfc 5470 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5471 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5472 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5473 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5474 }"
5475)
b11cae9e 5476
f7fbdd4a 5477(define_expand "storehi_single_op"
5478 [(set (match_operand:HI 0 "memory_operand" "")
5479 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5480 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5481 "
215b30b3 5482 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5483 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5484 "
5485)
f7fbdd4a 5486
b11cae9e 5487(define_expand "movhi"
5488 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5489 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5490 "TARGET_EITHER"
b11cae9e 5491 "
cffb2a26 5492 if (TARGET_ARM)
b11cae9e 5493 {
e1ba4a27 5494 if (can_create_pseudo_p ())
cffb2a26 5495 {
5496 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5497 {
cffb2a26 5498 if (arm_arch4)
5499 {
5500 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5501 DONE;
5502 }
5503 if (GET_CODE (operands[1]) == CONST_INT)
5504 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5505 else
cffb2a26 5506 {
5507 if (GET_CODE (operands[1]) == MEM)
5508 operands[1] = force_reg (HImode, operands[1]);
5509 if (BYTES_BIG_ENDIAN)
5510 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5511 else
5512 emit_insn (gen_storehi (operands[1], operands[0]));
5513 }
5514 DONE;
b11cae9e 5515 }
cffb2a26 5516 /* Sign extend a constant, and keep it in an SImode reg. */
5517 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5518 {
cffb2a26 5519 rtx reg = gen_reg_rtx (SImode);
5520 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5521
5522 /* If the constant is already valid, leave it alone. */
215b30b3 5523 if (!const_ok_for_arm (val))
cffb2a26 5524 {
5525 /* If setting all the top bits will make the constant
5526 loadable in a single instruction, then set them.
5527 Otherwise, sign extend the number. */
5528
215b30b3 5529 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5530 val |= ~0xffff;
5531 else if (val & 0x8000)
5532 val |= ~0xffff;
5533 }
5534
5535 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5536 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5537 }
e1ba4a27 5538 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5539 && GET_CODE (operands[1]) == MEM)
5540 {
5541 rtx reg = gen_reg_rtx (SImode);
5542
5543 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5544 operands[1] = gen_lowpart (HImode, reg);
5545 }
215b30b3 5546 else if (!arm_arch4)
f7fbdd4a 5547 {
cffb2a26 5548 if (GET_CODE (operands[1]) == MEM)
5549 {
c1a66faf 5550 rtx base;
5551 rtx offset = const0_rtx;
5552 rtx reg = gen_reg_rtx (SImode);
5553
5554 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5555 || (GET_CODE (base) == PLUS
5556 && (GET_CODE (offset = XEXP (base, 1))
5557 == CONST_INT)
5558 && ((INTVAL(offset) & 1) != 1)
5559 && GET_CODE (base = XEXP (base, 0)) == REG))
5560 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5561 {
8deb3959 5562 rtx new_rtx;
c1a66faf 5563
8deb3959 5564 new_rtx = widen_memory_access (operands[1], SImode,
5565 ((INTVAL (offset) & ~3)
5566 - INTVAL (offset)));
5567 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5568 if (((INTVAL (offset) & 2) != 0)
5569 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5570 {
5571 rtx reg2 = gen_reg_rtx (SImode);
5572
5573 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5574 reg = reg2;
5575 }
206ee9a2 5576 }
c1a66faf 5577 else
5578 emit_insn (gen_movhi_bytes (reg, operands[1]));
5579
5580 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5581 }
5582 }
5583 }
674a8f0b 5584 /* Handle loading a large integer during reload. */
cffb2a26 5585 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5586 && !const_ok_for_arm (INTVAL (operands[1]))
5587 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5588 {
5589 /* Writing a constant to memory needs a scratch, which should
5590 be handled with SECONDARY_RELOADs. */
ed29c566 5591 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5592
5593 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5594 emit_insn (gen_movsi (operands[0], operands[1]));
5595 DONE;
5596 }
5597 }
25f905c2 5598 else if (TARGET_THUMB2)
5599 {
5600 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5601 if (can_create_pseudo_p ())
25f905c2 5602 {
5603 if (GET_CODE (operands[0]) != REG)
5604 operands[1] = force_reg (HImode, operands[1]);
5605 /* Zero extend a constant, and keep it in an SImode reg. */
5606 else if (GET_CODE (operands[1]) == CONST_INT)
5607 {
5608 rtx reg = gen_reg_rtx (SImode);
5609 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5610
5611 emit_insn (gen_movsi (reg, GEN_INT (val)));
5612 operands[1] = gen_lowpart (HImode, reg);
5613 }
5614 }
5615 }
5616 else /* TARGET_THUMB1 */
cffb2a26 5617 {
e1ba4a27 5618 if (can_create_pseudo_p ())
cffb2a26 5619 {
6cffc037 5620 if (GET_CODE (operands[1]) == CONST_INT)
5621 {
5622 rtx reg = gen_reg_rtx (SImode);
5623
5624 emit_insn (gen_movsi (reg, operands[1]));
5625 operands[1] = gen_lowpart (HImode, reg);
5626 }
cffb2a26 5627
5628 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5629 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5630 virtual register (also rejected as illegitimate for HImode/QImode)
5631 relative address. */
cffb2a26 5632 /* ??? This should perhaps be fixed elsewhere, for instance, in
5633 fixup_stack_1, by checking for other kinds of invalid addresses,
5634 e.g. a bare reference to a virtual register. This may confuse the
5635 alpha though, which must handle this case differently. */
5636 if (GET_CODE (operands[0]) == MEM
215b30b3 5637 && !memory_address_p (GET_MODE (operands[0]),
5638 XEXP (operands[0], 0)))
537ffcfc 5639 operands[0]
5640 = replace_equiv_address (operands[0],
5641 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5642
5643 if (GET_CODE (operands[1]) == MEM
215b30b3 5644 && !memory_address_p (GET_MODE (operands[1]),
5645 XEXP (operands[1], 0)))
537ffcfc 5646 operands[1]
5647 = replace_equiv_address (operands[1],
5648 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5649
5650 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5651 {
5652 rtx reg = gen_reg_rtx (SImode);
5653
5654 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5655 operands[1] = gen_lowpart (HImode, reg);
5656 }
5657
5658 if (GET_CODE (operands[0]) == MEM)
5659 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5660 }
cffb2a26 5661 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5662 && !satisfies_constraint_I (operands[1]))
cffb2a26 5663 {
6cffc037 5664 /* Handle loading a large integer during reload. */
5665
cffb2a26 5666 /* Writing a constant to memory needs a scratch, which should
5667 be handled with SECONDARY_RELOADs. */
ed29c566 5668 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5669
1a83b3ff 5670 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5671 emit_insn (gen_movsi (operands[0], operands[1]));
5672 DONE;
5673 }
b11cae9e 5674 }
cffb2a26 5675 "
5676)
5677
25f905c2 5678(define_insn "*thumb1_movhi_insn"
a941568e 5679 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5680 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5681 "TARGET_THUMB1
cffb2a26 5682 && ( register_operand (operands[0], HImode)
5683 || register_operand (operands[1], HImode))"
5684 "*
5685 switch (which_alternative)
d79300ac 5686 {
cffb2a26 5687 case 0: return \"add %0, %1, #0\";
5688 case 2: return \"strh %1, %0\";
5689 case 3: return \"mov %0, %1\";
5690 case 4: return \"mov %0, %1\";
5691 case 5: return \"mov %0, %1\";
ed29c566 5692 default: gcc_unreachable ();
cffb2a26 5693 case 1:
5694 /* The stack pointer can end up being taken as an index register.
5695 Catch this case here and deal with it. */
5696 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5697 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5698 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5699 {
5700 rtx ops[2];
5701 ops[0] = operands[0];
5702 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5703
5704 output_asm_insn (\"mov %0, %1\", ops);
5705
5706 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5707
5708 }
5709 return \"ldrh %0, %1\";
5710 }"
5711 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 5712 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 5713)
d79300ac 5714
b11cae9e 5715
25f7a26e 5716(define_expand "movhi_bytes"
eab14235 5717 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5718 (set (match_dup 3)
eab14235 5719 (zero_extend:SI (match_dup 6)))
25f7a26e 5720 (set (match_operand:SI 0 "" "")
5721 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5722 "TARGET_ARM"
25f7a26e 5723 "
215b30b3 5724 {
5725 rtx mem1, mem2;
5726 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5727
788fcce0 5728 mem1 = change_address (operands[1], QImode, addr);
5729 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5730 operands[0] = gen_lowpart (SImode, operands[0]);
5731 operands[1] = mem1;
5732 operands[2] = gen_reg_rtx (SImode);
5733 operands[3] = gen_reg_rtx (SImode);
5734 operands[6] = mem2;
25f7a26e 5735
215b30b3 5736 if (BYTES_BIG_ENDIAN)
5737 {
5738 operands[4] = operands[2];
5739 operands[5] = operands[3];
5740 }
5741 else
5742 {
5743 operands[4] = operands[3];
5744 operands[5] = operands[2];
5745 }
5746 }"
5747)
25f7a26e 5748
c7597b5d 5749(define_expand "movhi_bigend"
5750 [(set (match_dup 2)
5751 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5752 (const_int 16)))
5753 (set (match_dup 3)
5754 (ashiftrt:SI (match_dup 2) (const_int 16)))
5755 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5756 (match_dup 4))]
cffb2a26 5757 "TARGET_ARM"
c7597b5d 5758 "
5759 operands[2] = gen_reg_rtx (SImode);
5760 operands[3] = gen_reg_rtx (SImode);
787f8210 5761 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5762 "
5763)
b11cae9e 5764
a2f10574 5765;; Pattern to recognize insn generated default case above
f7fbdd4a 5766(define_insn "*movhi_insn_arch4"
cffb2a26 5767 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5768 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5769 "TARGET_ARM
5770 && arm_arch4
f7fbdd4a 5771 && (GET_CODE (operands[1]) != CONST_INT
5772 || const_ok_for_arm (INTVAL (operands[1]))
5773 || const_ok_for_arm (~INTVAL (operands[1])))"
5774 "@
5775 mov%?\\t%0, %1\\t%@ movhi
5776 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5777 str%(h%)\\t%1, %0\\t%@ movhi
5778 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5779 [(set_attr "type" "*,*,store1,load1")
0d66636f 5780 (set_attr "predicable" "yes")
cffb2a26 5781 (set_attr "pool_range" "*,*,*,256")
5782 (set_attr "neg_pool_range" "*,*,*,244")]
5783)
f7fbdd4a 5784
f7fbdd4a 5785(define_insn "*movhi_bytes"
25f7a26e 5786 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5787 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5788 "TARGET_ARM"
25f7a26e 5789 "@
5790 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5791 mvn%?\\t%0, #%B1\\t%@ movhi"
5792 [(set_attr "predicable" "yes")]
5793)
25f7a26e 5794
f90b51f1 5795(define_expand "thumb_movhi_clobber"
5796 [(set (match_operand:HI 0 "memory_operand" "")
5797 (match_operand:HI 1 "register_operand" ""))
5798 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5799 "TARGET_THUMB1"
f90b51f1 5800 "
5801 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5802 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5803 {
5804 emit_insn (gen_movhi (operands[0], operands[1]));
5805 DONE;
5806 }
5807 /* XXX Fixme, need to handle other cases here as well. */
5808 gcc_unreachable ();
5809 "
cffb2a26 5810)
5811
bc5c7e08 5812;; We use a DImode scratch because we may occasionally need an additional
5813;; temporary if the address isn't offsettable -- push_reload doesn't seem
5814;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5815(define_expand "reload_outhi"
cffb2a26 5816 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5817 (match_operand:HI 1 "s_register_operand" "r")
5818 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5819 "TARGET_EITHER"
5820 "if (TARGET_ARM)
5821 arm_reload_out_hi (operands);
5822 else
5823 thumb_reload_out_hi (operands);
d3373b54 5824 DONE;
cffb2a26 5825 "
5826)
d3373b54 5827
25f7a26e 5828(define_expand "reload_inhi"
5829 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5830 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5831 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5832 "TARGET_EITHER"
25f7a26e 5833 "
cffb2a26 5834 if (TARGET_ARM)
5835 arm_reload_in_hi (operands);
5836 else
5837 thumb_reload_out_hi (operands);
25f7a26e 5838 DONE;
5839")
5840
9c08d1fa 5841(define_expand "movqi"
5842 [(set (match_operand:QI 0 "general_operand" "")
5843 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5844 "TARGET_EITHER"
9c08d1fa 5845 "
6cffc037 5846 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5847
e1ba4a27 5848 if (can_create_pseudo_p ())
cffb2a26 5849 {
6cffc037 5850 if (GET_CODE (operands[1]) == CONST_INT)
5851 {
5852 rtx reg = gen_reg_rtx (SImode);
5853
03770691 5854 /* For thumb we want an unsigned immediate, then we are more likely
5855 to be able to use a movs insn. */
5856 if (TARGET_THUMB)
5857 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5858
6cffc037 5859 emit_insn (gen_movsi (reg, operands[1]));
5860 operands[1] = gen_lowpart (QImode, reg);
5861 }
cffb2a26 5862
6cffc037 5863 if (TARGET_THUMB)
5864 {
cffb2a26 5865 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5866 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5867 virtual register (also rejected as illegitimate for HImode/QImode)
5868 relative address. */
cffb2a26 5869 /* ??? This should perhaps be fixed elsewhere, for instance, in
5870 fixup_stack_1, by checking for other kinds of invalid addresses,
5871 e.g. a bare reference to a virtual register. This may confuse the
5872 alpha though, which must handle this case differently. */
5873 if (GET_CODE (operands[0]) == MEM
215b30b3 5874 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5875 XEXP (operands[0], 0)))
537ffcfc 5876 operands[0]
5877 = replace_equiv_address (operands[0],
5878 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5879 if (GET_CODE (operands[1]) == MEM
5880 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5881 XEXP (operands[1], 0)))
537ffcfc 5882 operands[1]
5883 = replace_equiv_address (operands[1],
5884 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5885 }
5886
5887 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5888 {
5889 rtx reg = gen_reg_rtx (SImode);
5890
5891 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5892 operands[1] = gen_lowpart (QImode, reg);
5893 }
5894
5895 if (GET_CODE (operands[0]) == MEM)
5896 operands[1] = force_reg (QImode, operands[1]);
5897 }
5898 else if (TARGET_THUMB
5899 && GET_CODE (operands[1]) == CONST_INT
234f6557 5900 && !satisfies_constraint_I (operands[1]))
6cffc037 5901 {
674a8f0b 5902 /* Handle loading a large integer during reload. */
cffb2a26 5903
6cffc037 5904 /* Writing a constant to memory needs a scratch, which should
5905 be handled with SECONDARY_RELOADs. */
5906 gcc_assert (GET_CODE (operands[0]) == REG);
5907
5908 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5909 emit_insn (gen_movsi (operands[0], operands[1]));
5910 DONE;
cffb2a26 5911 }
5912 "
5913)
b11cae9e 5914
9c08d1fa 5915
cffb2a26 5916(define_insn "*arm_movqi_insn"
5917 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5918 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5919 "TARGET_32BIT
cffb2a26 5920 && ( register_operand (operands[0], QImode)
5921 || register_operand (operands[1], QImode))"
5565501b 5922 "@
5923 mov%?\\t%0, %1
5924 mvn%?\\t%0, #%B1
25f905c2 5925 ldr%(b%)\\t%0, %1
5926 str%(b%)\\t%1, %0"
a2cd141b 5927 [(set_attr "type" "*,*,load1,store1")
0d66636f 5928 (set_attr "predicable" "yes")]
cffb2a26 5929)
5930
25f905c2 5931(define_insn "*thumb1_movqi_insn"
cffb2a26 5932 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5933 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5934 "TARGET_THUMB1
cffb2a26 5935 && ( register_operand (operands[0], QImode)
5936 || register_operand (operands[1], QImode))"
5937 "@
5938 add\\t%0, %1, #0
5939 ldrb\\t%0, %1
5940 strb\\t%1, %0
5941 mov\\t%0, %1
5942 mov\\t%0, %1
5943 mov\\t%0, %1"
5944 [(set_attr "length" "2")
a2cd141b 5945 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5946 (set_attr "pool_range" "*,32,*,*,*,*")]
5947)
b11cae9e 5948
9b8516be 5949;; HFmode moves
5950(define_expand "movhf"
5951 [(set (match_operand:HF 0 "general_operand" "")
5952 (match_operand:HF 1 "general_operand" ""))]
5953 "TARGET_EITHER"
5954 "
5955 if (TARGET_32BIT)
5956 {
5957 if (GET_CODE (operands[0]) == MEM)
5958 operands[1] = force_reg (HFmode, operands[1]);
5959 }
5960 else /* TARGET_THUMB1 */
5961 {
5962 if (can_create_pseudo_p ())
5963 {
5964 if (GET_CODE (operands[0]) != REG)
5965 operands[1] = force_reg (HFmode, operands[1]);
5966 }
5967 }
5968 "
5969)
5970
5971(define_insn "*arm32_movhf"
5972 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5973 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 5974 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 5975 && ( s_register_operand (operands[0], HFmode)
5976 || s_register_operand (operands[1], HFmode))"
5977 "*
5978 switch (which_alternative)
5979 {
5980 case 0: /* ARM register from memory */
5981 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5982 case 1: /* memory from ARM register */
5983 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5984 case 2: /* ARM register from ARM register */
5985 return \"mov%?\\t%0, %1\\t%@ __fp16\";
5986 case 3: /* ARM register from constant */
5987 {
5988 REAL_VALUE_TYPE r;
5989 long bits;
5990 rtx ops[4];
5991
5992 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
5993 bits = real_to_target (NULL, &r, HFmode);
5994 ops[0] = operands[0];
5995 ops[1] = GEN_INT (bits);
5996 ops[2] = GEN_INT (bits & 0xff00);
5997 ops[3] = GEN_INT (bits & 0x00ff);
5998
5999 if (arm_arch_thumb2)
6000 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6001 else
6002 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6003 return \"\";
6004 }
6005 default:
6006 gcc_unreachable ();
6007 }
6008 "
6009 [(set_attr "conds" "unconditional")
6010 (set_attr "type" "load1,store1,*,*")
6011 (set_attr "length" "4,4,4,8")
6012 (set_attr "predicable" "yes")
6013 ]
6014)
6015
6016(define_insn "*thumb1_movhf"
6017 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6018 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6019 "TARGET_THUMB1
6020 && ( s_register_operand (operands[0], HFmode)
6021 || s_register_operand (operands[1], HFmode))"
6022 "*
6023 switch (which_alternative)
6024 {
6025 case 1:
6026 {
6027 rtx addr;
6028 gcc_assert (GET_CODE(operands[1]) == MEM);
6029 addr = XEXP (operands[1], 0);
6030 if (GET_CODE (addr) == LABEL_REF
6031 || (GET_CODE (addr) == CONST
6032 && GET_CODE (XEXP (addr, 0)) == PLUS
6033 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6034 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6035 {
6036 /* Constant pool entry. */
6037 return \"ldr\\t%0, %1\";
6038 }
6039 return \"ldrh\\t%0, %1\";
6040 }
6041 case 2: return \"strh\\t%1, %0\";
6042 default: return \"mov\\t%0, %1\";
6043 }
6044 "
6045 [(set_attr "length" "2")
6046 (set_attr "type" "*,load1,store1,*,*")
6047 (set_attr "pool_range" "*,1020,*,*,*")]
6048)
6049
87b22bf7 6050(define_expand "movsf"
6051 [(set (match_operand:SF 0 "general_operand" "")
6052 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6053 "TARGET_EITHER"
87b22bf7 6054 "
25f905c2 6055 if (TARGET_32BIT)
cffb2a26 6056 {
6057 if (GET_CODE (operands[0]) == MEM)
6058 operands[1] = force_reg (SFmode, operands[1]);
6059 }
25f905c2 6060 else /* TARGET_THUMB1 */
cffb2a26 6061 {
e1ba4a27 6062 if (can_create_pseudo_p ())
cffb2a26 6063 {
6064 if (GET_CODE (operands[0]) != REG)
6065 operands[1] = force_reg (SFmode, operands[1]);
6066 }
6067 }
6068 "
6069)
6070
03d440a6 6071;; Transform a floating-point move of a constant into a core register into
6072;; an SImode operation.
cffb2a26 6073(define_split
03d440a6 6074 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6075 (match_operand:SF 1 "immediate_operand" ""))]
25f905c2 6076 "TARGET_32BIT
cffb2a26 6077 && reload_completed
6078 && GET_CODE (operands[1]) == CONST_DOUBLE"
6079 [(set (match_dup 2) (match_dup 3))]
6080 "
6081 operands[2] = gen_lowpart (SImode, operands[0]);
6082 operands[3] = gen_lowpart (SImode, operands[1]);
6083 if (operands[2] == 0 || operands[3] == 0)
6084 FAIL;
215b30b3 6085 "
6086)
87b22bf7 6087
cffb2a26 6088(define_insn "*arm_movsf_soft_insn"
6089 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6090 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6091 "TARGET_ARM
6092 && TARGET_SOFT_FLOAT
215b30b3 6093 && (GET_CODE (operands[0]) != MEM
6094 || register_operand (operands[1], SFmode))"
9a1112d7 6095 "@
6096 mov%?\\t%0, %1
6097 ldr%?\\t%0, %1\\t%@ float
6098 str%?\\t%1, %0\\t%@ float"
cffb2a26 6099 [(set_attr "length" "4,4,4")
0d66636f 6100 (set_attr "predicable" "yes")
a2cd141b 6101 (set_attr "type" "*,load1,store1")
cffb2a26 6102 (set_attr "pool_range" "*,4096,*")
6103 (set_attr "neg_pool_range" "*,4084,*")]
6104)
6105
6106;;; ??? This should have alternatives for constants.
25f905c2 6107(define_insn "*thumb1_movsf_insn"
215b30b3 6108 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6109 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6110 "TARGET_THUMB1
cffb2a26 6111 && ( register_operand (operands[0], SFmode)
6112 || register_operand (operands[1], SFmode))"
6113 "@
6114 add\\t%0, %1, #0
6115 ldmia\\t%1, {%0}
6116 stmia\\t%0, {%1}
6117 ldr\\t%0, %1
6118 str\\t%1, %0
6119 mov\\t%0, %1
6120 mov\\t%0, %1"
6121 [(set_attr "length" "2")
a2cd141b 6122 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 6123 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
6124)
9a1112d7 6125
9c08d1fa 6126(define_expand "movdf"
87b22bf7 6127 [(set (match_operand:DF 0 "general_operand" "")
6128 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6129 "TARGET_EITHER"
9c08d1fa 6130 "
25f905c2 6131 if (TARGET_32BIT)
cffb2a26 6132 {
6133 if (GET_CODE (operands[0]) == MEM)
6134 operands[1] = force_reg (DFmode, operands[1]);
6135 }
6136 else /* TARGET_THUMB */
6137 {
e1ba4a27 6138 if (can_create_pseudo_p ())
cffb2a26 6139 {
6140 if (GET_CODE (operands[0]) != REG)
6141 operands[1] = force_reg (DFmode, operands[1]);
6142 }
6143 }
6144 "
6145)
b11cae9e 6146
9c08d1fa 6147;; Reloading a df mode value stored in integer regs to memory can require a
6148;; scratch reg.
6149(define_expand "reload_outdf"
cffb2a26 6150 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6151 (match_operand:DF 1 "s_register_operand" "r")
6152 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 6153 "TARGET_32BIT"
87b22bf7 6154 "
215b30b3 6155 {
6156 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6157
215b30b3 6158 if (code == REG)
6159 operands[2] = XEXP (operands[0], 0);
6160 else if (code == POST_INC || code == PRE_DEC)
6161 {
6162 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6163 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6164 emit_insn (gen_movdi (operands[0], operands[1]));
6165 DONE;
6166 }
6167 else if (code == PRE_INC)
6168 {
6169 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6170
215b30b3 6171 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6172 operands[2] = reg;
6173 }
6174 else if (code == POST_DEC)
6175 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6176 else
6177 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6178 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6179
788fcce0 6180 emit_insn (gen_rtx_SET (VOIDmode,
6181 replace_equiv_address (operands[0], operands[2]),
215b30b3 6182 operands[1]));
f7fbdd4a 6183
215b30b3 6184 if (code == POST_DEC)
6185 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6186
6187 DONE;
6188 }"
6189)
9c08d1fa 6190
9a1112d7 6191(define_insn "*movdf_soft_insn"
359a6e9f 6192 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6193 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 6194 "TARGET_ARM && TARGET_SOFT_FLOAT
b2778788 6195 && ( register_operand (operands[0], DFmode)
6196 || register_operand (operands[1], DFmode))"
d51f92df 6197 "*
6198 switch (which_alternative)
6199 {
6200 case 0:
6201 case 1:
6202 case 2:
6203 return \"#\";
6204 default:
6205 return output_move_double (operands);
6206 }
6207 "
359a6e9f 6208 [(set_attr "length" "8,12,16,8,8")
6209 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 6210 (set_attr "pool_range" "1020")
6211 (set_attr "neg_pool_range" "1008")]
cffb2a26 6212)
6213
6214;;; ??? This should have alternatives for constants.
6215;;; ??? This was originally identical to the movdi_insn pattern.
6216;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6217;;; thumb_reorg with a memory reference.
6218(define_insn "*thumb_movdf_insn"
215b30b3 6219 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6220 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6221 "TARGET_THUMB1
cffb2a26 6222 && ( register_operand (operands[0], DFmode)
6223 || register_operand (operands[1], DFmode))"
6224 "*
6225 switch (which_alternative)
6226 {
6227 default:
6228 case 0:
6229 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6230 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6231 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6232 case 1:
6233 return \"ldmia\\t%1, {%0, %H0}\";
6234 case 2:
6235 return \"stmia\\t%0, {%1, %H1}\";
6236 case 3:
6237 return thumb_load_double_from_address (operands);
6238 case 4:
1a83b3ff 6239 operands[2] = gen_rtx_MEM (SImode,
6240 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6241 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6242 return \"\";
6243 case 5:
6244 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6245 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6246 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6247 }
6248 "
6249 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6250 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 6251 (set_attr "pool_range" "*,*,*,1020,*,*")]
6252)
755eb2b4 6253
ccd90aaa 6254(define_expand "movxf"
6255 [(set (match_operand:XF 0 "general_operand" "")
6256 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6257 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6258 "
6259 if (GET_CODE (operands[0]) == MEM)
6260 operands[1] = force_reg (XFmode, operands[1]);
6261 "
6262)
6263
b11cae9e 6264\f
b11cae9e 6265
9c08d1fa 6266;; load- and store-multiple insns
6267;; The arm can load/store any set of registers, provided that they are in
6268;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 6269
9c08d1fa 6270(define_expand "load_multiple"
6271 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6272 (match_operand:SI 1 "" ""))
6273 (use (match_operand:SI 2 "" ""))])]
25f905c2 6274 "TARGET_32BIT"
9580c25f 6275{
6276 HOST_WIDE_INT offset = 0;
6277
bd5b4116 6278 /* Support only fixed point registers. */
9c08d1fa 6279 if (GET_CODE (operands[2]) != CONST_INT
6280 || INTVAL (operands[2]) > 14
6281 || INTVAL (operands[2]) < 2
6282 || GET_CODE (operands[1]) != MEM
6283 || GET_CODE (operands[0]) != REG
bd5b4116 6284 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6285 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6286 FAIL;
6287
6288 operands[3]
f082f1c4 6289 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6290 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 6291 TRUE, FALSE, operands[1], &offset);
6292})
b11cae9e 6293
9c08d1fa 6294;; Load multiple with write-back
6295
2162064c 6296(define_insn "*ldmsi_postinc4"
9c08d1fa 6297 [(match_parallel 0 "load_multiple_operation"
13e9316a 6298 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6299 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6300 (const_int 16)))
6301 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6302 (mem:SI (match_dup 2)))
a0a72ac3 6303 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 6304 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6305 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6306 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6307 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6308 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6309 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6310 "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
a2cd141b 6311 [(set_attr "type" "load4")
2162064c 6312 (set_attr "predicable" "yes")]
6313)
b11cae9e 6314
25f905c2 6315(define_insn "*ldmsi_postinc4_thumb1"
ccd90aaa 6316 [(match_parallel 0 "load_multiple_operation"
6317 [(set (match_operand:SI 1 "s_register_operand" "=l")
6318 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6319 (const_int 16)))
6320 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6321 (mem:SI (match_dup 2)))
6322 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6323 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6324 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6325 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6326 (set (match_operand:SI 6 "arm_hard_register_operand" "")
6327 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 6328 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6329 "ldmia\\t%1!, {%3, %4, %5, %6}"
6330 [(set_attr "type" "load4")]
6331)
6332
2162064c 6333(define_insn "*ldmsi_postinc3"
6334 [(match_parallel 0 "load_multiple_operation"
13e9316a 6335 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6336 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6337 (const_int 12)))
6338 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6339 (mem:SI (match_dup 2)))
6340 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6341 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6342 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6343 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
25f905c2 6344 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6345 "ldm%(ia%)\\t%1!, {%3, %4, %5}"
a2cd141b 6346 [(set_attr "type" "load3")
2162064c 6347 (set_attr "predicable" "yes")]
6348)
b11cae9e 6349
2162064c 6350(define_insn "*ldmsi_postinc2"
6351 [(match_parallel 0 "load_multiple_operation"
13e9316a 6352 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6353 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6354 (const_int 8)))
6355 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6356 (mem:SI (match_dup 2)))
6357 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6358 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
25f905c2 6359 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6360 "ldm%(ia%)\\t%1!, {%3, %4}"
a2cd141b 6361 [(set_attr "type" "load2")
0d66636f 6362 (set_attr "predicable" "yes")]
6363)
b11cae9e 6364
9c08d1fa 6365;; Ordinary load multiple
b11cae9e 6366
2162064c 6367(define_insn "*ldmsi4"
9c08d1fa 6368 [(match_parallel 0 "load_multiple_operation"
2162064c 6369 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6370 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6371 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6372 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6373 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6374 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6375 (set (match_operand:SI 5 "arm_hard_register_operand" "")
6376 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
25f905c2 6377 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6378 "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
a2cd141b 6379 [(set_attr "type" "load4")
2162064c 6380 (set_attr "predicable" "yes")]
6381)
9c08d1fa 6382
2162064c 6383(define_insn "*ldmsi3"
6384 [(match_parallel 0 "load_multiple_operation"
6385 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6386 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6387 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6388 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6389 (set (match_operand:SI 4 "arm_hard_register_operand" "")
6390 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
25f905c2 6391 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6392 "ldm%(ia%)\\t%1, {%2, %3, %4}"
a2cd141b 6393 [(set_attr "type" "load3")
2162064c 6394 (set_attr "predicable" "yes")]
6395)
9c08d1fa 6396
2162064c 6397(define_insn "*ldmsi2"
6398 [(match_parallel 0 "load_multiple_operation"
6399 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6400 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6401 (set (match_operand:SI 3 "arm_hard_register_operand" "")
6402 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
25f905c2 6403 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6404 "ldm%(ia%)\\t%1, {%2, %3}"
a2cd141b 6405 [(set_attr "type" "load2")
0d66636f 6406 (set_attr "predicable" "yes")]
6407)
9c08d1fa 6408
6409(define_expand "store_multiple"
6410 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6411 (match_operand:SI 1 "" ""))
6412 (use (match_operand:SI 2 "" ""))])]
25f905c2 6413 "TARGET_32BIT"
9580c25f 6414{
6415 HOST_WIDE_INT offset = 0;
6416
674a8f0b 6417 /* Support only fixed point registers. */
9c08d1fa 6418 if (GET_CODE (operands[2]) != CONST_INT
6419 || INTVAL (operands[2]) > 14
6420 || INTVAL (operands[2]) < 2
6421 || GET_CODE (operands[1]) != REG
6422 || GET_CODE (operands[0]) != MEM
bd5b4116 6423 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6424 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6425 FAIL;
6426
6427 operands[3]
f082f1c4 6428 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6429 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 6430 TRUE, FALSE, operands[0], &offset);
6431})
b11cae9e 6432
9c08d1fa 6433;; Store multiple with write-back
6434
2162064c 6435(define_insn "*stmsi_postinc4"
9c08d1fa 6436 [(match_parallel 0 "store_multiple_operation"
13e9316a 6437 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 6438 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 6439 (const_int 16)))
a0a72ac3 6440 (set (mem:SI (match_dup 2))
2162064c 6441 (match_operand:SI 3 "arm_hard_register_operand" ""))
6442 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6443 (match_operand:SI 4 "arm_hard_register_operand" ""))
6444 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6445 (match_operand:SI 5 "arm_hard_register_operand" ""))
6446 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6447 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6448 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6449 "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
2162064c 6450 [(set_attr "predicable" "yes")
6451 (set_attr "type" "store4")]
6452)
b11cae9e 6453
25f905c2 6454(define_insn "*stmsi_postinc4_thumb1"
ccd90aaa 6455 [(match_parallel 0 "store_multiple_operation"
6456 [(set (match_operand:SI 1 "s_register_operand" "=l")
6457 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6458 (const_int 16)))
6459 (set (mem:SI (match_dup 2))
6460 (match_operand:SI 3 "arm_hard_register_operand" ""))
6461 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6462 (match_operand:SI 4 "arm_hard_register_operand" ""))
6463 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6464 (match_operand:SI 5 "arm_hard_register_operand" ""))
6465 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6466 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6467 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6468 "stmia\\t%1!, {%3, %4, %5, %6}"
6469 [(set_attr "type" "store4")]
6470)
6471
2162064c 6472(define_insn "*stmsi_postinc3"
6473 [(match_parallel 0 "store_multiple_operation"
13e9316a 6474 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6475 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6476 (const_int 12)))
6477 (set (mem:SI (match_dup 2))
6478 (match_operand:SI 3 "arm_hard_register_operand" ""))
6479 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6480 (match_operand:SI 4 "arm_hard_register_operand" ""))
6481 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6482 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6483 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6484 "stm%(ia%)\\t%1!, {%3, %4, %5}"
2162064c 6485 [(set_attr "predicable" "yes")
6486 (set_attr "type" "store3")]
6487)
9c08d1fa 6488
2162064c 6489(define_insn "*stmsi_postinc2"
6490 [(match_parallel 0 "store_multiple_operation"
13e9316a 6491 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6492 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6493 (const_int 8)))
6494 (set (mem:SI (match_dup 2))
6495 (match_operand:SI 3 "arm_hard_register_operand" ""))
6496 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6497 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6498 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6499 "stm%(ia%)\\t%1!, {%3, %4}"
0d66636f 6500 [(set_attr "predicable" "yes")
2162064c 6501 (set_attr "type" "store2")]
cffb2a26 6502)
9c08d1fa 6503
6504;; Ordinary store multiple
6505
2162064c 6506(define_insn "*stmsi4"
9c08d1fa 6507 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 6508 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 6509 (match_operand:SI 2 "arm_hard_register_operand" ""))
6510 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6511 (match_operand:SI 3 "arm_hard_register_operand" ""))
6512 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6513 (match_operand:SI 4 "arm_hard_register_operand" ""))
6514 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6515 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6516 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6517 "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
2162064c 6518 [(set_attr "predicable" "yes")
6519 (set_attr "type" "store4")]
6520)
9c08d1fa 6521
2162064c 6522(define_insn "*stmsi3"
6523 [(match_parallel 0 "store_multiple_operation"
6524 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6525 (match_operand:SI 2 "arm_hard_register_operand" ""))
6526 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6527 (match_operand:SI 3 "arm_hard_register_operand" ""))
6528 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6529 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6530 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6531 "stm%(ia%)\\t%1, {%2, %3, %4}"
2162064c 6532 [(set_attr "predicable" "yes")
6533 (set_attr "type" "store3")]
6534)
9c08d1fa 6535
2162064c 6536(define_insn "*stmsi2"
6537 [(match_parallel 0 "store_multiple_operation"
6538 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6539 (match_operand:SI 2 "arm_hard_register_operand" ""))
6540 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6541 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
25f905c2 6542 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6543 "stm%(ia%)\\t%1, {%2, %3}"
0d66636f 6544 [(set_attr "predicable" "yes")
2162064c 6545 (set_attr "type" "store2")]
cffb2a26 6546)
9c08d1fa 6547
6548;; Move a block of memory if it is word aligned and MORE than 2 words long.
6549;; We could let this apply for blocks of less than this, but it clobbers so
6550;; many registers that there is then probably a better way.
6551
008c057d 6552(define_expand "movmemqi"
34191dd1 6553 [(match_operand:BLK 0 "general_operand" "")
6554 (match_operand:BLK 1 "general_operand" "")
6555 (match_operand:SI 2 "const_int_operand" "")
6556 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6557 "TARGET_EITHER"
9c08d1fa 6558 "
25f905c2 6559 if (TARGET_32BIT)
cffb2a26 6560 {
008c057d 6561 if (arm_gen_movmemqi (operands))
cffb2a26 6562 DONE;
6563 FAIL;
6564 }
25f905c2 6565 else /* TARGET_THUMB1 */
cffb2a26 6566 {
6567 if ( INTVAL (operands[3]) != 4
6568 || INTVAL (operands[2]) > 48)
6569 FAIL;
6570
008c057d 6571 thumb_expand_movmemqi (operands);
cffb2a26 6572 DONE;
6573 }
6574 "
6575)
6576
2162064c 6577;; Thumb block-move insns
cffb2a26 6578
6579(define_insn "movmem12b"
960f3acf 6580 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6581 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6582 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6583 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6584 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6585 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6586 (set (match_operand:SI 0 "register_operand" "=l")
6587 (plus:SI (match_dup 2) (const_int 12)))
6588 (set (match_operand:SI 1 "register_operand" "=l")
6589 (plus:SI (match_dup 3) (const_int 12)))
6590 (clobber (match_scratch:SI 4 "=&l"))
6591 (clobber (match_scratch:SI 5 "=&l"))
6592 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6593 "TARGET_THUMB1"
cffb2a26 6594 "* return thumb_output_move_mem_multiple (3, operands);"
6595 [(set_attr "length" "4")
215b30b3 6596 ; This isn't entirely accurate... It loads as well, but in terms of
6597 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6598 (set_attr "type" "store3")]
6599)
6600
6601(define_insn "movmem8b"
960f3acf 6602 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6603 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6604 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6605 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6606 (set (match_operand:SI 0 "register_operand" "=l")
6607 (plus:SI (match_dup 2) (const_int 8)))
6608 (set (match_operand:SI 1 "register_operand" "=l")
6609 (plus:SI (match_dup 3) (const_int 8)))
6610 (clobber (match_scratch:SI 4 "=&l"))
6611 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6612 "TARGET_THUMB1"
cffb2a26 6613 "* return thumb_output_move_mem_multiple (2, operands);"
6614 [(set_attr "length" "4")
215b30b3 6615 ; This isn't entirely accurate... It loads as well, but in terms of
6616 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6617 (set_attr "type" "store2")]
6618)
6619
9c08d1fa 6620\f
b11cae9e 6621
341940e8 6622;; Compare & branch insns
8d232dc7 6623;; The range calculations are based as follows:
341940e8 6624;; For forward branches, the address calculation returns the address of
6625;; the next instruction. This is 2 beyond the branch instruction.
6626;; For backward branches, the address calculation returns the address of
6627;; the first instruction in this pattern (cmp). This is 2 before the branch
6628;; instruction for the shortest sequence, and 4 before the branch instruction
6629;; if we have to jump around an unconditional branch.
6630;; To the basic branch range the PC offset must be added (this is +4).
6631;; So for forward branches we have
6632;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6633;; And for backward branches we have
6634;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6635;;
6636;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6637;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6638
aeac46d4 6639(define_expand "cbranchsi4"
6640 [(set (pc) (if_then_else
6641 (match_operator 0 "arm_comparison_operator"
6642 [(match_operand:SI 1 "s_register_operand" "")
6643 (match_operand:SI 2 "nonmemory_operand" "")])
6644 (label_ref (match_operand 3 "" ""))
6645 (pc)))]
74f4459c 6646 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6647 "
74f4459c 6648 if (!TARGET_THUMB1)
6649 {
6650 if (!arm_add_operand (operands[2], SImode))
6651 operands[2] = force_reg (SImode, operands[2]);
6652 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6653 operands[3]));
6654 DONE;
6655 }
25f905c2 6656 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6657 {
6658 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6659 operands[3], operands[0]));
6660 DONE;
6661 }
25f905c2 6662 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6663 operands[2] = force_reg (SImode, operands[2]);
6664 ")
6665
74f4459c 6666(define_expand "cbranchsf4"
6667 [(set (pc) (if_then_else
6668 (match_operator 0 "arm_comparison_operator"
6669 [(match_operand:SF 1 "s_register_operand" "")
6670 (match_operand:SF 2 "arm_float_compare_operand" "")])
6671 (label_ref (match_operand 3 "" ""))
6672 (pc)))]
6673 "TARGET_32BIT && TARGET_HARD_FLOAT"
6674 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6675 operands[3])); DONE;"
6676)
6677
6678(define_expand "cbranchdf4"
6679 [(set (pc) (if_then_else
6680 (match_operator 0 "arm_comparison_operator"
6681 [(match_operand:DF 1 "s_register_operand" "")
6682 (match_operand:DF 2 "arm_float_compare_operand" "")])
6683 (label_ref (match_operand 3 "" ""))
6684 (pc)))]
a50d7267 6685 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6686 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6687 operands[3])); DONE;"
6688)
6689
6690;; this uses the Cirrus DI compare instruction
6691(define_expand "cbranchdi4"
6692 [(set (pc) (if_then_else
6693 (match_operator 0 "arm_comparison_operator"
6694 [(match_operand:DI 1 "cirrus_fp_register" "")
6695 (match_operand:DI 2 "cirrus_fp_register" "")])
6696 (label_ref (match_operand 3 "" ""))
6697 (pc)))]
6698 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6699 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6700 operands[3])); DONE;"
6701)
6702
aeac46d4 6703(define_insn "*cbranchsi4_insn"
6704 [(set (pc) (if_then_else
6705 (match_operator 0 "arm_comparison_operator"
6706 [(match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 6707 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6708 (label_ref (match_operand 3 "" ""))
6709 (pc)))]
25f905c2 6710 "TARGET_THUMB1"
cffb2a26 6711 "*
6712 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 6713
cffb2a26 6714 switch (get_attr_length (insn))
6715 {
6716 case 4: return \"b%d0\\t%l3\";
6717 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6718 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6719 }
6720 "
6721 [(set (attr "far_jump")
6722 (if_then_else
6723 (eq_attr "length" "8")
6724 (const_string "yes")
6725 (const_string "no")))
6726 (set (attr "length")
6727 (if_then_else
6728 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6729 (le (minus (match_dup 3) (pc)) (const_int 256)))
6730 (const_int 4)
6731 (if_then_else
6732 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6733 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6734 (const_int 6)
6735 (const_int 8))))]
6736)
6737
aeac46d4 6738(define_insn "cbranchsi4_scratch"
6739 [(set (pc) (if_then_else
6740 (match_operator 4 "arm_comparison_operator"
6741 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6742 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6743 (label_ref (match_operand 3 "" ""))
6744 (pc)))
6745 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6746 "TARGET_THUMB1"
aeac46d4 6747 "*
6748 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6749
6750 switch (get_attr_length (insn))
6751 {
6752 case 4: return \"b%d4\\t%l3\";
6753 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6754 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6755 }
6756 "
6757 [(set (attr "far_jump")
6758 (if_then_else
6759 (eq_attr "length" "8")
6760 (const_string "yes")
6761 (const_string "no")))
6762 (set (attr "length")
6763 (if_then_else
6764 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6765 (le (minus (match_dup 3) (pc)) (const_int 256)))
6766 (const_int 4)
6767 (if_then_else
6768 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6769 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6770 (const_int 6)
6771 (const_int 8))))]
6772)
446a1e96 6773
aeac46d4 6774(define_insn "*movsi_cbranchsi4"
6775 [(set (pc)
6776 (if_then_else
6777 (match_operator 3 "arm_comparison_operator"
6778 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6779 (const_int 0)])
6780 (label_ref (match_operand 2 "" ""))
6781 (pc)))
6782 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6783 (match_dup 1))]
25f905c2 6784 "TARGET_THUMB1"
aeac46d4 6785 "*{
6786 if (which_alternative == 0)
6787 output_asm_insn (\"cmp\t%0, #0\", operands);
6788 else if (which_alternative == 1)
6789 output_asm_insn (\"sub\t%0, %1, #0\", operands);
6790 else
6791 {
6792 output_asm_insn (\"cmp\t%1, #0\", operands);
6793 if (which_alternative == 2)
6794 output_asm_insn (\"mov\t%0, %1\", operands);
6795 else
6796 output_asm_insn (\"str\t%1, %0\", operands);
6797 }
6798 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6799 {
6800 case 4: return \"b%d3\\t%l2\";
6801 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6802 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6803 }
6804 }"
6805 [(set (attr "far_jump")
6806 (if_then_else
6807 (ior (and (gt (symbol_ref ("which_alternative"))
6808 (const_int 1))
6809 (eq_attr "length" "8"))
6810 (eq_attr "length" "10"))
6811 (const_string "yes")
6812 (const_string "no")))
6813 (set (attr "length")
6814 (if_then_else
6815 (le (symbol_ref ("which_alternative"))
6816 (const_int 1))
6817 (if_then_else
6818 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6819 (le (minus (match_dup 2) (pc)) (const_int 256)))
6820 (const_int 4)
6821 (if_then_else
6822 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6823 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6824 (const_int 6)
6825 (const_int 8)))
6826 (if_then_else
6827 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6828 (le (minus (match_dup 2) (pc)) (const_int 256)))
6829 (const_int 6)
6830 (if_then_else
6831 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6832 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6833 (const_int 8)
6834 (const_int 10)))))]
6835)
6836
446a1e96 6837(define_peephole2
6838 [(set (match_operand:SI 0 "low_register_operand" "")
6839 (match_operand:SI 1 "low_register_operand" ""))
6840 (set (pc)
6841 (if_then_else (match_operator 2 "arm_comparison_operator"
6842 [(match_dup 1) (const_int 0)])
6843 (label_ref (match_operand 3 "" ""))
6844 (pc)))]
6845 "TARGET_THUMB1"
6846 [(parallel
6847 [(set (pc)
6848 (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6849 (label_ref (match_dup 3))
6850 (pc)))
6851 (set (match_dup 0) (match_dup 1))])]
6852 ""
6853)
6854
6855;; Sigh! This variant shouldn't be needed, but combine often fails to
6856;; merge cases like this because the op1 is a hard register in
6857;; CLASS_LIKELY_SPILLED_P.
6858(define_peephole2
6859 [(set (match_operand:SI 0 "low_register_operand" "")
6860 (match_operand:SI 1 "low_register_operand" ""))
6861 (set (pc)
6862 (if_then_else (match_operator 2 "arm_comparison_operator"
6863 [(match_dup 0) (const_int 0)])
6864 (label_ref (match_operand 3 "" ""))
6865 (pc)))]
6866 "TARGET_THUMB1"
6867 [(parallel
6868 [(set (pc)
6869 (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6870 (label_ref (match_dup 3))
6871 (pc)))
6872 (set (match_dup 0) (match_dup 1))])]
6873 ""
6874)
6875
cffb2a26 6876(define_insn "*negated_cbranchsi4"
6877 [(set (pc)
6878 (if_then_else
aed179ae 6879 (match_operator 0 "equality_operator"
aeac46d4 6880 [(match_operand:SI 1 "s_register_operand" "l")
6881 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6882 (label_ref (match_operand 3 "" ""))
215b30b3 6883 (pc)))]
25f905c2 6884 "TARGET_THUMB1"
cffb2a26 6885 "*
6886 output_asm_insn (\"cmn\\t%1, %2\", operands);
6887 switch (get_attr_length (insn))
6888 {
6889 case 4: return \"b%d0\\t%l3\";
6890 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6891 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6892 }
6893 "
6894 [(set (attr "far_jump")
6895 (if_then_else
6896 (eq_attr "length" "8")
6897 (const_string "yes")
6898 (const_string "no")))
6899 (set (attr "length")
6900 (if_then_else
6901 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6902 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6903 (const_int 4)
6904 (if_then_else
341940e8 6905 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6906 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6907 (const_int 6)
6908 (const_int 8))))]
6909)
6910
58d6528b 6911(define_insn "*tbit_cbranch"
6912 [(set (pc)
6913 (if_then_else
6914 (match_operator 0 "equality_operator"
6915 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6916 (const_int 1)
6917 (match_operand:SI 2 "const_int_operand" "i"))
6918 (const_int 0)])
6919 (label_ref (match_operand 3 "" ""))
6920 (pc)))
6921 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6922 "TARGET_THUMB1"
58d6528b 6923 "*
6924 {
6925 rtx op[3];
6926 op[0] = operands[4];
6927 op[1] = operands[1];
6928 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6929
86efa74d 6930 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6931 switch (get_attr_length (insn))
6932 {
6933 case 4: return \"b%d0\\t%l3\";
6934 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6935 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6936 }
6937 }"
6938 [(set (attr "far_jump")
6939 (if_then_else
6940 (eq_attr "length" "8")
6941 (const_string "yes")
6942 (const_string "no")))
6943 (set (attr "length")
6944 (if_then_else
6945 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6946 (le (minus (match_dup 3) (pc)) (const_int 256)))
6947 (const_int 4)
6948 (if_then_else
6949 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6950 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6951 (const_int 6)
6952 (const_int 8))))]
6953)
6954
6955(define_insn "*tlobits_cbranch"
6956 [(set (pc)
6957 (if_then_else
6958 (match_operator 0 "equality_operator"
6959 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6960 (match_operand:SI 2 "const_int_operand" "i")
6961 (const_int 0))
6962 (const_int 0)])
6963 (label_ref (match_operand 3 "" ""))
6964 (pc)))
6965 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6966 "TARGET_THUMB1"
86efa74d 6967 "*
6968 {
6969 rtx op[3];
6970 op[0] = operands[4];
6971 op[1] = operands[1];
6972 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6973
58d6528b 6974 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6975 switch (get_attr_length (insn))
6976 {
6977 case 4: return \"b%d0\\t%l3\";
6978 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6979 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6980 }
6981 }"
6982 [(set (attr "far_jump")
6983 (if_then_else
6984 (eq_attr "length" "8")
6985 (const_string "yes")
6986 (const_string "no")))
6987 (set (attr "length")
6988 (if_then_else
6989 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6990 (le (minus (match_dup 3) (pc)) (const_int 256)))
6991 (const_int 4)
6992 (if_then_else
6993 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6994 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6995 (const_int 6)
6996 (const_int 8))))]
6997)
6998
aeac46d4 6999(define_insn "*tstsi3_cbranch"
58d6528b 7000 [(set (pc)
7001 (if_then_else
aeac46d4 7002 (match_operator 3 "equality_operator"
7003 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7004 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 7005 (const_int 0)])
aeac46d4 7006 (label_ref (match_operand 2 "" ""))
7007 (pc)))]
25f905c2 7008 "TARGET_THUMB1"
58d6528b 7009 "*
7010 {
aeac46d4 7011 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 7012 switch (get_attr_length (insn))
7013 {
aeac46d4 7014 case 4: return \"b%d3\\t%l2\";
7015 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7016 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 7017 }
7018 }"
7019 [(set (attr "far_jump")
7020 (if_then_else
7021 (eq_attr "length" "8")
7022 (const_string "yes")
7023 (const_string "no")))
7024 (set (attr "length")
7025 (if_then_else
aeac46d4 7026 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7027 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 7028 (const_int 4)
7029 (if_then_else
aeac46d4 7030 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7031 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 7032 (const_int 6)
7033 (const_int 8))))]
7034)
7035
7036(define_insn "*andsi3_cbranch"
7037 [(set (pc)
7038 (if_then_else
7039 (match_operator 5 "equality_operator"
7040 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7041 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7042 (const_int 0)])
7043 (label_ref (match_operand 4 "" ""))
7044 (pc)))
aeac46d4 7045 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7046 (and:SI (match_dup 2) (match_dup 3)))
7047 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7048 "TARGET_THUMB1"
58d6528b 7049 "*
7050 {
7051 if (which_alternative == 0)
7052 output_asm_insn (\"and\\t%0, %3\", operands);
7053 else if (which_alternative == 1)
7054 {
7055 output_asm_insn (\"and\\t%1, %3\", operands);
7056 output_asm_insn (\"mov\\t%0, %1\", operands);
7057 }
7058 else
7059 {
7060 output_asm_insn (\"and\\t%1, %3\", operands);
7061 output_asm_insn (\"str\\t%1, %0\", operands);
7062 }
7063
7064 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7065 {
7066 case 4: return \"b%d5\\t%l4\";
7067 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7068 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7069 }
7070 }"
7071 [(set (attr "far_jump")
7072 (if_then_else
7073 (ior (and (eq (symbol_ref ("which_alternative"))
7074 (const_int 0))
7075 (eq_attr "length" "8"))
7076 (eq_attr "length" "10"))
7077 (const_string "yes")
7078 (const_string "no")))
7079 (set (attr "length")
7080 (if_then_else
7081 (eq (symbol_ref ("which_alternative"))
7082 (const_int 0))
7083 (if_then_else
7084 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7085 (le (minus (match_dup 4) (pc)) (const_int 256)))
7086 (const_int 4)
7087 (if_then_else
7088 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7089 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7090 (const_int 6)
7091 (const_int 8)))
7092 (if_then_else
7093 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7094 (le (minus (match_dup 4) (pc)) (const_int 256)))
7095 (const_int 6)
7096 (if_then_else
7097 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7098 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7099 (const_int 8)
7100 (const_int 10)))))]
7101)
7102
7103(define_insn "*orrsi3_cbranch_scratch"
7104 [(set (pc)
7105 (if_then_else
7106 (match_operator 4 "equality_operator"
7107 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
7108 (match_operand:SI 2 "s_register_operand" "l"))
7109 (const_int 0)])
7110 (label_ref (match_operand 3 "" ""))
7111 (pc)))
7112 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7113 "TARGET_THUMB1"
58d6528b 7114 "*
7115 {
7116 output_asm_insn (\"orr\\t%0, %2\", operands);
7117 switch (get_attr_length (insn))
7118 {
7119 case 4: return \"b%d4\\t%l3\";
7120 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7121 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7122 }
7123 }"
7124 [(set (attr "far_jump")
7125 (if_then_else
7126 (eq_attr "length" "8")
7127 (const_string "yes")
7128 (const_string "no")))
7129 (set (attr "length")
7130 (if_then_else
7131 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7132 (le (minus (match_dup 3) (pc)) (const_int 256)))
7133 (const_int 4)
7134 (if_then_else
7135 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7136 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7137 (const_int 6)
7138 (const_int 8))))]
7139)
7140
7141(define_insn "*orrsi3_cbranch"
7142 [(set (pc)
7143 (if_then_else
7144 (match_operator 5 "equality_operator"
7145 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7146 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7147 (const_int 0)])
7148 (label_ref (match_operand 4 "" ""))
7149 (pc)))
aeac46d4 7150 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7151 (ior:SI (match_dup 2) (match_dup 3)))
7152 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7153 "TARGET_THUMB1"
58d6528b 7154 "*
7155 {
7156 if (which_alternative == 0)
7157 output_asm_insn (\"orr\\t%0, %3\", operands);
7158 else if (which_alternative == 1)
7159 {
7160 output_asm_insn (\"orr\\t%1, %3\", operands);
7161 output_asm_insn (\"mov\\t%0, %1\", operands);
7162 }
7163 else
7164 {
7165 output_asm_insn (\"orr\\t%1, %3\", operands);
7166 output_asm_insn (\"str\\t%1, %0\", operands);
7167 }
7168
7169 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7170 {
7171 case 4: return \"b%d5\\t%l4\";
7172 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7173 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7174 }
7175 }"
7176 [(set (attr "far_jump")
7177 (if_then_else
7178 (ior (and (eq (symbol_ref ("which_alternative"))
7179 (const_int 0))
7180 (eq_attr "length" "8"))
7181 (eq_attr "length" "10"))
7182 (const_string "yes")
7183 (const_string "no")))
7184 (set (attr "length")
7185 (if_then_else
7186 (eq (symbol_ref ("which_alternative"))
7187 (const_int 0))
7188 (if_then_else
7189 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7190 (le (minus (match_dup 4) (pc)) (const_int 256)))
7191 (const_int 4)
7192 (if_then_else
7193 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7194 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7195 (const_int 6)
7196 (const_int 8)))
7197 (if_then_else
7198 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7199 (le (minus (match_dup 4) (pc)) (const_int 256)))
7200 (const_int 6)
7201 (if_then_else
7202 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7203 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7204 (const_int 8)
7205 (const_int 10)))))]
7206)
7207
7208(define_insn "*xorsi3_cbranch_scratch"
7209 [(set (pc)
7210 (if_then_else
7211 (match_operator 4 "equality_operator"
7212 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
7213 (match_operand:SI 2 "s_register_operand" "l"))
7214 (const_int 0)])
7215 (label_ref (match_operand 3 "" ""))
7216 (pc)))
7217 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7218 "TARGET_THUMB1"
58d6528b 7219 "*
7220 {
7221 output_asm_insn (\"eor\\t%0, %2\", operands);
7222 switch (get_attr_length (insn))
7223 {
7224 case 4: return \"b%d4\\t%l3\";
7225 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7226 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7227 }
7228 }"
7229 [(set (attr "far_jump")
7230 (if_then_else
7231 (eq_attr "length" "8")
7232 (const_string "yes")
7233 (const_string "no")))
7234 (set (attr "length")
7235 (if_then_else
7236 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7237 (le (minus (match_dup 3) (pc)) (const_int 256)))
7238 (const_int 4)
7239 (if_then_else
7240 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7241 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7242 (const_int 6)
7243 (const_int 8))))]
7244)
7245
7246(define_insn "*xorsi3_cbranch"
7247 [(set (pc)
7248 (if_then_else
7249 (match_operator 5 "equality_operator"
7250 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7251 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7252 (const_int 0)])
7253 (label_ref (match_operand 4 "" ""))
7254 (pc)))
aeac46d4 7255 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7256 (xor:SI (match_dup 2) (match_dup 3)))
7257 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7258 "TARGET_THUMB1"
58d6528b 7259 "*
7260 {
7261 if (which_alternative == 0)
7262 output_asm_insn (\"eor\\t%0, %3\", operands);
7263 else if (which_alternative == 1)
7264 {
7265 output_asm_insn (\"eor\\t%1, %3\", operands);
7266 output_asm_insn (\"mov\\t%0, %1\", operands);
7267 }
7268 else
7269 {
7270 output_asm_insn (\"eor\\t%1, %3\", operands);
7271 output_asm_insn (\"str\\t%1, %0\", operands);
7272 }
7273
7274 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7275 {
7276 case 4: return \"b%d5\\t%l4\";
7277 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7278 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7279 }
7280 }"
7281 [(set (attr "far_jump")
7282 (if_then_else
7283 (ior (and (eq (symbol_ref ("which_alternative"))
7284 (const_int 0))
7285 (eq_attr "length" "8"))
7286 (eq_attr "length" "10"))
7287 (const_string "yes")
7288 (const_string "no")))
7289 (set (attr "length")
7290 (if_then_else
7291 (eq (symbol_ref ("which_alternative"))
7292 (const_int 0))
7293 (if_then_else
7294 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7295 (le (minus (match_dup 4) (pc)) (const_int 256)))
7296 (const_int 4)
7297 (if_then_else
7298 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7299 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7300 (const_int 6)
7301 (const_int 8)))
7302 (if_then_else
7303 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7304 (le (minus (match_dup 4) (pc)) (const_int 256)))
7305 (const_int 6)
7306 (if_then_else
7307 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7308 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7309 (const_int 8)
7310 (const_int 10)))))]
7311)
7312
aeac46d4 7313(define_insn "*bicsi3_cbranch_scratch"
7314 [(set (pc)
7315 (if_then_else
7316 (match_operator 4 "equality_operator"
7317 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7318 (match_operand:SI 1 "s_register_operand" "0"))
7319 (const_int 0)])
7320 (label_ref (match_operand 3 "" ""))
7321 (pc)))
7322 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 7323 "TARGET_THUMB1"
aeac46d4 7324 "*
7325 {
7326 output_asm_insn (\"bic\\t%0, %2\", operands);
7327 switch (get_attr_length (insn))
7328 {
7329 case 4: return \"b%d4\\t%l3\";
7330 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7331 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7332 }
7333 }"
7334 [(set (attr "far_jump")
7335 (if_then_else
7336 (eq_attr "length" "8")
7337 (const_string "yes")
7338 (const_string "no")))
7339 (set (attr "length")
7340 (if_then_else
7341 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7342 (le (minus (match_dup 3) (pc)) (const_int 256)))
7343 (const_int 4)
7344 (if_then_else
7345 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7346 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7347 (const_int 6)
7348 (const_int 8))))]
7349)
7350
7351(define_insn "*bicsi3_cbranch"
7352 [(set (pc)
7353 (if_then_else
7354 (match_operator 5 "equality_operator"
01145ae6 7355 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7356 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 7357 (const_int 0)])
7358 (label_ref (match_operand 4 "" ""))
7359 (pc)))
01145ae6 7360 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 7361 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 7362 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
25f905c2 7363 "TARGET_THUMB1"
aeac46d4 7364 "*
7365 {
7366 if (which_alternative == 0)
7367 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 7368 else if (which_alternative <= 2)
aeac46d4 7369 {
7370 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 7371 /* It's ok if OP0 is a lo-reg, even though the mov will set the
7372 conditions again, since we're only testing for equality. */
aeac46d4 7373 output_asm_insn (\"mov\\t%0, %1\", operands);
7374 }
7375 else
7376 {
7377 output_asm_insn (\"bic\\t%1, %3\", operands);
7378 output_asm_insn (\"str\\t%1, %0\", operands);
7379 }
7380
7381 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7382 {
7383 case 4: return \"b%d5\\t%l4\";
7384 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7385 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7386 }
7387 }"
7388 [(set (attr "far_jump")
7389 (if_then_else
7390 (ior (and (eq (symbol_ref ("which_alternative"))
7391 (const_int 0))
7392 (eq_attr "length" "8"))
7393 (eq_attr "length" "10"))
7394 (const_string "yes")
7395 (const_string "no")))
7396 (set (attr "length")
7397 (if_then_else
7398 (eq (symbol_ref ("which_alternative"))
7399 (const_int 0))
7400 (if_then_else
7401 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7402 (le (minus (match_dup 4) (pc)) (const_int 256)))
7403 (const_int 4)
7404 (if_then_else
7405 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7406 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7407 (const_int 6)
7408 (const_int 8)))
7409 (if_then_else
7410 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7411 (le (minus (match_dup 4) (pc)) (const_int 256)))
7412 (const_int 6)
7413 (if_then_else
7414 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7415 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7416 (const_int 8)
7417 (const_int 10)))))]
7418)
7419
203c488f 7420(define_insn "*cbranchne_decr1"
7421 [(set (pc)
7422 (if_then_else (match_operator 3 "equality_operator"
7423 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7424 (const_int 0)])
7425 (label_ref (match_operand 4 "" ""))
7426 (pc)))
aeac46d4 7427 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7428 (plus:SI (match_dup 2) (const_int -1)))
7429 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7430 "TARGET_THUMB1"
203c488f 7431 "*
7432 {
7433 rtx cond[2];
7434 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7435 ? GEU : LTU),
58d6528b 7436 VOIDmode, operands[2], const1_rtx);
203c488f 7437 cond[1] = operands[4];
7438
7439 if (which_alternative == 0)
7440 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7441 else if (which_alternative == 1)
7442 {
7443 /* We must provide an alternative for a hi reg because reload
7444 cannot handle output reloads on a jump instruction, but we
7445 can't subtract into that. Fortunately a mov from lo to hi
7446 does not clobber the condition codes. */
7447 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7448 output_asm_insn (\"mov\\t%0, %1\", operands);
7449 }
7450 else
7451 {
7452 /* Similarly, but the target is memory. */
7453 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7454 output_asm_insn (\"str\\t%1, %0\", operands);
7455 }
7456
7457 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7458 {
7459 case 4:
8aea555f 7460 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7461 return \"\";
7462 case 6:
8aea555f 7463 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7464 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7465 default:
8aea555f 7466 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7467 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7468 }
7469 }
7470 "
7471 [(set (attr "far_jump")
7472 (if_then_else
7473 (ior (and (eq (symbol_ref ("which_alternative"))
7474 (const_int 0))
7475 (eq_attr "length" "8"))
7476 (eq_attr "length" "10"))
7477 (const_string "yes")
7478 (const_string "no")))
7479 (set_attr_alternative "length"
7480 [
7481 ;; Alternative 0
7482 (if_then_else
7483 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7484 (le (minus (match_dup 4) (pc)) (const_int 256)))
7485 (const_int 4)
7486 (if_then_else
7487 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7488 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7489 (const_int 6)
7490 (const_int 8)))
7491 ;; Alternative 1
7492 (if_then_else
7493 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7494 (le (minus (match_dup 4) (pc)) (const_int 256)))
7495 (const_int 6)
7496 (if_then_else
7497 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7498 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7499 (const_int 8)
7500 (const_int 10)))
7501 ;; Alternative 2
7502 (if_then_else
7503 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7504 (le (minus (match_dup 4) (pc)) (const_int 256)))
7505 (const_int 6)
7506 (if_then_else
7507 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7508 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7509 (const_int 8)
7510 (const_int 10)))
7511 ;; Alternative 3
7512 (if_then_else
7513 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7514 (le (minus (match_dup 4) (pc)) (const_int 256)))
7515 (const_int 6)
7516 (if_then_else
7517 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7518 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7519 (const_int 8)
7520 (const_int 10)))])]
7521)
cffb2a26 7522
58d6528b 7523(define_insn "*addsi3_cbranch"
7524 [(set (pc)
7525 (if_then_else
b0694be0 7526 (match_operator 4 "arm_comparison_operator"
58d6528b 7527 [(plus:SI
7528 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
7529 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
7530 (const_int 0)])
7531 (label_ref (match_operand 5 "" ""))
7532 (pc)))
aeac46d4 7533 (set
7534 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7535 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 7536 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
25f905c2 7537 "TARGET_THUMB1
58d6528b 7538 && (GET_CODE (operands[4]) == EQ
7539 || GET_CODE (operands[4]) == NE
7540 || GET_CODE (operands[4]) == GE
7541 || GET_CODE (operands[4]) == LT)"
7542 "*
7543 {
7544 rtx cond[3];
7545
7546
7547 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
7548 cond[1] = operands[2];
7549 cond[2] = operands[3];
7550
7551 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7552 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7553 else
7554 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7555
7556 if (which_alternative >= 3
7557 && which_alternative < 4)
7558 output_asm_insn (\"mov\\t%0, %1\", operands);
7559 else if (which_alternative >= 4)
7560 output_asm_insn (\"str\\t%1, %0\", operands);
7561
7562 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7563 {
7564 case 4:
7565 return \"b%d4\\t%l5\";
7566 case 6:
7567 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7568 default:
7569 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7570 }
7571 }
7572 "
7573 [(set (attr "far_jump")
7574 (if_then_else
7575 (ior (and (lt (symbol_ref ("which_alternative"))
7576 (const_int 3))
7577 (eq_attr "length" "8"))
7578 (eq_attr "length" "10"))
7579 (const_string "yes")
7580 (const_string "no")))
7581 (set (attr "length")
7582 (if_then_else
7583 (lt (symbol_ref ("which_alternative"))
7584 (const_int 3))
7585 (if_then_else
7586 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7587 (le (minus (match_dup 5) (pc)) (const_int 256)))
7588 (const_int 4)
7589 (if_then_else
7590 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7591 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7592 (const_int 6)
7593 (const_int 8)))
7594 (if_then_else
7595 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7596 (le (minus (match_dup 5) (pc)) (const_int 256)))
7597 (const_int 6)
7598 (if_then_else
7599 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7600 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7601 (const_int 8)
7602 (const_int 10)))))]
7603)
7604
7605(define_insn "*addsi3_cbranch_scratch"
7606 [(set (pc)
7607 (if_then_else
b0694be0 7608 (match_operator 3 "arm_comparison_operator"
58d6528b 7609 [(plus:SI
7610 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7611 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7612 (const_int 0)])
7613 (label_ref (match_operand 4 "" ""))
7614 (pc)))
7615 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7616 "TARGET_THUMB1
58d6528b 7617 && (GET_CODE (operands[3]) == EQ
7618 || GET_CODE (operands[3]) == NE
7619 || GET_CODE (operands[3]) == GE
7620 || GET_CODE (operands[3]) == LT)"
7621 "*
7622 {
7623 switch (which_alternative)
7624 {
7625 case 0:
7626 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7627 break;
7628 case 1:
7629 output_asm_insn (\"cmn\t%1, %2\", operands);
7630 break;
0f5e9701 7631 case 2:
3a445a04 7632 if (INTVAL (operands[2]) < 0)
7633 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7634 else
7635 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7636 break;
0f5e9701 7637 case 3:
3a445a04 7638 if (INTVAL (operands[2]) < 0)
7639 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7640 else
7641 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7642 break;
7643 }
7644
7645 switch (get_attr_length (insn))
7646 {
7647 case 4:
7648 return \"b%d3\\t%l4\";
7649 case 6:
7650 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7651 default:
7652 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7653 }
7654 }
7655 "
7656 [(set (attr "far_jump")
7657 (if_then_else
7658 (eq_attr "length" "8")
7659 (const_string "yes")
7660 (const_string "no")))
7661 (set (attr "length")
7662 (if_then_else
7663 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7664 (le (minus (match_dup 4) (pc)) (const_int 256)))
7665 (const_int 4)
7666 (if_then_else
7667 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7668 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7669 (const_int 6)
7670 (const_int 8))))]
7671)
7672
7673(define_insn "*subsi3_cbranch"
7674 [(set (pc)
7675 (if_then_else
b0694be0 7676 (match_operator 4 "arm_comparison_operator"
58d6528b 7677 [(minus:SI
7678 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7679 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7680 (const_int 0)])
7681 (label_ref (match_operand 5 "" ""))
7682 (pc)))
aeac46d4 7683 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7684 (minus:SI (match_dup 2) (match_dup 3)))
7685 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7686 "TARGET_THUMB1
58d6528b 7687 && (GET_CODE (operands[4]) == EQ
7688 || GET_CODE (operands[4]) == NE
7689 || GET_CODE (operands[4]) == GE
7690 || GET_CODE (operands[4]) == LT)"
7691 "*
7692 {
7693 if (which_alternative == 0)
7694 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7695 else if (which_alternative == 1)
7696 {
7697 /* We must provide an alternative for a hi reg because reload
7698 cannot handle output reloads on a jump instruction, but we
7699 can't subtract into that. Fortunately a mov from lo to hi
7700 does not clobber the condition codes. */
7701 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7702 output_asm_insn (\"mov\\t%0, %1\", operands);
7703 }
7704 else
7705 {
7706 /* Similarly, but the target is memory. */
7707 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7708 output_asm_insn (\"str\\t%1, %0\", operands);
7709 }
7710
7711 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7712 {
7713 case 4:
7714 return \"b%d4\\t%l5\";
7715 case 6:
7716 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7717 default:
7718 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7719 }
7720 }
7721 "
7722 [(set (attr "far_jump")
7723 (if_then_else
7724 (ior (and (eq (symbol_ref ("which_alternative"))
7725 (const_int 0))
7726 (eq_attr "length" "8"))
7727 (eq_attr "length" "10"))
7728 (const_string "yes")
7729 (const_string "no")))
7730 (set (attr "length")
7731 (if_then_else
7732 (eq (symbol_ref ("which_alternative"))
7733 (const_int 0))
7734 (if_then_else
7735 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7736 (le (minus (match_dup 5) (pc)) (const_int 256)))
7737 (const_int 4)
7738 (if_then_else
7739 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7740 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7741 (const_int 6)
7742 (const_int 8)))
7743 (if_then_else
7744 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7745 (le (minus (match_dup 5) (pc)) (const_int 256)))
7746 (const_int 6)
7747 (if_then_else
7748 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7749 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7750 (const_int 8)
7751 (const_int 10)))))]
7752)
7753
7754(define_insn "*subsi3_cbranch_scratch"
7755 [(set (pc)
7756 (if_then_else
7757 (match_operator 0 "arm_comparison_operator"
7758 [(minus:SI (match_operand:SI 1 "register_operand" "l")
7759 (match_operand:SI 2 "nonmemory_operand" "l"))
7760 (const_int 0)])
7761 (label_ref (match_operand 3 "" ""))
7762 (pc)))]
25f905c2 7763 "TARGET_THUMB1
58d6528b 7764 && (GET_CODE (operands[0]) == EQ
7765 || GET_CODE (operands[0]) == NE
7766 || GET_CODE (operands[0]) == GE
7767 || GET_CODE (operands[0]) == LT)"
7768 "*
7769 output_asm_insn (\"cmp\\t%1, %2\", operands);
7770 switch (get_attr_length (insn))
7771 {
7772 case 4: return \"b%d0\\t%l3\";
7773 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7774 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7775 }
7776 "
7777 [(set (attr "far_jump")
7778 (if_then_else
7779 (eq_attr "length" "8")
7780 (const_string "yes")
7781 (const_string "no")))
7782 (set (attr "length")
7783 (if_then_else
7784 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7785 (le (minus (match_dup 3) (pc)) (const_int 256)))
7786 (const_int 4)
7787 (if_then_else
7788 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7789 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7790 (const_int 6)
7791 (const_int 8))))]
7792)
7793
9c08d1fa 7794;; Comparison and test insns
7795
cffb2a26 7796(define_insn "*arm_cmpsi_insn"
bd5b4116 7797 [(set (reg:CC CC_REGNUM)
aea4c774 7798 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7799 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7800 "TARGET_32BIT"
5565501b 7801 "@
aea4c774 7802 cmp%?\\t%0, %1
7803 cmn%?\\t%0, #%n1"
cffb2a26 7804 [(set_attr "conds" "set")]
7805)
b11cae9e 7806
25f905c2 7807(define_insn "*arm_cmpsi_shiftsi"
bd5b4116 7808 [(set (reg:CC CC_REGNUM)
cffb2a26 7809 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
7810 (match_operator:SI 3 "shift_operator"
aea4c774 7811 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 7812 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
7813 "TARGET_ARM"
aea4c774 7814 "cmp%?\\t%0, %1%S3"
344495ea 7815 [(set_attr "conds" "set")
331beb1a 7816 (set_attr "shift" "1")
a2cd141b 7817 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7818 (const_string "alu_shift")
7819 (const_string "alu_shift_reg")))]
0d66636f 7820)
b11cae9e 7821
25f905c2 7822(define_insn "*arm_cmpsi_shiftsi_swp"
bd5b4116 7823 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7824 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7825 [(match_operand:SI 1 "s_register_operand" "r")
7826 (match_operand:SI 2 "reg_or_int_operand" "rM")])
7827 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7828 "TARGET_ARM"
aea4c774 7829 "cmp%?\\t%0, %1%S3"
344495ea 7830 [(set_attr "conds" "set")
331beb1a 7831 (set_attr "shift" "1")
a2cd141b 7832 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7833 (const_string "alu_shift")
7834 (const_string "alu_shift_reg")))]
0d66636f 7835)
b11cae9e 7836
25f905c2 7837(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7838 [(set (reg:CC_Z CC_REGNUM)
7839 (compare:CC_Z
7840 (neg:SI (match_operator:SI 1 "shift_operator"
7841 [(match_operand:SI 2 "s_register_operand" "r")
7842 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7843 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7844 "TARGET_ARM"
aed179ae 7845 "cmn%?\\t%0, %2%S1"
344495ea 7846 [(set_attr "conds" "set")
aed179ae 7847 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7848 (const_string "alu_shift")
7849 (const_string "alu_shift_reg")))]
0d66636f 7850)
b11cae9e 7851
7d57ec45 7852;; Cirrus SF compare instruction
7853(define_insn "*cirrus_cmpsf"
7854 [(set (reg:CCFP CC_REGNUM)
7855 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7856 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7857 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7858 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7859 [(set_attr "type" "mav_farith")
7d57ec45 7860 (set_attr "cirrus" "compare")]
7861)
7862
7863;; Cirrus DF compare instruction
7864(define_insn "*cirrus_cmpdf"
7865 [(set (reg:CCFP CC_REGNUM)
7866 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7867 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7868 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7869 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7870 [(set_attr "type" "mav_farith")
7d57ec45 7871 (set_attr "cirrus" "compare")]
7872)
7873
7d57ec45 7874(define_insn "*cirrus_cmpdi"
7875 [(set (reg:CC CC_REGNUM)
7876 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7877 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7878 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7879 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7880 [(set_attr "type" "mav_farith")
7d57ec45 7881 (set_attr "cirrus" "compare")]
7882)
7883
9c08d1fa 7884; This insn allows redundant compares to be removed by cse, nothing should
7885; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7886; is deleted later on. The match_dup will match the mode here, so that
7887; mode changes of the condition codes aren't lost by this even though we don't
7888; specify what they are.
7889
8a18b90c 7890(define_insn "*deleted_compare"
9c08d1fa 7891 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7892 "TARGET_32BIT"
40dbec34 7893 "\\t%@ deleted compare"
cffb2a26 7894 [(set_attr "conds" "set")
7895 (set_attr "length" "0")]
7896)
9c08d1fa 7897
7898\f
7899;; Conditional branch insns
7900
74f4459c 7901(define_expand "cbranch_cc"
9c08d1fa 7902 [(set (pc)
74f4459c 7903 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7904 (match_operand 2 "" "")])
7905 (label_ref (match_operand 3 "" ""))
9c08d1fa 7906 (pc)))]
25f905c2 7907 "TARGET_32BIT"
74f4459c 7908 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7909 operands[1], operands[2]);
7910 operands[2] = const0_rtx;"
8fa3ba89 7911)
7912
7913;;
7914;; Patterns to match conditional branch insns.
7915;;
7916
cffb2a26 7917(define_insn "*arm_cond_branch"
9c08d1fa 7918 [(set (pc)
8fa3ba89 7919 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7920 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7921 (label_ref (match_operand 0 "" ""))
7922 (pc)))]
25f905c2 7923 "TARGET_32BIT"
d75350ce 7924 "*
9c08d1fa 7925 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7926 {
7927 arm_ccfsm_state += 2;
7928 return \"\";
7929 }
e2348bcb 7930 return \"b%d1\\t%l0\";
cffb2a26 7931 "
a2cd141b 7932 [(set_attr "conds" "use")
7933 (set_attr "type" "branch")]
cffb2a26 7934)
d75350ce 7935
cffb2a26 7936(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7937 [(set (pc)
8fa3ba89 7938 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7939 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7940 (pc)
7941 (label_ref (match_operand 0 "" ""))))]
25f905c2 7942 "TARGET_32BIT"
d75350ce 7943 "*
9c08d1fa 7944 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7945 {
7946 arm_ccfsm_state += 2;
7947 return \"\";
7948 }
e2348bcb 7949 return \"b%D1\\t%l0\";
cffb2a26 7950 "
a2cd141b 7951 [(set_attr "conds" "use")
7952 (set_attr "type" "branch")]
cffb2a26 7953)
7954
b11cae9e 7955\f
9c08d1fa 7956
7957; scc insns
7958
74f4459c 7959(define_expand "cstore_cc"
7db9af5d 7960 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7961 (match_operator:SI 1 "" [(match_operand 2 "" "")
7962 (match_operand 3 "" "")]))]
25f905c2 7963 "TARGET_32BIT"
74f4459c 7964 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7965 operands[2], operands[3]);
7966 operands[3] = const0_rtx;"
8fa3ba89 7967)
7968
f7fbdd4a 7969(define_insn "*mov_scc"
9c08d1fa 7970 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7971 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7972 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7973 "TARGET_ARM"
4d61e570 7974 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7975 [(set_attr "conds" "use")
7976 (set_attr "length" "8")]
7977)
9c08d1fa 7978
f7fbdd4a 7979(define_insn "*mov_negscc"
9c08d1fa 7980 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7981 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7982 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7983 "TARGET_ARM"
4d61e570 7984 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7985 [(set_attr "conds" "use")
7986 (set_attr "length" "8")]
7987)
9c08d1fa 7988
f7fbdd4a 7989(define_insn "*mov_notscc"
9c08d1fa 7990 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7991 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7992 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7993 "TARGET_ARM"
4d61e570 7994 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7995 [(set_attr "conds" "use")
7996 (set_attr "length" "8")]
7997)
9c08d1fa 7998
595d88b5 7999(define_expand "cstoresi4"
8000 [(set (match_operand:SI 0 "s_register_operand" "")
8001 (match_operator:SI 1 "arm_comparison_operator"
8002 [(match_operand:SI 2 "s_register_operand" "")
8003 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 8004 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 8005 "{
8006 rtx op3, scratch, scratch2;
8007
74f4459c 8008 if (!TARGET_THUMB1)
8009 {
8010 if (!arm_add_operand (operands[3], SImode))
8011 operands[3] = force_reg (SImode, operands[3]);
8012 emit_insn (gen_cstore_cc (operands[0], operands[1],
8013 operands[2], operands[3]));
8014 DONE;
8015 }
8016
595d88b5 8017 if (operands[3] == const0_rtx)
8018 {
8019 switch (GET_CODE (operands[1]))
8020 {
8021 case EQ:
25f905c2 8022 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 8023 break;
8024
8025 case NE:
25f905c2 8026 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 8027 break;
8028
8029 case LE:
8030 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8031 NULL_RTX, 0, OPTAB_WIDEN);
8032 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8033 NULL_RTX, 0, OPTAB_WIDEN);
8034 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8035 operands[0], 1, OPTAB_WIDEN);
8036 break;
8037
8038 case GE:
8039 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8040 NULL_RTX, 1);
8041 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8042 NULL_RTX, 1, OPTAB_WIDEN);
8043 break;
8044
8045 case GT:
8046 scratch = expand_binop (SImode, ashr_optab, operands[2],
8047 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8048 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8049 NULL_RTX, 0, OPTAB_WIDEN);
8050 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8051 0, OPTAB_WIDEN);
8052 break;
8053
8054 /* LT is handled by generic code. No need for unsigned with 0. */
8055 default:
8056 FAIL;
8057 }
8058 DONE;
8059 }
8060
8061 switch (GET_CODE (operands[1]))
8062 {
8063 case EQ:
8064 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8065 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8066 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 8067 break;
8068
8069 case NE:
8070 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8071 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8072 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 8073 break;
8074
8075 case LE:
8076 op3 = force_reg (SImode, operands[3]);
8077
8078 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8079 NULL_RTX, 1, OPTAB_WIDEN);
8080 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8081 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8082 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8083 op3, operands[2]));
8084 break;
8085
8086 case GE:
8087 op3 = operands[3];
25f905c2 8088 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8089 op3 = force_reg (SImode, op3);
8090 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8091 NULL_RTX, 0, OPTAB_WIDEN);
8092 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8093 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 8094 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8095 operands[2], op3));
8096 break;
8097
8098 case LEU:
8099 op3 = force_reg (SImode, operands[3]);
8100 scratch = force_reg (SImode, const0_rtx);
25f905c2 8101 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8102 op3, operands[2]));
8103 break;
8104
8105 case GEU:
8106 op3 = operands[3];
25f905c2 8107 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8108 op3 = force_reg (SImode, op3);
8109 scratch = force_reg (SImode, const0_rtx);
25f905c2 8110 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8111 operands[2], op3));
8112 break;
8113
8114 case LTU:
8115 op3 = operands[3];
25f905c2 8116 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8117 op3 = force_reg (SImode, op3);
8118 scratch = gen_reg_rtx (SImode);
408b7ae5 8119 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 8120 break;
8121
8122 case GTU:
8123 op3 = force_reg (SImode, operands[3]);
8124 scratch = gen_reg_rtx (SImode);
408b7ae5 8125 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 8126 break;
8127
8128 /* No good sequences for GT, LT. */
8129 default:
8130 FAIL;
8131 }
8132 DONE;
8133}")
8134
74f4459c 8135(define_expand "cstoresf4"
8136 [(set (match_operand:SI 0 "s_register_operand" "")
8137 (match_operator:SI 1 "arm_comparison_operator"
8138 [(match_operand:SF 2 "s_register_operand" "")
8139 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8140 "TARGET_32BIT && TARGET_HARD_FLOAT"
8141 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8142 operands[2], operands[3])); DONE;"
8143)
8144
8145(define_expand "cstoredf4"
8146 [(set (match_operand:SI 0 "s_register_operand" "")
8147 (match_operator:SI 1 "arm_comparison_operator"
8148 [(match_operand:DF 2 "s_register_operand" "")
8149 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8150 "TARGET_32BIT && TARGET_HARD_FLOAT"
8151 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8152 operands[2], operands[3])); DONE;"
8153)
8154
8155;; this uses the Cirrus DI compare instruction
8156(define_expand "cstoredi4"
8157 [(set (match_operand:SI 0 "s_register_operand" "")
8158 (match_operator:SI 1 "arm_comparison_operator"
8159 [(match_operand:DI 2 "cirrus_fp_register" "")
8160 (match_operand:DI 3 "cirrus_fp_register" "")]))]
8161 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
8162 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8163 operands[2], operands[3])); DONE;"
8164)
8165
8166
25f905c2 8167(define_expand "cstoresi_eq0_thumb1"
595d88b5 8168 [(parallel
8169 [(set (match_operand:SI 0 "s_register_operand" "")
8170 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8171 (const_int 0)))
8172 (clobber (match_dup:SI 2))])]
25f905c2 8173 "TARGET_THUMB1"
595d88b5 8174 "operands[2] = gen_reg_rtx (SImode);"
8175)
8176
25f905c2 8177(define_expand "cstoresi_ne0_thumb1"
595d88b5 8178 [(parallel
8179 [(set (match_operand:SI 0 "s_register_operand" "")
8180 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8181 (const_int 0)))
8182 (clobber (match_dup:SI 2))])]
25f905c2 8183 "TARGET_THUMB1"
595d88b5 8184 "operands[2] = gen_reg_rtx (SImode);"
8185)
8186
25f905c2 8187(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 8188 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8189 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8190 (const_int 0)))
8191 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 8192 "TARGET_THUMB1"
595d88b5 8193 "@
8194 neg\\t%0, %1\;adc\\t%0, %0, %1
8195 neg\\t%2, %1\;adc\\t%0, %1, %2"
8196 [(set_attr "length" "4")]
8197)
8198
25f905c2 8199(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 8200 [(set (match_operand:SI 0 "s_register_operand" "=l")
8201 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8202 (const_int 0)))
8203 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8204 "TARGET_THUMB1"
595d88b5 8205 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8206 [(set_attr "length" "4")]
8207)
8208
408b7ae5 8209;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 8210(define_insn "cstoresi_nltu_thumb1"
595d88b5 8211 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8212 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8213 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8214 "TARGET_THUMB1"
595d88b5 8215 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8216 [(set_attr "length" "4")]
8217)
8218
408b7ae5 8219(define_insn_and_split "cstoresi_ltu_thumb1"
8220 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8221 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8222 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8223 "TARGET_THUMB1"
8224 "#"
8225 "TARGET_THUMB1"
8226 [(set (match_dup 3)
8227 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8228 (set (match_dup 0) (neg:SI (match_dup 3)))]
8229 "operands[3] = gen_reg_rtx (SImode);"
8230 [(set_attr "length" "4")]
8231)
8232
595d88b5 8233;; Used as part of the expansion of thumb les sequence.
25f905c2 8234(define_insn "thumb1_addsi3_addgeu"
595d88b5 8235 [(set (match_operand:SI 0 "s_register_operand" "=l")
8236 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8237 (match_operand:SI 2 "s_register_operand" "l"))
8238 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8239 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8240 "TARGET_THUMB1"
595d88b5 8241 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8242 [(set_attr "length" "4")]
8243)
8244
9c08d1fa 8245\f
39b5e676 8246;; Conditional move insns
8247
8248(define_expand "movsicc"
8a18b90c 8249 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 8250 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 8251 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8252 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8253 "TARGET_32BIT"
39b5e676 8254 "
215b30b3 8255 {
8256 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8257 rtx ccreg;
8258
8259 if (code == UNEQ || code == LTGT)
8260 FAIL;
39b5e676 8261
74f4459c 8262 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8263 XEXP (operands[1], 1));
29bb088d 8264 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8265 }"
8266)
39b5e676 8267
8268(define_expand "movsfcc"
8a18b90c 8269 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 8270 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8271 (match_operand:SF 2 "s_register_operand" "")
8272 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 8273 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8274 "
215b30b3 8275 {
8276 enum rtx_code code = GET_CODE (operands[1]);
8277 rtx ccreg;
f082f1c4 8278
278b301d 8279 if (code == UNEQ || code == LTGT)
8280 FAIL;
8281
215b30b3 8282 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 8283 Otherwise, ensure it is a valid FP add operand */
8284 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8285 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 8286 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8287
74f4459c 8288 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8289 XEXP (operands[1], 1));
29bb088d 8290 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8291 }"
8292)
39b5e676 8293
8294(define_expand "movdfcc"
8a18b90c 8295 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 8296 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8297 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8298 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 8299 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 8300 "
215b30b3 8301 {
8302 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8303 rtx ccreg;
39b5e676 8304
278b301d 8305 if (code == UNEQ || code == LTGT)
8306 FAIL;
8307
74f4459c 8308 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8309 XEXP (operands[1], 1));
29bb088d 8310 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8311 }"
8312)
39b5e676 8313
8314(define_insn "*movsicc_insn"
f082f1c4 8315 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8316 (if_then_else:SI
8fa3ba89 8317 (match_operator 3 "arm_comparison_operator"
8a18b90c 8318 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8319 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8320 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8321 "TARGET_ARM"
39b5e676 8322 "@
8a18b90c 8323 mov%D3\\t%0, %2
8324 mvn%D3\\t%0, #%B2
f082f1c4 8325 mov%d3\\t%0, %1
8326 mvn%d3\\t%0, #%B1
8a18b90c 8327 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8328 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8329 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8330 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8331 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 8332 (set_attr "conds" "use")]
8333)
39b5e676 8334
39b5e676 8335(define_insn "*movsfcc_soft_insn"
f082f1c4 8336 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8337 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8338 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8339 (match_operand:SF 1 "s_register_operand" "0,r")
8340 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8341 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8342 "@
8343 mov%D3\\t%0, %2
8344 mov%d3\\t%0, %1"
8fa3ba89 8345 [(set_attr "conds" "use")]
8346)
39b5e676 8347
39b5e676 8348\f
9c08d1fa 8349;; Jump and linkage insns
8350
cffb2a26 8351(define_expand "jump"
9c08d1fa 8352 [(set (pc)
8353 (label_ref (match_operand 0 "" "")))]
cffb2a26 8354 "TARGET_EITHER"
9c08d1fa 8355 ""
cffb2a26 8356)
8357
8358(define_insn "*arm_jump"
8359 [(set (pc)
8360 (label_ref (match_operand 0 "" "")))]
25f905c2 8361 "TARGET_32BIT"
9c08d1fa 8362 "*
0d66636f 8363 {
8364 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8365 {
8366 arm_ccfsm_state += 2;
8367 return \"\";
8368 }
8369 return \"b%?\\t%l0\";
8370 }
8371 "
8372 [(set_attr "predicable" "yes")]
8373)
9c08d1fa 8374
cffb2a26 8375(define_insn "*thumb_jump"
8376 [(set (pc)
8377 (label_ref (match_operand 0 "" "")))]
25f905c2 8378 "TARGET_THUMB1"
cffb2a26 8379 "*
8380 if (get_attr_length (insn) == 2)
8381 return \"b\\t%l0\";
8382 return \"bl\\t%l0\\t%@ far jump\";
8383 "
8384 [(set (attr "far_jump")
8385 (if_then_else
8386 (eq_attr "length" "4")
8387 (const_string "yes")
8388 (const_string "no")))
8389 (set (attr "length")
8390 (if_then_else
911ed8af 8391 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8392 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8393 (const_int 2)
8394 (const_int 4)))]
8395)
8396
d3373b54 8397(define_expand "call"
8398 [(parallel [(call (match_operand 0 "memory_operand" "")
8399 (match_operand 1 "general_operand" ""))
cffb2a26 8400 (use (match_operand 2 "" ""))
bd5b4116 8401 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8402 "TARGET_EITHER"
6c4c2133 8403 "
8404 {
bac7fc85 8405 rtx callee, pat;
bbe777ea 8406
bbe777ea 8407 /* In an untyped call, we can get NULL for operand 2. */
8408 if (operands[2] == NULL_RTX)
8409 operands[2] = const0_rtx;
8410
de55252a 8411 /* Decide if we should generate indirect calls by loading the
85c36fd1 8412 32-bit address of the callee into a register before performing the
de55252a 8413 branch and link. */
8414 callee = XEXP (operands[0], 0);
8415 if (GET_CODE (callee) == SYMBOL_REF
8416 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8417 : !REG_P (callee))
bbe777ea 8418 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8419
8420 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8421 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8422 DONE;
6c4c2133 8423 }"
8424)
d3373b54 8425
bac7fc85 8426(define_expand "call_internal"
8427 [(parallel [(call (match_operand 0 "memory_operand" "")
8428 (match_operand 1 "general_operand" ""))
8429 (use (match_operand 2 "" ""))
8430 (clobber (reg:SI LR_REGNUM))])])
8431
f1039640 8432(define_insn "*call_reg_armv5"
d3373b54 8433 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8434 (match_operand 1 "" ""))
8435 (use (match_operand 2 "" ""))
bd5b4116 8436 (clobber (reg:SI LR_REGNUM))]
f1039640 8437 "TARGET_ARM && arm_arch5"
8438 "blx%?\\t%0"
8439 [(set_attr "type" "call")]
8440)
8441
8442(define_insn "*call_reg_arm"
8443 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8444 (match_operand 1 "" ""))
8445 (use (match_operand 2 "" ""))
8446 (clobber (reg:SI LR_REGNUM))]
8447 "TARGET_ARM && !arm_arch5"
9c08d1fa 8448 "*
5565501b 8449 return output_call (operands);
cffb2a26 8450 "
8451 ;; length is worst case, normally it is only two
8452 [(set_attr "length" "12")
8453 (set_attr "type" "call")]
8454)
9c08d1fa 8455
f7fbdd4a 8456(define_insn "*call_mem"
a3c63a9d 8457 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8458 (match_operand 1 "" ""))
8459 (use (match_operand 2 "" ""))
bd5b4116 8460 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8461 "TARGET_ARM"
9c08d1fa 8462 "*
5565501b 8463 return output_call_mem (operands);
cffb2a26 8464 "
8465 [(set_attr "length" "12")
8466 (set_attr "type" "call")]
8467)
8468
25f905c2 8469(define_insn "*call_reg_thumb1_v5"
cffb2a26 8470 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8471 (match_operand 1 "" ""))
8472 (use (match_operand 2 "" ""))
bd5b4116 8473 (clobber (reg:SI LR_REGNUM))]
25f905c2 8474 "TARGET_THUMB1 && arm_arch5"
f1039640 8475 "blx\\t%0"
8476 [(set_attr "length" "2")
8477 (set_attr "type" "call")]
cffb2a26 8478)
8479
25f905c2 8480(define_insn "*call_reg_thumb1"
f1039640 8481 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8482 (match_operand 1 "" ""))
8483 (use (match_operand 2 "" ""))
bd5b4116 8484 (clobber (reg:SI LR_REGNUM))]
25f905c2 8485 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8486 "*
8487 {
150502c9 8488 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8489 return thumb_call_via_reg (operands[0]);
150502c9 8490 else if (operands[1] == const0_rtx)
f1039640 8491 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8492 else if (frame_pointer_needed)
8493 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8494 else
150502c9 8495 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8496 }"
8497 [(set_attr "type" "call")]
8498)
9c08d1fa 8499
d3373b54 8500(define_expand "call_value"
e0698af7 8501 [(parallel [(set (match_operand 0 "" "")
8502 (call (match_operand 1 "memory_operand" "")
8503 (match_operand 2 "general_operand" "")))
cffb2a26 8504 (use (match_operand 3 "" ""))
bd5b4116 8505 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8506 "TARGET_EITHER"
6c4c2133 8507 "
8508 {
bac7fc85 8509 rtx pat, callee;
bbe777ea 8510
8511 /* In an untyped call, we can get NULL for operand 2. */
8512 if (operands[3] == 0)
8513 operands[3] = const0_rtx;
8514
de55252a 8515 /* Decide if we should generate indirect calls by loading the
8516 32-bit address of the callee into a register before performing the
8517 branch and link. */
8518 callee = XEXP (operands[1], 0);
8519 if (GET_CODE (callee) == SYMBOL_REF
8520 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8521 : !REG_P (callee))
78fe751b 8522 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8523
8524 pat = gen_call_value_internal (operands[0], operands[1],
8525 operands[2], operands[3]);
8526 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8527 DONE;
6c4c2133 8528 }"
8529)
d3373b54 8530
bac7fc85 8531(define_expand "call_value_internal"
8532 [(parallel [(set (match_operand 0 "" "")
8533 (call (match_operand 1 "memory_operand" "")
8534 (match_operand 2 "general_operand" "")))
8535 (use (match_operand 3 "" ""))
8536 (clobber (reg:SI LR_REGNUM))])])
8537
f1039640 8538(define_insn "*call_value_reg_armv5"
27ed6835 8539 [(set (match_operand 0 "" "")
755eb2b4 8540 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8541 (match_operand 2 "" "")))
bbe777ea 8542 (use (match_operand 3 "" ""))
bd5b4116 8543 (clobber (reg:SI LR_REGNUM))]
f1039640 8544 "TARGET_ARM && arm_arch5"
8545 "blx%?\\t%1"
8546 [(set_attr "type" "call")]
8547)
8548
8549(define_insn "*call_value_reg_arm"
8550 [(set (match_operand 0 "" "")
8551 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8552 (match_operand 2 "" "")))
8553 (use (match_operand 3 "" ""))
8554 (clobber (reg:SI LR_REGNUM))]
8555 "TARGET_ARM && !arm_arch5"
9c08d1fa 8556 "*
215b30b3 8557 return output_call (&operands[1]);
cffb2a26 8558 "
8559 [(set_attr "length" "12")
8560 (set_attr "type" "call")]
8561)
9c08d1fa 8562
f7fbdd4a 8563(define_insn "*call_value_mem"
27ed6835 8564 [(set (match_operand 0 "" "")
a3c63a9d 8565 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8566 (match_operand 2 "" "")))
bbe777ea 8567 (use (match_operand 3 "" ""))
bd5b4116 8568 (clobber (reg:SI LR_REGNUM))]
215b30b3 8569 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8570 "*
215b30b3 8571 return output_call_mem (&operands[1]);
cffb2a26 8572 "
8573 [(set_attr "length" "12")
8574 (set_attr "type" "call")]
8575)
9c08d1fa 8576
25f905c2 8577(define_insn "*call_value_reg_thumb1_v5"
f1039640 8578 [(set (match_operand 0 "" "")
8579 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8580 (match_operand 2 "" "")))
8581 (use (match_operand 3 "" ""))
8582 (clobber (reg:SI LR_REGNUM))]
25f905c2 8583 "TARGET_THUMB1 && arm_arch5"
f1039640 8584 "blx\\t%1"
8585 [(set_attr "length" "2")
8586 (set_attr "type" "call")]
8587)
8588
25f905c2 8589(define_insn "*call_value_reg_thumb1"
f1039640 8590 [(set (match_operand 0 "" "")
8591 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8592 (match_operand 2 "" "")))
8593 (use (match_operand 3 "" ""))
8594 (clobber (reg:SI LR_REGNUM))]
25f905c2 8595 "TARGET_THUMB1 && !arm_arch5"
f1039640 8596 "*
8597 {
150502c9 8598 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8599 return thumb_call_via_reg (operands[1]);
150502c9 8600 else if (operands[2] == const0_rtx)
f1039640 8601 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8602 else if (frame_pointer_needed)
8603 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8604 else
150502c9 8605 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8606 }"
8607 [(set_attr "type" "call")]
8608)
8609
9c08d1fa 8610;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8611;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8612
f7fbdd4a 8613(define_insn "*call_symbol"
27ed6835 8614 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8615 (match_operand 1 "" ""))
bbe777ea 8616 (use (match_operand 2 "" ""))
bd5b4116 8617 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8618 "TARGET_ARM
8619 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8620 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8621 "*
8622 {
55c1e470 8623 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8624 }"
cffb2a26 8625 [(set_attr "type" "call")]
8626)
9c08d1fa 8627
f7fbdd4a 8628(define_insn "*call_value_symbol"
ccd90aaa 8629 [(set (match_operand 0 "" "")
27ed6835 8630 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8631 (match_operand:SI 2 "" "")))
bbe777ea 8632 (use (match_operand 3 "" ""))
bd5b4116 8633 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8634 "TARGET_ARM
8635 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8636 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8637 "*
8638 {
55c1e470 8639 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8640 }"
cffb2a26 8641 [(set_attr "type" "call")]
8642)
8643
8644(define_insn "*call_insn"
27ed6835 8645 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8646 (match_operand:SI 1 "" ""))
8647 (use (match_operand 2 "" ""))
bd5b4116 8648 (clobber (reg:SI LR_REGNUM))]
1c494086 8649 "TARGET_THUMB
1675c6e9 8650 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8651 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8652 "bl\\t%a0"
8653 [(set_attr "length" "4")
8654 (set_attr "type" "call")]
8655)
8656
8657(define_insn "*call_value_insn"
ccd90aaa 8658 [(set (match_operand 0 "" "")
27ed6835 8659 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8660 (match_operand 2 "" "")))
8661 (use (match_operand 3 "" ""))
bd5b4116 8662 (clobber (reg:SI LR_REGNUM))]
1c494086 8663 "TARGET_THUMB
1675c6e9 8664 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8665 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8666 "bl\\t%a1"
8667 [(set_attr "length" "4")
8668 (set_attr "type" "call")]
8669)
9c08d1fa 8670
1c494086 8671;; We may also be able to do sibcalls for Thumb, but it's much harder...
8672(define_expand "sibcall"
8673 [(parallel [(call (match_operand 0 "memory_operand" "")
8674 (match_operand 1 "general_operand" ""))
2ba80634 8675 (return)
8676 (use (match_operand 2 "" ""))])]
1c494086 8677 "TARGET_ARM"
8678 "
8679 {
8680 if (operands[2] == NULL_RTX)
8681 operands[2] = const0_rtx;
1c494086 8682 }"
8683)
8684
8685(define_expand "sibcall_value"
ccd90aaa 8686 [(parallel [(set (match_operand 0 "" "")
1c494086 8687 (call (match_operand 1 "memory_operand" "")
8688 (match_operand 2 "general_operand" "")))
2ba80634 8689 (return)
8690 (use (match_operand 3 "" ""))])]
1c494086 8691 "TARGET_ARM"
8692 "
8693 {
8694 if (operands[3] == NULL_RTX)
8695 operands[3] = const0_rtx;
1c494086 8696 }"
8697)
8698
8699(define_insn "*sibcall_insn"
8700 [(call (mem:SI (match_operand:SI 0 "" "X"))
8701 (match_operand 1 "" ""))
2ba80634 8702 (return)
8703 (use (match_operand 2 "" ""))]
1c494086 8704 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8705 "*
8706 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8707 "
8708 [(set_attr "type" "call")]
8709)
8710
8711(define_insn "*sibcall_value_insn"
ccd90aaa 8712 [(set (match_operand 0 "" "")
755eb2b4 8713 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8714 (match_operand 2 "" "")))
2ba80634 8715 (return)
8716 (use (match_operand 3 "" ""))]
1c494086 8717 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8718 "*
8719 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8720 "
8721 [(set_attr "type" "call")]
8722)
8723
9c08d1fa 8724;; Often the return insn will be the same as loading from memory, so set attr
8725(define_insn "return"
8726 [(return)]
cffb2a26 8727 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8728 "*
9c08d1fa 8729 {
cffb2a26 8730 if (arm_ccfsm_state == 2)
8731 {
8732 arm_ccfsm_state += 2;
8733 return \"\";
8734 }
5db468b7 8735 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8736 }"
a2cd141b 8737 [(set_attr "type" "load1")
755eb2b4 8738 (set_attr "length" "12")
0d66636f 8739 (set_attr "predicable" "yes")]
cffb2a26 8740)
9c08d1fa 8741
f7fbdd4a 8742(define_insn "*cond_return"
9c08d1fa 8743 [(set (pc)
8fa3ba89 8744 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8745 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8746 (return)
8747 (pc)))]
cffb2a26 8748 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8749 "*
8fa3ba89 8750 {
8751 if (arm_ccfsm_state == 2)
8752 {
8753 arm_ccfsm_state += 2;
8754 return \"\";
8755 }
8756 return output_return_instruction (operands[0], TRUE, FALSE);
8757 }"
8758 [(set_attr "conds" "use")
755eb2b4 8759 (set_attr "length" "12")
a2cd141b 8760 (set_attr "type" "load1")]
8fa3ba89 8761)
9c08d1fa 8762
f7fbdd4a 8763(define_insn "*cond_return_inverted"
9c08d1fa 8764 [(set (pc)
8fa3ba89 8765 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8766 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8767 (pc)
8768 (return)))]
cffb2a26 8769 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8770 "*
8fa3ba89 8771 {
8772 if (arm_ccfsm_state == 2)
8773 {
8774 arm_ccfsm_state += 2;
8775 return \"\";
8776 }
8777 return output_return_instruction (operands[0], TRUE, TRUE);
8778 }"
8779 [(set_attr "conds" "use")
37a1317b 8780 (set_attr "length" "12")
a2cd141b 8781 (set_attr "type" "load1")]
8fa3ba89 8782)
9c08d1fa 8783
68121397 8784;; Generate a sequence of instructions to determine if the processor is
8785;; in 26-bit or 32-bit mode, and return the appropriate return address
8786;; mask.
8787
8788(define_expand "return_addr_mask"
8789 [(set (match_dup 1)
8790 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8791 (const_int 0)))
8792 (set (match_operand:SI 0 "s_register_operand" "")
8793 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8794 (const_int -1)
8795 (const_int 67108860)))] ; 0x03fffffc
8796 "TARGET_ARM"
8797 "
62eddbd4 8798 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8799 ")
8800
8801(define_insn "*check_arch2"
8802 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8803 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8804 (const_int 0)))]
8805 "TARGET_ARM"
8806 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8807 [(set_attr "length" "8")
8808 (set_attr "conds" "set")]
8809)
8810
9c08d1fa 8811;; Call subroutine returning any type.
8812
8813(define_expand "untyped_call"
8814 [(parallel [(call (match_operand 0 "" "")
8815 (const_int 0))
8816 (match_operand 1 "" "")
8817 (match_operand 2 "" "")])]
ccd90aaa 8818 "TARGET_EITHER"
9c08d1fa 8819 "
215b30b3 8820 {
8821 int i;
ccd90aaa 8822 rtx par = gen_rtx_PARALLEL (VOIDmode,
8823 rtvec_alloc (XVECLEN (operands[2], 0)));
8824 rtx addr = gen_reg_rtx (Pmode);
8825 rtx mem;
8826 int size = 0;
9c08d1fa 8827
ccd90aaa 8828 emit_move_insn (addr, XEXP (operands[1], 0));
8829 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8830
215b30b3 8831 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8832 {
ccd90aaa 8833 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8834
ccd90aaa 8835 /* Default code only uses r0 as a return value, but we could
8836 be using anything up to 4 registers. */
8837 if (REGNO (src) == R0_REGNUM)
8838 src = gen_rtx_REG (TImode, R0_REGNUM);
8839
8840 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8841 GEN_INT (size));
8842 size += GET_MODE_SIZE (GET_MODE (src));
8843 }
8844
8845 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8846 const0_rtx));
8847
8848 size = 0;
8849
8850 for (i = 0; i < XVECLEN (par, 0); i++)
8851 {
8852 HOST_WIDE_INT offset = 0;
8853 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8854
8855 if (size != 0)
8856 emit_move_insn (addr, plus_constant (addr, size));
8857
8858 mem = change_address (mem, GET_MODE (reg), NULL);
8859 if (REGNO (reg) == R0_REGNUM)
8860 {
8861 /* On thumb we have to use a write-back instruction. */
8862 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8863 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8864 size = TARGET_ARM ? 16 : 0;
8865 }
8866 else
8867 {
8868 emit_move_insn (mem, reg);
8869 size = GET_MODE_SIZE (GET_MODE (reg));
8870 }
215b30b3 8871 }
9c08d1fa 8872
215b30b3 8873 /* The optimizer does not know that the call sets the function value
8874 registers we stored in the result block. We avoid problems by
8875 claiming that all hard registers are used and clobbered at this
8876 point. */
8877 emit_insn (gen_blockage ());
8878
8879 DONE;
8880 }"
8881)
9c08d1fa 8882
ccd90aaa 8883(define_expand "untyped_return"
8884 [(match_operand:BLK 0 "memory_operand" "")
8885 (match_operand 1 "" "")]
8886 "TARGET_EITHER"
8887 "
8888 {
8889 int i;
8890 rtx addr = gen_reg_rtx (Pmode);
8891 rtx mem;
8892 int size = 0;
8893
8894 emit_move_insn (addr, XEXP (operands[0], 0));
8895 mem = change_address (operands[0], BLKmode, addr);
8896
8897 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8898 {
8899 HOST_WIDE_INT offset = 0;
8900 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8901
8902 if (size != 0)
8903 emit_move_insn (addr, plus_constant (addr, size));
8904
8905 mem = change_address (mem, GET_MODE (reg), NULL);
8906 if (REGNO (reg) == R0_REGNUM)
8907 {
8908 /* On thumb we have to use a write-back instruction. */
8909 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8910 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8911 size = TARGET_ARM ? 16 : 0;
8912 }
8913 else
8914 {
8915 emit_move_insn (reg, mem);
8916 size = GET_MODE_SIZE (GET_MODE (reg));
8917 }
8918 }
8919
8920 /* Emit USE insns before the return. */
8921 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8922 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8923
8924 /* Construct the return. */
8925 expand_naked_return ();
8926
8927 DONE;
8928 }"
8929)
8930
9c08d1fa 8931;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8932;; all of memory. This blocks insns from being moved across this point.
8933
8934(define_insn "blockage"
e1159bbe 8935 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8936 "TARGET_EITHER"
9c08d1fa 8937 ""
cffb2a26 8938 [(set_attr "length" "0")
8939 (set_attr "type" "block")]
8940)
9c08d1fa 8941
f7fbdd4a 8942(define_expand "casesi"
8943 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8944 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8945 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8946 (match_operand:SI 3 "" "") ; table label
8947 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8948 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8949 "
215b30b3 8950 {
e6ac8414 8951 enum insn_code code;
215b30b3 8952 if (operands[1] != const0_rtx)
8953 {
e6ac8414 8954 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8955
215b30b3 8956 emit_insn (gen_addsi3 (reg, operands[0],
8957 GEN_INT (-INTVAL (operands[1]))));
8958 operands[0] = reg;
8959 }
9c08d1fa 8960
25f905c2 8961 if (TARGET_ARM)
e6ac8414 8962 code = CODE_FOR_arm_casesi_internal;
3db2019b 8963 else if (TARGET_THUMB1)
e6ac8414 8964 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8965 else if (flag_pic)
e6ac8414 8966 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8967 else
e6ac8414 8968 code = CODE_FOR_thumb2_casesi_internal;
8969
8970 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8971 operands[2] = force_reg (SImode, operands[2]);
8972
8973 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8974 operands[3], operands[4]));
215b30b3 8975 DONE;
8976 }"
8977)
f7fbdd4a 8978
f082f1c4 8979;; The USE in this pattern is needed to tell flow analysis that this is
8980;; a CASESI insn. It has no other purpose.
25f905c2 8981(define_insn "arm_casesi_internal"
f082f1c4 8982 [(parallel [(set (pc)
8983 (if_then_else
8984 (leu (match_operand:SI 0 "s_register_operand" "r")
8985 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8986 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8987 (label_ref (match_operand 2 "" ""))))
8988 (label_ref (match_operand 3 "" ""))))
bd5b4116 8989 (clobber (reg:CC CC_REGNUM))
f082f1c4 8990 (use (label_ref (match_dup 2)))])]
cffb2a26 8991 "TARGET_ARM"
f7fbdd4a 8992 "*
0d66636f 8993 if (flag_pic)
8994 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8995 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8996 "
8997 [(set_attr "conds" "clob")
8998 (set_attr "length" "12")]
8999)
9c08d1fa 9000
e6ac8414 9001(define_expand "thumb1_casesi_internal_pic"
9002 [(match_operand:SI 0 "s_register_operand" "")
9003 (match_operand:SI 1 "thumb1_cmp_operand" "")
9004 (match_operand 2 "" "")
9005 (match_operand 3 "" "")]
3db2019b 9006 "TARGET_THUMB1"
e6ac8414 9007 {
9008 rtx reg0;
9009 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9010 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9011 operands[3]));
9012 reg0 = gen_rtx_REG (SImode, 0);
9013 emit_move_insn (reg0, operands[0]);
9014 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9015 DONE;
9016 }
9017)
9018
9019(define_insn "thumb1_casesi_dispatch"
9020 [(parallel [(set (pc) (unspec [(reg:SI 0)
9021 (label_ref (match_operand 0 "" ""))
9022;; (label_ref (match_operand 1 "" ""))
9023]
9024 UNSPEC_THUMB1_CASESI))
9025 (clobber (reg:SI IP_REGNUM))
9026 (clobber (reg:SI LR_REGNUM))])]
3db2019b 9027 "TARGET_THUMB1"
e6ac8414 9028 "* return thumb1_output_casesi(operands);"
9029 [(set_attr "length" "4")]
9030)
9031
cffb2a26 9032(define_expand "indirect_jump"
9c08d1fa 9033 [(set (pc)
cffb2a26 9034 (match_operand:SI 0 "s_register_operand" ""))]
9035 "TARGET_EITHER"
25f905c2 9036 "
9037 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
9038 address and use bx. */
9039 if (TARGET_THUMB2)
9040 {
9041 rtx tmp;
9042 tmp = gen_reg_rtx (SImode);
9043 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9044 operands[0] = tmp;
9045 }
9046 "
cffb2a26 9047)
9048
f1039640 9049;; NB Never uses BX.
cffb2a26 9050(define_insn "*arm_indirect_jump"
9051 [(set (pc)
9052 (match_operand:SI 0 "s_register_operand" "r"))]
9053 "TARGET_ARM"
9054 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 9055 [(set_attr "predicable" "yes")]
cffb2a26 9056)
9c08d1fa 9057
f7fbdd4a 9058(define_insn "*load_indirect_jump"
9c08d1fa 9059 [(set (pc)
9060 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 9061 "TARGET_ARM"
9062 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 9063 [(set_attr "type" "load1")
61a2d04c 9064 (set_attr "pool_range" "4096")
9065 (set_attr "neg_pool_range" "4084")
0d66636f 9066 (set_attr "predicable" "yes")]
cffb2a26 9067)
9068
f1039640 9069;; NB Never uses BX.
25f905c2 9070(define_insn "*thumb1_indirect_jump"
cffb2a26 9071 [(set (pc)
9072 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 9073 "TARGET_THUMB1"
cffb2a26 9074 "mov\\tpc, %0"
9075 [(set_attr "conds" "clob")
9076 (set_attr "length" "2")]
9077)
9078
9c08d1fa 9079\f
9080;; Misc insns
9081
9082(define_insn "nop"
9083 [(const_int 0)]
cffb2a26 9084 "TARGET_EITHER"
9085 "*
25f905c2 9086 if (TARGET_UNIFIED_ASM)
9087 return \"nop\";
cffb2a26 9088 if (TARGET_ARM)
9089 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9090 return \"mov\\tr8, r8\";
9091 "
9092 [(set (attr "length")
9093 (if_then_else (eq_attr "is_thumb" "yes")
9094 (const_int 2)
9095 (const_int 4)))]
9096)
9097
9c08d1fa 9098\f
9099;; Patterns to allow combination of arithmetic, cond code and shifts
9100
f7fbdd4a 9101(define_insn "*arith_shiftsi"
9c08d1fa 9102 [(set (match_operand:SI 0 "s_register_operand" "=r")
9103 (match_operator:SI 1 "shiftable_operator"
9104 [(match_operator:SI 3 "shift_operator"
9105 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9106 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9107 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 9108 "TARGET_ARM"
6c4c2133 9109 "%i1%?\\t%0, %2, %4%S3"
344495ea 9110 [(set_attr "predicable" "yes")
331beb1a 9111 (set_attr "shift" "4")
a2cd141b 9112 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9113 (const_string "alu_shift")
9114 (const_string "alu_shift_reg")))]
6c4c2133 9115)
9c08d1fa 9116
d7863cfe 9117(define_split
9118 [(set (match_operand:SI 0 "s_register_operand" "")
9119 (match_operator:SI 1 "shiftable_operator"
9120 [(match_operator:SI 2 "shiftable_operator"
9121 [(match_operator:SI 3 "shift_operator"
9122 [(match_operand:SI 4 "s_register_operand" "")
9123 (match_operand:SI 5 "reg_or_int_operand" "")])
9124 (match_operand:SI 6 "s_register_operand" "")])
9125 (match_operand:SI 7 "arm_rhs_operand" "")]))
9126 (clobber (match_operand:SI 8 "s_register_operand" ""))]
9127 "TARGET_ARM"
9128 [(set (match_dup 8)
9129 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9130 (match_dup 6)]))
9131 (set (match_dup 0)
9132 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9133 "")
9134
f7fbdd4a 9135(define_insn "*arith_shiftsi_compare0"
bd5b4116 9136 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 9137 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9138 [(match_operator:SI 3 "shift_operator"
9139 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9140 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9141 (match_operand:SI 2 "s_register_operand" "r")])
9142 (const_int 0)))
9143 (set (match_operand:SI 0 "s_register_operand" "=r")
9144 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9145 (match_dup 2)]))]
cffb2a26 9146 "TARGET_ARM"
25f905c2 9147 "%i1%.\\t%0, %2, %4%S3"
344495ea 9148 [(set_attr "conds" "set")
331beb1a 9149 (set_attr "shift" "4")
a2cd141b 9150 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9151 (const_string "alu_shift")
9152 (const_string "alu_shift_reg")))]
0d66636f 9153)
9c08d1fa 9154
f7fbdd4a 9155(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9156 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 9157 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9158 [(match_operator:SI 3 "shift_operator"
9159 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 9160 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 9161 (match_operand:SI 2 "s_register_operand" "r")])
9162 (const_int 0)))
9163 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 9164 "TARGET_ARM"
25f905c2 9165 "%i1%.\\t%0, %2, %4%S3"
344495ea 9166 [(set_attr "conds" "set")
331beb1a 9167 (set_attr "shift" "4")
a2cd141b 9168 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9169 (const_string "alu_shift")
9170 (const_string "alu_shift_reg")))]
0d66636f 9171)
9c08d1fa 9172
f7fbdd4a 9173(define_insn "*sub_shiftsi"
9c08d1fa 9174 [(set (match_operand:SI 0 "s_register_operand" "=r")
9175 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9176 (match_operator:SI 2 "shift_operator"
9177 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9178 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 9179 "TARGET_ARM"
6c4c2133 9180 "sub%?\\t%0, %1, %3%S2"
344495ea 9181 [(set_attr "predicable" "yes")
331beb1a 9182 (set_attr "shift" "3")
a2cd141b 9183 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9184 (const_string "alu_shift")
9185 (const_string "alu_shift_reg")))]
6c4c2133 9186)
9c08d1fa 9187
f7fbdd4a 9188(define_insn "*sub_shiftsi_compare0"
bd5b4116 9189 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9190 (compare:CC_NOOV
9191 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9192 (match_operator:SI 2 "shift_operator"
9193 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9194 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 9195 (const_int 0)))
9c08d1fa 9196 (set (match_operand:SI 0 "s_register_operand" "=r")
9197 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9198 (match_dup 4)])))]
cffb2a26 9199 "TARGET_ARM"
25f905c2 9200 "sub%.\\t%0, %1, %3%S2"
344495ea 9201 [(set_attr "conds" "set")
a2cd141b 9202 (set_attr "shift" "3")
9203 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9204 (const_string "alu_shift")
9205 (const_string "alu_shift_reg")))]
0d66636f 9206)
9c08d1fa 9207
f7fbdd4a 9208(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9209 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9210 (compare:CC_NOOV
9211 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9212 (match_operator:SI 2 "shift_operator"
9213 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 9214 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 9215 (const_int 0)))
9c08d1fa 9216 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 9217 "TARGET_ARM"
25f905c2 9218 "sub%.\\t%0, %1, %3%S2"
344495ea 9219 [(set_attr "conds" "set")
a2cd141b 9220 (set_attr "shift" "3")
9221 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9222 (const_string "alu_shift")
9223 (const_string "alu_shift_reg")))]
0d66636f 9224)
9c08d1fa 9225
9c08d1fa 9226\f
9227
f7fbdd4a 9228(define_insn "*and_scc"
9c08d1fa 9229 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9230 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9231 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9232 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9233 "TARGET_ARM"
e2348bcb 9234 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9235 [(set_attr "conds" "use")
9236 (set_attr "length" "8")]
9237)
9c08d1fa 9238
f7fbdd4a 9239(define_insn "*ior_scc"
9c08d1fa 9240 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9241 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9242 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9243 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9244 "TARGET_ARM"
e2348bcb 9245 "@
899850b0 9246 orr%d2\\t%0, %1, #1
9247 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9248 [(set_attr "conds" "use")
9249 (set_attr "length" "4,8")]
9250)
9c08d1fa 9251
f7fbdd4a 9252(define_insn "*compare_scc"
5565501b 9253 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9254 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9255 [(match_operand:SI 2 "s_register_operand" "r,r")
9256 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9257 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9258 "TARGET_ARM"
9c08d1fa 9259 "*
601f584c 9260 if (operands[3] == const0_rtx)
9261 {
9262 if (GET_CODE (operands[1]) == LT)
9263 return \"mov\\t%0, %2, lsr #31\";
9264
9265 if (GET_CODE (operands[1]) == GE)
9266 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 9267
601f584c 9268 if (GET_CODE (operands[1]) == EQ)
9269 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9270 }
e2348bcb 9271
8fa3ba89 9272 if (GET_CODE (operands[1]) == NE)
9273 {
9274 if (which_alternative == 1)
9275 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9276 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9277 }
9278 if (which_alternative == 1)
9279 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9280 else
9281 output_asm_insn (\"cmp\\t%2, %3\", operands);
9282 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9283 "
9284 [(set_attr "conds" "clob")
9285 (set_attr "length" "12")]
9286)
9c08d1fa 9287
f7fbdd4a 9288(define_insn "*cond_move"
9c08d1fa 9289 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9290 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9291 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9292 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9293 (const_int 0)])
9294 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9295 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9296 "TARGET_ARM"
9c08d1fa 9297 "*
8fa3ba89 9298 if (GET_CODE (operands[3]) == NE)
9299 {
9300 if (which_alternative != 1)
9301 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9302 if (which_alternative != 0)
9303 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9304 return \"\";
9305 }
9306 if (which_alternative != 0)
9307 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9308 if (which_alternative != 1)
9309 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9310 return \"\";
9311 "
9312 [(set_attr "conds" "use")
9313 (set_attr "length" "4,4,8")]
9314)
9c08d1fa 9315
f7fbdd4a 9316(define_insn "*cond_arith"
9c08d1fa 9317 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9318 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9319 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9320 [(match_operand:SI 2 "s_register_operand" "r,r")
9321 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9322 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9323 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9324 "TARGET_ARM"
9c08d1fa 9325 "*
8fa3ba89 9326 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9327 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9328
8fa3ba89 9329 output_asm_insn (\"cmp\\t%2, %3\", operands);
9330 if (GET_CODE (operands[5]) == AND)
9331 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9332 else if (GET_CODE (operands[5]) == MINUS)
9333 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9334 else if (which_alternative != 0)
9335 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9336 return \"%i5%d4\\t%0, %1, #1\";
9337 "
9338 [(set_attr "conds" "clob")
9339 (set_attr "length" "12")]
9340)
9c08d1fa 9341
f7fbdd4a 9342(define_insn "*cond_sub"
9c08d1fa 9343 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9344 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9345 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9346 [(match_operand:SI 2 "s_register_operand" "r,r")
9347 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9348 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9349 "TARGET_ARM"
9c08d1fa 9350 "*
8fa3ba89 9351 output_asm_insn (\"cmp\\t%2, %3\", operands);
9352 if (which_alternative != 0)
9353 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9354 return \"sub%d4\\t%0, %1, #1\";
9355 "
9356 [(set_attr "conds" "clob")
9357 (set_attr "length" "8,12")]
9358)
9c08d1fa 9359
25f905c2 9360;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 9361(define_insn "*cmp_ite0"
cffb2a26 9362 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9363 (compare
9364 (if_then_else:SI
8fa3ba89 9365 (match_operator 4 "arm_comparison_operator"
aea4c774 9366 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9367 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9368 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9369 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9370 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9371 (const_int 0))
9372 (const_int 0)))]
cffb2a26 9373 "TARGET_ARM"
9c08d1fa 9374 "*
aea4c774 9375 {
8fa3ba89 9376 static const char * const opcodes[4][2] =
9377 {
9378 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9379 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9380 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9381 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9382 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9383 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9384 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9385 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9386 };
9387 int swap =
9388 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9389
9390 return opcodes[which_alternative][swap];
9391 }"
9392 [(set_attr "conds" "set")
9393 (set_attr "length" "8")]
9394)
9c08d1fa 9395
aea4c774 9396(define_insn "*cmp_ite1"
cffb2a26 9397 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9398 (compare
9399 (if_then_else:SI
8fa3ba89 9400 (match_operator 4 "arm_comparison_operator"
aea4c774 9401 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 9402 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9403 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9404 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 9405 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 9406 (const_int 1))
9407 (const_int 0)))]
cffb2a26 9408 "TARGET_ARM"
9c08d1fa 9409 "*
9c08d1fa 9410 {
215b30b3 9411 static const char * const opcodes[4][2] =
9412 {
9413 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9414 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9415 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9416 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9417 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9418 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9419 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9420 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9421 };
9422 int swap =
9423 comparison_dominates_p (GET_CODE (operands[5]),
9424 reverse_condition (GET_CODE (operands[4])));
9425
9426 return opcodes[which_alternative][swap];
9427 }"
8fa3ba89 9428 [(set_attr "conds" "set")
9429 (set_attr "length" "8")]
9430)
9c08d1fa 9431
f6c53574 9432(define_insn "*cmp_and"
9433 [(set (match_operand 6 "dominant_cc_register" "")
9434 (compare
9435 (and:SI
9436 (match_operator 4 "arm_comparison_operator"
9437 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9438 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9439 (match_operator:SI 5 "arm_comparison_operator"
9440 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9441 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9442 (const_int 0)))]
9443 "TARGET_ARM"
9444 "*
9445 {
35823b64 9446 static const char *const opcodes[4][2] =
f6c53574 9447 {
9448 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9449 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9450 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9451 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9452 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9453 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9454 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9455 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9456 };
9457 int swap =
9458 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9459
9460 return opcodes[which_alternative][swap];
9461 }"
9462 [(set_attr "conds" "set")
9463 (set_attr "predicable" "no")
9464 (set_attr "length" "8")]
9465)
9466
9467(define_insn "*cmp_ior"
9468 [(set (match_operand 6 "dominant_cc_register" "")
9469 (compare
9470 (ior:SI
9471 (match_operator 4 "arm_comparison_operator"
9472 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9473 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9474 (match_operator:SI 5 "arm_comparison_operator"
9475 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9476 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9477 (const_int 0)))]
9478 "TARGET_ARM"
9479 "*
9480{
35823b64 9481 static const char *const opcodes[4][2] =
f6c53574 9482 {
9483 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9484 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9485 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9486 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9487 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9488 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9489 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9490 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9491 };
9492 int swap =
9493 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9494
9495 return opcodes[which_alternative][swap];
9496}
9497"
9498 [(set_attr "conds" "set")
9499 (set_attr "length" "8")]
9500)
9501
3c5afce6 9502(define_insn_and_split "*ior_scc_scc"
9503 [(set (match_operand:SI 0 "s_register_operand" "=r")
9504 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9505 [(match_operand:SI 1 "s_register_operand" "r")
9506 (match_operand:SI 2 "arm_add_operand" "rIL")])
9507 (match_operator:SI 6 "arm_comparison_operator"
9508 [(match_operand:SI 4 "s_register_operand" "r")
9509 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9510 (clobber (reg:CC CC_REGNUM))]
9511 "TARGET_ARM
9512 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9513 != CCmode)"
9514 "#"
9515 "TARGET_ARM && reload_completed"
9516 [(set (match_dup 7)
9517 (compare
9518 (ior:SI
9519 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9520 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9521 (const_int 0)))
9522 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9523 "operands[7]
9524 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9525 DOM_CC_X_OR_Y),
601f584c 9526 CC_REGNUM);"
9527 [(set_attr "conds" "clob")
9528 (set_attr "length" "16")])
9529
9530; If the above pattern is followed by a CMP insn, then the compare is
9531; redundant, since we can rework the conditional instruction that follows.
9532(define_insn_and_split "*ior_scc_scc_cmp"
9533 [(set (match_operand 0 "dominant_cc_register" "")
9534 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9535 [(match_operand:SI 1 "s_register_operand" "r")
9536 (match_operand:SI 2 "arm_add_operand" "rIL")])
9537 (match_operator:SI 6 "arm_comparison_operator"
9538 [(match_operand:SI 4 "s_register_operand" "r")
9539 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9540 (const_int 0)))
9541 (set (match_operand:SI 7 "s_register_operand" "=r")
9542 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9543 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9544 "TARGET_ARM"
9545 "#"
9546 "TARGET_ARM && reload_completed"
9547 [(set (match_dup 0)
9548 (compare
9549 (ior:SI
9550 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9551 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9552 (const_int 0)))
9553 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9554 ""
9555 [(set_attr "conds" "set")
9556 (set_attr "length" "16")])
3c5afce6 9557
9558(define_insn_and_split "*and_scc_scc"
9559 [(set (match_operand:SI 0 "s_register_operand" "=r")
9560 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9561 [(match_operand:SI 1 "s_register_operand" "r")
9562 (match_operand:SI 2 "arm_add_operand" "rIL")])
9563 (match_operator:SI 6 "arm_comparison_operator"
9564 [(match_operand:SI 4 "s_register_operand" "r")
9565 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9566 (clobber (reg:CC CC_REGNUM))]
9567 "TARGET_ARM
9568 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9569 != CCmode)"
9570 "#"
601f584c 9571 "TARGET_ARM && reload_completed
9572 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9573 != CCmode)"
3c5afce6 9574 [(set (match_dup 7)
9575 (compare
9576 (and:SI
9577 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9578 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9579 (const_int 0)))
9580 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9581 "operands[7]
9582 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9583 DOM_CC_X_AND_Y),
601f584c 9584 CC_REGNUM);"
9585 [(set_attr "conds" "clob")
9586 (set_attr "length" "16")])
9587
9588; If the above pattern is followed by a CMP insn, then the compare is
9589; redundant, since we can rework the conditional instruction that follows.
9590(define_insn_and_split "*and_scc_scc_cmp"
9591 [(set (match_operand 0 "dominant_cc_register" "")
9592 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9593 [(match_operand:SI 1 "s_register_operand" "r")
9594 (match_operand:SI 2 "arm_add_operand" "rIL")])
9595 (match_operator:SI 6 "arm_comparison_operator"
9596 [(match_operand:SI 4 "s_register_operand" "r")
9597 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9598 (const_int 0)))
9599 (set (match_operand:SI 7 "s_register_operand" "=r")
9600 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9601 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9602 "TARGET_ARM"
9603 "#"
9604 "TARGET_ARM && reload_completed"
9605 [(set (match_dup 0)
9606 (compare
9607 (and:SI
9608 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9609 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9610 (const_int 0)))
9611 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9612 ""
9613 [(set_attr "conds" "set")
9614 (set_attr "length" "16")])
9615
9616;; If there is no dominance in the comparison, then we can still save an
9617;; instruction in the AND case, since we can know that the second compare
9618;; need only zero the value if false (if true, then the value is already
9619;; correct).
9620(define_insn_and_split "*and_scc_scc_nodom"
9621 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9622 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9623 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9624 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9625 (match_operator:SI 6 "arm_comparison_operator"
9626 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9627 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9628 (clobber (reg:CC CC_REGNUM))]
9629 "TARGET_ARM
9630 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9631 == CCmode)"
9632 "#"
9633 "TARGET_ARM && reload_completed"
9634 [(parallel [(set (match_dup 0)
9635 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9636 (clobber (reg:CC CC_REGNUM))])
9637 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9638 (set (match_dup 0)
9639 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9640 (match_dup 0)
9641 (const_int 0)))]
9642 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9643 operands[4], operands[5]),
9644 CC_REGNUM);
9645 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9646 operands[5]);"
9647 [(set_attr "conds" "clob")
9648 (set_attr "length" "20")])
3c5afce6 9649
3a0bdee0 9650(define_split
9651 [(set (reg:CC_NOOV CC_REGNUM)
9652 (compare:CC_NOOV (ior:SI
9653 (and:SI (match_operand:SI 0 "s_register_operand" "")
9654 (const_int 1))
b0694be0 9655 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9656 [(match_operand:SI 2 "s_register_operand" "")
9657 (match_operand:SI 3 "arm_add_operand" "")]))
9658 (const_int 0)))
9659 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9660 "TARGET_ARM"
9661 [(set (match_dup 4)
9662 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9663 (match_dup 0)))
9664 (set (reg:CC_NOOV CC_REGNUM)
9665 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9666 (const_int 0)))]
9667 "")
9668
9669(define_split
9670 [(set (reg:CC_NOOV CC_REGNUM)
9671 (compare:CC_NOOV (ior:SI
b0694be0 9672 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9673 [(match_operand:SI 2 "s_register_operand" "")
9674 (match_operand:SI 3 "arm_add_operand" "")])
9675 (and:SI (match_operand:SI 0 "s_register_operand" "")
9676 (const_int 1)))
9677 (const_int 0)))
9678 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9679 "TARGET_ARM"
9680 [(set (match_dup 4)
9681 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9682 (match_dup 0)))
9683 (set (reg:CC_NOOV CC_REGNUM)
9684 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9685 (const_int 0)))]
9686 "")
25f905c2 9687;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9688
f7fbdd4a 9689(define_insn "*negscc"
9c08d1fa 9690 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9691 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9692 [(match_operand:SI 1 "s_register_operand" "r")
9693 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9694 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9695 "TARGET_ARM"
9c08d1fa 9696 "*
2ca2ec2e 9697 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9698 return \"mov\\t%0, %1, asr #31\";
9699
9c08d1fa 9700 if (GET_CODE (operands[3]) == NE)
e2348bcb 9701 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9702
e2348bcb 9703 output_asm_insn (\"cmp\\t%1, %2\", operands);
9704 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9705 return \"mvn%d3\\t%0, #0\";
215b30b3 9706 "
8fa3ba89 9707 [(set_attr "conds" "clob")
9708 (set_attr "length" "12")]
9709)
9c08d1fa 9710
9711(define_insn "movcond"
9712 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9713 (if_then_else:SI
8fa3ba89 9714 (match_operator 5 "arm_comparison_operator"
5565501b 9715 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9716 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9717 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9718 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9719 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9720 "TARGET_ARM"
9c08d1fa 9721 "*
9722 if (GET_CODE (operands[5]) == LT
9723 && (operands[4] == const0_rtx))
9724 {
5565501b 9725 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9726 {
9c08d1fa 9727 if (operands[2] == const0_rtx)
e2348bcb 9728 return \"and\\t%0, %1, %3, asr #31\";
9729 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9730 }
9731 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9732 {
9c08d1fa 9733 if (operands[1] == const0_rtx)
e2348bcb 9734 return \"bic\\t%0, %2, %3, asr #31\";
9735 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9736 }
9737 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9738 are constants. */
9c08d1fa 9739 }
e2348bcb 9740
9c08d1fa 9741 if (GET_CODE (operands[5]) == GE
9742 && (operands[4] == const0_rtx))
9743 {
9744 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9745 {
9c08d1fa 9746 if (operands[2] == const0_rtx)
e2348bcb 9747 return \"bic\\t%0, %1, %3, asr #31\";
9748 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9749 }
9750 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9751 {
9c08d1fa 9752 if (operands[1] == const0_rtx)
e2348bcb 9753 return \"and\\t%0, %2, %3, asr #31\";
9754 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9755 }
9756 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9757 are constants. */
9c08d1fa 9758 }
9759 if (GET_CODE (operands[4]) == CONST_INT
9760 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9761 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9762 else
e2348bcb 9763 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9764 if (which_alternative != 0)
e2348bcb 9765 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9766 if (which_alternative != 1)
e2348bcb 9767 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9768 return \"\";
215b30b3 9769 "
8fa3ba89 9770 [(set_attr "conds" "clob")
9771 (set_attr "length" "8,8,12")]
9772)
9c08d1fa 9773
25f905c2 9774;; ??? The patterns below need checking for Thumb-2 usefulness.
9775
8a18b90c 9776(define_insn "*ifcompare_plus_move"
9777 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9778 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9779 [(match_operand:SI 4 "s_register_operand" "r,r")
9780 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9781 (plus:SI
9782 (match_operand:SI 2 "s_register_operand" "r,r")
9783 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9784 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9785 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9786 "TARGET_ARM"
8a18b90c 9787 "#"
8fa3ba89 9788 [(set_attr "conds" "clob")
9789 (set_attr "length" "8,12")]
9790)
8a18b90c 9791
9792(define_insn "*if_plus_move"
129a2fe4 9793 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9794 (if_then_else:SI
8fa3ba89 9795 (match_operator 4 "arm_comparison_operator"
8a18b90c 9796 [(match_operand 5 "cc_register" "") (const_int 0)])
9797 (plus:SI
129a2fe4 9798 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9799 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9800 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9801 "TARGET_ARM"
8a18b90c 9802 "@
9803 add%d4\\t%0, %2, %3
9804 sub%d4\\t%0, %2, #%n3
9805 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9806 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9807 [(set_attr "conds" "use")
9808 (set_attr "length" "4,4,8,8")
9809 (set_attr "type" "*,*,*,*")]
9810)
8a18b90c 9811
9812(define_insn "*ifcompare_move_plus"
5565501b 9813 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9814 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9815 [(match_operand:SI 4 "s_register_operand" "r,r")
9816 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9817 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9818 (plus:SI
9819 (match_operand:SI 2 "s_register_operand" "r,r")
9820 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9821 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9822 "TARGET_ARM"
8a18b90c 9823 "#"
8fa3ba89 9824 [(set_attr "conds" "clob")
9825 (set_attr "length" "8,12")]
9826)
8a18b90c 9827
9828(define_insn "*if_move_plus"
129a2fe4 9829 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9830 (if_then_else:SI
8fa3ba89 9831 (match_operator 4 "arm_comparison_operator"
8a18b90c 9832 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9833 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9834 (plus:SI
129a2fe4 9835 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9836 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9837 "TARGET_ARM"
8a18b90c 9838 "@
9839 add%D4\\t%0, %2, %3
9840 sub%D4\\t%0, %2, #%n3
9841 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9842 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9843 [(set_attr "conds" "use")
9844 (set_attr "length" "4,4,8,8")
9845 (set_attr "type" "*,*,*,*")]
9846)
8a18b90c 9847
9848(define_insn "*ifcompare_arith_arith"
9849 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9850 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9851 [(match_operand:SI 5 "s_register_operand" "r")
9852 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9853 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9854 [(match_operand:SI 1 "s_register_operand" "r")
9855 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9856 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9857 [(match_operand:SI 3 "s_register_operand" "r")
9858 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9859 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9860 "TARGET_ARM"
8a18b90c 9861 "#"
8fa3ba89 9862 [(set_attr "conds" "clob")
9863 (set_attr "length" "12")]
9864)
9c08d1fa 9865
8a18b90c 9866(define_insn "*if_arith_arith"
9867 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9868 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9869 [(match_operand 8 "cc_register" "") (const_int 0)])
9870 (match_operator:SI 6 "shiftable_operator"
9871 [(match_operand:SI 1 "s_register_operand" "r")
9872 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9873 (match_operator:SI 7 "shiftable_operator"
9874 [(match_operand:SI 3 "s_register_operand" "r")
9875 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9876 "TARGET_ARM"
8a18b90c 9877 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9878 [(set_attr "conds" "use")
9879 (set_attr "length" "8")]
9880)
8a18b90c 9881
f7fbdd4a 9882(define_insn "*ifcompare_arith_move"
9c08d1fa 9883 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9884 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9885 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9886 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9887 (match_operator:SI 7 "shiftable_operator"
9888 [(match_operand:SI 4 "s_register_operand" "r,r")
9889 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9890 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9891 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9892 "TARGET_ARM"
9c08d1fa 9893 "*
9c08d1fa 9894 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9895 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9896 everything is in registers then we can do this in two instructions. */
9c08d1fa 9897 if (operands[3] == const0_rtx
9898 && GET_CODE (operands[7]) != AND
9899 && GET_CODE (operands[5]) == REG
9900 && GET_CODE (operands[1]) == REG
9901 && REGNO (operands[1]) == REGNO (operands[4])
9902 && REGNO (operands[4]) != REGNO (operands[0]))
9903 {
9904 if (GET_CODE (operands[6]) == LT)
40dbec34 9905 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9906 else if (GET_CODE (operands[6]) == GE)
40dbec34 9907 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9908 }
9909 if (GET_CODE (operands[3]) == CONST_INT
9910 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9911 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9912 else
e2348bcb 9913 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9914 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9915 if (which_alternative != 0)
129a2fe4 9916 return \"mov%D6\\t%0, %1\";
9c08d1fa 9917 return \"\";
215b30b3 9918 "
8fa3ba89 9919 [(set_attr "conds" "clob")
9920 (set_attr "length" "8,12")]
9921)
9c08d1fa 9922
8a18b90c 9923(define_insn "*if_arith_move"
129a2fe4 9924 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9925 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9926 [(match_operand 6 "cc_register" "") (const_int 0)])
9927 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9928 [(match_operand:SI 2 "s_register_operand" "r,r")
9929 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9930 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9931 "TARGET_ARM"
8a18b90c 9932 "@
9933 %I5%d4\\t%0, %2, %3
129a2fe4 9934 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9935 [(set_attr "conds" "use")
9936 (set_attr "length" "4,8")
9937 (set_attr "type" "*,*")]
9938)
8a18b90c 9939
f7fbdd4a 9940(define_insn "*ifcompare_move_arith"
9c08d1fa 9941 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9942 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9943 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9944 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9945 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9946 (match_operator:SI 7 "shiftable_operator"
9947 [(match_operand:SI 2 "s_register_operand" "r,r")
9948 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9949 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9950 "TARGET_ARM"
9c08d1fa 9951 "*
9c08d1fa 9952 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9953 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9954 everything is in registers then we can do this in two instructions */
9955 if (operands[5] == const0_rtx
9956 && GET_CODE (operands[7]) != AND
9957 && GET_CODE (operands[3]) == REG
9958 && GET_CODE (operands[1]) == REG
9959 && REGNO (operands[1]) == REGNO (operands[2])
9960 && REGNO (operands[2]) != REGNO (operands[0]))
9961 {
9962 if (GET_CODE (operands[6]) == GE)
40dbec34 9963 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9964 else if (GET_CODE (operands[6]) == LT)
40dbec34 9965 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9966 }
40dbec34 9967
9c08d1fa 9968 if (GET_CODE (operands[5]) == CONST_INT
9969 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9970 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9971 else
e2348bcb 9972 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9973
9c08d1fa 9974 if (which_alternative != 0)
129a2fe4 9975 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9976 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9977 "
8fa3ba89 9978 [(set_attr "conds" "clob")
9979 (set_attr "length" "8,12")]
9980)
9c08d1fa 9981
8a18b90c 9982(define_insn "*if_move_arith"
129a2fe4 9983 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9984 (if_then_else:SI
8fa3ba89 9985 (match_operator 4 "arm_comparison_operator"
8a18b90c 9986 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9987 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9988 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9989 [(match_operand:SI 2 "s_register_operand" "r,r")
9990 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9991 "TARGET_ARM"
8a18b90c 9992 "@
9993 %I5%D4\\t%0, %2, %3
129a2fe4 9994 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9995 [(set_attr "conds" "use")
9996 (set_attr "length" "4,8")
9997 (set_attr "type" "*,*")]
9998)
8a18b90c 9999
10000(define_insn "*ifcompare_move_not"
9c08d1fa 10001 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10002 (if_then_else:SI
8fa3ba89 10003 (match_operator 5 "arm_comparison_operator"
8a18b90c 10004 [(match_operand:SI 3 "s_register_operand" "r,r")
10005 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10006 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10007 (not:SI
10008 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10009 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10010 "TARGET_ARM"
8a18b90c 10011 "#"
8fa3ba89 10012 [(set_attr "conds" "clob")
10013 (set_attr "length" "8,12")]
10014)
9c08d1fa 10015
8a18b90c 10016(define_insn "*if_move_not"
10017 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10018 (if_then_else:SI
8fa3ba89 10019 (match_operator 4 "arm_comparison_operator"
8a18b90c 10020 [(match_operand 3 "cc_register" "") (const_int 0)])
10021 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10022 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10023 "TARGET_ARM"
8a18b90c 10024 "@
10025 mvn%D4\\t%0, %2
10026 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10027 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10028 [(set_attr "conds" "use")
10029 (set_attr "length" "4,8,8")]
10030)
8a18b90c 10031
10032(define_insn "*ifcompare_not_move"
9c08d1fa 10033 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10034 (if_then_else:SI
8fa3ba89 10035 (match_operator 5 "arm_comparison_operator"
8a18b90c 10036 [(match_operand:SI 3 "s_register_operand" "r,r")
10037 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10038 (not:SI
10039 (match_operand:SI 2 "s_register_operand" "r,r"))
10040 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10041 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10042 "TARGET_ARM"
8a18b90c 10043 "#"
8fa3ba89 10044 [(set_attr "conds" "clob")
10045 (set_attr "length" "8,12")]
10046)
9c08d1fa 10047
8a18b90c 10048(define_insn "*if_not_move"
10049 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10050 (if_then_else:SI
8fa3ba89 10051 (match_operator 4 "arm_comparison_operator"
8a18b90c 10052 [(match_operand 3 "cc_register" "") (const_int 0)])
10053 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10054 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10055 "TARGET_ARM"
8a18b90c 10056 "@
10057 mvn%d4\\t%0, %2
10058 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10059 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10060 [(set_attr "conds" "use")
10061 (set_attr "length" "4,8,8")]
10062)
8a18b90c 10063
10064(define_insn "*ifcompare_shift_move"
9c08d1fa 10065 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10066 (if_then_else:SI
8fa3ba89 10067 (match_operator 6 "arm_comparison_operator"
8a18b90c 10068 [(match_operand:SI 4 "s_register_operand" "r,r")
10069 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10070 (match_operator:SI 7 "shift_operator"
10071 [(match_operand:SI 2 "s_register_operand" "r,r")
10072 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10073 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10074 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10075 "TARGET_ARM"
9c08d1fa 10076 "#"
8fa3ba89 10077 [(set_attr "conds" "clob")
10078 (set_attr "length" "8,12")]
10079)
9c08d1fa 10080
8a18b90c 10081(define_insn "*if_shift_move"
10082 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10083 (if_then_else:SI
8fa3ba89 10084 (match_operator 5 "arm_comparison_operator"
8a18b90c 10085 [(match_operand 6 "cc_register" "") (const_int 0)])
10086 (match_operator:SI 4 "shift_operator"
10087 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10088 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10089 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10090 "TARGET_ARM"
5565501b 10091 "@
8a18b90c 10092 mov%d5\\t%0, %2%S4
10093 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10094 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10095 [(set_attr "conds" "use")
331beb1a 10096 (set_attr "shift" "2")
a2cd141b 10097 (set_attr "length" "4,8,8")
10098 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10099 (const_string "alu_shift")
10100 (const_string "alu_shift_reg")))]
8fa3ba89 10101)
5565501b 10102
8a18b90c 10103(define_insn "*ifcompare_move_shift"
10104 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10105 (if_then_else:SI
8fa3ba89 10106 (match_operator 6 "arm_comparison_operator"
8a18b90c 10107 [(match_operand:SI 4 "s_register_operand" "r,r")
10108 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10109 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10110 (match_operator:SI 7 "shift_operator"
8a18b90c 10111 [(match_operand:SI 2 "s_register_operand" "r,r")
10112 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10113 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10114 "TARGET_ARM"
8a18b90c 10115 "#"
8fa3ba89 10116 [(set_attr "conds" "clob")
10117 (set_attr "length" "8,12")]
10118)
5565501b 10119
8a18b90c 10120(define_insn "*if_move_shift"
10121 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10122 (if_then_else:SI
8fa3ba89 10123 (match_operator 5 "arm_comparison_operator"
8a18b90c 10124 [(match_operand 6 "cc_register" "") (const_int 0)])
10125 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
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")])))]
cffb2a26 10129 "TARGET_ARM"
5565501b 10130 "@
8a18b90c 10131 mov%D5\\t%0, %2%S4
10132 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10133 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10134 [(set_attr "conds" "use")
331beb1a 10135 (set_attr "shift" "2")
a2cd141b 10136 (set_attr "length" "4,8,8")
10137 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10138 (const_string "alu_shift")
10139 (const_string "alu_shift_reg")))]
8fa3ba89 10140)
9c08d1fa 10141
f7fbdd4a 10142(define_insn "*ifcompare_shift_shift"
8a18b90c 10143 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10144 (if_then_else:SI
8fa3ba89 10145 (match_operator 7 "arm_comparison_operator"
8a18b90c 10146 [(match_operand:SI 5 "s_register_operand" "r")
10147 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10148 (match_operator:SI 8 "shift_operator"
8a18b90c 10149 [(match_operand:SI 1 "s_register_operand" "r")
10150 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10151 (match_operator:SI 9 "shift_operator"
8a18b90c 10152 [(match_operand:SI 3 "s_register_operand" "r")
10153 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10154 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10155 "TARGET_ARM"
8a18b90c 10156 "#"
8fa3ba89 10157 [(set_attr "conds" "clob")
10158 (set_attr "length" "12")]
10159)
9c08d1fa 10160
8a18b90c 10161(define_insn "*if_shift_shift"
10162 [(set (match_operand:SI 0 "s_register_operand" "=r")
10163 (if_then_else:SI
8fa3ba89 10164 (match_operator 5 "arm_comparison_operator"
8a18b90c 10165 [(match_operand 8 "cc_register" "") (const_int 0)])
10166 (match_operator:SI 6 "shift_operator"
10167 [(match_operand:SI 1 "s_register_operand" "r")
10168 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10169 (match_operator:SI 7 "shift_operator"
10170 [(match_operand:SI 3 "s_register_operand" "r")
10171 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10172 "TARGET_ARM"
8a18b90c 10173 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10174 [(set_attr "conds" "use")
331beb1a 10175 (set_attr "shift" "1")
a2cd141b 10176 (set_attr "length" "8")
10177 (set (attr "type") (if_then_else
10178 (and (match_operand 2 "const_int_operand" "")
10179 (match_operand 4 "const_int_operand" ""))
10180 (const_string "alu_shift")
10181 (const_string "alu_shift_reg")))]
8fa3ba89 10182)
8a18b90c 10183
f7fbdd4a 10184(define_insn "*ifcompare_not_arith"
8a18b90c 10185 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10186 (if_then_else:SI
8fa3ba89 10187 (match_operator 6 "arm_comparison_operator"
8a18b90c 10188 [(match_operand:SI 4 "s_register_operand" "r")
10189 (match_operand:SI 5 "arm_add_operand" "rIL")])
10190 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10191 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10192 [(match_operand:SI 2 "s_register_operand" "r")
10193 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
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_not_arith"
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 4 "cc_register" "") (const_int 0)])
10206 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10207 (match_operator:SI 6 "shiftable_operator"
10208 [(match_operand:SI 2 "s_register_operand" "r")
10209 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10210 "TARGET_ARM"
8a18b90c 10211 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10212 [(set_attr "conds" "use")
10213 (set_attr "length" "8")]
10214)
8a18b90c 10215
10216(define_insn "*ifcompare_arith_not"
10217 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10218 (if_then_else:SI
8fa3ba89 10219 (match_operator 6 "arm_comparison_operator"
8a18b90c 10220 [(match_operand:SI 4 "s_register_operand" "r")
10221 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10222 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10223 [(match_operand:SI 2 "s_register_operand" "r")
10224 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10225 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10226 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10227 "TARGET_ARM"
8a18b90c 10228 "#"
8fa3ba89 10229 [(set_attr "conds" "clob")
10230 (set_attr "length" "12")]
10231)
9c08d1fa 10232
8a18b90c 10233(define_insn "*if_arith_not"
10234 [(set (match_operand:SI 0 "s_register_operand" "=r")
10235 (if_then_else:SI
8fa3ba89 10236 (match_operator 5 "arm_comparison_operator"
8a18b90c 10237 [(match_operand 4 "cc_register" "") (const_int 0)])
10238 (match_operator:SI 6 "shiftable_operator"
10239 [(match_operand:SI 2 "s_register_operand" "r")
10240 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10241 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10242 "TARGET_ARM"
8a18b90c 10243 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10244 [(set_attr "conds" "use")
10245 (set_attr "length" "8")]
10246)
8a18b90c 10247
f7fbdd4a 10248(define_insn "*ifcompare_neg_move"
8a18b90c 10249 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10250 (if_then_else:SI
8fa3ba89 10251 (match_operator 5 "arm_comparison_operator"
8a18b90c 10252 [(match_operand:SI 3 "s_register_operand" "r,r")
10253 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10254 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10255 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10256 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10257 "TARGET_ARM"
8a18b90c 10258 "#"
8fa3ba89 10259 [(set_attr "conds" "clob")
10260 (set_attr "length" "8,12")]
10261)
8a18b90c 10262
10263(define_insn "*if_neg_move"
10264 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10265 (if_then_else:SI
8fa3ba89 10266 (match_operator 4 "arm_comparison_operator"
8a18b90c 10267 [(match_operand 3 "cc_register" "") (const_int 0)])
10268 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10269 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10270 "TARGET_ARM"
8a18b90c 10271 "@
10272 rsb%d4\\t%0, %2, #0
10273 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10274 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10275 [(set_attr "conds" "use")
10276 (set_attr "length" "4,8,8")]
10277)
9c08d1fa 10278
f7fbdd4a 10279(define_insn "*ifcompare_move_neg"
8a18b90c 10280 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10281 (if_then_else:SI
8fa3ba89 10282 (match_operator 5 "arm_comparison_operator"
8a18b90c 10283 [(match_operand:SI 3 "s_register_operand" "r,r")
10284 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10285 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10286 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10287 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10288 "TARGET_ARM"
8a18b90c 10289 "#"
8fa3ba89 10290 [(set_attr "conds" "clob")
10291 (set_attr "length" "8,12")]
10292)
8a18b90c 10293
10294(define_insn "*if_move_neg"
10295 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10296 (if_then_else:SI
8fa3ba89 10297 (match_operator 4 "arm_comparison_operator"
8a18b90c 10298 [(match_operand 3 "cc_register" "") (const_int 0)])
10299 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10300 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10301 "TARGET_ARM"
8a18b90c 10302 "@
10303 rsb%D4\\t%0, %2, #0
10304 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10305 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10306 [(set_attr "conds" "use")
10307 (set_attr "length" "4,8,8")]
10308)
9c08d1fa 10309
f7fbdd4a 10310(define_insn "*arith_adjacentmem"
9c08d1fa 10311 [(set (match_operand:SI 0 "s_register_operand" "=r")
10312 (match_operator:SI 1 "shiftable_operator"
10313 [(match_operand:SI 2 "memory_operand" "m")
10314 (match_operand:SI 3 "memory_operand" "m")]))
10315 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10316 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10317 "*
215b30b3 10318 {
10319 rtx ldm[3];
10320 rtx arith[4];
94dee231 10321 rtx base_reg;
10322 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10323
215b30b3 10324 if (REGNO (operands[0]) > REGNO (operands[4]))
10325 {
10326 ldm[1] = operands[4];
10327 ldm[2] = operands[0];
10328 }
10329 else
10330 {
10331 ldm[1] = operands[0];
10332 ldm[2] = operands[4];
10333 }
94dee231 10334
10335 base_reg = XEXP (operands[2], 0);
10336
10337 if (!REG_P (base_reg))
10338 {
10339 val1 = INTVAL (XEXP (base_reg, 1));
10340 base_reg = XEXP (base_reg, 0);
10341 }
10342
10343 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10344 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10345
215b30b3 10346 arith[0] = operands[0];
10347 arith[3] = operands[1];
94dee231 10348
215b30b3 10349 if (val1 < val2)
10350 {
10351 arith[1] = ldm[1];
10352 arith[2] = ldm[2];
10353 }
10354 else
10355 {
10356 arith[1] = ldm[2];
10357 arith[2] = ldm[1];
10358 }
94dee231 10359
10360 ldm[0] = base_reg;
10361 if (val1 !=0 && val2 != 0)
215b30b3 10362 {
cdb1295a 10363 rtx ops[3];
10364
94dee231 10365 if (val1 == 4 || val2 == 4)
10366 /* Other val must be 8, since we know they are adjacent and neither
10367 is zero. */
25f905c2 10368 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10369 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10370 {
94dee231 10371 ldm[0] = ops[0] = operands[4];
10372 ops[1] = base_reg;
10373 ops[2] = GEN_INT (val1);
10374 output_add_immediate (ops);
10375 if (val1 < val2)
25f905c2 10376 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10377 else
25f905c2 10378 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10379 }
cdb1295a 10380 else
10381 {
10382 /* Offset is out of range for a single add, so use two ldr. */
10383 ops[0] = ldm[1];
10384 ops[1] = base_reg;
10385 ops[2] = GEN_INT (val1);
10386 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10387 ops[0] = ldm[2];
10388 ops[2] = GEN_INT (val2);
10389 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10390 }
215b30b3 10391 }
94dee231 10392 else if (val1 != 0)
215b30b3 10393 {
215b30b3 10394 if (val1 < val2)
25f905c2 10395 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10396 else
25f905c2 10397 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10398 }
10399 else
10400 {
215b30b3 10401 if (val1 < val2)
25f905c2 10402 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10403 else
25f905c2 10404 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10405 }
10406 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10407 return \"\";
10408 }"
10409 [(set_attr "length" "12")
10410 (set_attr "predicable" "yes")
a2cd141b 10411 (set_attr "type" "load1")]
215b30b3 10412)
9c08d1fa 10413
9c08d1fa 10414; This pattern is never tried by combine, so do it as a peephole
10415
a0f94409 10416(define_peephole2
372575c7 10417 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10418 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10419 (set (reg:CC CC_REGNUM)
aea4c774 10420 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10421 "TARGET_ARM"
a0f94409 10422 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10423 (set (match_dup 0) (match_dup 1))])]
10424 ""
0d66636f 10425)
9c08d1fa 10426
675d848d 10427; Peepholes to spot possible load- and store-multiples, if the ordering is
10428; reversed, check that the memory references aren't volatile.
9c08d1fa 10429
10430(define_peephole
aaa37ad6 10431 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10432 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10433 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10434 (match_operand:SI 5 "memory_operand" "m"))
aaa37ad6 10435 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10436 (match_operand:SI 6 "memory_operand" "m"))
aaa37ad6 10437 (set (match_operand:SI 3 "s_register_operand" "=rk")
aea4c774 10438 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 10439 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10440 "*
10441 return emit_ldm_seq (operands, 4);
215b30b3 10442 "
10443)
9c08d1fa 10444
10445(define_peephole
aaa37ad6 10446 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10447 (match_operand:SI 3 "memory_operand" "m"))
aaa37ad6 10448 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10449 (match_operand:SI 4 "memory_operand" "m"))
aaa37ad6 10450 (set (match_operand:SI 2 "s_register_operand" "=rk")
aea4c774 10451 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 10452 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10453 "*
10454 return emit_ldm_seq (operands, 3);
215b30b3 10455 "
10456)
9c08d1fa 10457
10458(define_peephole
aaa37ad6 10459 [(set (match_operand:SI 0 "s_register_operand" "=rk")
aea4c774 10460 (match_operand:SI 2 "memory_operand" "m"))
aaa37ad6 10461 (set (match_operand:SI 1 "s_register_operand" "=rk")
aea4c774 10462 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 10463 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10464 "*
10465 return emit_ldm_seq (operands, 2);
215b30b3 10466 "
10467)
9c08d1fa 10468
10469(define_peephole
aea4c774 10470 [(set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10471 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10472 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10473 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10474 (set (match_operand:SI 6 "memory_operand" "=m")
aaa37ad6 10475 (match_operand:SI 2 "s_register_operand" "rk"))
aea4c774 10476 (set (match_operand:SI 7 "memory_operand" "=m")
aaa37ad6 10477 (match_operand:SI 3 "s_register_operand" "rk"))]
cffb2a26 10478 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10479 "*
10480 return emit_stm_seq (operands, 4);
215b30b3 10481 "
10482)
9c08d1fa 10483
10484(define_peephole
aea4c774 10485 [(set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10486 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10487 (set (match_operand:SI 4 "memory_operand" "=m")
aaa37ad6 10488 (match_operand:SI 1 "s_register_operand" "rk"))
aea4c774 10489 (set (match_operand:SI 5 "memory_operand" "=m")
aaa37ad6 10490 (match_operand:SI 2 "s_register_operand" "rk"))]
cffb2a26 10491 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10492 "*
10493 return emit_stm_seq (operands, 3);
215b30b3 10494 "
10495)
9c08d1fa 10496
10497(define_peephole
aea4c774 10498 [(set (match_operand:SI 2 "memory_operand" "=m")
aaa37ad6 10499 (match_operand:SI 0 "s_register_operand" "rk"))
aea4c774 10500 (set (match_operand:SI 3 "memory_operand" "=m")
aaa37ad6 10501 (match_operand:SI 1 "s_register_operand" "rk"))]
cffb2a26 10502 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10503 "*
10504 return emit_stm_seq (operands, 2);
215b30b3 10505 "
10506)
9c08d1fa 10507
9c08d1fa 10508(define_split
10509 [(set (match_operand:SI 0 "s_register_operand" "")
10510 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10511 (const_int 0))
8fa3ba89 10512 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10513 [(match_operand:SI 3 "s_register_operand" "")
10514 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10515 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10516 "TARGET_ARM"
9c08d1fa 10517 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10518 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10519 (match_dup 5)))]
215b30b3 10520 ""
10521)
9c08d1fa 10522
aea4c774 10523;; This split can be used because CC_Z mode implies that the following
10524;; branch will be an equality, or an unsigned inequality, so the sign
10525;; extension is not needed.
9c08d1fa 10526
aea4c774 10527(define_split
bd5b4116 10528 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10529 (compare:CC_Z
10530 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10531 (const_int 24))
aea4c774 10532 (match_operand 1 "const_int_operand" "")))
10533 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10534 "TARGET_ARM
10535 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10536 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10537 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10538 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10539 "
9c08d1fa 10540 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10541 "
10542)
25f905c2 10543;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10544
87b22bf7 10545(define_expand "prologue"
10546 [(clobber (const_int 0))]
cffb2a26 10547 "TARGET_EITHER"
25f905c2 10548 "if (TARGET_32BIT)
cffb2a26 10549 arm_expand_prologue ();
10550 else
25f905c2 10551 thumb1_expand_prologue ();
87b22bf7 10552 DONE;
cffb2a26 10553 "
10554)
87b22bf7 10555
56d27660 10556(define_expand "epilogue"
4c44712e 10557 [(clobber (const_int 0))]
cffb2a26 10558 "TARGET_EITHER"
56d27660 10559 "
18d50ae6 10560 if (crtl->calls_eh_return)
4c44712e 10561 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10562 if (TARGET_THUMB1)
10563 thumb1_expand_epilogue ();
cffb2a26 10564 else if (USE_RETURN_INSN (FALSE))
56d27660 10565 {
10566 emit_jump_insn (gen_return ());
10567 DONE;
10568 }
cffb2a26 10569 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10570 gen_rtvec (1,
10571 gen_rtx_RETURN (VOIDmode)),
e1159bbe 10572 VUNSPEC_EPILOGUE));
cffb2a26 10573 DONE;
10574 "
10575)
56d27660 10576
ef5651d0 10577;; Note - although unspec_volatile's USE all hard registers,
10578;; USEs are ignored after relaod has completed. Thus we need
10579;; to add an unspec of the link register to ensure that flow
10580;; does not think that it is unused by the sibcall branch that
10581;; will replace the standard function epilogue.
1c494086 10582(define_insn "sibcall_epilogue"
ef5651d0 10583 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10584 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10585 "TARGET_32BIT"
1c494086 10586 "*
ffc9d00c 10587 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10588 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10589 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10590 "
10591;; Length is absolute worst case
10592 [(set_attr "length" "44")
defc47cf 10593 (set_attr "type" "block")
10594 ;; We don't clobber the conditions, but the potential length of this
10595 ;; operation is sufficient to make conditionalizing the sequence
10596 ;; unlikely to be profitable.
10597 (set_attr "conds" "clob")]
1c494086 10598)
10599
cffb2a26 10600(define_insn "*epilogue_insns"
e1159bbe 10601 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10602 "TARGET_EITHER"
56d27660 10603 "*
25f905c2 10604 if (TARGET_32BIT)
ffc9d00c 10605 return arm_output_epilogue (NULL);
25f905c2 10606 else /* TARGET_THUMB1 */
cffb2a26 10607 return thumb_unexpanded_epilogue ();
10608 "
215b30b3 10609 ; Length is absolute worst case
cffb2a26 10610 [(set_attr "length" "44")
defc47cf 10611 (set_attr "type" "block")
10612 ;; We don't clobber the conditions, but the potential length of this
10613 ;; operation is sufficient to make conditionalizing the sequence
10614 ;; unlikely to be profitable.
10615 (set_attr "conds" "clob")]
cffb2a26 10616)
10617
10618(define_expand "eh_epilogue"
7db9af5d 10619 [(use (match_operand:SI 0 "register_operand" ""))
10620 (use (match_operand:SI 1 "register_operand" ""))
10621 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10622 "TARGET_EITHER"
10623 "
215b30b3 10624 {
10625 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10626 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10627 {
10628 rtx ra = gen_rtx_REG (Pmode, 2);
10629
10630 emit_move_insn (ra, operands[2]);
10631 operands[2] = ra;
10632 }
5cf3595a 10633 /* This is a hack -- we may have crystalized the function type too
10634 early. */
10635 cfun->machine->func_type = 0;
215b30b3 10636 }"
10637)
56d27660 10638
9c08d1fa 10639;; This split is only used during output to reduce the number of patterns
10640;; that need assembler instructions adding to them. We allowed the setting
10641;; of the conditions to be implicit during rtl generation so that
10642;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10643;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10644;; up again here.
10645
25f905c2 10646;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10647;; conditional execution sufficient?
10648
9c08d1fa 10649(define_split
10650 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10651 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10652 [(match_operand 2 "" "") (match_operand 3 "" "")])
10653 (match_dup 0)
10654 (match_operand 4 "" "")))
bd5b4116 10655 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10656 "TARGET_ARM && reload_completed"
8fa3ba89 10657 [(set (match_dup 5) (match_dup 6))
10658 (cond_exec (match_dup 7)
10659 (set (match_dup 0) (match_dup 4)))]
10660 "
10661 {
10662 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10663 operands[2], operands[3]);
10664 enum rtx_code rc = GET_CODE (operands[1]);
10665
bd5b4116 10666 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10667 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10668 if (mode == CCFPmode || mode == CCFPEmode)
10669 rc = reverse_condition_maybe_unordered (rc);
10670 else
10671 rc = reverse_condition (rc);
10672
10673 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10674 }"
10675)
10676
10677(define_split
10678 [(set (match_operand:SI 0 "s_register_operand" "")
10679 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10680 [(match_operand 2 "" "") (match_operand 3 "" "")])
10681 (match_operand 4 "" "")
10682 (match_dup 0)))
bd5b4116 10683 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10684 "TARGET_ARM && reload_completed"
8fa3ba89 10685 [(set (match_dup 5) (match_dup 6))
10686 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10687 (set (match_dup 0) (match_dup 4)))]
10688 "
10689 {
10690 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10691 operands[2], operands[3]);
10692
bd5b4116 10693 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10694 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10695 }"
10696)
10697
10698(define_split
10699 [(set (match_operand:SI 0 "s_register_operand" "")
10700 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10701 [(match_operand 2 "" "") (match_operand 3 "" "")])
10702 (match_operand 4 "" "")
10703 (match_operand 5 "" "")))
bd5b4116 10704 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10705 "TARGET_ARM && reload_completed"
8fa3ba89 10706 [(set (match_dup 6) (match_dup 7))
10707 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10708 (set (match_dup 0) (match_dup 4)))
10709 (cond_exec (match_dup 8)
10710 (set (match_dup 0) (match_dup 5)))]
10711 "
10712 {
10713 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10714 operands[2], operands[3]);
10715 enum rtx_code rc = GET_CODE (operands[1]);
10716
bd5b4116 10717 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10718 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10719 if (mode == CCFPmode || mode == CCFPEmode)
10720 rc = reverse_condition_maybe_unordered (rc);
10721 else
10722 rc = reverse_condition (rc);
10723
10724 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10725 }"
10726)
10727
cffb2a26 10728(define_split
10729 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10730 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10731 [(match_operand:SI 2 "s_register_operand" "")
10732 (match_operand:SI 3 "arm_add_operand" "")])
10733 (match_operand:SI 4 "arm_rhs_operand" "")
10734 (not:SI
10735 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10736 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10737 "TARGET_ARM && reload_completed"
cffb2a26 10738 [(set (match_dup 6) (match_dup 7))
f6c53574 10739 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10740 (set (match_dup 0) (match_dup 4)))
10741 (cond_exec (match_dup 8)
10742 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10743 "
215b30b3 10744 {
10745 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10746 operands[2], operands[3]);
f6c53574 10747 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10748
bd5b4116 10749 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10750 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10751 if (mode == CCFPmode || mode == CCFPEmode)
10752 rc = reverse_condition_maybe_unordered (rc);
10753 else
10754 rc = reverse_condition (rc);
10755
10756 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10757 }"
10758)
cffb2a26 10759
10760(define_insn "*cond_move_not"
10761 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10762 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10763 [(match_operand 3 "cc_register" "") (const_int 0)])
10764 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10765 (not:SI
10766 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10767 "TARGET_ARM"
10768 "@
10769 mvn%D4\\t%0, %2
10770 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10771 [(set_attr "conds" "use")
10772 (set_attr "length" "4,8")]
10773)
cffb2a26 10774
9c08d1fa 10775;; The next two patterns occur when an AND operation is followed by a
10776;; scc insn sequence
10777
f7fbdd4a 10778(define_insn "*sign_extract_onebit"
9c08d1fa 10779 [(set (match_operand:SI 0 "s_register_operand" "=r")
10780 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10781 (const_int 1)
ed750274 10782 (match_operand:SI 2 "const_int_operand" "n")))
10783 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10784 "TARGET_ARM"
9c08d1fa 10785 "*
0d66636f 10786 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10787 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10788 return \"mvnne\\t%0, #0\";
10789 "
10790 [(set_attr "conds" "clob")
10791 (set_attr "length" "8")]
10792)
9c08d1fa 10793
f7fbdd4a 10794(define_insn "*not_signextract_onebit"
9c08d1fa 10795 [(set (match_operand:SI 0 "s_register_operand" "=r")
10796 (not:SI
10797 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10798 (const_int 1)
ed750274 10799 (match_operand:SI 2 "const_int_operand" "n"))))
10800 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10801 "TARGET_ARM"
9c08d1fa 10802 "*
0d66636f 10803 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10804 output_asm_insn (\"tst\\t%1, %2\", operands);
10805 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10806 return \"movne\\t%0, #0\";
10807 "
10808 [(set_attr "conds" "clob")
10809 (set_attr "length" "12")]
10810)
25f905c2 10811;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10812
0d66636f 10813;; Push multiple registers to the stack. Registers are in parallel (use ...)
10814;; expressions. For simplicity, the first register is also in the unspec
10815;; part.
f7fbdd4a 10816(define_insn "*push_multi"
87b22bf7 10817 [(match_parallel 2 "multi_register_push"
10818 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10819 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10820 UNSPEC_PUSH_MULT))])]
25f905c2 10821 "TARGET_32BIT"
87b22bf7 10822 "*
215b30b3 10823 {
10824 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10825
215b30b3 10826 /* For the StrongARM at least it is faster to
25f905c2 10827 use STR to store only a single register.
542d5028 10828 In Thumb mode always use push, and the assembler will pick
10829 something appropriate. */
25f905c2 10830 if (num_saves == 1 && TARGET_ARM)
215b30b3 10831 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10832 else
10833 {
10834 int i;
10835 char pattern[100];
ed593f11 10836
25f905c2 10837 if (TARGET_ARM)
10838 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10839 else
10840 strcpy (pattern, \"push\\t{%1\");
215b30b3 10841
6079f055 10842 for (i = 1; i < num_saves; i++)
215b30b3 10843 {
10844 strcat (pattern, \", %|\");
10845 strcat (pattern,
10846 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10847 }
10848
10849 strcat (pattern, \"}\");
10850 output_asm_insn (pattern, operands);
10851 }
10852
10853 return \"\";
10854 }"
10855 [(set_attr "type" "store4")]
10856)
f7fbdd4a 10857
4c58c898 10858(define_insn "stack_tie"
10859 [(set (mem:BLK (scratch))
aaa37ad6 10860 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10861 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10862 UNSPEC_PRLG_STK))]
10863 ""
10864 ""
10865 [(set_attr "length" "0")]
10866)
10867
3398e91d 10868;; Similarly for the floating point registers
7b1d2fc4 10869(define_insn "*push_fp_multi"
10870 [(match_parallel 2 "multi_register_push"
10871 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10872 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10873 UNSPEC_PUSH_MULT))])]
25f905c2 10874 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10875 "*
215b30b3 10876 {
10877 char pattern[100];
7b1d2fc4 10878
215b30b3 10879 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10880 output_asm_insn (pattern, operands);
10881 return \"\";
10882 }"
10883 [(set_attr "type" "f_store")]
10884)
7b1d2fc4 10885
f7fbdd4a 10886;; Special patterns for dealing with the constant pool
10887
cffb2a26 10888(define_insn "align_4"
e1159bbe 10889 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10890 "TARGET_EITHER"
f7fbdd4a 10891 "*
cffb2a26 10892 assemble_align (32);
f7fbdd4a 10893 return \"\";
cffb2a26 10894 "
10895)
f7fbdd4a 10896
755eb2b4 10897(define_insn "align_8"
10898 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10899 "TARGET_EITHER"
755eb2b4 10900 "*
10901 assemble_align (64);
10902 return \"\";
10903 "
10904)
10905
cffb2a26 10906(define_insn "consttable_end"
e1159bbe 10907 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10908 "TARGET_EITHER"
f7fbdd4a 10909 "*
cffb2a26 10910 making_const_table = FALSE;
f7fbdd4a 10911 return \"\";
cffb2a26 10912 "
10913)
f7fbdd4a 10914
cffb2a26 10915(define_insn "consttable_1"
e1159bbe 10916 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10917 "TARGET_THUMB1"
f7fbdd4a 10918 "*
cffb2a26 10919 making_const_table = TRUE;
09d688ff 10920 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10921 assemble_zeros (3);
f7fbdd4a 10922 return \"\";
cffb2a26 10923 "
10924 [(set_attr "length" "4")]
10925)
f7fbdd4a 10926
cffb2a26 10927(define_insn "consttable_2"
e1159bbe 10928 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10929 "TARGET_THUMB1"
f7fbdd4a 10930 "*
cffb2a26 10931 making_const_table = TRUE;
9b8516be 10932 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10933 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10934 assemble_zeros (2);
f7fbdd4a 10935 return \"\";
cffb2a26 10936 "
10937 [(set_attr "length" "4")]
10938)
10939
10940(define_insn "consttable_4"
e1159bbe 10941 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10942 "TARGET_EITHER"
10943 "*
10944 {
9b8516be 10945 rtx x = operands[0];
cffb2a26 10946 making_const_table = TRUE;
9b8516be 10947 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10948 {
10949 case MODE_FLOAT:
9b8516be 10950 if (GET_MODE (x) == HFmode)
10951 arm_emit_fp16_const (x);
10952 else
10953 {
10954 REAL_VALUE_TYPE r;
10955 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10956 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10957 }
10958 break;
cffb2a26 10959 default:
9b8516be 10960 assemble_integer (x, 4, BITS_PER_WORD, 1);
10961 mark_symbol_refs_as_used (x);
cffb2a26 10962 break;
10963 }
10964 return \"\";
10965 }"
10966 [(set_attr "length" "4")]
10967)
10968
10969(define_insn "consttable_8"
e1159bbe 10970 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10971 "TARGET_EITHER"
10972 "*
10973 {
10974 making_const_table = TRUE;
10975 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10976 {
10977 case MODE_FLOAT:
10978 {
badfe841 10979 REAL_VALUE_TYPE r;
10980 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10981 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10982 break;
10983 }
10984 default:
09d688ff 10985 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10986 break;
10987 }
10988 return \"\";
10989 }"
10990 [(set_attr "length" "8")]
10991)
10992
d98a3884 10993(define_insn "consttable_16"
10994 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10995 "TARGET_EITHER"
10996 "*
10997 {
10998 making_const_table = TRUE;
10999 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11000 {
11001 case MODE_FLOAT:
11002 {
11003 REAL_VALUE_TYPE r;
11004 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11005 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11006 break;
11007 }
11008 default:
11009 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11010 break;
11011 }
11012 return \"\";
11013 }"
11014 [(set_attr "length" "16")]
11015)
11016
cffb2a26 11017;; Miscellaneous Thumb patterns
11018
fd957ef3 11019(define_expand "tablejump"
7db9af5d 11020 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 11021 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 11022 "TARGET_THUMB1"
fd957ef3 11023 "
11024 if (flag_pic)
11025 {
11026 /* Hopefully, CSE will eliminate this copy. */
11027 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11028 rtx reg2 = gen_reg_rtx (SImode);
11029
11030 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11031 operands[0] = reg2;
11032 }
11033 "
11034)
11035
f1039640 11036;; NB never uses BX.
25f905c2 11037(define_insn "*thumb1_tablejump"
cffb2a26 11038 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11039 (use (label_ref (match_operand 1 "" "")))]
25f905c2 11040 "TARGET_THUMB1"
fd957ef3 11041 "mov\\t%|pc, %0"
cffb2a26 11042 [(set_attr "length" "2")]
11043)
0d66636f 11044
331beb1a 11045;; V5 Instructions,
11046
8f4be2be 11047(define_insn "clzsi2"
11048 [(set (match_operand:SI 0 "s_register_operand" "=r")
11049 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11050 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11051 "clz%?\\t%0, %1"
bcaec148 11052 [(set_attr "predicable" "yes")
11053 (set_attr "insn" "clz")])
331beb1a 11054
099ad98b 11055(define_insn "rbitsi2"
11056 [(set (match_operand:SI 0 "s_register_operand" "=r")
11057 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11058 "TARGET_32BIT && arm_arch_thumb2"
11059 "rbit%?\\t%0, %1"
11060 [(set_attr "predicable" "yes")
11061 (set_attr "insn" "clz")])
11062
11063(define_expand "ctzsi2"
11064 [(set (match_operand:SI 0 "s_register_operand" "")
11065 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
11066 "TARGET_32BIT && arm_arch_thumb2"
11067 "
30191172 11068 {
11069 rtx tmp = gen_reg_rtx (SImode);
11070 emit_insn (gen_rbitsi2 (tmp, operands[1]));
11071 emit_insn (gen_clzsi2 (operands[0], tmp));
11072 }
099ad98b 11073 DONE;
11074 "
11075)
11076
e1159bbe 11077;; V5E instructions.
331beb1a 11078
11079(define_insn "prefetch"
f4e79814 11080 [(prefetch (match_operand:SI 0 "address_operand" "p")
11081 (match_operand:SI 1 "" "")
11082 (match_operand:SI 2 "" ""))]
25f905c2 11083 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 11084 "pld\\t%a0")
331beb1a 11085
0d66636f 11086;; General predication pattern
11087
11088(define_cond_exec
11089 [(match_operator 0 "arm_comparison_operator"
11090 [(match_operand 1 "cc_register" "")
11091 (const_int 0)])]
25f905c2 11092 "TARGET_32BIT"
0d66636f 11093 ""
11094)
11095
063a05c7 11096(define_insn "prologue_use"
11097 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11098 ""
11099 "%@ %0 needed for prologue"
02cfc9c9 11100 [(set_attr "length" "0")]
063a05c7 11101)
7db9af5d 11102
4c44712e 11103
11104;; Patterns for exception handling
11105
11106(define_expand "eh_return"
11107 [(use (match_operand 0 "general_operand" ""))]
11108 "TARGET_EITHER"
11109 "
11110 {
25f905c2 11111 if (TARGET_32BIT)
4c44712e 11112 emit_insn (gen_arm_eh_return (operands[0]));
11113 else
11114 emit_insn (gen_thumb_eh_return (operands[0]));
11115 DONE;
11116 }"
11117)
11118
11119;; We can't expand this before we know where the link register is stored.
11120(define_insn_and_split "arm_eh_return"
11121 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11122 VUNSPEC_EH_RETURN)
11123 (clobber (match_scratch:SI 1 "=&r"))]
11124 "TARGET_ARM"
11125 "#"
11126 "&& reload_completed"
11127 [(const_int 0)]
11128 "
11129 {
11130 arm_set_return_address (operands[0], operands[1]);
11131 DONE;
11132 }"
11133)
11134
11135(define_insn_and_split "thumb_eh_return"
11136 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11137 VUNSPEC_EH_RETURN)
11138 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 11139 "TARGET_THUMB1"
4c44712e 11140 "#"
11141 "&& reload_completed"
11142 [(const_int 0)]
11143 "
11144 {
11145 thumb_set_return_address (operands[0], operands[1]);
11146 DONE;
11147 }"
11148)
11149
f655717d 11150\f
11151;; TLS support
11152
11153(define_insn "load_tp_hard"
11154 [(set (match_operand:SI 0 "register_operand" "=r")
11155 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11156 "TARGET_HARD_TP"
11157 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11158 [(set_attr "predicable" "yes")]
11159)
11160
11161;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11162(define_insn "load_tp_soft"
11163 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11164 (clobber (reg:SI LR_REGNUM))
11165 (clobber (reg:SI IP_REGNUM))
11166 (clobber (reg:CC CC_REGNUM))]
11167 "TARGET_SOFT_TP"
11168 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11169 [(set_attr "conds" "clob")]
11170)
11171
eca5c984 11172(define_insn "*arm_movtas_ze"
11173 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11174 (const_int 16)
11175 (const_int 16))
11176 (match_operand:SI 1 "const_int_operand" ""))]
11177 "TARGET_32BIT"
11178 "movt%?\t%0, %c1"
11179 [(set_attr "predicable" "yes")
11180 (set_attr "length" "4")]
11181)
11182
7db9af5d 11183;; Load the FPA co-processor patterns
11184(include "fpa.md")
11185;; Load the Maverick co-processor patterns
11186(include "cirrus.md")
d98a3884 11187;; Vector bits common to IWMMXT and Neon
11188(include "vec-common.md")
755eb2b4 11189;; Load the Intel Wireless Multimedia Extension patterns
11190(include "iwmmxt.md")
a2cd141b 11191;; Load the VFP co-processor patterns
11192(include "vfp.md")
25f905c2 11193;; Thumb-2 patterns
11194(include "thumb2.md")
d98a3884 11195;; Neon patterns
11196(include "neon.md")
a2cd141b 11197