]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
2007-07-25 Janis Johnson <janis187@us.ibm.com>
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
25f905c2 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
b11cae9e 4;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 5;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 6;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 7
acf6ed70 8;; This file is part of GCC.
b11cae9e 9
acf6ed70 10;; GCC is free software; you can redistribute it and/or modify it
11;; under the terms of the GNU General Public License as published
12;; by the Free Software Foundation; either version 2, or (at your
13;; option) any later version.
b11cae9e 14
acf6ed70 15;; GCC is distributed in the hope that it will be useful, but WITHOUT
16;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18;; License for more details.
b11cae9e 19
20;; You should have received a copy of the GNU General Public License
acf6ed70 21;; along with GCC; see the file COPYING. If not, write to
dbddc6c4 22;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23;; Boston, MA 02110-1301, USA.
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.
e1159bbe 54
55(define_constants
56 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
60 ; operand 0 is the result,
61 ; operand 1 the parameter.
62 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63 ; operand 0 is the first register,
64 ; subsequent registers are in parallel (use ...)
65 ; expressions.
66 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
67 ; usage, that is, we will add the pic_register
68 ; value to it before trying to dereference it.
2c96dc5a 69 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
70 ; GLOBAL_OFFSET_TABLE. The operation is fully
71 ; described by the RTL but must be wrapped to
72 ; prevent combine from trying to rip it apart.
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.
25f905c2 96 (UNSPEC_STACK_ALIGN 20) ; Doubleword aligned stack pointer. Used to
97 ; generate correct unwind information.
bac7fc85 98 (UNSPEC_PIC_OFFSET 22) ; A symbolic 12-bit OFFSET that has been treated
99 ; correctly for PIC usage.
e1159bbe 100 ]
101)
102
215b30b3 103;; UNSPEC_VOLATILE Usage:
e1159bbe 104
105(define_constants
106 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
107 ; insn in the code.
108 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
109 ; instruction epilogue sequence that isn't expanded
110 ; into normal RTL. Used for both normal and sibcall
111 ; epilogues.
112 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
113 ; for inlined constants.
114 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
115 ; table.
116 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
117 ; an 8-bit object.
118 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
119 ; a 16-bit object.
120 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
121 ; a 32-bit object.
122 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
123 ; a 64-bit object.
755eb2b4 124 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
125 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
126 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
127 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
128 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
129 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 130 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 131 ; handling.
e1159bbe 132 ]
133)
b11cae9e 134\f
e1159bbe 135;;---------------------------------------------------------------------------
9c08d1fa 136;; Attributes
137
215b30b3 138; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
139; generating ARM code. This is used to control the length of some insn
140; patterns that share the same RTL in both ARM and Thumb code.
1c494086 141(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 142
215b30b3 143; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
144; scheduling decisions for the load unit and the multiplier.
74a71f7d 145(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
9c08d1fa 146
5ecb8da7 147; IS_XSCALE is set to 'yes' when compiling for XScale.
148(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
149
331beb1a 150;; Operand number of an input operand that is shifted. Zero if the
151;; given instruction does not shift one of its input operands.
331beb1a 152(define_attr "shift" "" (const_int 0))
153
3d91c5d6 154; Floating Point Unit. If we only have floating point emulation, then there
155; is no point in scheduling the floating point insns. (Well, for best
156; performance we should try and group them together).
a2cd141b 157(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 158 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 159
094e994f 160; LENGTH of an instruction (in bytes)
161(define_attr "length" "" (const_int 4))
9c08d1fa 162
56d27660 163; POOL_RANGE is how far away from a constant pool entry that this insn
164; can be placed. If the distance is zero, then this insn will never
165; reference the pool.
cffb2a26 166; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
167; before its address.
56d27660 168(define_attr "pool_range" "" (const_int 0))
cffb2a26 169(define_attr "neg_pool_range" "" (const_int 0))
56d27660 170
215b30b3 171; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 172; If such an insn references the pool, then we have no way of knowing how,
173; so use the most conservative value for pool_range.
9c08d1fa 174(define_asm_attributes
4d7a8451 175 [(set_attr "conds" "clob")
176 (set_attr "length" "4")
177 (set_attr "pool_range" "250")])
9c08d1fa 178
a2cd141b 179;; The instruction used to implement a particular pattern. This
180;; information is used by pipeline descriptions to provide accurate
181;; scheduling information.
182
183(define_attr "insn"
184 "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,other"
185 (const_string "other"))
186
9c08d1fa 187; TYPE attribute is used to detect floating point instructions which, if
188; running on a co-processor can run in parallel with other, basic instructions
189; If write-buffer scheduling is enabled then it can also be used in the
190; scheduling of writes.
191
192; Classification of each insn
a2cd141b 193; alu any alu instruction that doesn't hit memory or fp
194; regs or have a shifted source operand
195; alu_shift any data instruction that doesn't hit memory or fp
196; regs, but has a source operand shifted by a constant
197; alu_shift_reg any data instruction that doesn't hit memory or fp
198; regs, but has a source operand shifted by a register value
f7fbdd4a 199; mult a multiply instruction
9c08d1fa 200; block blockage insn, this blocks all functional units
201; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 202; fdivd DFmode floating point division
203; fdivs SFmode floating point division
204; fmul Floating point multiply
205; ffmul Fast floating point multiply
206; farith Floating point arithmetic (4 cycle)
207; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 208; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 209; even on a machine with an fpa.
9c08d1fa 210; f_load a floating point load from memory
211; f_store a floating point store to memory
9aff9709 212; f_load[sd] single/double load from memory
213; f_store[sd] single/double store to memory
c0e1af52 214; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 215; f_mem_r a transfer of a floating point register to a real reg via mem
216; r_mem_f the reverse of f_mem_r
217; f_2_r fast transfer float to arm (no memory needed)
218; r_2_f fast transfer arm to float
c0e1af52 219; f_cvt convert floating<->integral
a2cd141b 220; branch a branch
9c08d1fa 221; call a subroutine call
a2cd141b 222; load_byte load byte(s) from memory to arm registers
223; load1 load 1 word from memory to arm registers
224; load2 load 2 words from memory to arm registers
225; load3 load 3 words from memory to arm registers
226; load4 load 4 words from memory to arm registers
227; store store 1 word to memory from arm registers
9c08d1fa 228; store2 store 2 words
229; store3 store 3 words
a2cd141b 230; store4 store 4 (or more) words
2c6c7d8b 231; Additions for Cirrus Maverick co-processor:
232; mav_farith Floating point arithmetic (4 cycle)
233; mav_dmult Double multiplies (7 cycle)
9c08d1fa 234;
235(define_attr "type"
c0e1af52 236 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,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"
a2cd141b 237 (if_then_else
238 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
239 (const_string "mult")
240 (const_string "alu")))
9c08d1fa 241
9888ad6d 242; Load scheduling, set from the arm_ld_sched variable
457275b6 243; initialized by arm_override_options()
9888ad6d 244(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 245
f7fbdd4a 246; condition codes: this one is used by final_prescan_insn to speed up
247; conditionalizing instructions. It saves having to scan the rtl to see if
248; it uses or alters the condition codes.
215b30b3 249;
f7fbdd4a 250; USE means that the condition codes are used by the insn in the process of
215b30b3 251; outputting code, this means (at present) that we can't use the insn in
252; inlined branches
253;
f7fbdd4a 254; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 255; well defined manner.
256;
f7fbdd4a 257; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 258; they are altered at all
259;
8fa3ba89 260; JUMP_CLOB is used when the condition cannot be represented by a single
215b30b3 261; instruction (UNEQ and LTGT). These cannot be predicated.
262;
f7fbdd4a 263; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 264; output of this insn
f7fbdd4a 265
266(define_attr "conds" "use,set,clob,jump_clob,nocond"
267 (if_then_else (eq_attr "type" "call")
c1a66faf 268 (const_string "clob")
f7fbdd4a 269 (const_string "nocond")))
270
215b30b3 271; Predicable means that the insn can be conditionally executed based on
272; an automatically added predicate (additional patterns are generated by
273; gen...). We default to 'no' because no Thumb patterns match this rule
274; and not all ARM patterns do.
0d66636f 275(define_attr "predicable" "no,yes" (const_string "no"))
276
129a2fe4 277; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
278; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 279; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 280; affect the schedule).
74a71f7d 281(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 282
215b30b3 283; WRITE_CONFLICT implies that a read following an unrelated write is likely
284; to stall the processor. Used with model_wbuf above.
9c08d1fa 285(define_attr "write_conflict" "no,yes"
286 (if_then_else (eq_attr "type"
a2cd141b 287 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 288 (const_string "yes")
289 (const_string "no")))
290
215b30b3 291; Classify the insns into those that take one cycle and those that take more
292; than one on the main cpu execution unit.
f7fbdd4a 293(define_attr "core_cycles" "single,multi"
294 (if_then_else (eq_attr "type"
a2cd141b 295 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 296 (const_string "single")
297 (const_string "multi")))
298
cffb2a26 299;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 300;; distant label. Only applicable to Thumb code.
cffb2a26 301(define_attr "far_jump" "yes,no" (const_string "no"))
302
d51f92df 303
25f905c2 304;; The number of machine instructions this pattern expands to.
305;; Used for Thumb-2 conditional execution.
306(define_attr "ce_count" "" (const_int 1))
307
d51f92df 308;;---------------------------------------------------------------------------
309;; Mode macros
310
311; A list of modes that are exactly 64 bits in size. We use this to expand
312; some splits that are the same for all modes when operating on ARM
313; registers.
314(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
315
316;;---------------------------------------------------------------------------
317;; Predicates
318
9c9db025 319(include "predicates.md")
234f6557 320(include "constraints.md")
9c9db025 321
a2cd141b 322;;---------------------------------------------------------------------------
323;; Pipeline descriptions
215b30b3 324
06469f9e 325;; Processor type. This is created automatically from arm-cores.def.
326(include "arm-tune.md")
331beb1a 327
a2cd141b 328;; True if the generic scheduling description should be used.
329
330(define_attr "generic_sched" "yes,no"
4d5cb40d 331 (const (if_then_else
c0e1af52 332 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
4d5cb40d 333 (const_string "no")
334 (const_string "yes"))))
335
c0e1af52 336(define_attr "generic_vfp" "yes,no"
337 (const (if_then_else
338 (and (eq_attr "fpu" "vfp")
339 (eq_attr "tune" "!arm1020e,arm1022e"))
340 (const_string "yes")
341 (const_string "no"))))
342
a2cd141b 343(include "arm-generic.md")
344(include "arm926ejs.md")
c0e1af52 345(include "arm1020e.md")
a2cd141b 346(include "arm1026ejs.md")
347(include "arm1136jfs.md")
3586df96 348
9c08d1fa 349\f
215b30b3 350;;---------------------------------------------------------------------------
e1159bbe 351;; Insn patterns
352;;
a0f94409 353;; Addition insns.
215b30b3 354
9c08d1fa 355;; Note: For DImode insns, there is normally no reason why operands should
356;; not be in the same register, what we don't want is for something being
357;; written to partially overlap something that is an input.
7d57ec45 358;; Cirrus 64bit additions should not be split because we have a native
359;; 64bit addition instructions.
9c08d1fa 360
cffb2a26 361(define_expand "adddi3"
362 [(parallel
215b30b3 363 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 364 (plus:DI (match_operand:DI 1 "s_register_operand" "")
365 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 366 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 367 "TARGET_EITHER"
368 "
a2cd141b 369 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 370 {
371 if (!cirrus_fp_register (operands[0], DImode))
372 operands[0] = force_reg (DImode, operands[0]);
373 if (!cirrus_fp_register (operands[1], DImode))
374 operands[1] = force_reg (DImode, operands[1]);
375 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
376 DONE;
377 }
378
25f905c2 379 if (TARGET_THUMB1)
cffb2a26 380 {
381 if (GET_CODE (operands[1]) != REG)
382 operands[1] = force_reg (SImode, operands[1]);
383 if (GET_CODE (operands[2]) != REG)
384 operands[2] = force_reg (SImode, operands[2]);
385 }
386 "
387)
388
25f905c2 389(define_insn "*thumb1_adddi3"
cffb2a26 390 [(set (match_operand:DI 0 "register_operand" "=l")
391 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 392 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 393 (clobber (reg:CC CC_REGNUM))
cffb2a26 394 ]
25f905c2 395 "TARGET_THUMB1"
cffb2a26 396 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
397 [(set_attr "length" "4")]
398)
399
a0f94409 400(define_insn_and_split "*arm_adddi3"
cffb2a26 401 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 402 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
403 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 404 (clobber (reg:CC CC_REGNUM))]
25f905c2 405 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 406 "#"
25f905c2 407 "TARGET_32BIT && reload_completed"
a0f94409 408 [(parallel [(set (reg:CC_C CC_REGNUM)
409 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
410 (match_dup 1)))
411 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
412 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
413 (plus:SI (match_dup 4) (match_dup 5))))]
414 "
415 {
416 operands[3] = gen_highpart (SImode, operands[0]);
417 operands[0] = gen_lowpart (SImode, operands[0]);
418 operands[4] = gen_highpart (SImode, operands[1]);
419 operands[1] = gen_lowpart (SImode, operands[1]);
420 operands[5] = gen_highpart (SImode, operands[2]);
421 operands[2] = gen_lowpart (SImode, operands[2]);
422 }"
cffb2a26 423 [(set_attr "conds" "clob")
424 (set_attr "length" "8")]
425)
9c08d1fa 426
a0f94409 427(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 428 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
429 (plus:DI (sign_extend:DI
97499065 430 (match_operand:SI 2 "s_register_operand" "r,r"))
431 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 432 (clobber (reg:CC CC_REGNUM))]
25f905c2 433 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 434 "#"
25f905c2 435 "TARGET_32BIT && reload_completed"
a0f94409 436 [(parallel [(set (reg:CC_C CC_REGNUM)
437 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
438 (match_dup 1)))
439 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
440 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
441 (plus:SI (ashiftrt:SI (match_dup 2)
442 (const_int 31))
443 (match_dup 4))))]
444 "
445 {
446 operands[3] = gen_highpart (SImode, operands[0]);
447 operands[0] = gen_lowpart (SImode, operands[0]);
448 operands[4] = gen_highpart (SImode, operands[1]);
449 operands[1] = gen_lowpart (SImode, operands[1]);
450 operands[2] = gen_lowpart (SImode, operands[2]);
451 }"
215b30b3 452 [(set_attr "conds" "clob")
453 (set_attr "length" "8")]
454)
9c08d1fa 455
a0f94409 456(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 457 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
458 (plus:DI (zero_extend:DI
97499065 459 (match_operand:SI 2 "s_register_operand" "r,r"))
460 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 461 (clobber (reg:CC CC_REGNUM))]
25f905c2 462 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 463 "#"
25f905c2 464 "TARGET_32BIT && reload_completed"
a0f94409 465 [(parallel [(set (reg:CC_C CC_REGNUM)
466 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
467 (match_dup 1)))
468 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
469 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
470 (plus:SI (match_dup 4) (const_int 0))))]
471 "
472 {
473 operands[3] = gen_highpart (SImode, operands[0]);
474 operands[0] = gen_lowpart (SImode, operands[0]);
475 operands[4] = gen_highpart (SImode, operands[1]);
476 operands[1] = gen_lowpart (SImode, operands[1]);
477 operands[2] = gen_lowpart (SImode, operands[2]);
478 }"
cffb2a26 479 [(set_attr "conds" "clob")
480 (set_attr "length" "8")]
481)
b11cae9e 482
87b22bf7 483(define_expand "addsi3"
cffb2a26 484 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 485 (plus:SI (match_operand:SI 1 "s_register_operand" "")
486 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 487 "TARGET_EITHER"
87b22bf7 488 "
25f905c2 489 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 490 {
96f57e36 491 arm_split_constant (PLUS, SImode, NULL_RTX,
492 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 493 optimize && can_create_pseudo_p ());
87b22bf7 494 DONE;
495 }
cffb2a26 496 "
497)
87b22bf7 498
5bd751ff 499; If there is a scratch available, this will be faster than synthesizing the
a0f94409 500; addition.
501(define_peephole2
502 [(match_scratch:SI 3 "r")
372575c7 503 (set (match_operand:SI 0 "arm_general_register_operand" "")
504 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 505 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 506 "TARGET_32BIT &&
a0f94409 507 !(const_ok_for_arm (INTVAL (operands[2]))
508 || const_ok_for_arm (-INTVAL (operands[2])))
509 && const_ok_for_arm (~INTVAL (operands[2]))"
510 [(set (match_dup 3) (match_dup 2))
511 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
512 ""
513)
87b22bf7 514
a0f94409 515(define_insn_and_split "*arm_addsi3"
cffb2a26 516 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
a0f94409 517 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
87b22bf7 518 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
25f905c2 519 "TARGET_32BIT"
5565501b 520 "@
521 add%?\\t%0, %1, %2
87b22bf7 522 sub%?\\t%0, %1, #%n2
523 #"
25f905c2 524 "TARGET_32BIT &&
a0f94409 525 GET_CODE (operands[2]) == CONST_INT
526 && !(const_ok_for_arm (INTVAL (operands[2]))
527 || const_ok_for_arm (-INTVAL (operands[2])))"
528 [(clobber (const_int 0))]
529 "
96f57e36 530 arm_split_constant (PLUS, SImode, curr_insn,
531 INTVAL (operands[2]), operands[0],
a0f94409 532 operands[1], 0);
533 DONE;
534 "
0d66636f 535 [(set_attr "length" "4,4,16")
536 (set_attr "predicable" "yes")]
cffb2a26 537)
538
539;; Register group 'k' is a single register group containing only the stack
540;; register. Trying to reload it will always fail catastrophically,
541;; so never allow those alternatives to match if reloading is needed.
542
25f905c2 543(define_insn "*thumb1_addsi3"
cffb2a26 544 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
545 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
546 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
25f905c2 547 "TARGET_THUMB1"
cffb2a26 548 "*
0d66636f 549 static const char * const asms[] =
cffb2a26 550 {
551 \"add\\t%0, %0, %2\",
552 \"sub\\t%0, %0, #%n2\",
553 \"add\\t%0, %1, %2\",
554 \"add\\t%0, %0, %2\",
555 \"add\\t%0, %0, %2\",
556 \"add\\t%0, %1, %2\",
557 \"add\\t%0, %1, %2\"
558 };
559 if ((which_alternative == 2 || which_alternative == 6)
560 && GET_CODE (operands[2]) == CONST_INT
561 && INTVAL (operands[2]) < 0)
562 return \"sub\\t%0, %1, #%n2\";
563 return asms[which_alternative];
564 "
565 [(set_attr "length" "2")]
566)
567
568;; Reloading and elimination of the frame pointer can
569;; sometimes cause this optimization to be missed.
a0f94409 570(define_peephole2
372575c7 571 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 572 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 573 (set (match_dup 0)
372575c7 574 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 575 "TARGET_THUMB1
cffb2a26 576 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
577 && (INTVAL (operands[1]) & 3) == 0"
372575c7 578 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 579 ""
cffb2a26 580)
b11cae9e 581
25f905c2 582;; ??? Make Thumb-2 variants which prefer low regs
f7fbdd4a 583(define_insn "*addsi3_compare0"
bd5b4116 584 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 585 (compare:CC_NOOV
215b30b3 586 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
587 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 588 (const_int 0)))
589 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 590 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 591 "TARGET_32BIT"
5565501b 592 "@
25f905c2 593 add%.\\t%0, %1, %2
594 sub%.\\t%0, %1, #%n2"
cffb2a26 595 [(set_attr "conds" "set")]
596)
9c08d1fa 597
aea4c774 598(define_insn "*addsi3_compare0_scratch"
bd5b4116 599 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 600 (compare:CC_NOOV
215b30b3 601 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
602 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 603 (const_int 0)))]
25f905c2 604 "TARGET_32BIT"
cffb2a26 605 "@
606 cmn%?\\t%0, %1
607 cmp%?\\t%0, #%n1"
0d66636f 608 [(set_attr "conds" "set")]
609)
cffb2a26 610
aed179ae 611(define_insn "*compare_negsi_si"
612 [(set (reg:CC_Z CC_REGNUM)
613 (compare:CC_Z
614 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
615 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 616 "TARGET_32BIT"
aed179ae 617 "cmn%?\\t%1, %0"
0d66636f 618 [(set_attr "conds" "set")]
619)
aea4c774 620
203c488f 621;; This is the canonicalization of addsi3_compare0_for_combiner when the
622;; addend is a constant.
623(define_insn "*cmpsi2_addneg"
624 [(set (reg:CC CC_REGNUM)
625 (compare:CC
626 (match_operand:SI 1 "s_register_operand" "r,r")
627 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
628 (set (match_operand:SI 0 "s_register_operand" "=r,r")
629 (plus:SI (match_dup 1)
630 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
25f905c2 631 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 632 "@
25f905c2 633 sub%.\\t%0, %1, %2
634 add%.\\t%0, %1, #%n2"
203c488f 635 [(set_attr "conds" "set")]
636)
637
638;; Convert the sequence
639;; sub rd, rn, #1
640;; cmn rd, #1 (equivalent to cmp rd, #-1)
641;; bne dest
642;; into
643;; subs rd, rn, #1
644;; bcs dest ((unsigned)rn >= 1)
645;; similarly for the beq variant using bcc.
646;; This is a common looping idiom (while (n--))
647(define_peephole2
372575c7 648 [(set (match_operand:SI 0 "arm_general_register_operand" "")
649 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 650 (const_int -1)))
651 (set (match_operand 2 "cc_register" "")
652 (compare (match_dup 0) (const_int -1)))
653 (set (pc)
654 (if_then_else (match_operator 3 "equality_operator"
655 [(match_dup 2) (const_int 0)])
656 (match_operand 4 "" "")
657 (match_operand 5 "" "")))]
25f905c2 658 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 659 [(parallel[
660 (set (match_dup 2)
661 (compare:CC
662 (match_dup 1) (const_int 1)))
663 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
664 (set (pc)
665 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
666 (match_dup 4)
667 (match_dup 5)))]
668 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
669 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
670 ? GEU : LTU),
671 VOIDmode,
672 operands[2], const0_rtx);"
673)
674
ebcc79bc 675;; The next four insns work because they compare the result with one of
676;; the operands, and we know that the use of the condition code is
677;; either GEU or LTU, so we can use the carry flag from the addition
678;; instead of doing the compare a second time.
679(define_insn "*addsi3_compare_op1"
bd5b4116 680 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 681 (compare:CC_C
682 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
683 (match_operand:SI 2 "arm_add_operand" "rI,L"))
684 (match_dup 1)))
685 (set (match_operand:SI 0 "s_register_operand" "=r,r")
686 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 687 "TARGET_32BIT"
ebcc79bc 688 "@
25f905c2 689 add%.\\t%0, %1, %2
690 sub%.\\t%0, %1, #%n2"
0d66636f 691 [(set_attr "conds" "set")]
692)
ebcc79bc 693
694(define_insn "*addsi3_compare_op2"
bd5b4116 695 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 696 (compare:CC_C
697 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
698 (match_operand:SI 2 "arm_add_operand" "rI,L"))
699 (match_dup 2)))
5565501b 700 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 701 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 702 "TARGET_32BIT"
5565501b 703 "@
25f905c2 704 add%.\\t%0, %1, %2
705 sub%.\\t%0, %1, #%n2"
0d66636f 706 [(set_attr "conds" "set")]
707)
9c08d1fa 708
ebcc79bc 709(define_insn "*compare_addsi2_op0"
bd5b4116 710 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 711 (compare:CC_C
712 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
713 (match_operand:SI 1 "arm_add_operand" "rI,L"))
714 (match_dup 0)))]
25f905c2 715 "TARGET_32BIT"
ebcc79bc 716 "@
717 cmn%?\\t%0, %1
718 cmp%?\\t%0, #%n1"
0d66636f 719 [(set_attr "conds" "set")]
720)
ebcc79bc 721
722(define_insn "*compare_addsi2_op1"
bd5b4116 723 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 724 (compare:CC_C
725 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
726 (match_operand:SI 1 "arm_add_operand" "rI,L"))
727 (match_dup 1)))]
25f905c2 728 "TARGET_32BIT"
ebcc79bc 729 "@
730 cmn%?\\t%0, %1
731 cmp%?\\t%0, #%n1"
0d66636f 732 [(set_attr "conds" "set")]
733)
ebcc79bc 734
735(define_insn "*addsi3_carryin"
736 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 737 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 738 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
739 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
25f905c2 740 "TARGET_32BIT"
ebcc79bc 741 "adc%?\\t%0, %1, %2"
cffb2a26 742 [(set_attr "conds" "use")]
743)
ebcc79bc 744
33782ec7 745(define_insn "*addsi3_carryin_shift"
7b63a8dd 746 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 747 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 748 (plus:SI
749 (match_operator:SI 2 "shift_operator"
7b63a8dd 750 [(match_operand:SI 3 "s_register_operand" "r")
751 (match_operand:SI 4 "reg_or_int_operand" "rM")])
752 (match_operand:SI 1 "s_register_operand" "r"))))]
25f905c2 753 "TARGET_32BIT"
33782ec7 754 "adc%?\\t%0, %1, %3%S2"
a2cd141b 755 [(set_attr "conds" "use")
756 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
757 (const_string "alu_shift")
758 (const_string "alu_shift_reg")))]
33782ec7 759)
760
ebcc79bc 761(define_insn "*addsi3_carryin_alt1"
762 [(set (match_operand:SI 0 "s_register_operand" "=r")
763 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
764 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 765 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
25f905c2 766 "TARGET_32BIT"
ebcc79bc 767 "adc%?\\t%0, %1, %2"
cffb2a26 768 [(set_attr "conds" "use")]
769)
ebcc79bc 770
771(define_insn "*addsi3_carryin_alt2"
772 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 773 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 774 (match_operand:SI 1 "s_register_operand" "r"))
775 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 776 "TARGET_32BIT"
ebcc79bc 777 "adc%?\\t%0, %1, %2"
0d66636f 778 [(set_attr "conds" "use")]
779)
ebcc79bc 780
781(define_insn "*addsi3_carryin_alt3"
782 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 783 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 784 (match_operand:SI 2 "arm_rhs_operand" "rI"))
785 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 786 "TARGET_32BIT"
ebcc79bc 787 "adc%?\\t%0, %1, %2"
cffb2a26 788 [(set_attr "conds" "use")]
789)
ebcc79bc 790
25f905c2 791(define_expand "incscc"
792 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
793 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
794 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
795 (match_operand:SI 1 "s_register_operand" "0,?r")))]
796 "TARGET_32BIT"
797 ""
798)
799
800(define_insn "*arm_incscc"
9c08d1fa 801 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 802 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 803 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 804 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 805 "TARGET_ARM"
5565501b 806 "@
807 add%d2\\t%0, %1, #1
808 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 809 [(set_attr "conds" "use")
215b30b3 810 (set_attr "length" "4,8")]
811)
9c08d1fa 812
d795fb69 813; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
814(define_split
815 [(set (match_operand:SI 0 "s_register_operand" "")
816 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
817 (match_operand:SI 2 "s_register_operand" ""))
818 (const_int -1)))
819 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 820 "TARGET_32BIT"
d795fb69 821 [(set (match_dup 3) (match_dup 1))
822 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
823 "
824 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
825")
826
604f3a0a 827(define_expand "addsf3"
828 [(set (match_operand:SF 0 "s_register_operand" "")
829 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 830 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 831 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 832 "
a2cd141b 833 if (TARGET_MAVERICK
604f3a0a 834 && !cirrus_fp_register (operands[2], SFmode))
835 operands[2] = force_reg (SFmode, operands[2]);
836")
837
604f3a0a 838(define_expand "adddf3"
839 [(set (match_operand:DF 0 "s_register_operand" "")
840 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 841 (match_operand:DF 2 "arm_float_add_operand" "")))]
25f905c2 842 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 843 "
a2cd141b 844 if (TARGET_MAVERICK
604f3a0a 845 && !cirrus_fp_register (operands[2], DFmode))
846 operands[2] = force_reg (DFmode, operands[2]);
847")
848
cffb2a26 849(define_expand "subdi3"
850 [(parallel
851 [(set (match_operand:DI 0 "s_register_operand" "")
852 (minus:DI (match_operand:DI 1 "s_register_operand" "")
853 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 854 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 855 "TARGET_EITHER"
856 "
a2cd141b 857 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 858 && TARGET_32BIT
7d57ec45 859 && cirrus_fp_register (operands[0], DImode)
860 && cirrus_fp_register (operands[1], DImode))
861 {
862 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
863 DONE;
864 }
865
25f905c2 866 if (TARGET_THUMB1)
cffb2a26 867 {
868 if (GET_CODE (operands[1]) != REG)
869 operands[1] = force_reg (SImode, operands[1]);
870 if (GET_CODE (operands[2]) != REG)
871 operands[2] = force_reg (SImode, operands[2]);
872 }
873 "
874)
875
876(define_insn "*arm_subdi3"
877 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 878 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
879 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 880 (clobber (reg:CC CC_REGNUM))]
25f905c2 881 "TARGET_32BIT"
97499065 882 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 883 [(set_attr "conds" "clob")
884 (set_attr "length" "8")]
885)
886
887(define_insn "*thumb_subdi3"
888 [(set (match_operand:DI 0 "register_operand" "=l")
889 (minus:DI (match_operand:DI 1 "register_operand" "0")
890 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 891 (clobber (reg:CC CC_REGNUM))]
25f905c2 892 "TARGET_THUMB1"
cffb2a26 893 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
894 [(set_attr "length" "4")]
895)
9c08d1fa 896
f7fbdd4a 897(define_insn "*subdi_di_zesidi"
cffb2a26 898 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
899 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 900 (zero_extend:DI
cffb2a26 901 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 902 (clobber (reg:CC CC_REGNUM))]
25f905c2 903 "TARGET_32BIT"
97499065 904 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 905 [(set_attr "conds" "clob")
906 (set_attr "length" "8")]
907)
9c08d1fa 908
f7fbdd4a 909(define_insn "*subdi_di_sesidi"
cffb2a26 910 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
911 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 912 (sign_extend:DI
cffb2a26 913 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 914 (clobber (reg:CC CC_REGNUM))]
25f905c2 915 "TARGET_32BIT"
97499065 916 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 917 [(set_attr "conds" "clob")
918 (set_attr "length" "8")]
919)
9c08d1fa 920
f7fbdd4a 921(define_insn "*subdi_zesidi_di"
cffb2a26 922 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 923 (minus:DI (zero_extend:DI
cffb2a26 924 (match_operand:SI 2 "s_register_operand" "r,r"))
925 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 926 (clobber (reg:CC CC_REGNUM))]
cffb2a26 927 "TARGET_ARM"
97499065 928 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 929 [(set_attr "conds" "clob")
930 (set_attr "length" "8")]
931)
9c08d1fa 932
f7fbdd4a 933(define_insn "*subdi_sesidi_di"
cffb2a26 934 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 935 (minus:DI (sign_extend:DI
cffb2a26 936 (match_operand:SI 2 "s_register_operand" "r,r"))
937 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 938 (clobber (reg:CC CC_REGNUM))]
cffb2a26 939 "TARGET_ARM"
97499065 940 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 941 [(set_attr "conds" "clob")
942 (set_attr "length" "8")]
943)
9c08d1fa 944
f7fbdd4a 945(define_insn "*subdi_zesidi_zesidi"
cffb2a26 946 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 947 (minus:DI (zero_extend:DI
cffb2a26 948 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 949 (zero_extend:DI
cffb2a26 950 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 951 (clobber (reg:CC CC_REGNUM))]
25f905c2 952 "TARGET_32BIT"
953 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 954 [(set_attr "conds" "clob")
955 (set_attr "length" "8")]
956)
b11cae9e 957
87b22bf7 958(define_expand "subsi3"
cffb2a26 959 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 960 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
961 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 962 "TARGET_EITHER"
87b22bf7 963 "
964 if (GET_CODE (operands[1]) == CONST_INT)
965 {
25f905c2 966 if (TARGET_32BIT)
cffb2a26 967 {
96f57e36 968 arm_split_constant (MINUS, SImode, NULL_RTX,
969 INTVAL (operands[1]), operands[0],
e1ba4a27 970 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 971 DONE;
972 }
25f905c2 973 else /* TARGET_THUMB1 */
cffb2a26 974 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 975 }
cffb2a26 976 "
977)
87b22bf7 978
25f905c2 979(define_insn "*thumb1_subsi3_insn"
cffb2a26 980 [(set (match_operand:SI 0 "register_operand" "=l")
981 (minus:SI (match_operand:SI 1 "register_operand" "l")
982 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 983 "TARGET_THUMB1"
cffb2a26 984 "sub\\t%0, %1, %2"
985 [(set_attr "length" "2")]
986)
987
25f905c2 988; ??? Check Thumb-2 split length
a0f94409 989(define_insn_and_split "*arm_subsi3_insn"
cffb2a26 990 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 991 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
992 (match_operand:SI 2 "s_register_operand" "r,r")))]
25f905c2 993 "TARGET_32BIT"
e2348bcb 994 "@
87b22bf7 995 rsb%?\\t%0, %2, %1
996 #"
25f905c2 997 "TARGET_32BIT
a0f94409 998 && GET_CODE (operands[1]) == CONST_INT
999 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 1000 [(clobber (const_int 0))]
1001 "
96f57e36 1002 arm_split_constant (MINUS, SImode, curr_insn,
1003 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1004 DONE;
cffb2a26 1005 "
a0f94409 1006 [(set_attr "length" "4,16")
1007 (set_attr "predicable" "yes")]
1008)
1009
1010(define_peephole2
1011 [(match_scratch:SI 3 "r")
372575c7 1012 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1013 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1014 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1015 "TARGET_32BIT
a0f94409 1016 && !const_ok_for_arm (INTVAL (operands[1]))
1017 && const_ok_for_arm (~INTVAL (operands[1]))"
1018 [(set (match_dup 3) (match_dup 1))
1019 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1020 ""
cffb2a26 1021)
b11cae9e 1022
f7fbdd4a 1023(define_insn "*subsi3_compare0"
bd5b4116 1024 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1025 (compare:CC_NOOV
1026 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1027 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1028 (const_int 0)))
9c08d1fa 1029 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1030 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1031 "TARGET_32BIT"
e2348bcb 1032 "@
25f905c2 1033 sub%.\\t%0, %1, %2
1034 rsb%.\\t%0, %2, %1"
cffb2a26 1035 [(set_attr "conds" "set")]
1036)
9c08d1fa 1037
25f905c2 1038(define_expand "decscc"
1039 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1040 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1041 (match_operator:SI 2 "arm_comparison_operator"
1042 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1043 "TARGET_32BIT"
1044 ""
1045)
1046
1047(define_insn "*arm_decscc"
cffb2a26 1048 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1049 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1050 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1051 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1052 "TARGET_ARM"
e2348bcb 1053 "@
215b30b3 1054 sub%d2\\t%0, %1, #1
1055 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1056 [(set_attr "conds" "use")
1057 (set_attr "length" "*,8")]
1058)
9c08d1fa 1059
604f3a0a 1060(define_expand "subsf3"
1061 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1062 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1063 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1064 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1065 "
a2cd141b 1066 if (TARGET_MAVERICK)
604f3a0a 1067 {
1068 if (!cirrus_fp_register (operands[1], SFmode))
1069 operands[1] = force_reg (SFmode, operands[1]);
1070 if (!cirrus_fp_register (operands[2], SFmode))
1071 operands[2] = force_reg (SFmode, operands[2]);
1072 }
1073")
1074
604f3a0a 1075(define_expand "subdf3"
1076 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1077 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1078 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1079 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1080 "
a2cd141b 1081 if (TARGET_MAVERICK)
604f3a0a 1082 {
1083 if (!cirrus_fp_register (operands[1], DFmode))
1084 operands[1] = force_reg (DFmode, operands[1]);
1085 if (!cirrus_fp_register (operands[2], DFmode))
1086 operands[2] = force_reg (DFmode, operands[2]);
1087 }
1088")
1089
b11cae9e 1090\f
1091;; Multiplication insns
1092
cffb2a26 1093(define_expand "mulsi3"
1094 [(set (match_operand:SI 0 "s_register_operand" "")
1095 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1096 (match_operand:SI 1 "s_register_operand" "")))]
1097 "TARGET_EITHER"
1098 ""
1099)
1100
9c08d1fa 1101;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1102(define_insn "*arm_mulsi3"
1103 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1104 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1105 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
58d7d654 1106 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1107 "mul%?\\t%0, %2, %1"
a2cd141b 1108 [(set_attr "insn" "mul")
0d66636f 1109 (set_attr "predicable" "yes")]
cffb2a26 1110)
1111
58d7d654 1112(define_insn "*arm_mulsi3_v6"
1113 [(set (match_operand:SI 0 "s_register_operand" "=r")
1114 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1115 (match_operand:SI 2 "s_register_operand" "r")))]
1116 "TARGET_32BIT && arm_arch6"
1117 "mul%?\\t%0, %1, %2"
1118 [(set_attr "insn" "mul")
1119 (set_attr "predicable" "yes")]
1120)
1121
215b30b3 1122; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1123; 1 and 2; are the same, because reload will make operand 0 match
1124; operand 1 without realizing that this conflicts with operand 2. We fix
1125; this by adding another alternative to match this case, and then `reload'
1126; it ourselves. This alternative must come first.
cffb2a26 1127(define_insn "*thumb_mulsi3"
1128 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1129 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1130 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1131 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1132 "*
1133 if (which_alternative < 2)
20c4e896 1134 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1135 else
20c4e896 1136 return \"mul\\t%0, %2\";
cffb2a26 1137 "
1138 [(set_attr "length" "4,4,2")
a2cd141b 1139 (set_attr "insn" "mul")]
cffb2a26 1140)
b11cae9e 1141
58d7d654 1142(define_insn "*thumb_mulsi3_v6"
1143 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1144 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1145 (match_operand:SI 2 "register_operand" "l,0,0")))]
1146 "TARGET_THUMB1 && arm_arch6"
1147 "@
1148 mul\\t%0, %2
1149 mul\\t%0, %1
1150 mul\\t%0, %1"
1151 [(set_attr "length" "2")
1152 (set_attr "insn" "mul")]
1153)
1154
f7fbdd4a 1155(define_insn "*mulsi3_compare0"
bd5b4116 1156 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1157 (compare:CC_NOOV (mult:SI
1158 (match_operand:SI 2 "s_register_operand" "r,r")
1159 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1160 (const_int 0)))
1161 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1162 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1163 "TARGET_ARM && !arm_arch6"
1164 "mul%.\\t%0, %2, %1"
1165 [(set_attr "conds" "set")
1166 (set_attr "insn" "muls")]
1167)
1168
1169(define_insn "*mulsi3_compare0_v6"
1170 [(set (reg:CC_NOOV CC_REGNUM)
1171 (compare:CC_NOOV (mult:SI
1172 (match_operand:SI 2 "s_register_operand" "r")
1173 (match_operand:SI 1 "s_register_operand" "r"))
1174 (const_int 0)))
1175 (set (match_operand:SI 0 "s_register_operand" "=r")
1176 (mult:SI (match_dup 2) (match_dup 1)))]
1177 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1178 "mul%.\\t%0, %2, %1"
cffb2a26 1179 [(set_attr "conds" "set")
a2cd141b 1180 (set_attr "insn" "muls")]
cffb2a26 1181)
9c08d1fa 1182
f7fbdd4a 1183(define_insn "*mulsi_compare0_scratch"
bd5b4116 1184 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1185 (compare:CC_NOOV (mult:SI
1186 (match_operand:SI 2 "s_register_operand" "r,r")
1187 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1188 (const_int 0)))
1189 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1190 "TARGET_ARM && !arm_arch6"
1191 "mul%.\\t%0, %2, %1"
1192 [(set_attr "conds" "set")
1193 (set_attr "insn" "muls")]
1194)
1195
1196(define_insn "*mulsi_compare0_scratch_v6"
1197 [(set (reg:CC_NOOV CC_REGNUM)
1198 (compare:CC_NOOV (mult:SI
1199 (match_operand:SI 2 "s_register_operand" "r")
1200 (match_operand:SI 1 "s_register_operand" "r"))
1201 (const_int 0)))
1202 (clobber (match_scratch:SI 0 "=r"))]
1203 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1204 "mul%.\\t%0, %2, %1"
cffb2a26 1205 [(set_attr "conds" "set")
a2cd141b 1206 (set_attr "insn" "muls")]
cffb2a26 1207)
9c08d1fa 1208
b11cae9e 1209;; Unnamed templates to match MLA instruction.
1210
f7fbdd4a 1211(define_insn "*mulsi3addsi"
9c08d1fa 1212 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1213 (plus:SI
9c08d1fa 1214 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1215 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1216 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
58d7d654 1217 "TARGET_32BIT && !arm_arch6"
1218 "mla%?\\t%0, %2, %1, %3"
1219 [(set_attr "insn" "mla")
1220 (set_attr "predicable" "yes")]
1221)
1222
1223(define_insn "*mulsi3addsi_v6"
1224 [(set (match_operand:SI 0 "s_register_operand" "=r")
1225 (plus:SI
1226 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1227 (match_operand:SI 1 "s_register_operand" "r"))
1228 (match_operand:SI 3 "s_register_operand" "r")))]
1229 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1230 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1231 [(set_attr "insn" "mla")
0d66636f 1232 (set_attr "predicable" "yes")]
1233)
b11cae9e 1234
f7fbdd4a 1235(define_insn "*mulsi3addsi_compare0"
bd5b4116 1236 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1237 (compare:CC_NOOV
1238 (plus:SI (mult:SI
1239 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1240 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1241 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1242 (const_int 0)))
9c08d1fa 1243 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1244 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1245 (match_dup 3)))]
58d7d654 1246 "TARGET_ARM && arm_arch6"
1247 "mla%.\\t%0, %2, %1, %3"
1248 [(set_attr "conds" "set")
1249 (set_attr "insn" "mlas")]
1250)
1251
1252(define_insn "*mulsi3addsi_compare0_v6"
1253 [(set (reg:CC_NOOV CC_REGNUM)
1254 (compare:CC_NOOV
1255 (plus:SI (mult:SI
1256 (match_operand:SI 2 "s_register_operand" "r")
1257 (match_operand:SI 1 "s_register_operand" "r"))
1258 (match_operand:SI 3 "s_register_operand" "r"))
1259 (const_int 0)))
1260 (set (match_operand:SI 0 "s_register_operand" "=r")
1261 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1262 (match_dup 3)))]
1263 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1264 "mla%.\\t%0, %2, %1, %3"
0d66636f 1265 [(set_attr "conds" "set")
a2cd141b 1266 (set_attr "insn" "mlas")]
0d66636f 1267)
9c08d1fa 1268
f7fbdd4a 1269(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1270 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1271 (compare:CC_NOOV
1272 (plus:SI (mult:SI
1273 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1274 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1275 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1276 (const_int 0)))
9c08d1fa 1277 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1278 "TARGET_ARM && !arm_arch6"
1279 "mla%.\\t%0, %2, %1, %3"
1280 [(set_attr "conds" "set")
1281 (set_attr "insn" "mlas")]
1282)
1283
1284(define_insn "*mulsi3addsi_compare0_scratch_v6"
1285 [(set (reg:CC_NOOV CC_REGNUM)
1286 (compare:CC_NOOV
1287 (plus:SI (mult:SI
1288 (match_operand:SI 2 "s_register_operand" "r")
1289 (match_operand:SI 1 "s_register_operand" "r"))
1290 (match_operand:SI 3 "s_register_operand" "r"))
1291 (const_int 0)))
1292 (clobber (match_scratch:SI 0 "=r"))]
1293 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1294 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1295 [(set_attr "conds" "set")
a2cd141b 1296 (set_attr "insn" "mlas")]
cffb2a26 1297)
f7fbdd4a 1298
89545238 1299(define_insn "*mulsi3subsi"
1300 [(set (match_operand:SI 0 "s_register_operand" "=r")
1301 (minus:SI
1302 (match_operand:SI 3 "s_register_operand" "r")
1303 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1304 (match_operand:SI 1 "s_register_operand" "r"))))]
1305 "TARGET_32BIT && arm_arch_thumb2"
1306 "mls%?\\t%0, %2, %1, %3"
1307 [(set_attr "insn" "mla")
1308 (set_attr "predicable" "yes")]
1309)
1310
efee20da 1311;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1312
1313(define_insn "*mulsidi3adddi"
fe8dbf85 1314 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1315 (plus:DI
215b30b3 1316 (mult:DI
fe8dbf85 1317 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1318 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1319 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1320 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1321 "smlal%?\\t%Q0, %R0, %3, %2"
1322 [(set_attr "insn" "smlal")
1323 (set_attr "predicable" "yes")]
1324)
1325
1326(define_insn "*mulsidi3adddi_v6"
1327 [(set (match_operand:DI 0 "s_register_operand" "=r")
1328 (plus:DI
1329 (mult:DI
1330 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1331 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1332 (match_operand:DI 1 "s_register_operand" "0")))]
1333 "TARGET_32BIT && arm_arch6"
fe8dbf85 1334 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1335 [(set_attr "insn" "smlal")
0d66636f 1336 (set_attr "predicable" "yes")]
1337)
82b85d08 1338
f7fbdd4a 1339(define_insn "mulsidi3"
1340 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1341 (mult:DI
1342 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1343 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1344 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1345 "smull%?\\t%Q0, %R0, %1, %2"
1346 [(set_attr "insn" "smull")
1347 (set_attr "predicable" "yes")]
1348)
1349
1350(define_insn "mulsidi3_v6"
1351 [(set (match_operand:DI 0 "s_register_operand" "=r")
1352 (mult:DI
1353 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1354 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1355 "TARGET_32BIT && arm_arch6"
97499065 1356 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1357 [(set_attr "insn" "smull")
0d66636f 1358 (set_attr "predicable" "yes")]
1359)
f7fbdd4a 1360
1361(define_insn "umulsidi3"
1362 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1363 (mult:DI
1364 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1365 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1366 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1367 "umull%?\\t%Q0, %R0, %1, %2"
1368 [(set_attr "insn" "umull")
1369 (set_attr "predicable" "yes")]
1370)
1371
1372(define_insn "umulsidi3_v6"
1373 [(set (match_operand:DI 0 "s_register_operand" "=r")
1374 (mult:DI
1375 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1376 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1377 "TARGET_32BIT && arm_arch6"
97499065 1378 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1379 [(set_attr "insn" "umull")
0d66636f 1380 (set_attr "predicable" "yes")]
1381)
b11cae9e 1382
efee20da 1383;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1384
1385(define_insn "*umulsidi3adddi"
8ead09f9 1386 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1387 (plus:DI
215b30b3 1388 (mult:DI
fe8dbf85 1389 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1390 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1391 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1392 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1393 "umlal%?\\t%Q0, %R0, %3, %2"
1394 [(set_attr "insn" "umlal")
1395 (set_attr "predicable" "yes")]
1396)
1397
1398(define_insn "*umulsidi3adddi_v6"
1399 [(set (match_operand:DI 0 "s_register_operand" "=r")
1400 (plus:DI
1401 (mult:DI
1402 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1403 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1404 (match_operand:DI 1 "s_register_operand" "0")))]
1405 "TARGET_32BIT && arm_arch6"
fe8dbf85 1406 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1407 [(set_attr "insn" "umlal")
0d66636f 1408 (set_attr "predicable" "yes")]
1409)
82b85d08 1410
f082f1c4 1411(define_insn "smulsi3_highpart"
1412 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1413 (truncate:SI
1414 (lshiftrt:DI
215b30b3 1415 (mult:DI
1416 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1417 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1418 (const_int 32))))
1419 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1420 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1421 "smull%?\\t%3, %0, %2, %1"
1422 [(set_attr "insn" "smull")
1423 (set_attr "predicable" "yes")]
1424)
1425
1426(define_insn "smulsi3_highpart_v6"
1427 [(set (match_operand:SI 0 "s_register_operand" "=r")
1428 (truncate:SI
1429 (lshiftrt:DI
1430 (mult:DI
1431 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1432 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1433 (const_int 32))))
1434 (clobber (match_scratch:SI 3 "=r"))]
1435 "TARGET_32BIT && arm_arch6"
f082f1c4 1436 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1437 [(set_attr "insn" "smull")
0d66636f 1438 (set_attr "predicable" "yes")]
cffb2a26 1439)
f082f1c4 1440
1441(define_insn "umulsi3_highpart"
1442 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1443 (truncate:SI
1444 (lshiftrt:DI
215b30b3 1445 (mult:DI
1446 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1447 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1448 (const_int 32))))
1449 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1450 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1451 "umull%?\\t%3, %0, %2, %1"
1452 [(set_attr "insn" "umull")
1453 (set_attr "predicable" "yes")]
1454)
1455
1456(define_insn "umulsi3_highpart_v6"
1457 [(set (match_operand:SI 0 "s_register_operand" "=r")
1458 (truncate:SI
1459 (lshiftrt:DI
1460 (mult:DI
1461 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1462 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1463 (const_int 32))))
1464 (clobber (match_scratch:SI 3 "=r"))]
1465 "TARGET_32BIT && arm_arch6"
f082f1c4 1466 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1467 [(set_attr "insn" "umull")
0d66636f 1468 (set_attr "predicable" "yes")]
cffb2a26 1469)
f082f1c4 1470
331beb1a 1471(define_insn "mulhisi3"
1472 [(set (match_operand:SI 0 "s_register_operand" "=r")
1473 (mult:SI (sign_extend:SI
1474 (match_operand:HI 1 "s_register_operand" "%r"))
1475 (sign_extend:SI
1476 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1477 "TARGET_DSP_MULTIPLY"
61a2d04c 1478 "smulbb%?\\t%0, %1, %2"
a2cd141b 1479 [(set_attr "insn" "smulxy")
fec538d9 1480 (set_attr "predicable" "yes")]
1481)
1482
1483(define_insn "*mulhisi3tb"
1484 [(set (match_operand:SI 0 "s_register_operand" "=r")
1485 (mult:SI (ashiftrt:SI
1486 (match_operand:SI 1 "s_register_operand" "r")
1487 (const_int 16))
1488 (sign_extend:SI
1489 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1490 "TARGET_DSP_MULTIPLY"
fec538d9 1491 "smultb%?\\t%0, %1, %2"
a2cd141b 1492 [(set_attr "insn" "smulxy")
fec538d9 1493 (set_attr "predicable" "yes")]
1494)
1495
1496(define_insn "*mulhisi3bt"
1497 [(set (match_operand:SI 0 "s_register_operand" "=r")
1498 (mult:SI (sign_extend:SI
1499 (match_operand:HI 1 "s_register_operand" "r"))
1500 (ashiftrt:SI
1501 (match_operand:SI 2 "s_register_operand" "r")
1502 (const_int 16))))]
25f905c2 1503 "TARGET_DSP_MULTIPLY"
fec538d9 1504 "smulbt%?\\t%0, %1, %2"
a2cd141b 1505 [(set_attr "insn" "smulxy")
fec538d9 1506 (set_attr "predicable" "yes")]
1507)
1508
1509(define_insn "*mulhisi3tt"
1510 [(set (match_operand:SI 0 "s_register_operand" "=r")
1511 (mult:SI (ashiftrt:SI
1512 (match_operand:SI 1 "s_register_operand" "r")
1513 (const_int 16))
1514 (ashiftrt:SI
1515 (match_operand:SI 2 "s_register_operand" "r")
1516 (const_int 16))))]
25f905c2 1517 "TARGET_DSP_MULTIPLY"
fec538d9 1518 "smultt%?\\t%0, %1, %2"
a2cd141b 1519 [(set_attr "insn" "smulxy")
fec538d9 1520 (set_attr "predicable" "yes")]
331beb1a 1521)
1522
1523(define_insn "*mulhisi3addsi"
1524 [(set (match_operand:SI 0 "s_register_operand" "=r")
1525 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1526 (mult:SI (sign_extend:SI
1527 (match_operand:HI 2 "s_register_operand" "%r"))
1528 (sign_extend:SI
1529 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1530 "TARGET_DSP_MULTIPLY"
61a2d04c 1531 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1532 [(set_attr "insn" "smlaxy")
fec538d9 1533 (set_attr "predicable" "yes")]
331beb1a 1534)
1535
1536(define_insn "*mulhidi3adddi"
1537 [(set (match_operand:DI 0 "s_register_operand" "=r")
1538 (plus:DI
1539 (match_operand:DI 1 "s_register_operand" "0")
1540 (mult:DI (sign_extend:DI
1541 (match_operand:HI 2 "s_register_operand" "%r"))
1542 (sign_extend:DI
1543 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1544 "TARGET_DSP_MULTIPLY"
331beb1a 1545 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1546 [(set_attr "insn" "smlalxy")
fec538d9 1547 (set_attr "predicable" "yes")])
331beb1a 1548
604f3a0a 1549(define_expand "mulsf3"
1550 [(set (match_operand:SF 0 "s_register_operand" "")
1551 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1552 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1553 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1554 "
a2cd141b 1555 if (TARGET_MAVERICK
604f3a0a 1556 && !cirrus_fp_register (operands[2], SFmode))
1557 operands[2] = force_reg (SFmode, operands[2]);
1558")
1559
604f3a0a 1560(define_expand "muldf3"
1561 [(set (match_operand:DF 0 "s_register_operand" "")
1562 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1563 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1564 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1565 "
a2cd141b 1566 if (TARGET_MAVERICK
604f3a0a 1567 && !cirrus_fp_register (operands[2], DFmode))
1568 operands[2] = force_reg (DFmode, operands[2]);
1569")
b11cae9e 1570\f
1571;; Division insns
1572
7db9af5d 1573(define_expand "divsf3"
1574 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1575 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1576 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1577 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1578 "")
9c08d1fa 1579
7db9af5d 1580(define_expand "divdf3"
1581 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1582 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1583 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1584 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1585 "")
b11cae9e 1586\f
1587;; Modulo insns
1588
7db9af5d 1589(define_expand "modsf3"
1590 [(set (match_operand:SF 0 "s_register_operand" "")
1591 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1592 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1593 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1594 "")
9c08d1fa 1595
7db9af5d 1596(define_expand "moddf3"
1597 [(set (match_operand:DF 0 "s_register_operand" "")
1598 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1599 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1600 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1601 "")
b11cae9e 1602\f
1603;; Boolean and,ior,xor insns
1604
f6ebffac 1605;; Split up double word logical operations
1606
1607;; Split up simple DImode logical operations. Simply perform the logical
1608;; operation on the upper and lower halves of the registers.
1609(define_split
1610 [(set (match_operand:DI 0 "s_register_operand" "")
1611 (match_operator:DI 6 "logical_binary_operator"
1612 [(match_operand:DI 1 "s_register_operand" "")
1613 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1614 "TARGET_32BIT && reload_completed
1615 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1616 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1617 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1618 "
215b30b3 1619 {
1620 operands[3] = gen_highpart (SImode, operands[0]);
1621 operands[0] = gen_lowpart (SImode, operands[0]);
1622 operands[4] = gen_highpart (SImode, operands[1]);
1623 operands[1] = gen_lowpart (SImode, operands[1]);
1624 operands[5] = gen_highpart (SImode, operands[2]);
1625 operands[2] = gen_lowpart (SImode, operands[2]);
1626 }"
1627)
f6ebffac 1628
f6ebffac 1629(define_split
1630 [(set (match_operand:DI 0 "s_register_operand" "")
1631 (match_operator:DI 6 "logical_binary_operator"
1632 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1633 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1634 "TARGET_32BIT && reload_completed"
f6ebffac 1635 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1636 (set (match_dup 3) (match_op_dup:SI 6
1637 [(ashiftrt:SI (match_dup 2) (const_int 31))
1638 (match_dup 4)]))]
1639 "
215b30b3 1640 {
1641 operands[3] = gen_highpart (SImode, operands[0]);
1642 operands[0] = gen_lowpart (SImode, operands[0]);
1643 operands[4] = gen_highpart (SImode, operands[1]);
1644 operands[1] = gen_lowpart (SImode, operands[1]);
1645 operands[5] = gen_highpart (SImode, operands[2]);
1646 operands[2] = gen_lowpart (SImode, operands[2]);
1647 }"
1648)
f6ebffac 1649
f6ebffac 1650;; The zero extend of operand 2 means we can just copy the high part of
1651;; operand1 into operand0.
1652(define_split
1653 [(set (match_operand:DI 0 "s_register_operand" "")
1654 (ior:DI
1655 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1656 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1657 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1658 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1659 (set (match_dup 3) (match_dup 4))]
1660 "
215b30b3 1661 {
1662 operands[4] = gen_highpart (SImode, operands[1]);
1663 operands[3] = gen_highpart (SImode, operands[0]);
1664 operands[0] = gen_lowpart (SImode, operands[0]);
1665 operands[1] = gen_lowpart (SImode, operands[1]);
1666 }"
1667)
f6ebffac 1668
1669;; The zero extend of operand 2 means we can just copy the high part of
1670;; operand1 into operand0.
1671(define_split
1672 [(set (match_operand:DI 0 "s_register_operand" "")
1673 (xor:DI
1674 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1675 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1676 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1677 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1678 (set (match_dup 3) (match_dup 4))]
1679 "
215b30b3 1680 {
1681 operands[4] = gen_highpart (SImode, operands[1]);
1682 operands[3] = gen_highpart (SImode, operands[0]);
1683 operands[0] = gen_lowpart (SImode, operands[0]);
1684 operands[1] = gen_lowpart (SImode, operands[1]);
1685 }"
1686)
f6ebffac 1687
b11cae9e 1688(define_insn "anddi3"
cffb2a26 1689 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1690 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1691 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 1692 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 1693 "#"
215b30b3 1694 [(set_attr "length" "8")]
1695)
b11cae9e 1696
a0f94409 1697(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1698 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1699 (and:DI (zero_extend:DI
1700 (match_operand:SI 2 "s_register_operand" "r,r"))
1701 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1702 "TARGET_32BIT"
f6ebffac 1703 "#"
25f905c2 1704 "TARGET_32BIT && reload_completed"
a0f94409 1705 ; The zero extend of operand 2 clears the high word of the output
1706 ; operand.
1707 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1708 (set (match_dup 3) (const_int 0))]
1709 "
1710 {
1711 operands[3] = gen_highpart (SImode, operands[0]);
1712 operands[0] = gen_lowpart (SImode, operands[0]);
1713 operands[1] = gen_lowpart (SImode, operands[1]);
1714 }"
215b30b3 1715 [(set_attr "length" "8")]
1716)
b11cae9e 1717
f7fbdd4a 1718(define_insn "*anddi_sesdi_di"
cffb2a26 1719 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1720 (and:DI (sign_extend:DI
1721 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1722 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1723 "TARGET_32BIT"
f6ebffac 1724 "#"
cffb2a26 1725 [(set_attr "length" "8")]
1726)
b11cae9e 1727
87b22bf7 1728(define_expand "andsi3"
cffb2a26 1729 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1730 (and:SI (match_operand:SI 1 "s_register_operand" "")
1731 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1732 "TARGET_EITHER"
87b22bf7 1733 "
25f905c2 1734 if (TARGET_32BIT)
87b22bf7 1735 {
cffb2a26 1736 if (GET_CODE (operands[2]) == CONST_INT)
1737 {
96f57e36 1738 arm_split_constant (AND, SImode, NULL_RTX,
1739 INTVAL (operands[2]), operands[0],
e1ba4a27 1740 operands[1], optimize && can_create_pseudo_p ());
615caa51 1741
cffb2a26 1742 DONE;
1743 }
87b22bf7 1744 }
25f905c2 1745 else /* TARGET_THUMB1 */
cffb2a26 1746 {
1747 if (GET_CODE (operands[2]) != CONST_INT)
1748 operands[2] = force_reg (SImode, operands[2]);
1749 else
1750 {
1751 int i;
1752
215b30b3 1753 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1754 {
215b30b3 1755 operands[2] = force_reg (SImode,
1756 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1757
1758 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1759
1760 DONE;
1761 }
87b22bf7 1762
cffb2a26 1763 for (i = 9; i <= 31; i++)
1764 {
1765 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1766 {
1767 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1768 const0_rtx));
1769 DONE;
1770 }
215b30b3 1771 else if ((((HOST_WIDE_INT) 1) << i) - 1
1772 == ~INTVAL (operands[2]))
cffb2a26 1773 {
1774 rtx shift = GEN_INT (i);
1775 rtx reg = gen_reg_rtx (SImode);
1776
1777 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1778 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1779
1780 DONE;
1781 }
1782 }
1783
1784 operands[2] = force_reg (SImode, operands[2]);
1785 }
215b30b3 1786 }
1787 "
cffb2a26 1788)
1789
25f905c2 1790; ??? Check split length for Thumb-2
a0f94409 1791(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1792 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1793 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1794 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 1795 "TARGET_32BIT"
5565501b 1796 "@
1797 and%?\\t%0, %1, %2
87b22bf7 1798 bic%?\\t%0, %1, #%B2
1799 #"
25f905c2 1800 "TARGET_32BIT
a0f94409 1801 && GET_CODE (operands[2]) == CONST_INT
1802 && !(const_ok_for_arm (INTVAL (operands[2]))
1803 || const_ok_for_arm (~INTVAL (operands[2])))"
1804 [(clobber (const_int 0))]
1805 "
96f57e36 1806 arm_split_constant (AND, SImode, curr_insn,
1807 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1808 DONE;
1809 "
0d66636f 1810 [(set_attr "length" "4,4,16")
1811 (set_attr "predicable" "yes")]
cffb2a26 1812)
1813
25f905c2 1814(define_insn "*thumb1_andsi3_insn"
cffb2a26 1815 [(set (match_operand:SI 0 "register_operand" "=l")
1816 (and:SI (match_operand:SI 1 "register_operand" "%0")
1817 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1818 "TARGET_THUMB1"
cffb2a26 1819 "and\\t%0, %0, %2"
1820 [(set_attr "length" "2")]
1821)
87b22bf7 1822
f7fbdd4a 1823(define_insn "*andsi3_compare0"
bd5b4116 1824 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1825 (compare:CC_NOOV
1826 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1827 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1828 (const_int 0)))
cffb2a26 1829 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 1830 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 1831 "TARGET_32BIT"
5565501b 1832 "@
25f905c2 1833 and%.\\t%0, %1, %2
1834 bic%.\\t%0, %1, #%B2"
cffb2a26 1835 [(set_attr "conds" "set")]
1836)
9c08d1fa 1837
f7fbdd4a 1838(define_insn "*andsi3_compare0_scratch"
bd5b4116 1839 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1840 (compare:CC_NOOV
1841 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1842 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1843 (const_int 0)))
dd193d7c 1844 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 1845 "TARGET_32BIT"
5565501b 1846 "@
1847 tst%?\\t%0, %1
25f905c2 1848 bic%.\\t%2, %0, #%B1"
0d66636f 1849 [(set_attr "conds" "set")]
1850)
9c08d1fa 1851
f7fbdd4a 1852(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 1853 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1854 (compare:CC_NOOV (zero_extract:SI
1855 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 1856 (match_operand 1 "const_int_operand" "n")
1857 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 1858 (const_int 0)))]
25f905c2 1859 "TARGET_32BIT
cffb2a26 1860 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1861 && INTVAL (operands[1]) > 0
1862 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1863 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 1864 "*
5c49a439 1865 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1866 << INTVAL (operands[2]));
40dbec34 1867 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 1868 return \"\";
0d66636f 1869 "
1870 [(set_attr "conds" "set")]
1871)
9c08d1fa 1872
f4462328 1873(define_insn_and_split "*ne_zeroextractsi"
c4034607 1874 [(set (match_operand:SI 0 "s_register_operand" "=r")
1875 (ne:SI (zero_extract:SI
1876 (match_operand:SI 1 "s_register_operand" "r")
1877 (match_operand:SI 2 "const_int_operand" "n")
1878 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 1879 (const_int 0)))
1880 (clobber (reg:CC CC_REGNUM))]
25f905c2 1881 "TARGET_32BIT
cffb2a26 1882 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1883 && INTVAL (operands[2]) > 0
1884 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1885 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 1886 "#"
25f905c2 1887 "TARGET_32BIT
f4462328 1888 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1889 && INTVAL (operands[2]) > 0
1890 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1891 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1892 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1893 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1894 (const_int 0)))
1895 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1896 (set (match_dup 0)
1897 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1898 (match_dup 0) (const_int 1)))]
1899 "
1900 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1901 << INTVAL (operands[3]));
1902 "
1903 [(set_attr "conds" "clob")
25f905c2 1904 (set (attr "length")
1905 (if_then_else (eq_attr "is_thumb" "yes")
1906 (const_int 12)
1907 (const_int 8)))]
f4462328 1908)
1909
1910(define_insn_and_split "*ne_zeroextractsi_shifted"
1911 [(set (match_operand:SI 0 "s_register_operand" "=r")
1912 (ne:SI (zero_extract:SI
1913 (match_operand:SI 1 "s_register_operand" "r")
1914 (match_operand:SI 2 "const_int_operand" "n")
1915 (const_int 0))
1916 (const_int 0)))
1917 (clobber (reg:CC CC_REGNUM))]
1918 "TARGET_ARM"
1919 "#"
1920 "TARGET_ARM"
1921 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1922 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1923 (const_int 0)))
1924 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1925 (set (match_dup 0)
1926 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1927 (match_dup 0) (const_int 1)))]
1928 "
1929 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1930 "
1931 [(set_attr "conds" "clob")
1932 (set_attr "length" "8")]
1933)
1934
1935(define_insn_and_split "*ite_ne_zeroextractsi"
1936 [(set (match_operand:SI 0 "s_register_operand" "=r")
1937 (if_then_else:SI (ne (zero_extract:SI
1938 (match_operand:SI 1 "s_register_operand" "r")
1939 (match_operand:SI 2 "const_int_operand" "n")
1940 (match_operand:SI 3 "const_int_operand" "n"))
1941 (const_int 0))
1942 (match_operand:SI 4 "arm_not_operand" "rIK")
1943 (const_int 0)))
1944 (clobber (reg:CC CC_REGNUM))]
1945 "TARGET_ARM
1946 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1947 && INTVAL (operands[2]) > 0
1948 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1949 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1950 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1951 "#"
1952 "TARGET_ARM
1953 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1954 && INTVAL (operands[2]) > 0
1955 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1956 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1957 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1958 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1959 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1960 (const_int 0)))
1961 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1962 (set (match_dup 0)
1963 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1964 (match_dup 0) (match_dup 4)))]
1965 "
c4034607 1966 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 1967 << INTVAL (operands[3]));
1968 "
1969 [(set_attr "conds" "clob")
1970 (set_attr "length" "8")]
1971)
1972
1973(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1974 [(set (match_operand:SI 0 "s_register_operand" "=r")
1975 (if_then_else:SI (ne (zero_extract:SI
1976 (match_operand:SI 1 "s_register_operand" "r")
1977 (match_operand:SI 2 "const_int_operand" "n")
1978 (const_int 0))
1979 (const_int 0))
1980 (match_operand:SI 3 "arm_not_operand" "rIK")
1981 (const_int 0)))
1982 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 1983 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1984 "#"
f8d7bf2f 1985 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1986 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1987 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1988 (const_int 0)))
1989 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1990 (set (match_dup 0)
1991 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1992 (match_dup 0) (match_dup 3)))]
1993 "
1994 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 1995 "
1996 [(set_attr "conds" "clob")
215b30b3 1997 (set_attr "length" "8")]
1998)
9c08d1fa 1999
58d6528b 2000(define_split
2001 [(set (match_operand:SI 0 "s_register_operand" "")
2002 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2003 (match_operand:SI 2 "const_int_operand" "")
2004 (match_operand:SI 3 "const_int_operand" "")))
2005 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2006 "TARGET_THUMB1"
58d6528b 2007 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2008 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2009 "{
2010 HOST_WIDE_INT temp = INTVAL (operands[2]);
2011
2012 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2013 operands[3] = GEN_INT (32 - temp);
2014 }"
2015)
2016
25f905c2 2017;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2018(define_split
2019 [(set (match_operand:SI 0 "s_register_operand" "")
2020 (match_operator:SI 1 "shiftable_operator"
2021 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2022 (match_operand:SI 3 "const_int_operand" "")
2023 (match_operand:SI 4 "const_int_operand" ""))
2024 (match_operand:SI 5 "s_register_operand" "")]))
2025 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2026 "TARGET_ARM"
2027 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2028 (set (match_dup 0)
2029 (match_op_dup 1
2030 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2031 (match_dup 5)]))]
2032 "{
2033 HOST_WIDE_INT temp = INTVAL (operands[3]);
2034
2035 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2036 operands[4] = GEN_INT (32 - temp);
2037 }"
2038)
2039
58d6528b 2040(define_split
2041 [(set (match_operand:SI 0 "s_register_operand" "")
2042 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2043 (match_operand:SI 2 "const_int_operand" "")
2044 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2045 "TARGET_THUMB1"
58d6528b 2046 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2047 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2048 "{
2049 HOST_WIDE_INT temp = INTVAL (operands[2]);
2050
2051 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2052 operands[3] = GEN_INT (32 - temp);
2053 }"
2054)
2055
d7863cfe 2056(define_split
2057 [(set (match_operand:SI 0 "s_register_operand" "")
2058 (match_operator:SI 1 "shiftable_operator"
2059 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2060 (match_operand:SI 3 "const_int_operand" "")
2061 (match_operand:SI 4 "const_int_operand" ""))
2062 (match_operand:SI 5 "s_register_operand" "")]))
2063 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2064 "TARGET_ARM"
2065 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2066 (set (match_dup 0)
2067 (match_op_dup 1
2068 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2069 (match_dup 5)]))]
2070 "{
2071 HOST_WIDE_INT temp = INTVAL (operands[3]);
2072
2073 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2074 operands[4] = GEN_INT (32 - temp);
2075 }"
2076)
2077
a42059fd 2078;;; ??? This pattern is bogus. If operand3 has bits outside the range
2079;;; represented by the bitfield, then this will produce incorrect results.
2080;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2081;;; which have a real bit-field insert instruction, the truncation happens
2082;;; in the bit-field insert instruction itself. Since arm does not have a
2083;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2084;;; the value before we insert. This loses some of the advantage of having
2085;;; this insv pattern, so this pattern needs to be reevalutated.
2086
25f905c2 2087; ??? Use Thumb-2 bitfield insert/extract instructions
8a18b90c 2088(define_expand "insv"
2089 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2090 (match_operand:SI 1 "general_operand" "")
2091 (match_operand:SI 2 "general_operand" ""))
19335226 2092 (match_operand:SI 3 "reg_or_int_operand" ""))]
cffb2a26 2093 "TARGET_ARM"
8a18b90c 2094 "
215b30b3 2095 {
2096 int start_bit = INTVAL (operands[2]);
2097 int width = INTVAL (operands[1]);
2098 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2099 rtx target, subtarget;
2100
2101 target = operands[0];
2102 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2103 subreg as the final target. */
2104 if (GET_CODE (target) == SUBREG)
2105 {
2106 subtarget = gen_reg_rtx (SImode);
2107 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2108 < GET_MODE_SIZE (SImode))
2109 target = SUBREG_REG (target);
2110 }
2111 else
2112 subtarget = target;
8a18b90c 2113
215b30b3 2114 if (GET_CODE (operands[3]) == CONST_INT)
2115 {
2116 /* Since we are inserting a known constant, we may be able to
2117 reduce the number of bits that we have to clear so that
2118 the mask becomes simple. */
2119 /* ??? This code does not check to see if the new mask is actually
2120 simpler. It may not be. */
2121 rtx op1 = gen_reg_rtx (SImode);
2122 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2123 start of this pattern. */
2124 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2125 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2126
c5b3a71b 2127 emit_insn (gen_andsi3 (op1, operands[0],
2128 gen_int_mode (~mask2, SImode)));
215b30b3 2129 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2130 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2131 }
2132 else if (start_bit == 0
2133 && !(const_ok_for_arm (mask)
2134 || const_ok_for_arm (~mask)))
2135 {
2136 /* A Trick, since we are setting the bottom bits in the word,
2137 we can shift operand[3] up, operand[0] down, OR them together
2138 and rotate the result back again. This takes 3 insns, and
5910bb95 2139 the third might be mergeable into another op. */
215b30b3 2140 /* The shift up copes with the possibility that operand[3] is
2141 wider than the bitfield. */
2142 rtx op0 = gen_reg_rtx (SImode);
2143 rtx op1 = gen_reg_rtx (SImode);
2144
2145 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2146 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2147 emit_insn (gen_iorsi3 (op1, op1, op0));
2148 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2149 }
2150 else if ((width + start_bit == 32)
2151 && !(const_ok_for_arm (mask)
2152 || const_ok_for_arm (~mask)))
2153 {
2154 /* Similar trick, but slightly less efficient. */
8a18b90c 2155
215b30b3 2156 rtx op0 = gen_reg_rtx (SImode);
2157 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2158
215b30b3 2159 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2160 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2161 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2162 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2163 }
2164 else
2165 {
c5b3a71b 2166 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2167 rtx op1 = gen_reg_rtx (SImode);
2168 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2169
215b30b3 2170 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2171 {
2172 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2173
215b30b3 2174 emit_insn (gen_movsi (tmp, op0));
2175 op0 = tmp;
2176 }
8a18b90c 2177
215b30b3 2178 /* Mask out any bits in operand[3] that are not needed. */
2179 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2180
215b30b3 2181 if (GET_CODE (op0) == CONST_INT
2182 && (const_ok_for_arm (mask << start_bit)
2183 || const_ok_for_arm (~(mask << start_bit))))
2184 {
c5b3a71b 2185 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2186 emit_insn (gen_andsi3 (op2, operands[0], op0));
2187 }
2188 else
2189 {
2190 if (GET_CODE (op0) == CONST_INT)
2191 {
2192 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2193
215b30b3 2194 emit_insn (gen_movsi (tmp, op0));
2195 op0 = tmp;
2196 }
2197
2198 if (start_bit != 0)
2199 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2200
215b30b3 2201 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2202 }
8a18b90c 2203
215b30b3 2204 if (start_bit != 0)
2205 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2206
215b30b3 2207 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2208 }
f082f1c4 2209
215b30b3 2210 if (subtarget != target)
2211 {
2212 /* If TARGET is still a SUBREG, then it must be wider than a word,
2213 so we must be careful only to set the subword we were asked to. */
2214 if (GET_CODE (target) == SUBREG)
2215 emit_move_insn (target, subtarget);
2216 else
2217 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2218 }
8a18b90c 2219
215b30b3 2220 DONE;
2221 }"
2222)
8a18b90c 2223
215b30b3 2224; constants for op 2 will never be given to these patterns.
a0f94409 2225(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2226 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 2227 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2228 (match_operand:DI 2 "s_register_operand" "0,r")))]
25f905c2 2229 "TARGET_32BIT"
f6ebffac 2230 "#"
25f905c2 2231 "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2232 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2233 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2234 "
2235 {
2236 operands[3] = gen_highpart (SImode, operands[0]);
2237 operands[0] = gen_lowpart (SImode, operands[0]);
2238 operands[4] = gen_highpart (SImode, operands[1]);
2239 operands[1] = gen_lowpart (SImode, operands[1]);
2240 operands[5] = gen_highpart (SImode, operands[2]);
2241 operands[2] = gen_lowpart (SImode, operands[2]);
2242 }"
0d66636f 2243 [(set_attr "length" "8")
2244 (set_attr "predicable" "yes")]
2245)
9c08d1fa 2246
a0f94409 2247(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2248 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2249 (and:DI (not:DI (zero_extend:DI
2250 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2251 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2252 "TARGET_32BIT"
e2348bcb 2253 "@
97499065 2254 bic%?\\t%Q0, %Q1, %2
f6ebffac 2255 #"
a0f94409 2256 ; (not (zero_extend ...)) allows us to just copy the high word from
2257 ; operand1 to operand0.
25f905c2 2258 "TARGET_32BIT
a0f94409 2259 && reload_completed
2260 && operands[0] != operands[1]"
5a097f7d 2261 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2262 (set (match_dup 3) (match_dup 4))]
2263 "
2264 {
2265 operands[3] = gen_highpart (SImode, operands[0]);
2266 operands[0] = gen_lowpart (SImode, operands[0]);
2267 operands[4] = gen_highpart (SImode, operands[1]);
2268 operands[1] = gen_lowpart (SImode, operands[1]);
2269 }"
0d66636f 2270 [(set_attr "length" "4,8")
2271 (set_attr "predicable" "yes")]
2272)
9c08d1fa 2273
a0f94409 2274(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2275 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2276 (and:DI (not:DI (sign_extend:DI
2277 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2278 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2279 "TARGET_32BIT"
f6ebffac 2280 "#"
25f905c2 2281 "TARGET_32BIT && reload_completed"
5a097f7d 2282 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2283 (set (match_dup 3) (and:SI (not:SI
2284 (ashiftrt:SI (match_dup 2) (const_int 31)))
2285 (match_dup 4)))]
2286 "
2287 {
2288 operands[3] = gen_highpart (SImode, operands[0]);
2289 operands[0] = gen_lowpart (SImode, operands[0]);
2290 operands[4] = gen_highpart (SImode, operands[1]);
2291 operands[1] = gen_lowpart (SImode, operands[1]);
2292 }"
0d66636f 2293 [(set_attr "length" "8")
2294 (set_attr "predicable" "yes")]
2295)
9c08d1fa 2296
8a18b90c 2297(define_insn "andsi_notsi_si"
9c08d1fa 2298 [(set (match_operand:SI 0 "s_register_operand" "=r")
2299 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2300 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2301 "TARGET_32BIT"
0d66636f 2302 "bic%?\\t%0, %1, %2"
2303 [(set_attr "predicable" "yes")]
2304)
b11cae9e 2305
cffb2a26 2306(define_insn "bicsi3"
2307 [(set (match_operand:SI 0 "register_operand" "=l")
2308 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2309 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2310 "TARGET_THUMB1"
cffb2a26 2311 "bic\\t%0, %0, %1"
2312 [(set_attr "length" "2")]
2313)
2314
8a18b90c 2315(define_insn "andsi_not_shiftsi_si"
a2cd141b 2316 [(set (match_operand:SI 0 "s_register_operand" "=r")
2317 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2318 [(match_operand:SI 2 "s_register_operand" "r")
2319 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2320 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2321 "TARGET_ARM"
6c4c2133 2322 "bic%?\\t%0, %1, %2%S4"
344495ea 2323 [(set_attr "predicable" "yes")
331beb1a 2324 (set_attr "shift" "2")
a2cd141b 2325 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2326 (const_string "alu_shift")
2327 (const_string "alu_shift_reg")))]
6c4c2133 2328)
8a18b90c 2329
f7fbdd4a 2330(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2331 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2332 (compare:CC_NOOV
2333 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2334 (match_operand:SI 1 "s_register_operand" "r"))
2335 (const_int 0)))
9c08d1fa 2336 (set (match_operand:SI 0 "s_register_operand" "=r")
2337 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2338 "TARGET_32BIT"
2339 "bic%.\\t%0, %1, %2"
0d66636f 2340 [(set_attr "conds" "set")]
2341)
9c08d1fa 2342
f7fbdd4a 2343(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2344 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2345 (compare:CC_NOOV
2346 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2347 (match_operand:SI 1 "s_register_operand" "r"))
2348 (const_int 0)))
9c08d1fa 2349 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2350 "TARGET_32BIT"
2351 "bic%.\\t%0, %1, %2"
0d66636f 2352 [(set_attr "conds" "set")]
2353)
9c08d1fa 2354
2355(define_insn "iordi3"
cffb2a26 2356 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2357 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2358 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2359 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 2360 "#"
0d66636f 2361 [(set_attr "length" "8")
2362 (set_attr "predicable" "yes")]
cffb2a26 2363)
9c08d1fa 2364
f7fbdd4a 2365(define_insn "*iordi_zesidi_di"
9c08d1fa 2366 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2367 (ior:DI (zero_extend:DI
2368 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2369 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2370 "TARGET_32BIT"
e2348bcb 2371 "@
97499065 2372 orr%?\\t%Q0, %Q1, %2
f6ebffac 2373 #"
0d66636f 2374 [(set_attr "length" "4,8")
2375 (set_attr "predicable" "yes")]
cffb2a26 2376)
9c08d1fa 2377
f7fbdd4a 2378(define_insn "*iordi_sesidi_di"
9c08d1fa 2379 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2380 (ior:DI (sign_extend:DI
2381 (match_operand:SI 2 "s_register_operand" "r,r"))
2382 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2383 "TARGET_32BIT"
f6ebffac 2384 "#"
0d66636f 2385 [(set_attr "length" "8")
2386 (set_attr "predicable" "yes")]
cffb2a26 2387)
9c08d1fa 2388
87b22bf7 2389(define_expand "iorsi3"
cffb2a26 2390 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2391 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2392 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2393 "TARGET_EITHER"
87b22bf7 2394 "
2395 if (GET_CODE (operands[2]) == CONST_INT)
2396 {
25f905c2 2397 if (TARGET_32BIT)
cffb2a26 2398 {
96f57e36 2399 arm_split_constant (IOR, SImode, NULL_RTX,
2400 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2401 optimize && can_create_pseudo_p ());
cffb2a26 2402 DONE;
2403 }
25f905c2 2404 else /* TARGET_THUMB1 */
cffb2a26 2405 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2406 }
cffb2a26 2407 "
2408)
87b22bf7 2409
a0f94409 2410(define_insn_and_split "*arm_iorsi3"
cffb2a26 2411 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2412 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2413 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
25f905c2 2414 "TARGET_32BIT"
87b22bf7 2415 "@
2416 orr%?\\t%0, %1, %2
2417 #"
25f905c2 2418 "TARGET_32BIT
a0f94409 2419 && GET_CODE (operands[2]) == CONST_INT
2420 && !const_ok_for_arm (INTVAL (operands[2]))"
2421 [(clobber (const_int 0))]
2422 "
96f57e36 2423 arm_split_constant (IOR, SImode, curr_insn,
2424 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2425 DONE;
2426 "
0d66636f 2427 [(set_attr "length" "4,16")
2428 (set_attr "predicable" "yes")]
cffb2a26 2429)
2430
25f905c2 2431(define_insn "*thumb1_iorsi3"
cffb2a26 2432 [(set (match_operand:SI 0 "register_operand" "=l")
2433 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2434 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2435 "TARGET_THUMB1"
cffb2a26 2436 "orr\\t%0, %0, %2"
2437 [(set_attr "length" "2")]
2438)
9c08d1fa 2439
a0f94409 2440(define_peephole2
2441 [(match_scratch:SI 3 "r")
372575c7 2442 (set (match_operand:SI 0 "arm_general_register_operand" "")
2443 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2444 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 2445 "TARGET_32BIT
a0f94409 2446 && !const_ok_for_arm (INTVAL (operands[2]))
2447 && const_ok_for_arm (~INTVAL (operands[2]))"
2448 [(set (match_dup 3) (match_dup 2))
2449 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2450 ""
215b30b3 2451)
a0f94409 2452
f7fbdd4a 2453(define_insn "*iorsi3_compare0"
bd5b4116 2454 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2455 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2456 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2457 (const_int 0)))
2458 (set (match_operand:SI 0 "s_register_operand" "=r")
2459 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2460 "TARGET_32BIT"
2461 "orr%.\\t%0, %1, %2"
cffb2a26 2462 [(set_attr "conds" "set")]
2463)
9c08d1fa 2464
f7fbdd4a 2465(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2466 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2467 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2468 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2469 (const_int 0)))
2470 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2471 "TARGET_32BIT"
2472 "orr%.\\t%0, %1, %2"
0d66636f 2473 [(set_attr "conds" "set")]
2474)
9c08d1fa 2475
2476(define_insn "xordi3"
cffb2a26 2477 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2478 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2479 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2480 "TARGET_32BIT && !TARGET_IWMMXT"
f6ebffac 2481 "#"
0d66636f 2482 [(set_attr "length" "8")
2483 (set_attr "predicable" "yes")]
cffb2a26 2484)
9c08d1fa 2485
f7fbdd4a 2486(define_insn "*xordi_zesidi_di"
9c08d1fa 2487 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2488 (xor:DI (zero_extend:DI
2489 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2490 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2491 "TARGET_32BIT"
e2348bcb 2492 "@
97499065 2493 eor%?\\t%Q0, %Q1, %2
f6ebffac 2494 #"
0d66636f 2495 [(set_attr "length" "4,8")
2496 (set_attr "predicable" "yes")]
cffb2a26 2497)
9c08d1fa 2498
f7fbdd4a 2499(define_insn "*xordi_sesidi_di"
9c08d1fa 2500 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2501 (xor:DI (sign_extend:DI
2502 (match_operand:SI 2 "s_register_operand" "r,r"))
2503 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2504 "TARGET_32BIT"
f6ebffac 2505 "#"
0d66636f 2506 [(set_attr "length" "8")
2507 (set_attr "predicable" "yes")]
cffb2a26 2508)
9c08d1fa 2509
cffb2a26 2510(define_expand "xorsi3"
2511 [(set (match_operand:SI 0 "s_register_operand" "")
2512 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2513 (match_operand:SI 2 "arm_rhs_operand" "")))]
2514 "TARGET_EITHER"
25f905c2 2515 "if (TARGET_THUMB1)
cffb2a26 2516 if (GET_CODE (operands[2]) == CONST_INT)
2517 operands[2] = force_reg (SImode, operands[2]);
2518 "
2519)
2520
2521(define_insn "*arm_xorsi3"
2522 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2523 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2524 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2525 "TARGET_32BIT"
cffb2a26 2526 "eor%?\\t%0, %1, %2"
0d66636f 2527 [(set_attr "predicable" "yes")]
cffb2a26 2528)
2529
25f905c2 2530(define_insn "*thumb1_xorsi3"
cffb2a26 2531 [(set (match_operand:SI 0 "register_operand" "=l")
2532 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2533 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2534 "TARGET_THUMB1"
cffb2a26 2535 "eor\\t%0, %0, %2"
2536 [(set_attr "length" "2")]
2537)
9c08d1fa 2538
f7fbdd4a 2539(define_insn "*xorsi3_compare0"
bd5b4116 2540 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2541 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2542 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2543 (const_int 0)))
2544 (set (match_operand:SI 0 "s_register_operand" "=r")
2545 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2546 "TARGET_32BIT"
2547 "eor%.\\t%0, %1, %2"
0d66636f 2548 [(set_attr "conds" "set")]
2549)
9c08d1fa 2550
f7fbdd4a 2551(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2552 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2553 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2554 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2555 (const_int 0)))]
25f905c2 2556 "TARGET_32BIT"
40dbec34 2557 "teq%?\\t%0, %1"
cffb2a26 2558 [(set_attr "conds" "set")]
2559)
9c08d1fa 2560
215b30b3 2561; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2562; (NOT D) we can sometimes merge the final NOT into one of the following
2563; insns.
9c08d1fa 2564
2565(define_split
a058e94a 2566 [(set (match_operand:SI 0 "s_register_operand" "")
2567 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2568 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2569 (match_operand:SI 3 "arm_rhs_operand" "")))
2570 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2571 "TARGET_32BIT"
9c08d1fa 2572 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2573 (not:SI (match_dup 3))))
2574 (set (match_dup 0) (not:SI (match_dup 4)))]
2575 ""
2576)
2577
f7fbdd4a 2578(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2579 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2580 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2581 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2582 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2583 "TARGET_32BIT"
40dbec34 2584 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2585 [(set_attr "length" "8")
25f905c2 2586 (set_attr "ce_count" "2")
0d66636f 2587 (set_attr "predicable" "yes")]
cffb2a26 2588)
9c08d1fa 2589
25f905c2 2590; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2591; insns are available?
d7863cfe 2592(define_split
2593 [(set (match_operand:SI 0 "s_register_operand" "")
2594 (match_operator:SI 1 "logical_binary_operator"
2595 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2596 (match_operand:SI 3 "const_int_operand" "")
2597 (match_operand:SI 4 "const_int_operand" ""))
2598 (match_operator:SI 9 "logical_binary_operator"
2599 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2600 (match_operand:SI 6 "const_int_operand" ""))
2601 (match_operand:SI 7 "s_register_operand" "")])]))
2602 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2603 "TARGET_32BIT
d7863cfe 2604 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2605 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2606 [(set (match_dup 8)
2607 (match_op_dup 1
2608 [(ashift:SI (match_dup 2) (match_dup 4))
2609 (match_dup 5)]))
2610 (set (match_dup 0)
2611 (match_op_dup 1
2612 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2613 (match_dup 7)]))]
2614 "
2615 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2616")
2617
2618(define_split
2619 [(set (match_operand:SI 0 "s_register_operand" "")
2620 (match_operator:SI 1 "logical_binary_operator"
2621 [(match_operator:SI 9 "logical_binary_operator"
2622 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2623 (match_operand:SI 6 "const_int_operand" ""))
2624 (match_operand:SI 7 "s_register_operand" "")])
2625 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2626 (match_operand:SI 3 "const_int_operand" "")
2627 (match_operand:SI 4 "const_int_operand" ""))]))
2628 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2629 "TARGET_32BIT
d7863cfe 2630 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2631 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2632 [(set (match_dup 8)
2633 (match_op_dup 1
2634 [(ashift:SI (match_dup 2) (match_dup 4))
2635 (match_dup 5)]))
2636 (set (match_dup 0)
2637 (match_op_dup 1
2638 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2639 (match_dup 7)]))]
2640 "
2641 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2642")
2643
2644(define_split
2645 [(set (match_operand:SI 0 "s_register_operand" "")
2646 (match_operator:SI 1 "logical_binary_operator"
2647 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2648 (match_operand:SI 3 "const_int_operand" "")
2649 (match_operand:SI 4 "const_int_operand" ""))
2650 (match_operator:SI 9 "logical_binary_operator"
2651 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2652 (match_operand:SI 6 "const_int_operand" ""))
2653 (match_operand:SI 7 "s_register_operand" "")])]))
2654 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2655 "TARGET_32BIT
d7863cfe 2656 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2657 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2658 [(set (match_dup 8)
2659 (match_op_dup 1
2660 [(ashift:SI (match_dup 2) (match_dup 4))
2661 (match_dup 5)]))
2662 (set (match_dup 0)
2663 (match_op_dup 1
2664 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2665 (match_dup 7)]))]
2666 "
2667 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2668")
2669
2670(define_split
2671 [(set (match_operand:SI 0 "s_register_operand" "")
2672 (match_operator:SI 1 "logical_binary_operator"
2673 [(match_operator:SI 9 "logical_binary_operator"
2674 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2675 (match_operand:SI 6 "const_int_operand" ""))
2676 (match_operand:SI 7 "s_register_operand" "")])
2677 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2678 (match_operand:SI 3 "const_int_operand" "")
2679 (match_operand:SI 4 "const_int_operand" ""))]))
2680 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2681 "TARGET_32BIT
d7863cfe 2682 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2683 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2684 [(set (match_dup 8)
2685 (match_op_dup 1
2686 [(ashift:SI (match_dup 2) (match_dup 4))
2687 (match_dup 5)]))
2688 (set (match_dup 0)
2689 (match_op_dup 1
2690 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2691 (match_dup 7)]))]
2692 "
2693 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2694")
9c08d1fa 2695\f
2696
2697;; Minimum and maximum insns
2698
8b9dc177 2699(define_expand "smaxsi3"
2700 [(parallel [
2701 (set (match_operand:SI 0 "s_register_operand" "")
2702 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2703 (match_operand:SI 2 "arm_rhs_operand" "")))
2704 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2705 "TARGET_32BIT"
8b9dc177 2706 "
8774928b 2707 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 2708 {
2709 /* No need for a clobber of the condition code register here. */
2710 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2711 gen_rtx_SMAX (SImode, operands[1],
2712 operands[2])));
2713 DONE;
2714 }
2715")
2716
2717(define_insn "*smax_0"
2718 [(set (match_operand:SI 0 "s_register_operand" "=r")
2719 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2720 (const_int 0)))]
25f905c2 2721 "TARGET_32BIT"
8b9dc177 2722 "bic%?\\t%0, %1, %1, asr #31"
2723 [(set_attr "predicable" "yes")]
2724)
2725
8774928b 2726(define_insn "*smax_m1"
2727 [(set (match_operand:SI 0 "s_register_operand" "=r")
2728 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2729 (const_int -1)))]
25f905c2 2730 "TARGET_32BIT"
8774928b 2731 "orr%?\\t%0, %1, %1, asr #31"
2732 [(set_attr "predicable" "yes")]
2733)
2734
25f905c2 2735(define_insn "*arm_smax_insn"
8b9dc177 2736 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2737 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2738 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 2739 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2740 "TARGET_ARM"
e2348bcb 2741 "@
2742 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 2743 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2744 [(set_attr "conds" "clob")
8b9dc177 2745 (set_attr "length" "8,12")]
cffb2a26 2746)
9c08d1fa 2747
8b9dc177 2748(define_expand "sminsi3"
2749 [(parallel [
2750 (set (match_operand:SI 0 "s_register_operand" "")
2751 (smin:SI (match_operand:SI 1 "s_register_operand" "")
2752 (match_operand:SI 2 "arm_rhs_operand" "")))
2753 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2754 "TARGET_32BIT"
8b9dc177 2755 "
2756 if (operands[2] == const0_rtx)
2757 {
2758 /* No need for a clobber of the condition code register here. */
2759 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2760 gen_rtx_SMIN (SImode, operands[1],
2761 operands[2])));
2762 DONE;
2763 }
2764")
2765
2766(define_insn "*smin_0"
2767 [(set (match_operand:SI 0 "s_register_operand" "=r")
2768 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2769 (const_int 0)))]
25f905c2 2770 "TARGET_32BIT"
8b9dc177 2771 "and%?\\t%0, %1, %1, asr #31"
2772 [(set_attr "predicable" "yes")]
2773)
2774
25f905c2 2775(define_insn "*arm_smin_insn"
8b9dc177 2776 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2777 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2778 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 2779 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2780 "TARGET_ARM"
e2348bcb 2781 "@
2782 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 2783 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 2784 [(set_attr "conds" "clob")
8b9dc177 2785 (set_attr "length" "8,12")]
0d66636f 2786)
9c08d1fa 2787
25f905c2 2788(define_expand "umaxsi3"
2789 [(parallel [
2790 (set (match_operand:SI 0 "s_register_operand" "")
2791 (umax:SI (match_operand:SI 1 "s_register_operand" "")
2792 (match_operand:SI 2 "arm_rhs_operand" "")))
2793 (clobber (reg:CC CC_REGNUM))])]
2794 "TARGET_32BIT"
2795 ""
2796)
2797
2798(define_insn "*arm_umaxsi3"
9c08d1fa 2799 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2800 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2801 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2802 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2803 "TARGET_ARM"
e2348bcb 2804 "@
2805 cmp\\t%1, %2\;movcc\\t%0, %2
2806 cmp\\t%1, %2\;movcs\\t%0, %1
2807 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 2808 [(set_attr "conds" "clob")
2809 (set_attr "length" "8,8,12")]
2810)
9c08d1fa 2811
25f905c2 2812(define_expand "uminsi3"
2813 [(parallel [
2814 (set (match_operand:SI 0 "s_register_operand" "")
2815 (umin:SI (match_operand:SI 1 "s_register_operand" "")
2816 (match_operand:SI 2 "arm_rhs_operand" "")))
2817 (clobber (reg:CC CC_REGNUM))])]
2818 "TARGET_32BIT"
2819 ""
2820)
2821
2822(define_insn "*arm_uminsi3"
9c08d1fa 2823 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2824 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2825 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2826 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2827 "TARGET_ARM"
e2348bcb 2828 "@
2829 cmp\\t%1, %2\;movcs\\t%0, %2
2830 cmp\\t%1, %2\;movcc\\t%0, %1
2831 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 2832 [(set_attr "conds" "clob")
2833 (set_attr "length" "8,8,12")]
2834)
9c08d1fa 2835
8a18b90c 2836(define_insn "*store_minmaxsi"
9c08d1fa 2837 [(set (match_operand:SI 0 "memory_operand" "=m")
2838 (match_operator:SI 3 "minmax_operator"
2839 [(match_operand:SI 1 "s_register_operand" "r")
2840 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 2841 (clobber (reg:CC CC_REGNUM))]
25f905c2 2842 "TARGET_32BIT"
9c08d1fa 2843 "*
dc55b8a9 2844 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2845 operands[1], operands[2]);
e2348bcb 2846 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 2847 if (TARGET_THUMB2)
2848 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 2849 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2850 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2851 return \"\";
0d66636f 2852 "
2853 [(set_attr "conds" "clob")
25f905c2 2854 (set (attr "length")
2855 (if_then_else (eq_attr "is_thumb" "yes")
2856 (const_int 14)
2857 (const_int 12)))
0d66636f 2858 (set_attr "type" "store1")]
2859)
9c08d1fa 2860
8a18b90c 2861; Reject the frame pointer in operand[1], since reloading this after
2862; it has been eliminated can cause carnage.
f7fbdd4a 2863(define_insn "*minmax_arithsi"
9c08d1fa 2864 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2865 (match_operator:SI 4 "shiftable_operator"
2866 [(match_operator:SI 5 "minmax_operator"
2867 [(match_operand:SI 2 "s_register_operand" "r,r")
2868 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2869 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 2870 (clobber (reg:CC CC_REGNUM))]
25f905c2 2871 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 2872 "*
0d66636f 2873 {
2874 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 2875 bool need_else;
2876
2877 if (which_alternative != 0 || operands[3] != const0_rtx
2878 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2879 need_else = true;
2880 else
2881 need_else = false;
0d66636f 2882
dc55b8a9 2883 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2884 operands[2], operands[3]);
0d66636f 2885 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 2886 if (TARGET_THUMB2)
2887 {
2888 if (need_else)
2889 output_asm_insn (\"ite\\t%d5\", operands);
2890 else
2891 output_asm_insn (\"it\\t%d5\", operands);
2892 }
0d66636f 2893 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 2894 if (need_else)
0d66636f 2895 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2896 return \"\";
215b30b3 2897 }"
0d66636f 2898 [(set_attr "conds" "clob")
25f905c2 2899 (set (attr "length")
2900 (if_then_else (eq_attr "is_thumb" "yes")
2901 (const_int 14)
2902 (const_int 12)))]
0d66636f 2903)
9c08d1fa 2904
b11cae9e 2905\f
2906;; Shift and rotation insns
2907
a2cd141b 2908(define_expand "ashldi3"
2909 [(set (match_operand:DI 0 "s_register_operand" "")
2910 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2911 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 2912 "TARGET_32BIT"
a2cd141b 2913 "
2914 if (GET_CODE (operands[2]) == CONST_INT)
2915 {
2916 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2917 {
2918 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2919 DONE;
2920 }
2921 /* Ideally we shouldn't fail here if we could know that operands[1]
2922 ends up already living in an iwmmxt register. Otherwise it's
2923 cheaper to have the alternate code being generated than moving
1d60d981 2924 values to iwmmxt regs and back. */
a2cd141b 2925 FAIL;
2926 }
2927 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2928 FAIL;
2929 "
2930)
2931
2932(define_insn "arm_ashldi3_1bit"
2933 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2934 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2935 (const_int 1)))
2936 (clobber (reg:CC CC_REGNUM))]
25f905c2 2937 "TARGET_32BIT"
a2cd141b 2938 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2939 [(set_attr "conds" "clob")
2940 (set_attr "length" "8")]
2941)
2942
87b22bf7 2943(define_expand "ashlsi3"
cffb2a26 2944 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2945 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2946 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2947 "TARGET_EITHER"
87b22bf7 2948 "
2949 if (GET_CODE (operands[2]) == CONST_INT
2950 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2951 {
2952 emit_insn (gen_movsi (operands[0], const0_rtx));
2953 DONE;
2954 }
cffb2a26 2955 "
2956)
2957
25f905c2 2958(define_insn "*thumb1_ashlsi3"
cffb2a26 2959 [(set (match_operand:SI 0 "register_operand" "=l,l")
2960 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2961 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 2962 "TARGET_THUMB1"
cffb2a26 2963 "lsl\\t%0, %1, %2"
2964 [(set_attr "length" "2")]
2965)
b11cae9e 2966
a2cd141b 2967(define_expand "ashrdi3"
2968 [(set (match_operand:DI 0 "s_register_operand" "")
2969 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2970 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 2971 "TARGET_32BIT"
a2cd141b 2972 "
2973 if (GET_CODE (operands[2]) == CONST_INT)
2974 {
2975 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2976 {
2977 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2978 DONE;
2979 }
2980 /* Ideally we shouldn't fail here if we could know that operands[1]
2981 ends up already living in an iwmmxt register. Otherwise it's
2982 cheaper to have the alternate code being generated than moving
1d60d981 2983 values to iwmmxt regs and back. */
a2cd141b 2984 FAIL;
2985 }
2986 else if (!TARGET_REALLY_IWMMXT)
2987 FAIL;
2988 "
2989)
2990
2991(define_insn "arm_ashrdi3_1bit"
2992 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2993 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2994 (const_int 1)))
2995 (clobber (reg:CC CC_REGNUM))]
25f905c2 2996 "TARGET_32BIT"
a2cd141b 2997 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2998 [(set_attr "conds" "clob")
2999 (set_attr "length" "8")]
3000)
3001
87b22bf7 3002(define_expand "ashrsi3"
cffb2a26 3003 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3004 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3005 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3006 "TARGET_EITHER"
87b22bf7 3007 "
3008 if (GET_CODE (operands[2]) == CONST_INT
3009 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3010 operands[2] = GEN_INT (31);
cffb2a26 3011 "
3012)
3013
25f905c2 3014(define_insn "*thumb1_ashrsi3"
cffb2a26 3015 [(set (match_operand:SI 0 "register_operand" "=l,l")
3016 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3017 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3018 "TARGET_THUMB1"
cffb2a26 3019 "asr\\t%0, %1, %2"
3020 [(set_attr "length" "2")]
3021)
b11cae9e 3022
a2cd141b 3023(define_expand "lshrdi3"
3024 [(set (match_operand:DI 0 "s_register_operand" "")
3025 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3026 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3027 "TARGET_32BIT"
a2cd141b 3028 "
3029 if (GET_CODE (operands[2]) == CONST_INT)
3030 {
3031 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3032 {
3033 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3034 DONE;
3035 }
3036 /* Ideally we shouldn't fail here if we could know that operands[1]
3037 ends up already living in an iwmmxt register. Otherwise it's
3038 cheaper to have the alternate code being generated than moving
1d60d981 3039 values to iwmmxt regs and back. */
a2cd141b 3040 FAIL;
3041 }
3042 else if (!TARGET_REALLY_IWMMXT)
3043 FAIL;
3044 "
3045)
3046
3047(define_insn "arm_lshrdi3_1bit"
3048 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3049 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3050 (const_int 1)))
3051 (clobber (reg:CC CC_REGNUM))]
25f905c2 3052 "TARGET_32BIT"
a2cd141b 3053 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3054 [(set_attr "conds" "clob")
3055 (set_attr "length" "8")]
3056)
3057
87b22bf7 3058(define_expand "lshrsi3"
cffb2a26 3059 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3060 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3061 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3062 "TARGET_EITHER"
87b22bf7 3063 "
3064 if (GET_CODE (operands[2]) == CONST_INT
3065 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3066 {
3067 emit_insn (gen_movsi (operands[0], const0_rtx));
3068 DONE;
3069 }
cffb2a26 3070 "
3071)
3072
25f905c2 3073(define_insn "*thumb1_lshrsi3"
cffb2a26 3074 [(set (match_operand:SI 0 "register_operand" "=l,l")
3075 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3076 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3077 "TARGET_THUMB1"
cffb2a26 3078 "lsr\\t%0, %1, %2"
3079 [(set_attr "length" "2")]
3080)
b11cae9e 3081
87b22bf7 3082(define_expand "rotlsi3"
cffb2a26 3083 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3084 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3085 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3086 "TARGET_32BIT"
87b22bf7 3087 "
3088 if (GET_CODE (operands[2]) == CONST_INT)
3089 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3090 else
b11cae9e 3091 {
87b22bf7 3092 rtx reg = gen_reg_rtx (SImode);
3093 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3094 operands[2] = reg;
b11cae9e 3095 }
cffb2a26 3096 "
3097)
9c08d1fa 3098
87b22bf7 3099(define_expand "rotrsi3"
cffb2a26 3100 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3101 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3102 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3103 "TARGET_EITHER"
87b22bf7 3104 "
25f905c2 3105 if (TARGET_32BIT)
cffb2a26 3106 {
3107 if (GET_CODE (operands[2]) == CONST_INT
3108 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3109 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3110 }
25f905c2 3111 else /* TARGET_THUMB1 */
cffb2a26 3112 {
3113 if (GET_CODE (operands [2]) == CONST_INT)
3114 operands [2] = force_reg (SImode, operands[2]);
3115 }
3116 "
3117)
87b22bf7 3118
25f905c2 3119(define_insn "*thumb1_rotrsi3"
cffb2a26 3120 [(set (match_operand:SI 0 "register_operand" "=l")
3121 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3122 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3123 "TARGET_THUMB1"
cffb2a26 3124 "ror\\t%0, %0, %2"
3125 [(set_attr "length" "2")]
3126)
3127
3128(define_insn "*arm_shiftsi3"
3129 [(set (match_operand:SI 0 "s_register_operand" "=r")
3130 (match_operator:SI 3 "shift_operator"
3131 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3132 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3133 "TARGET_32BIT"
3134 "* return arm_output_shift(operands, 0);"
344495ea 3135 [(set_attr "predicable" "yes")
331beb1a 3136 (set_attr "shift" "1")
a2cd141b 3137 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3138 (const_string "alu_shift")
3139 (const_string "alu_shift_reg")))]
6c4c2133 3140)
87b22bf7 3141
f7fbdd4a 3142(define_insn "*shiftsi3_compare0"
bd5b4116 3143 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3144 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3145 [(match_operand:SI 1 "s_register_operand" "r")
3146 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3147 (const_int 0)))
3148 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3149 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3150 "TARGET_32BIT"
3151 "* return arm_output_shift(operands, 1);"
344495ea 3152 [(set_attr "conds" "set")
331beb1a 3153 (set_attr "shift" "1")
a2cd141b 3154 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3155 (const_string "alu_shift")
3156 (const_string "alu_shift_reg")))]
0d66636f 3157)
9c08d1fa 3158
f7fbdd4a 3159(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3160 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3161 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3162 [(match_operand:SI 1 "s_register_operand" "r")
3163 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3164 (const_int 0)))
3165 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3166 "TARGET_32BIT"
3167 "* return arm_output_shift(operands, 1);"
344495ea 3168 [(set_attr "conds" "set")
a2cd141b 3169 (set_attr "shift" "1")]
0d66636f 3170)
9c08d1fa 3171
25f905c2 3172(define_insn "*arm_notsi_shiftsi"
9c08d1fa 3173 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3174 (not:SI (match_operator:SI 3 "shift_operator"
3175 [(match_operand:SI 1 "s_register_operand" "r")
3176 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 3177 "TARGET_ARM"
6c4c2133 3178 "mvn%?\\t%0, %1%S3"
344495ea 3179 [(set_attr "predicable" "yes")
331beb1a 3180 (set_attr "shift" "1")
a2cd141b 3181 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3182 (const_string "alu_shift")
3183 (const_string "alu_shift_reg")))]
0d66636f 3184)
9c08d1fa 3185
25f905c2 3186(define_insn "*arm_notsi_shiftsi_compare0"
bd5b4116 3187 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3188 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3189 [(match_operand:SI 1 "s_register_operand" "r")
3190 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3191 (const_int 0)))
3192 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3193 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 3194 "TARGET_ARM"
25f905c2 3195 "mvn%.\\t%0, %1%S3"
344495ea 3196 [(set_attr "conds" "set")
331beb1a 3197 (set_attr "shift" "1")
a2cd141b 3198 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3199 (const_string "alu_shift")
3200 (const_string "alu_shift_reg")))]
0d66636f 3201)
9c08d1fa 3202
25f905c2 3203(define_insn "*arm_not_shiftsi_compare0_scratch"
bd5b4116 3204 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3205 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3206 [(match_operand:SI 1 "s_register_operand" "r")
3207 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3208 (const_int 0)))
3209 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3210 "TARGET_ARM"
25f905c2 3211 "mvn%.\\t%0, %1%S3"
344495ea 3212 [(set_attr "conds" "set")
331beb1a 3213 (set_attr "shift" "1")
a2cd141b 3214 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3215 (const_string "alu_shift")
3216 (const_string "alu_shift_reg")))]
0d66636f 3217)
9c08d1fa 3218
cffb2a26 3219;; We don't really have extzv, but defining this using shifts helps
3220;; to reduce register pressure later on.
3221
3222(define_expand "extzv"
3223 [(set (match_dup 4)
3224 (ashift:SI (match_operand:SI 1 "register_operand" "")
3225 (match_operand:SI 2 "const_int_operand" "")))
3226 (set (match_operand:SI 0 "register_operand" "")
3227 (lshiftrt:SI (match_dup 4)
215b30b3 3228 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 3229 "TARGET_THUMB1"
cffb2a26 3230 "
3231 {
3232 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3233 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3234
3235 operands[3] = GEN_INT (rshift);
3236
3237 if (lshift == 0)
3238 {
3239 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3240 DONE;
3241 }
3242
3243 operands[2] = GEN_INT (lshift);
3244 operands[4] = gen_reg_rtx (SImode);
215b30b3 3245 }"
cffb2a26 3246)
3247
b11cae9e 3248\f
3249;; Unary arithmetic insns
3250
cffb2a26 3251(define_expand "negdi2"
3252 [(parallel
3253 [(set (match_operand:DI 0 "s_register_operand" "")
3254 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3255 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3256 "TARGET_EITHER"
3257 "
25f905c2 3258 if (TARGET_THUMB1)
cffb2a26 3259 {
3260 if (GET_CODE (operands[1]) != REG)
3261 operands[1] = force_reg (SImode, operands[1]);
3262 }
215b30b3 3263 "
cffb2a26 3264)
3265
3266;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3267;; The second alternative is to allow the common case of a *full* overlap.
3268(define_insn "*arm_negdi2"
3269 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3270 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 3271 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3272 "TARGET_ARM"
97499065 3273 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3274 [(set_attr "conds" "clob")
3275 (set_attr "length" "8")]
3276)
b11cae9e 3277
25f905c2 3278(define_insn "*thumb1_negdi2"
cffb2a26 3279 [(set (match_operand:DI 0 "register_operand" "=&l")
3280 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3281 (clobber (reg:CC CC_REGNUM))]
25f905c2 3282 "TARGET_THUMB1"
cffb2a26 3283 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3284 [(set_attr "length" "6")]
3285)
3286
3287(define_expand "negsi2"
3288 [(set (match_operand:SI 0 "s_register_operand" "")
3289 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3290 "TARGET_EITHER"
b11cae9e 3291 ""
cffb2a26 3292)
3293
3294(define_insn "*arm_negsi2"
3295 [(set (match_operand:SI 0 "s_register_operand" "=r")
3296 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3297 "TARGET_32BIT"
cffb2a26 3298 "rsb%?\\t%0, %1, #0"
0d66636f 3299 [(set_attr "predicable" "yes")]
cffb2a26 3300)
3301
25f905c2 3302(define_insn "*thumb1_negsi2"
cffb2a26 3303 [(set (match_operand:SI 0 "register_operand" "=l")
3304 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3305 "TARGET_THUMB1"
cffb2a26 3306 "neg\\t%0, %1"
3307 [(set_attr "length" "2")]
3308)
b11cae9e 3309
604f3a0a 3310(define_expand "negsf2"
3311 [(set (match_operand:SF 0 "s_register_operand" "")
3312 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3313 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3314 ""
3315)
3316
3317(define_expand "negdf2"
3318 [(set (match_operand:DF 0 "s_register_operand" "")
3319 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3320 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3321 "")
3322
9c08d1fa 3323;; abssi2 doesn't really clobber the condition codes if a different register
3324;; is being set. To keep things simple, assume during rtl manipulations that
3325;; it does, but tell the final scan operator the truth. Similarly for
3326;; (neg (abs...))
3327
604f3a0a 3328(define_expand "abssi2"
3329 [(parallel
3330 [(set (match_operand:SI 0 "s_register_operand" "")
3331 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3332 (clobber (match_dup 2))])]
3333 "TARGET_EITHER"
3334 "
25f905c2 3335 if (TARGET_THUMB1)
ba156559 3336 operands[2] = gen_rtx_SCRATCH (SImode);
3337 else
3338 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3339")
604f3a0a 3340
7d57ec45 3341(define_insn "*arm_abssi2"
ba156559 3342 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3343 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3344 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3345 "TARGET_ARM"
e2348bcb 3346 "@
3347 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3348 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3349 [(set_attr "conds" "clob,*")
331beb1a 3350 (set_attr "shift" "1")
0d66636f 3351 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3352 (set_attr "length" "8")]
3353)
9c08d1fa 3354
25f905c2 3355(define_insn_and_split "*thumb1_abssi2"
ba156559 3356 [(set (match_operand:SI 0 "s_register_operand" "=l")
3357 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3358 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3359 "TARGET_THUMB1"
ba156559 3360 "#"
25f905c2 3361 "TARGET_THUMB1 && reload_completed"
ba156559 3362 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3363 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3364 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3365 ""
3366 [(set_attr "length" "6")]
3367)
3368
3369(define_insn "*arm_neg_abssi2"
9c08d1fa 3370 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3371 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3372 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3373 "TARGET_ARM"
e2348bcb 3374 "@
3375 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3376 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3377 [(set_attr "conds" "clob,*")
331beb1a 3378 (set_attr "shift" "1")
0d66636f 3379 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3380 (set_attr "length" "8")]
3381)
b11cae9e 3382
25f905c2 3383(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3384 [(set (match_operand:SI 0 "s_register_operand" "=l")
3385 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3386 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3387 "TARGET_THUMB1"
ba156559 3388 "#"
25f905c2 3389 "TARGET_THUMB1 && reload_completed"
ba156559 3390 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3391 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3392 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3393 ""
3394 [(set_attr "length" "6")]
3395)
3396
604f3a0a 3397(define_expand "abssf2"
3398 [(set (match_operand:SF 0 "s_register_operand" "")
3399 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3400 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3401 "")
3402
604f3a0a 3403(define_expand "absdf2"
3404 [(set (match_operand:DF 0 "s_register_operand" "")
3405 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3406 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3407 "")
3408
7db9af5d 3409(define_expand "sqrtsf2"
3410 [(set (match_operand:SF 0 "s_register_operand" "")
3411 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3412 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3413 "")
9c08d1fa 3414
7db9af5d 3415(define_expand "sqrtdf2"
3416 [(set (match_operand:DF 0 "s_register_operand" "")
3417 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3418 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3419 "")
9c08d1fa 3420
a0f94409 3421(define_insn_and_split "one_cmpldi2"
9c08d1fa 3422 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3423 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 3424 "TARGET_32BIT"
f6ebffac 3425 "#"
25f905c2 3426 "TARGET_32BIT && reload_completed"
a0f94409 3427 [(set (match_dup 0) (not:SI (match_dup 1)))
3428 (set (match_dup 2) (not:SI (match_dup 3)))]
3429 "
3430 {
3431 operands[2] = gen_highpart (SImode, operands[0]);
3432 operands[0] = gen_lowpart (SImode, operands[0]);
3433 operands[3] = gen_highpart (SImode, operands[1]);
3434 operands[1] = gen_lowpart (SImode, operands[1]);
3435 }"
0d66636f 3436 [(set_attr "length" "8")
3437 (set_attr "predicable" "yes")]
cffb2a26 3438)
b11cae9e 3439
cffb2a26 3440(define_expand "one_cmplsi2"
3441 [(set (match_operand:SI 0 "s_register_operand" "")
3442 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3443 "TARGET_EITHER"
b11cae9e 3444 ""
cffb2a26 3445)
3446
3447(define_insn "*arm_one_cmplsi2"
3448 [(set (match_operand:SI 0 "s_register_operand" "=r")
3449 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3450 "TARGET_32BIT"
cffb2a26 3451 "mvn%?\\t%0, %1"
0d66636f 3452 [(set_attr "predicable" "yes")]
cffb2a26 3453)
3454
25f905c2 3455(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3456 [(set (match_operand:SI 0 "register_operand" "=l")
3457 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3458 "TARGET_THUMB1"
cffb2a26 3459 "mvn\\t%0, %1"
3460 [(set_attr "length" "2")]
3461)
9c08d1fa 3462
f7fbdd4a 3463(define_insn "*notsi_compare0"
bd5b4116 3464 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3465 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3466 (const_int 0)))
3467 (set (match_operand:SI 0 "s_register_operand" "=r")
3468 (not:SI (match_dup 1)))]
25f905c2 3469 "TARGET_32BIT"
3470 "mvn%.\\t%0, %1"
cffb2a26 3471 [(set_attr "conds" "set")]
3472)
9c08d1fa 3473
f7fbdd4a 3474(define_insn "*notsi_compare0_scratch"
bd5b4116 3475 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3476 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3477 (const_int 0)))
3478 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3479 "TARGET_32BIT"
3480 "mvn%.\\t%0, %1"
cffb2a26 3481 [(set_attr "conds" "set")]
3482)
b11cae9e 3483\f
3484;; Fixed <--> Floating conversion insns
3485
604f3a0a 3486(define_expand "floatsisf2"
3487 [(set (match_operand:SF 0 "s_register_operand" "")
3488 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3489 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3490 "
a2cd141b 3491 if (TARGET_MAVERICK)
604f3a0a 3492 {
3493 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3494 DONE;
3495 }
3496")
3497
604f3a0a 3498(define_expand "floatsidf2"
3499 [(set (match_operand:DF 0 "s_register_operand" "")
3500 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3501 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3502 "
a2cd141b 3503 if (TARGET_MAVERICK)
604f3a0a 3504 {
3505 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3506 DONE;
3507 }
3508")
3509
604f3a0a 3510(define_expand "fix_truncsfsi2"
3511 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3512 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3513 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3514 "
a2cd141b 3515 if (TARGET_MAVERICK)
604f3a0a 3516 {
3517 if (!cirrus_fp_register (operands[0], SImode))
3518 operands[0] = force_reg (SImode, operands[0]);
3519 if (!cirrus_fp_register (operands[1], SFmode))
3520 operands[1] = force_reg (SFmode, operands[0]);
3521 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3522 DONE;
3523 }
3524")
3525
604f3a0a 3526(define_expand "fix_truncdfsi2"
3527 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3528 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
25f905c2 3529 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3530 "
a2cd141b 3531 if (TARGET_MAVERICK)
604f3a0a 3532 {
3533 if (!cirrus_fp_register (operands[1], DFmode))
3534 operands[1] = force_reg (DFmode, operands[0]);
3535 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3536 DONE;
3537 }
3538")
3539
f544c6d2 3540;; Truncation insns
b11cae9e 3541
604f3a0a 3542(define_expand "truncdfsf2"
3543 [(set (match_operand:SF 0 "s_register_operand" "")
3544 (float_truncate:SF
3545 (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3546 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3547 ""
3548)
b11cae9e 3549\f
9c08d1fa 3550;; Zero and sign extension instructions.
b11cae9e 3551
25f905c2 3552(define_expand "zero_extendsidi2"
3553 [(set (match_operand:DI 0 "s_register_operand" "")
3554 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3555 "TARGET_32BIT"
3556 ""
3557)
3558
3559(define_insn "*arm_zero_extendsidi2"
9c08d1fa 3560 [(set (match_operand:DI 0 "s_register_operand" "=r")
3561 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3562 "TARGET_ARM"
9c08d1fa 3563 "*
0d66636f 3564 if (REGNO (operands[1])
3565 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3566 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3567 return \"mov%?\\t%R0, #0\";
3568 "
3569 [(set_attr "length" "8")
3570 (set_attr "predicable" "yes")]
3571)
9c08d1fa 3572
25f905c2 3573(define_expand "zero_extendqidi2"
3574 [(set (match_operand:DI 0 "s_register_operand" "")
3575 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3576 "TARGET_32BIT"
3577 ""
3578)
3579
3580(define_insn "*arm_zero_extendqidi2"
cffb2a26 3581 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3582 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3583 "TARGET_ARM"
e2348bcb 3584 "@
97499065 3585 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
25f905c2 3586 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3587 [(set_attr "length" "8")
0d66636f 3588 (set_attr "predicable" "yes")
a2cd141b 3589 (set_attr "type" "*,load_byte")
cffb2a26 3590 (set_attr "pool_range" "*,4092")
3591 (set_attr "neg_pool_range" "*,4084")]
3592)
9c08d1fa 3593
25f905c2 3594(define_expand "extendsidi2"
3595 [(set (match_operand:DI 0 "s_register_operand" "")
3596 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3597 "TARGET_32BIT"
3598 ""
3599)
3600
3601(define_insn "*arm_extendsidi2"
9c08d1fa 3602 [(set (match_operand:DI 0 "s_register_operand" "=r")
3603 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3604 "TARGET_ARM"
9c08d1fa 3605 "*
0d66636f 3606 if (REGNO (operands[1])
3607 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3608 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3609 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3610 "
3611 [(set_attr "length" "8")
331beb1a 3612 (set_attr "shift" "1")
0d66636f 3613 (set_attr "predicable" "yes")]
3614)
9c08d1fa 3615
3616(define_expand "zero_extendhisi2"
cffb2a26 3617 [(set (match_dup 2)
0d66636f 3618 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3619 (const_int 16)))
9c08d1fa 3620 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3621 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3622 "TARGET_EITHER"
9c08d1fa 3623 "
cffb2a26 3624 {
25f905c2 3625 if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3626 {
a2cd141b 3627 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3628 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3629 DONE;
cffb2a26 3630 }
cffb2a26 3631
c1a66faf 3632 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3633 {
3634 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3635 DONE;
3636 }
cffb2a26 3637
a2cd141b 3638 if (!s_register_operand (operands[1], HImode))
3639 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3640
a2cd141b 3641 if (arm_arch6)
3642 {
3643 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3644 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3645 DONE;
cffb2a26 3646 }
a2cd141b 3647
3648 operands[1] = gen_lowpart (SImode, operands[1]);
3649 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3650 }"
3651)
3652
25f905c2 3653(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 3654 [(set (match_operand:SI 0 "register_operand" "=l")
3655 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
25f905c2 3656 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 3657 "*
3658 rtx mem = XEXP (operands[1], 0);
3659
3660 if (GET_CODE (mem) == CONST)
3661 mem = XEXP (mem, 0);
3662
3663 if (GET_CODE (mem) == LABEL_REF)
3664 return \"ldr\\t%0, %1\";
3665
3666 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3667 {
cffb2a26 3668 rtx a = XEXP (mem, 0);
3669 rtx b = XEXP (mem, 1);
3670
3671 /* This can happen due to bugs in reload. */
3672 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3673 {
3674 rtx ops[2];
3675 ops[0] = operands[0];
3676 ops[1] = a;
3677
3678 output_asm_insn (\"mov %0, %1\", ops);
3679
3680 XEXP (mem, 0) = operands[0];
3681 }
3682
3683 else if ( GET_CODE (a) == LABEL_REF
3684 && GET_CODE (b) == CONST_INT)
3685 return \"ldr\\t%0, %1\";
25f7a26e 3686 }
cffb2a26 3687
3688 return \"ldrh\\t%0, %1\";
3689 "
3690 [(set_attr "length" "4")
a2cd141b 3691 (set_attr "type" "load_byte")
cffb2a26 3692 (set_attr "pool_range" "60")]
3693)
9c08d1fa 3694
25f905c2 3695(define_insn "*thumb1_zero_extendhisi2_v6"
a2cd141b 3696 [(set (match_operand:SI 0 "register_operand" "=l,l")
3697 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
25f905c2 3698 "TARGET_THUMB1 && arm_arch6"
a2cd141b 3699 "*
3700 rtx mem;
3701
3702 if (which_alternative == 0)
3703 return \"uxth\\t%0, %1\";
3704
3705 mem = XEXP (operands[1], 0);
3706
3707 if (GET_CODE (mem) == CONST)
3708 mem = XEXP (mem, 0);
3709
3710 if (GET_CODE (mem) == LABEL_REF)
3711 return \"ldr\\t%0, %1\";
3712
3713 if (GET_CODE (mem) == PLUS)
3714 {
3715 rtx a = XEXP (mem, 0);
3716 rtx b = XEXP (mem, 1);
3717
3718 /* This can happen due to bugs in reload. */
3719 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3720 {
3721 rtx ops[2];
3722 ops[0] = operands[0];
3723 ops[1] = a;
3724
3725 output_asm_insn (\"mov %0, %1\", ops);
3726
3727 XEXP (mem, 0) = operands[0];
3728 }
3729
3730 else if ( GET_CODE (a) == LABEL_REF
3731 && GET_CODE (b) == CONST_INT)
3732 return \"ldr\\t%0, %1\";
3733 }
3734
3735 return \"ldrh\\t%0, %1\";
3736 "
3737 [(set_attr "length" "2,4")
3738 (set_attr "type" "alu_shift,load_byte")
3739 (set_attr "pool_range" "*,60")]
3740)
3741
cffb2a26 3742(define_insn "*arm_zero_extendhisi2"
a2cd141b 3743 [(set (match_operand:SI 0 "s_register_operand" "=r")
3744 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3745 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 3746 "ldr%(h%)\\t%0, %1"
a2cd141b 3747 [(set_attr "type" "load_byte")
0d66636f 3748 (set_attr "predicable" "yes")
cffb2a26 3749 (set_attr "pool_range" "256")
3750 (set_attr "neg_pool_range" "244")]
3751)
f7fbdd4a 3752
a2cd141b 3753(define_insn "*arm_zero_extendhisi2_v6"
3754 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3755 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3756 "TARGET_ARM && arm_arch6"
3757 "@
3758 uxth%?\\t%0, %1
25f905c2 3759 ldr%(h%)\\t%0, %1"
a2cd141b 3760 [(set_attr "type" "alu_shift,load_byte")
3761 (set_attr "predicable" "yes")
3762 (set_attr "pool_range" "*,256")
3763 (set_attr "neg_pool_range" "*,244")]
3764)
3765
3766(define_insn "*arm_zero_extendhisi2addsi"
3767 [(set (match_operand:SI 0 "s_register_operand" "=r")
3768 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3769 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 3770 "TARGET_INT_SIMD"
a2cd141b 3771 "uxtah%?\\t%0, %2, %1"
3772 [(set_attr "type" "alu_shift")
3773 (set_attr "predicable" "yes")]
3774)
3775
87b22bf7 3776(define_expand "zero_extendqisi2"
cffb2a26 3777 [(set (match_operand:SI 0 "s_register_operand" "")
3778 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3779 "TARGET_EITHER"
87b22bf7 3780 "
a2cd141b 3781 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 3782 {
cffb2a26 3783 if (TARGET_ARM)
3784 {
215b30b3 3785 emit_insn (gen_andsi3 (operands[0],
3786 gen_lowpart (SImode, operands[1]),
cffb2a26 3787 GEN_INT (255)));
3788 }
3789 else /* TARGET_THUMB */
3790 {
3791 rtx temp = gen_reg_rtx (SImode);
3792 rtx ops[3];
3793
3794 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3795 operands[1] = gen_lowpart (SImode, operands[1]);
3796
3797 ops[0] = temp;
3798 ops[1] = operands[1];
3799 ops[2] = GEN_INT (24);
3800
215b30b3 3801 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3802 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3803
3804 ops[0] = operands[0];
3805 ops[1] = temp;
3806 ops[2] = GEN_INT (24);
3807
215b30b3 3808 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3809 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3810 }
87b22bf7 3811 DONE;
3812 }
215b30b3 3813 "
3814)
9c08d1fa 3815
25f905c2 3816(define_insn "*thumb1_zero_extendqisi2"
a2cd141b 3817 [(set (match_operand:SI 0 "register_operand" "=l")
3818 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
25f905c2 3819 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 3820 "ldrb\\t%0, %1"
3821 [(set_attr "length" "2")
a2cd141b 3822 (set_attr "type" "load_byte")
cffb2a26 3823 (set_attr "pool_range" "32")]
3824)
3825
25f905c2 3826(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 3827 [(set (match_operand:SI 0 "register_operand" "=l,l")
3828 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 3829 "TARGET_THUMB1 && arm_arch6"
a2cd141b 3830 "@
3831 uxtb\\t%0, %1
3832 ldrb\\t%0, %1"
3833 [(set_attr "length" "2,2")
3834 (set_attr "type" "alu_shift,load_byte")
3835 (set_attr "pool_range" "*,32")]
3836)
3837
cffb2a26 3838(define_insn "*arm_zero_extendqisi2"
a2cd141b 3839 [(set (match_operand:SI 0 "s_register_operand" "=r")
3840 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3841 "TARGET_ARM && !arm_arch6"
25f905c2 3842 "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 3843 [(set_attr "type" "load_byte")
0d66636f 3844 (set_attr "predicable" "yes")
cffb2a26 3845 (set_attr "pool_range" "4096")
3846 (set_attr "neg_pool_range" "4084")]
3847)
87b22bf7 3848
a2cd141b 3849(define_insn "*arm_zero_extendqisi2_v6"
3850 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3851 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3852 "TARGET_ARM && arm_arch6"
3853 "@
25f905c2 3854 uxtb%(%)\\t%0, %1
3855 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 3856 [(set_attr "type" "alu_shift,load_byte")
3857 (set_attr "predicable" "yes")
3858 (set_attr "pool_range" "*,4096")
3859 (set_attr "neg_pool_range" "*,4084")]
3860)
3861
3862(define_insn "*arm_zero_extendqisi2addsi"
3863 [(set (match_operand:SI 0 "s_register_operand" "=r")
3864 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3865 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 3866 "TARGET_INT_SIMD"
a2cd141b 3867 "uxtab%?\\t%0, %2, %1"
3868 [(set_attr "predicable" "yes")
3869 (set_attr "type" "alu_shift")]
3870)
3871
87b22bf7 3872(define_split
3873 [(set (match_operand:SI 0 "s_register_operand" "")
3874 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3875 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 3876 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 3877 [(set (match_dup 2) (match_dup 1))
3878 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 3879 ""
3880)
9c08d1fa 3881
8a4d25d6 3882(define_split
3883 [(set (match_operand:SI 0 "s_register_operand" "")
3884 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3885 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 3886 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 3887 [(set (match_dup 2) (match_dup 1))
3888 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3889 ""
3890)
3891
f7fbdd4a 3892(define_insn "*compareqi_eq0"
bd5b4116 3893 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 3894 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 3895 (const_int 0)))]
25f905c2 3896 "TARGET_32BIT"
87b22bf7 3897 "tst\\t%0, #255"
cffb2a26 3898 [(set_attr "conds" "set")]
3899)
b11cae9e 3900
b11cae9e 3901(define_expand "extendhisi2"
c8f69309 3902 [(set (match_dup 2)
25f7a26e 3903 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 3904 (const_int 16)))
9c08d1fa 3905 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3906 (ashiftrt:SI (match_dup 2)
3907 (const_int 16)))]
cffb2a26 3908 "TARGET_EITHER"
b11cae9e 3909 "
cffb2a26 3910 {
a2cd141b 3911 if (GET_CODE (operands[1]) == MEM)
cffb2a26 3912 {
25f905c2 3913 if (TARGET_THUMB1)
a2cd141b 3914 {
25f905c2 3915 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 3916 DONE;
3917 }
3918 else if (arm_arch4)
3919 {
a2cd141b 3920 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3921 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3922 DONE;
3923 }
cffb2a26 3924 }
7bd8ccc9 3925
c1a66faf 3926 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 3927 {
3928 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3929 DONE;
3930 }
a2cd141b 3931
215b30b3 3932 if (!s_register_operand (operands[1], HImode))
cffb2a26 3933 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3934
a2cd141b 3935 if (arm_arch6)
cffb2a26 3936 {
25f905c2 3937 if (TARGET_THUMB1)
3938 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 3939 else
3940 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3941 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3942
cffb2a26 3943 DONE;
3944 }
a2cd141b 3945
3946 operands[1] = gen_lowpart (SImode, operands[1]);
3947 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3948 }"
3949)
3950
25f905c2 3951(define_insn "thumb1_extendhisi2"
a2cd141b 3952 [(set (match_operand:SI 0 "register_operand" "=l")
3953 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3954 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3955 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 3956 "*
3957 {
3958 rtx ops[4];
3959 rtx mem = XEXP (operands[1], 0);
3960
3961 /* This code used to try to use 'V', and fix the address only if it was
3962 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3963 range of QImode offsets, and offsettable_address_p does a QImode
3964 address check. */
3965
3966 if (GET_CODE (mem) == CONST)
3967 mem = XEXP (mem, 0);
3968
3969 if (GET_CODE (mem) == LABEL_REF)
3970 return \"ldr\\t%0, %1\";
3971
3972 if (GET_CODE (mem) == PLUS)
3973 {
3974 rtx a = XEXP (mem, 0);
3975 rtx b = XEXP (mem, 1);
3976
3977 if (GET_CODE (a) == LABEL_REF
3978 && GET_CODE (b) == CONST_INT)
3979 return \"ldr\\t%0, %1\";
3980
3981 if (GET_CODE (b) == REG)
3982 return \"ldrsh\\t%0, %1\";
3983
3984 ops[1] = a;
3985 ops[2] = b;
3986 }
3987 else
3988 {
3989 ops[1] = mem;
3990 ops[2] = const0_rtx;
3991 }
ed29c566 3992
3993 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 3994
3995 ops[0] = operands[0];
3996 ops[3] = operands[2];
3997 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3998 return \"\";
3999 }"
4000 [(set_attr "length" "4")
a2cd141b 4001 (set_attr "type" "load_byte")
cffb2a26 4002 (set_attr "pool_range" "1020")]
4003)
25f7a26e 4004
a2cd141b 4005;; We used to have an early-clobber on the scratch register here.
4006;; However, there's a bug somewhere in reload which means that this
4007;; can be partially ignored during spill allocation if the memory
ed29c566 4008;; address also needs reloading; this causes us to die later on when
a2cd141b 4009;; we try to verify the operands. Fortunately, we don't really need
4010;; the early-clobber: we can always use operand 0 if operand 2
4011;; overlaps the address.
25f905c2 4012(define_insn "*thumb1_extendhisi2_insn_v6"
a2cd141b 4013 [(set (match_operand:SI 0 "register_operand" "=l,l")
4014 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4015 (clobber (match_scratch:SI 2 "=X,l"))]
25f905c2 4016 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4017 "*
4018 {
4019 rtx ops[4];
4020 rtx mem;
4021
4022 if (which_alternative == 0)
4023 return \"sxth\\t%0, %1\";
4024
4025 mem = XEXP (operands[1], 0);
4026
4027 /* This code used to try to use 'V', and fix the address only if it was
4028 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4029 range of QImode offsets, and offsettable_address_p does a QImode
4030 address check. */
4031
4032 if (GET_CODE (mem) == CONST)
4033 mem = XEXP (mem, 0);
4034
4035 if (GET_CODE (mem) == LABEL_REF)
4036 return \"ldr\\t%0, %1\";
4037
4038 if (GET_CODE (mem) == PLUS)
4039 {
4040 rtx a = XEXP (mem, 0);
4041 rtx b = XEXP (mem, 1);
4042
4043 if (GET_CODE (a) == LABEL_REF
4044 && GET_CODE (b) == CONST_INT)
4045 return \"ldr\\t%0, %1\";
4046
4047 if (GET_CODE (b) == REG)
4048 return \"ldrsh\\t%0, %1\";
4049
4050 ops[1] = a;
4051 ops[2] = b;
4052 }
4053 else
4054 {
4055 ops[1] = mem;
4056 ops[2] = const0_rtx;
4057 }
4058
ed29c566 4059 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4060
4061 ops[0] = operands[0];
4062 if (reg_mentioned_p (operands[2], ops[1]))
4063 ops[3] = ops[0];
4064 else
4065 ops[3] = operands[2];
4066 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4067 return \"\";
4068 }"
4069 [(set_attr "length" "2,4")
4070 (set_attr "type" "alu_shift,load_byte")
4071 (set_attr "pool_range" "*,1020")]
4072)
4073
25f905c2 4074;; This pattern will only be used when ldsh is not available
25f7a26e 4075(define_expand "extendhisi2_mem"
eab14235 4076 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4077 (set (match_dup 3)
eab14235 4078 (zero_extend:SI (match_dup 7)))
25f7a26e 4079 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4080 (set (match_operand:SI 0 "" "")
4081 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4082 "TARGET_ARM"
25f7a26e 4083 "
215b30b3 4084 {
4085 rtx mem1, mem2;
4086 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4087
788fcce0 4088 mem1 = change_address (operands[1], QImode, addr);
4089 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4090 operands[0] = gen_lowpart (SImode, operands[0]);
4091 operands[1] = mem1;
4092 operands[2] = gen_reg_rtx (SImode);
4093 operands[3] = gen_reg_rtx (SImode);
4094 operands[6] = gen_reg_rtx (SImode);
4095 operands[7] = mem2;
25f7a26e 4096
215b30b3 4097 if (BYTES_BIG_ENDIAN)
4098 {
4099 operands[4] = operands[2];
4100 operands[5] = operands[3];
4101 }
4102 else
4103 {
4104 operands[4] = operands[3];
4105 operands[5] = operands[2];
4106 }
4107 }"
4108)
b11cae9e 4109
a2cd141b 4110(define_insn "*arm_extendhisi2"
4111 [(set (match_operand:SI 0 "s_register_operand" "=r")
4112 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4113 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4114 "ldr%(sh%)\\t%0, %1"
a2cd141b 4115 [(set_attr "type" "load_byte")
0d66636f 4116 (set_attr "predicable" "yes")
cffb2a26 4117 (set_attr "pool_range" "256")
4118 (set_attr "neg_pool_range" "244")]
4119)
f7fbdd4a 4120
25f905c2 4121;; ??? Check Thumb-2 pool range
a2cd141b 4122(define_insn "*arm_extendhisi2_v6"
4123 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4124 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4125 "TARGET_32BIT && arm_arch6"
a2cd141b 4126 "@
4127 sxth%?\\t%0, %1
25f905c2 4128 ldr%(sh%)\\t%0, %1"
a2cd141b 4129 [(set_attr "type" "alu_shift,load_byte")
4130 (set_attr "predicable" "yes")
4131 (set_attr "pool_range" "*,256")
4132 (set_attr "neg_pool_range" "*,244")]
4133)
4134
4135(define_insn "*arm_extendhisi2addsi"
4136 [(set (match_operand:SI 0 "s_register_operand" "=r")
4137 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4138 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4139 "TARGET_INT_SIMD"
a2cd141b 4140 "sxtah%?\\t%0, %2, %1"
4141)
4142
c8f69309 4143(define_expand "extendqihi2"
4144 [(set (match_dup 2)
f7fbdd4a 4145 (ashift:SI (match_operand:QI 1 "general_operand" "")
c8f69309 4146 (const_int 24)))
9c08d1fa 4147 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4148 (ashiftrt:SI (match_dup 2)
4149 (const_int 24)))]
cffb2a26 4150 "TARGET_ARM"
c8f69309 4151 "
215b30b3 4152 {
4153 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4154 {
4155 emit_insn (gen_rtx_SET (VOIDmode,
4156 operands[0],
4157 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4158 DONE;
4159 }
4160 if (!s_register_operand (operands[1], QImode))
4161 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4162 operands[0] = gen_lowpart (SImode, operands[0]);
4163 operands[1] = gen_lowpart (SImode, operands[1]);
4164 operands[2] = gen_reg_rtx (SImode);
4165 }"
4166)
f7fbdd4a 4167
25f905c2 4168(define_insn "*arm_extendqihi_insn"
b4e8a300 4169 [(set (match_operand:HI 0 "s_register_operand" "=r")
4170 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
cffb2a26 4171 "TARGET_ARM && arm_arch4"
25f905c2 4172 "ldr%(sb%)\\t%0, %1"
a2cd141b 4173 [(set_attr "type" "load_byte")
0d66636f 4174 (set_attr "predicable" "yes")
cffb2a26 4175 (set_attr "pool_range" "256")
4176 (set_attr "neg_pool_range" "244")]
4177)
3fc2009e 4178
b11cae9e 4179(define_expand "extendqisi2"
c8f69309 4180 [(set (match_dup 2)
3fc2009e 4181 (ashift:SI (match_operand:QI 1 "general_operand" "")
b11cae9e 4182 (const_int 24)))
9c08d1fa 4183 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4184 (ashiftrt:SI (match_dup 2)
4185 (const_int 24)))]
cffb2a26 4186 "TARGET_EITHER"
b11cae9e 4187 "
cffb2a26 4188 {
a2cd141b 4189 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 4190 {
a2cd141b 4191 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 4192 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4193 DONE;
4194 }
a2cd141b 4195
215b30b3 4196 if (!s_register_operand (operands[1], QImode))
cffb2a26 4197 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 4198
a2cd141b 4199 if (arm_arch6)
4200 {
4201 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4202 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4203 DONE;
cffb2a26 4204 }
a2cd141b 4205
4206 operands[1] = gen_lowpart (SImode, operands[1]);
4207 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4208 }"
4209)
f7fbdd4a 4210
a2cd141b 4211(define_insn "*arm_extendqisi"
4212 [(set (match_operand:SI 0 "s_register_operand" "=r")
b4e8a300 4213 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
a2cd141b 4214 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4215 "ldr%(sb%)\\t%0, %1"
a2cd141b 4216 [(set_attr "type" "load_byte")
0d66636f 4217 (set_attr "predicable" "yes")
cffb2a26 4218 (set_attr "pool_range" "256")
4219 (set_attr "neg_pool_range" "244")]
4220)
3fc2009e 4221
a2cd141b 4222(define_insn "*arm_extendqisi_v6"
4223 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
b4e8a300 4224 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
a2cd141b 4225 "TARGET_ARM && arm_arch6"
b4e8a300 4226 "@
4227 sxtb%?\\t%0, %1
25f905c2 4228 ldr%(sb%)\\t%0, %1"
a2cd141b 4229 [(set_attr "type" "alu_shift,load_byte")
4230 (set_attr "predicable" "yes")
a2cd141b 4231 (set_attr "pool_range" "*,256")
4232 (set_attr "neg_pool_range" "*,244")]
4233)
4234
4235(define_insn "*arm_extendqisi2addsi"
4236 [(set (match_operand:SI 0 "s_register_operand" "=r")
4237 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4238 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4239 "TARGET_INT_SIMD"
a2cd141b 4240 "sxtab%?\\t%0, %2, %1"
4241 [(set_attr "type" "alu_shift")
4242 (set_attr "predicable" "yes")]
4243)
4244
25f905c2 4245(define_insn "*thumb1_extendqisi2"
a2cd141b 4246 [(set (match_operand:SI 0 "register_operand" "=l,l")
4247 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
25f905c2 4248 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4249 "*
4250 {
4251 rtx ops[3];
4252 rtx mem = XEXP (operands[1], 0);
4253
4254 if (GET_CODE (mem) == CONST)
4255 mem = XEXP (mem, 0);
4256
4257 if (GET_CODE (mem) == LABEL_REF)
4258 return \"ldr\\t%0, %1\";
4259
4260 if (GET_CODE (mem) == PLUS
4261 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4262 return \"ldr\\t%0, %1\";
4263
4264 if (which_alternative == 0)
4265 return \"ldrsb\\t%0, %1\";
4266
4267 ops[0] = operands[0];
4268
4269 if (GET_CODE (mem) == PLUS)
4270 {
4271 rtx a = XEXP (mem, 0);
4272 rtx b = XEXP (mem, 1);
4273
4274 ops[1] = a;
4275 ops[2] = b;
4276
4277 if (GET_CODE (a) == REG)
4278 {
4279 if (GET_CODE (b) == REG)
4280 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4281 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 4282 {
4283 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4284 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4285 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4286 }
cffb2a26 4287 else
4288 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4289 }
cffb2a26 4290 else
4291 {
ed29c566 4292 gcc_assert (GET_CODE (b) == REG);
cffb2a26 4293 if (REGNO (b) == REGNO (ops[0]))
215b30b3 4294 {
4295 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4296 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4297 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4298 }
cffb2a26 4299 else
4300 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4301 }
4302 }
4303 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4304 {
215b30b3 4305 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4306 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4307 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 4308 }
4309 else
4310 {
4311 ops[1] = mem;
4312 ops[2] = const0_rtx;
4313
4314 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4315 }
4316 return \"\";
4317 }"
4318 [(set_attr "length" "2,6")
a2cd141b 4319 (set_attr "type" "load_byte,load_byte")
cffb2a26 4320 (set_attr "pool_range" "32,32")]
4321)
4322
25f905c2 4323(define_insn "*thumb1_extendqisi2_v6"
a2cd141b 4324 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4325 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
25f905c2 4326 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4327 "*
4328 {
4329 rtx ops[3];
4330 rtx mem;
4331
4332 if (which_alternative == 0)
4333 return \"sxtb\\t%0, %1\";
4334
4335 mem = XEXP (operands[1], 0);
4336
4337 if (GET_CODE (mem) == CONST)
4338 mem = XEXP (mem, 0);
4339
4340 if (GET_CODE (mem) == LABEL_REF)
4341 return \"ldr\\t%0, %1\";
4342
4343 if (GET_CODE (mem) == PLUS
4344 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4345 return \"ldr\\t%0, %1\";
4346
4347 if (which_alternative == 0)
4348 return \"ldrsb\\t%0, %1\";
4349
4350 ops[0] = operands[0];
4351
4352 if (GET_CODE (mem) == PLUS)
4353 {
4354 rtx a = XEXP (mem, 0);
4355 rtx b = XEXP (mem, 1);
4356
4357 ops[1] = a;
4358 ops[2] = b;
4359
4360 if (GET_CODE (a) == REG)
4361 {
4362 if (GET_CODE (b) == REG)
4363 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4364 else if (REGNO (a) == REGNO (ops[0]))
4365 {
4366 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4367 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4368 }
4369 else
4370 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4371 }
a2cd141b 4372 else
4373 {
ed29c566 4374 gcc_assert (GET_CODE (b) == REG);
a2cd141b 4375 if (REGNO (b) == REGNO (ops[0]))
4376 {
4377 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4378 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4379 }
4380 else
4381 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4382 }
4383 }
4384 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4385 {
4386 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4387 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4388 }
4389 else
4390 {
4391 ops[1] = mem;
4392 ops[2] = const0_rtx;
4393
4394 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4395 }
4396 return \"\";
4397 }"
4398 [(set_attr "length" "2,2,4")
4399 (set_attr "type" "alu_shift,load_byte,load_byte")
4400 (set_attr "pool_range" "*,32,32")]
4401)
4402
caedf871 4403(define_expand "extendsfdf2"
4404 [(set (match_operand:DF 0 "s_register_operand" "")
4405 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4406 "TARGET_32BIT && TARGET_HARD_FLOAT"
caedf871 4407 ""
4408)
b11cae9e 4409\f
4410;; Move insns (including loads and stores)
4411
4412;; XXX Just some ideas about movti.
9c08d1fa 4413;; I don't think these are a good idea on the arm, there just aren't enough
4414;; registers
b11cae9e 4415;;(define_expand "loadti"
9c08d1fa 4416;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4417;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4418;; "" "")
4419
4420;;(define_expand "storeti"
4421;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4422;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4423;; "" "")
4424
4425;;(define_expand "movti"
4426;; [(set (match_operand:TI 0 "general_operand" "")
4427;; (match_operand:TI 1 "general_operand" ""))]
4428;; ""
4429;; "
4430;;{
4431;; rtx insn;
4432;;
4433;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4434;; operands[1] = copy_to_reg (operands[1]);
4435;; if (GET_CODE (operands[0]) == MEM)
4436;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4437;; else if (GET_CODE (operands[1]) == MEM)
4438;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4439;; else
4440;; FAIL;
4441;;
4442;; emit_insn (insn);
4443;; DONE;
4444;;}")
4445
a2f10574 4446;; Recognize garbage generated above.
b11cae9e 4447
4448;;(define_insn ""
4449;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4450;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4451;; ""
4452;; "*
4453;; {
4454;; register mem = (which_alternative < 3);
0d66636f 4455;; register const char *template;
b11cae9e 4456;;
4457;; operands[mem] = XEXP (operands[mem], 0);
4458;; switch (which_alternative)
4459;; {
4460;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4461;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4462;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4463;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4464;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4465;; case 5: template = \"stmia\\t%0, %M1\"; break;
4466;; }
e2348bcb 4467;; output_asm_insn (template, operands);
4468;; return \"\";
b11cae9e 4469;; }")
4470
cffb2a26 4471(define_expand "movdi"
4472 [(set (match_operand:DI 0 "general_operand" "")
4473 (match_operand:DI 1 "general_operand" ""))]
4474 "TARGET_EITHER"
4475 "
e1ba4a27 4476 if (can_create_pseudo_p ())
cffb2a26 4477 {
b2778788 4478 if (GET_CODE (operands[0]) != REG)
4479 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4480 }
4481 "
4482)
b11cae9e 4483
cffb2a26 4484(define_insn "*arm_movdi"
d51f92df 4485 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4486 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4487 "TARGET_ARM
b2778788 4488 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4489 && !TARGET_IWMMXT
4490 && ( register_operand (operands[0], DImode)
4491 || register_operand (operands[1], DImode))"
b11cae9e 4492 "*
d51f92df 4493 switch (which_alternative)
4494 {
4495 case 0:
4496 case 1:
4497 case 2:
4498 return \"#\";
4499 default:
4500 return output_move_double (operands);
4501 }
cffb2a26 4502 "
359a6e9f 4503 [(set_attr "length" "8,12,16,8,8")
4504 (set_attr "type" "*,*,*,load2,store2")
4505 (set_attr "pool_range" "*,*,*,1020,*")
4506 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4507)
4508
d51f92df 4509(define_split
4510 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4511 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4512 "TARGET_32BIT
d51f92df 4513 && reload_completed
4514 && (arm_const_double_inline_cost (operands[1])
4515 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4516 [(const_int 0)]
4517 "
4518 arm_split_constant (SET, SImode, curr_insn,
4519 INTVAL (gen_lowpart (SImode, operands[1])),
4520 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4521 arm_split_constant (SET, SImode, curr_insn,
4522 INTVAL (gen_highpart_mode (SImode,
4523 GET_MODE (operands[0]),
4524 operands[1])),
4525 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4526 DONE;
4527 "
4528)
4529
e5ba9289 4530; If optimizing for size, or if we have load delay slots, then
4531; we want to split the constant into two separate operations.
4532; In both cases this may split a trivial part into a single data op
4533; leaving a single complex constant to load. We can also get longer
4534; offsets in a LDR which means we get better chances of sharing the pool
4535; entries. Finally, we can normally do a better job of scheduling
4536; LDR instructions than we can with LDM.
4537; This pattern will only match if the one above did not.
4538(define_split
4539 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4540 (match_operand:ANY64 1 "const_double_operand" ""))]
4541 "TARGET_ARM && reload_completed
4542 && arm_const_double_by_parts (operands[1])"
4543 [(set (match_dup 0) (match_dup 1))
4544 (set (match_dup 2) (match_dup 3))]
4545 "
4546 operands[2] = gen_highpart (SImode, operands[0]);
4547 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4548 operands[1]);
4549 operands[0] = gen_lowpart (SImode, operands[0]);
4550 operands[1] = gen_lowpart (SImode, operands[1]);
4551 "
4552)
4553
d51f92df 4554(define_split
4555 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4556 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4557 "TARGET_EITHER && reload_completed"
4558 [(set (match_dup 0) (match_dup 1))
4559 (set (match_dup 2) (match_dup 3))]
4560 "
4561 operands[2] = gen_highpart (SImode, operands[0]);
4562 operands[3] = gen_highpart (SImode, operands[1]);
4563 operands[0] = gen_lowpart (SImode, operands[0]);
4564 operands[1] = gen_lowpart (SImode, operands[1]);
4565
4566 /* Handle a partial overlap. */
4567 if (rtx_equal_p (operands[0], operands[3]))
4568 {
4569 rtx tmp0 = operands[0];
4570 rtx tmp1 = operands[1];
4571
4572 operands[0] = operands[2];
4573 operands[1] = operands[3];
4574 operands[2] = tmp0;
4575 operands[3] = tmp1;
4576 }
4577 "
4578)
4579
a8a3b539 4580;; We can't actually do base+index doubleword loads if the index and
4581;; destination overlap. Split here so that we at least have chance to
4582;; schedule.
4583(define_split
4584 [(set (match_operand:DI 0 "s_register_operand" "")
4585 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4586 (match_operand:SI 2 "s_register_operand" ""))))]
4587 "TARGET_LDRD
4588 && reg_overlap_mentioned_p (operands[0], operands[1])
4589 && reg_overlap_mentioned_p (operands[0], operands[2])"
4590 [(set (match_dup 4)
4591 (plus:SI (match_dup 1)
4592 (match_dup 2)))
4593 (set (match_dup 0)
4594 (mem:DI (match_dup 4)))]
4595 "
4596 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4597 "
4598)
4599
cffb2a26 4600;;; ??? This should have alternatives for constants.
4601;;; ??? This was originally identical to the movdf_insn pattern.
4602;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4603;;; thumb_reorg with a memory reference.
25f905c2 4604(define_insn "*thumb1_movdi_insn"
215b30b3 4605 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4606 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4607 "TARGET_THUMB1
a2cd141b 4608 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4609 && ( register_operand (operands[0], DImode)
4610 || register_operand (operands[1], DImode))"
4611 "*
4612 {
4613 switch (which_alternative)
4614 {
4615 default:
4616 case 0:
4617 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4618 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4619 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4620 case 1:
4621 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4622 case 2:
4623 operands[1] = GEN_INT (- INTVAL (operands[1]));
4624 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4625 case 3:
4626 return \"ldmia\\t%1, {%0, %H0}\";
4627 case 4:
4628 return \"stmia\\t%0, {%1, %H1}\";
4629 case 5:
4630 return thumb_load_double_from_address (operands);
4631 case 6:
1a83b3ff 4632 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4633 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4634 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4635 return \"\";
4636 case 7:
4637 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4638 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4639 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4640 }
4641 }"
4642 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4643 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4644 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4645)
b11cae9e 4646
9c08d1fa 4647(define_expand "movsi"
4648 [(set (match_operand:SI 0 "general_operand" "")
4649 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4650 "TARGET_EITHER"
9c08d1fa 4651 "
e348ff3e 4652 rtx base, offset, tmp;
4653
25f905c2 4654 if (TARGET_32BIT)
9c08d1fa 4655 {
674a8f0b 4656 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4657 if (GET_CODE (operands[0]) == MEM)
4658 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4659 if (arm_general_register_operand (operands[0], SImode)
4660 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4661 && !(const_ok_for_arm (INTVAL (operands[1]))
4662 || const_ok_for_arm (~INTVAL (operands[1]))))
4663 {
96f57e36 4664 arm_split_constant (SET, SImode, NULL_RTX,
4665 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 4666 optimize && can_create_pseudo_p ());
cffb2a26 4667 DONE;
4668 }
4669 }
25f905c2 4670 else /* TARGET_THUMB1... */
cffb2a26 4671 {
e1ba4a27 4672 if (can_create_pseudo_p ())
cffb2a26 4673 {
4674 if (GET_CODE (operands[0]) != REG)
4675 operands[1] = force_reg (SImode, operands[1]);
4676 }
9c08d1fa 4677 }
f655717d 4678
e348ff3e 4679 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
4680 {
4681 split_const (operands[1], &base, &offset);
4682 if (GET_CODE (base) == SYMBOL_REF
4683 && !offset_within_block_p (base, INTVAL (offset)))
4684 {
b308ddcf 4685 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 4686 emit_move_insn (tmp, base);
4687 emit_insn (gen_addsi3 (operands[0], tmp, offset));
4688 DONE;
4689 }
4690 }
4691
f655717d 4692 /* Recognize the case where operand[1] is a reference to thread-local
4693 data and load its address to a register. */
4694 if (arm_tls_referenced_p (operands[1]))
4695 {
4696 rtx tmp = operands[1];
4697 rtx addend = NULL;
4698
4699 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4700 {
4701 addend = XEXP (XEXP (tmp, 0), 1);
4702 tmp = XEXP (XEXP (tmp, 0), 0);
4703 }
4704
4705 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4706 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4707
e1ba4a27 4708 tmp = legitimize_tls_address (tmp,
4709 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 4710 if (addend)
4711 {
4712 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4713 tmp = force_operand (tmp, operands[0]);
4714 }
4715 operands[1] = tmp;
4716 }
4717 else if (flag_pic
4718 && (CONSTANT_P (operands[1])
4719 || symbol_mentioned_p (operands[1])
4720 || label_mentioned_p (operands[1])))
4721 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 4722 (!can_create_pseudo_p ()
4723 ? operands[0]
4724 : 0));
215b30b3 4725 "
4726)
9c08d1fa 4727
cffb2a26 4728(define_insn "*arm_movsi_insn"
25f905c2 4729 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r, m")
4730 (match_operand:SI 1 "general_operand" "rI,K,N,mi,r"))]
755eb2b4 4731 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 4732 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 4733 && ( register_operand (operands[0], SImode)
4734 || register_operand (operands[1], SImode))"
f7fbdd4a 4735 "@
4736 mov%?\\t%0, %1
4737 mvn%?\\t%0, #%B1
25f905c2 4738 movw%?\\t%0, %1
f7fbdd4a 4739 ldr%?\\t%0, %1
4740 str%?\\t%1, %0"
25f905c2 4741 [(set_attr "type" "*,*,*,load1,store1")
0d66636f 4742 (set_attr "predicable" "yes")
25f905c2 4743 (set_attr "pool_range" "*,*,*,4096,*")
4744 (set_attr "neg_pool_range" "*,*,*,4084,*")]
cffb2a26 4745)
87b22bf7 4746
4747(define_split
a2cd141b 4748 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 4749 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 4750 "TARGET_32BIT
215b30b3 4751 && (!(const_ok_for_arm (INTVAL (operands[1]))
4752 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 4753 [(clobber (const_int 0))]
4754 "
96f57e36 4755 arm_split_constant (SET, SImode, NULL_RTX,
4756 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 4757 DONE;
215b30b3 4758 "
4759)
9c08d1fa 4760
25f905c2 4761(define_insn "*thumb1_movsi_insn"
215b30b3 4762 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4763 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
25f905c2 4764 "TARGET_THUMB1
cffb2a26 4765 && ( register_operand (operands[0], SImode)
4766 || register_operand (operands[1], SImode))"
4767 "@
4768 mov %0, %1
4769 mov %0, %1
4770 #
4771 #
4772 ldmia\\t%1, {%0}
4773 stmia\\t%0, {%1}
4774 ldr\\t%0, %1
4775 str\\t%1, %0
4776 mov\\t%0, %1"
4777 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 4778 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 4779 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4780)
4781
4782(define_split
4783 [(set (match_operand:SI 0 "register_operand" "")
4784 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 4785 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
cffb2a26 4786 [(set (match_dup 0) (match_dup 1))
4787 (set (match_dup 0) (neg:SI (match_dup 0)))]
4788 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4789)
4790
4791(define_split
4792 [(set (match_operand:SI 0 "register_operand" "")
4793 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 4794 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
cffb2a26 4795 [(set (match_dup 0) (match_dup 1))
4796 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4797 "
4798 {
4799 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4800 unsigned HOST_WIDE_INT mask = 0xff;
4801 int i;
4802
4803 for (i = 0; i < 25; i++)
4804 if ((val & (mask << i)) == val)
4805 break;
4806
f5b3169c 4807 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 4808 if (i == 0)
4809 FAIL;
4810
4811 operands[1] = GEN_INT (val >> i);
4812 operands[2] = GEN_INT (i);
4813 }"
4814)
4815
67336bcf 4816;; When generating pic, we need to load the symbol offset into a register.
4817;; So that the optimizer does not confuse this with a normal symbol load
4818;; we use an unspec. The offset will be loaded from a constant pool entry,
4819;; since that is the only type of relocation we can use.
4820
4821;; The rather odd constraints on the following are to force reload to leave
4822;; the insn alone, and to force the minipool generation pass to then move
4823;; the GOT symbol to memory.
849170fd 4824
8c4d8060 4825(define_insn "pic_load_addr_arm"
849170fd 4826 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4827 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4828 "TARGET_ARM && flag_pic"
67336bcf 4829 "ldr%?\\t%0, %1"
a2cd141b 4830 [(set_attr "type" "load1")
8c4d8060 4831 (set (attr "pool_range") (const_int 4096))
4832 (set (attr "neg_pool_range") (const_int 4084))]
4833)
4834
25f905c2 4835(define_insn "pic_load_addr_thumb1"
8c4d8060 4836 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 4837 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 4838 "TARGET_THUMB1 && flag_pic"
8c4d8060 4839 "ldr\\t%0, %1"
a2cd141b 4840 [(set_attr "type" "load1")
8c4d8060 4841 (set (attr "pool_range") (const_int 1024))]
cffb2a26 4842)
849170fd 4843
4844;; This variant is used for AOF assembly, since it needs to mention the
4845;; pic register in the rtl.
4846(define_expand "pic_load_addr_based"
7db9af5d 4847 [(set (match_operand:SI 0 "s_register_operand" "")
e1159bbe 4848 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
cffb2a26 4849 "TARGET_ARM && flag_pic"
2cb7d577 4850 "operands[2] = cfun->machine->pic_reg;"
cffb2a26 4851)
849170fd 4852
4853(define_insn "*pic_load_addr_based_insn"
4854 [(set (match_operand:SI 0 "s_register_operand" "=r")
4855 (unspec:SI [(match_operand 1 "" "")
e1159bbe 4856 (match_operand 2 "s_register_operand" "r")]
4857 UNSPEC_PIC_SYM))]
2cb7d577 4858 "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
849170fd 4859 "*
4860#ifdef AOF_ASSEMBLER
4861 operands[1] = aof_pic_entry (operands[1]);
4862#endif
4863 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4864 return \"\";
cffb2a26 4865 "
a2cd141b 4866 [(set_attr "type" "load1")
cffb2a26 4867 (set (attr "pool_range")
4868 (if_then_else (eq_attr "is_thumb" "yes")
4869 (const_int 1024)
4870 (const_int 4096)))
4871 (set (attr "neg_pool_range")
4872 (if_then_else (eq_attr "is_thumb" "yes")
4873 (const_int 0)
4874 (const_int 4084)))]
4875)
4876
4877(define_insn "pic_add_dot_plus_four"
15d5d060 4878 [(set (match_operand:SI 0 "register_operand" "=r")
4879 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
beef0fb5 4880 (const (plus:SI (pc) (const_int 4))))
4881 (match_operand 2 "" "")]
4882 UNSPEC_PIC_BASE))]
25f905c2 4883 "TARGET_THUMB1"
cffb2a26 4884 "*
6cdcb15c 4885 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4886 INTVAL (operands[2]));
cffb2a26 4887 return \"add\\t%0, %|pc\";
4888 "
4889 [(set_attr "length" "2")]
4890)
849170fd 4891
4892(define_insn "pic_add_dot_plus_eight"
15d5d060 4893 [(set (match_operand:SI 0 "register_operand" "=r")
4894 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
beef0fb5 4895 (const (plus:SI (pc) (const_int 8))))
4896 (match_operand 2 "" "")]
4897 UNSPEC_PIC_BASE))]
f655717d 4898 "TARGET_ARM"
c4034607 4899 "*
6cdcb15c 4900 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4901 INTVAL (operands[2]));
15d5d060 4902 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 4903 "
0d66636f 4904 [(set_attr "predicable" "yes")]
cffb2a26 4905)
849170fd 4906
f655717d 4907(define_insn "tls_load_dot_plus_eight"
4908 [(set (match_operand:SI 0 "register_operand" "+r")
4909 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
beef0fb5 4910 (const (plus:SI (pc) (const_int 8))))
4911 (match_operand 2 "" "")]
4912 UNSPEC_PIC_BASE)))]
f655717d 4913 "TARGET_ARM"
4914 "*
6cdcb15c 4915 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4916 INTVAL (operands[2]));
f655717d 4917 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4918 "
4919 [(set_attr "predicable" "yes")]
4920)
4921
4922;; PIC references to local variables can generate pic_add_dot_plus_eight
4923;; followed by a load. These sequences can be crunched down to
4924;; tls_load_dot_plus_eight by a peephole.
4925
4926(define_peephole2
4927 [(parallel [(set (match_operand:SI 0 "register_operand" "")
15d5d060 4928 (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
f655717d 4929 (const (plus:SI (pc) (const_int 8))))]
4930 UNSPEC_PIC_BASE))
4931 (use (label_ref (match_operand 1 "" "")))])
4932 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4933 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
15d5d060 4934 [(parallel [(set (match_dup 2)
4935 (mem:SI (unspec:SI [(plus:SI (match_dup 3)
f655717d 4936 (const (plus:SI (pc) (const_int 8))))]
4937 UNSPEC_PIC_BASE)))
15d5d060 4938 (use (label_ref (match_dup 1)))])]
f655717d 4939 ""
4940)
4941
bac7fc85 4942(define_insn "pic_offset_arm"
4943 [(set (match_operand:SI 0 "register_operand" "=r")
4944 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
4945 (unspec:SI [(match_operand:SI 2 "" "X")]
4946 UNSPEC_PIC_OFFSET))))]
4947 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
4948 "ldr%?\\t%0, [%1,%2]"
4949 [(set_attr "type" "load1")]
4950)
4951
95373f08 4952(define_expand "builtin_setjmp_receiver"
4953 [(label_ref (match_operand 0 "" ""))]
4954 "flag_pic"
4955 "
4956{
b935b306 4957 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4958 register. */
2cb7d577 4959 if (arm_pic_register != INVALID_REGNUM)
4960 arm_load_pic_register (1UL << 3);
95373f08 4961 DONE;
4962}")
4963
9c08d1fa 4964;; If copying one reg to another we can set the condition codes according to
4965;; its value. Such a move is common after a return from subroutine and the
4966;; result is being tested against zero.
4967
f7fbdd4a 4968(define_insn "*movsi_compare0"
bd5b4116 4969 [(set (reg:CC CC_REGNUM)
cffb2a26 4970 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4971 (const_int 0)))
4972 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4973 (match_dup 1))]
25f905c2 4974 "TARGET_32BIT"
e2348bcb 4975 "@
40dbec34 4976 cmp%?\\t%0, #0
25f905c2 4977 sub%.\\t%0, %1, #0"
cffb2a26 4978 [(set_attr "conds" "set")]
4979)
b11cae9e 4980
b11cae9e 4981;; Subroutine to store a half word from a register into memory.
4982;; Operand 0 is the source register (HImode)
c8f69309 4983;; Operand 1 is the destination address in a register (SImode)
b11cae9e 4984
9c08d1fa 4985;; In both this routine and the next, we must be careful not to spill
01cc3b75 4986;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 4987;; can generate unrecognizable rtl.
4988
b11cae9e 4989(define_expand "storehi"
c8f69309 4990 [;; store the low byte
f082f1c4 4991 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 4992 ;; extract the high byte
c8f69309 4993 (set (match_dup 2)
4994 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 4995 ;; store the high byte
787f8210 4996 (set (match_dup 4) (match_dup 5))]
cffb2a26 4997 "TARGET_ARM"
b11cae9e 4998 "
215b30b3 4999 {
537ffcfc 5000 rtx op1 = operands[1];
5001 rtx addr = XEXP (op1, 0);
215b30b3 5002 enum rtx_code code = GET_CODE (addr);
5003
5004 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5005 || code == MINUS)
537ffcfc 5006 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5007
537ffcfc 5008 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5009 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5010 operands[3] = gen_lowpart (QImode, operands[0]);
5011 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5012 operands[2] = gen_reg_rtx (SImode);
5013 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5014 }"
5015)
b11cae9e 5016
c7597b5d 5017(define_expand "storehi_bigend"
f082f1c4 5018 [(set (match_dup 4) (match_dup 3))
c7597b5d 5019 (set (match_dup 2)
5020 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5021 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5022 "TARGET_ARM"
b11cae9e 5023 "
215b30b3 5024 {
537ffcfc 5025 rtx op1 = operands[1];
5026 rtx addr = XEXP (op1, 0);
215b30b3 5027 enum rtx_code code = GET_CODE (addr);
5028
5029 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5030 || code == MINUS)
537ffcfc 5031 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5032
537ffcfc 5033 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5034 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5035 operands[3] = gen_lowpart (QImode, operands[0]);
5036 operands[0] = gen_lowpart (SImode, operands[0]);
5037 operands[2] = gen_reg_rtx (SImode);
787f8210 5038 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5039 }"
5040)
c7597b5d 5041
5042;; Subroutine to store a half word integer constant into memory.
5043(define_expand "storeinthi"
f082f1c4 5044 [(set (match_operand 0 "" "")
787f8210 5045 (match_operand 1 "" ""))
9e8503e6 5046 (set (match_dup 3) (match_dup 2))]
cffb2a26 5047 "TARGET_ARM"
c7597b5d 5048 "
215b30b3 5049 {
5050 HOST_WIDE_INT value = INTVAL (operands[1]);
5051 rtx addr = XEXP (operands[0], 0);
537ffcfc 5052 rtx op0 = operands[0];
215b30b3 5053 enum rtx_code code = GET_CODE (addr);
c7597b5d 5054
215b30b3 5055 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5056 || code == MINUS)
537ffcfc 5057 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5058
215b30b3 5059 operands[1] = gen_reg_rtx (SImode);
5060 if (BYTES_BIG_ENDIAN)
5061 {
5062 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5063 if ((value & 255) == ((value >> 8) & 255))
5064 operands[2] = operands[1];
5065 else
5066 {
5067 operands[2] = gen_reg_rtx (SImode);
5068 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5069 }
5070 }
5071 else
5072 {
5073 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5074 if ((value & 255) == ((value >> 8) & 255))
5075 operands[2] = operands[1];
5076 else
5077 {
5078 operands[2] = gen_reg_rtx (SImode);
5079 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5080 }
5081 }
c7597b5d 5082
537ffcfc 5083 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5084 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5085 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5086 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5087 }"
5088)
b11cae9e 5089
f7fbdd4a 5090(define_expand "storehi_single_op"
5091 [(set (match_operand:HI 0 "memory_operand" "")
5092 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5093 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5094 "
215b30b3 5095 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5096 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5097 "
5098)
f7fbdd4a 5099
b11cae9e 5100(define_expand "movhi"
5101 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5102 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5103 "TARGET_EITHER"
b11cae9e 5104 "
cffb2a26 5105 if (TARGET_ARM)
b11cae9e 5106 {
e1ba4a27 5107 if (can_create_pseudo_p ())
cffb2a26 5108 {
5109 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5110 {
cffb2a26 5111 if (arm_arch4)
5112 {
5113 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5114 DONE;
5115 }
5116 if (GET_CODE (operands[1]) == CONST_INT)
5117 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5118 else
cffb2a26 5119 {
5120 if (GET_CODE (operands[1]) == MEM)
5121 operands[1] = force_reg (HImode, operands[1]);
5122 if (BYTES_BIG_ENDIAN)
5123 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5124 else
5125 emit_insn (gen_storehi (operands[1], operands[0]));
5126 }
5127 DONE;
b11cae9e 5128 }
cffb2a26 5129 /* Sign extend a constant, and keep it in an SImode reg. */
5130 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5131 {
cffb2a26 5132 rtx reg = gen_reg_rtx (SImode);
5133 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5134
5135 /* If the constant is already valid, leave it alone. */
215b30b3 5136 if (!const_ok_for_arm (val))
cffb2a26 5137 {
5138 /* If setting all the top bits will make the constant
5139 loadable in a single instruction, then set them.
5140 Otherwise, sign extend the number. */
5141
215b30b3 5142 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5143 val |= ~0xffff;
5144 else if (val & 0x8000)
5145 val |= ~0xffff;
5146 }
5147
5148 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5149 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5150 }
e1ba4a27 5151 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5152 && GET_CODE (operands[1]) == MEM)
5153 {
5154 rtx reg = gen_reg_rtx (SImode);
5155
5156 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5157 operands[1] = gen_lowpart (HImode, reg);
5158 }
215b30b3 5159 else if (!arm_arch4)
f7fbdd4a 5160 {
cffb2a26 5161 if (GET_CODE (operands[1]) == MEM)
5162 {
c1a66faf 5163 rtx base;
5164 rtx offset = const0_rtx;
5165 rtx reg = gen_reg_rtx (SImode);
5166
5167 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5168 || (GET_CODE (base) == PLUS
5169 && (GET_CODE (offset = XEXP (base, 1))
5170 == CONST_INT)
5171 && ((INTVAL(offset) & 1) != 1)
5172 && GET_CODE (base = XEXP (base, 0)) == REG))
5173 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5174 {
c1a66faf 5175 rtx new;
5176
788fcce0 5177 new = widen_memory_access (operands[1], SImode,
5178 ((INTVAL (offset) & ~3)
5179 - INTVAL (offset)));
c1a66faf 5180 emit_insn (gen_movsi (reg, new));
5181 if (((INTVAL (offset) & 2) != 0)
5182 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5183 {
5184 rtx reg2 = gen_reg_rtx (SImode);
5185
5186 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5187 reg = reg2;
5188 }
206ee9a2 5189 }
c1a66faf 5190 else
5191 emit_insn (gen_movhi_bytes (reg, operands[1]));
5192
5193 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5194 }
5195 }
5196 }
674a8f0b 5197 /* Handle loading a large integer during reload. */
cffb2a26 5198 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5199 && !const_ok_for_arm (INTVAL (operands[1]))
5200 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5201 {
5202 /* Writing a constant to memory needs a scratch, which should
5203 be handled with SECONDARY_RELOADs. */
ed29c566 5204 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5205
5206 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5207 emit_insn (gen_movsi (operands[0], operands[1]));
5208 DONE;
5209 }
5210 }
25f905c2 5211 else if (TARGET_THUMB2)
5212 {
5213 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5214 if (can_create_pseudo_p ())
25f905c2 5215 {
5216 if (GET_CODE (operands[0]) != REG)
5217 operands[1] = force_reg (HImode, operands[1]);
5218 /* Zero extend a constant, and keep it in an SImode reg. */
5219 else if (GET_CODE (operands[1]) == CONST_INT)
5220 {
5221 rtx reg = gen_reg_rtx (SImode);
5222 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5223
5224 emit_insn (gen_movsi (reg, GEN_INT (val)));
5225 operands[1] = gen_lowpart (HImode, reg);
5226 }
5227 }
5228 }
5229 else /* TARGET_THUMB1 */
cffb2a26 5230 {
e1ba4a27 5231 if (can_create_pseudo_p ())
cffb2a26 5232 {
6cffc037 5233 if (GET_CODE (operands[1]) == CONST_INT)
5234 {
5235 rtx reg = gen_reg_rtx (SImode);
5236
5237 emit_insn (gen_movsi (reg, operands[1]));
5238 operands[1] = gen_lowpart (HImode, reg);
5239 }
cffb2a26 5240
5241 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5242 happen if we are passed a SP (never OK for HImode/QImode) or
5243 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5244 HImode/QImode) relative address. */
cffb2a26 5245 /* ??? This should perhaps be fixed elsewhere, for instance, in
5246 fixup_stack_1, by checking for other kinds of invalid addresses,
5247 e.g. a bare reference to a virtual register. This may confuse the
5248 alpha though, which must handle this case differently. */
5249 if (GET_CODE (operands[0]) == MEM
215b30b3 5250 && !memory_address_p (GET_MODE (operands[0]),
5251 XEXP (operands[0], 0)))
537ffcfc 5252 operands[0]
5253 = replace_equiv_address (operands[0],
5254 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5255
5256 if (GET_CODE (operands[1]) == MEM
215b30b3 5257 && !memory_address_p (GET_MODE (operands[1]),
5258 XEXP (operands[1], 0)))
537ffcfc 5259 operands[1]
5260 = replace_equiv_address (operands[1],
5261 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5262
5263 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5264 {
5265 rtx reg = gen_reg_rtx (SImode);
5266
5267 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5268 operands[1] = gen_lowpart (HImode, reg);
5269 }
5270
5271 if (GET_CODE (operands[0]) == MEM)
5272 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5273 }
cffb2a26 5274 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5275 && !satisfies_constraint_I (operands[1]))
cffb2a26 5276 {
6cffc037 5277 /* Handle loading a large integer during reload. */
5278
cffb2a26 5279 /* Writing a constant to memory needs a scratch, which should
5280 be handled with SECONDARY_RELOADs. */
ed29c566 5281 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5282
1a83b3ff 5283 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5284 emit_insn (gen_movsi (operands[0], operands[1]));
5285 DONE;
5286 }
b11cae9e 5287 }
cffb2a26 5288 "
5289)
5290
25f905c2 5291(define_insn "*thumb1_movhi_insn"
a941568e 5292 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5293 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5294 "TARGET_THUMB1
cffb2a26 5295 && ( register_operand (operands[0], HImode)
5296 || register_operand (operands[1], HImode))"
5297 "*
5298 switch (which_alternative)
d79300ac 5299 {
cffb2a26 5300 case 0: return \"add %0, %1, #0\";
5301 case 2: return \"strh %1, %0\";
5302 case 3: return \"mov %0, %1\";
5303 case 4: return \"mov %0, %1\";
5304 case 5: return \"mov %0, %1\";
ed29c566 5305 default: gcc_unreachable ();
cffb2a26 5306 case 1:
5307 /* The stack pointer can end up being taken as an index register.
5308 Catch this case here and deal with it. */
5309 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5310 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5311 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5312 {
5313 rtx ops[2];
5314 ops[0] = operands[0];
5315 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5316
5317 output_asm_insn (\"mov %0, %1\", ops);
5318
5319 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5320
5321 }
5322 return \"ldrh %0, %1\";
5323 }"
5324 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 5325 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 5326)
d79300ac 5327
b11cae9e 5328
25f7a26e 5329(define_expand "movhi_bytes"
eab14235 5330 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5331 (set (match_dup 3)
eab14235 5332 (zero_extend:SI (match_dup 6)))
25f7a26e 5333 (set (match_operand:SI 0 "" "")
5334 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5335 "TARGET_ARM"
25f7a26e 5336 "
215b30b3 5337 {
5338 rtx mem1, mem2;
5339 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5340
788fcce0 5341 mem1 = change_address (operands[1], QImode, addr);
5342 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5343 operands[0] = gen_lowpart (SImode, operands[0]);
5344 operands[1] = mem1;
5345 operands[2] = gen_reg_rtx (SImode);
5346 operands[3] = gen_reg_rtx (SImode);
5347 operands[6] = mem2;
25f7a26e 5348
215b30b3 5349 if (BYTES_BIG_ENDIAN)
5350 {
5351 operands[4] = operands[2];
5352 operands[5] = operands[3];
5353 }
5354 else
5355 {
5356 operands[4] = operands[3];
5357 operands[5] = operands[2];
5358 }
5359 }"
5360)
25f7a26e 5361
c7597b5d 5362(define_expand "movhi_bigend"
5363 [(set (match_dup 2)
5364 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5365 (const_int 16)))
5366 (set (match_dup 3)
5367 (ashiftrt:SI (match_dup 2) (const_int 16)))
5368 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5369 (match_dup 4))]
cffb2a26 5370 "TARGET_ARM"
c7597b5d 5371 "
5372 operands[2] = gen_reg_rtx (SImode);
5373 operands[3] = gen_reg_rtx (SImode);
787f8210 5374 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5375 "
5376)
b11cae9e 5377
a2f10574 5378;; Pattern to recognize insn generated default case above
f7fbdd4a 5379(define_insn "*movhi_insn_arch4"
cffb2a26 5380 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5381 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5382 "TARGET_ARM
5383 && arm_arch4
f7fbdd4a 5384 && (GET_CODE (operands[1]) != CONST_INT
5385 || const_ok_for_arm (INTVAL (operands[1]))
5386 || const_ok_for_arm (~INTVAL (operands[1])))"
5387 "@
5388 mov%?\\t%0, %1\\t%@ movhi
5389 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5390 str%(h%)\\t%1, %0\\t%@ movhi
5391 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5392 [(set_attr "type" "*,*,store1,load1")
0d66636f 5393 (set_attr "predicable" "yes")
cffb2a26 5394 (set_attr "pool_range" "*,*,*,256")
5395 (set_attr "neg_pool_range" "*,*,*,244")]
5396)
f7fbdd4a 5397
f7fbdd4a 5398(define_insn "*movhi_bytes"
25f7a26e 5399 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5400 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5401 "TARGET_ARM"
25f7a26e 5402 "@
5403 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5404 mvn%?\\t%0, #%B1\\t%@ movhi"
5405 [(set_attr "predicable" "yes")]
5406)
25f7a26e 5407
f90b51f1 5408(define_expand "thumb_movhi_clobber"
5409 [(set (match_operand:HI 0 "memory_operand" "")
5410 (match_operand:HI 1 "register_operand" ""))
5411 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5412 "TARGET_THUMB1"
f90b51f1 5413 "
5414 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5415 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5416 {
5417 emit_insn (gen_movhi (operands[0], operands[1]));
5418 DONE;
5419 }
5420 /* XXX Fixme, need to handle other cases here as well. */
5421 gcc_unreachable ();
5422 "
cffb2a26 5423)
5424
bc5c7e08 5425;; We use a DImode scratch because we may occasionally need an additional
5426;; temporary if the address isn't offsettable -- push_reload doesn't seem
5427;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5428(define_expand "reload_outhi"
cffb2a26 5429 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5430 (match_operand:HI 1 "s_register_operand" "r")
5431 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5432 "TARGET_EITHER"
5433 "if (TARGET_ARM)
5434 arm_reload_out_hi (operands);
5435 else
5436 thumb_reload_out_hi (operands);
d3373b54 5437 DONE;
cffb2a26 5438 "
5439)
d3373b54 5440
25f7a26e 5441(define_expand "reload_inhi"
5442 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5443 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5444 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5445 "TARGET_EITHER"
25f7a26e 5446 "
cffb2a26 5447 if (TARGET_ARM)
5448 arm_reload_in_hi (operands);
5449 else
5450 thumb_reload_out_hi (operands);
25f7a26e 5451 DONE;
5452")
5453
9c08d1fa 5454(define_expand "movqi"
5455 [(set (match_operand:QI 0 "general_operand" "")
5456 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5457 "TARGET_EITHER"
9c08d1fa 5458 "
6cffc037 5459 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5460
e1ba4a27 5461 if (can_create_pseudo_p ())
cffb2a26 5462 {
6cffc037 5463 if (GET_CODE (operands[1]) == CONST_INT)
5464 {
5465 rtx reg = gen_reg_rtx (SImode);
5466
5467 emit_insn (gen_movsi (reg, operands[1]));
5468 operands[1] = gen_lowpart (QImode, reg);
5469 }
cffb2a26 5470
6cffc037 5471 if (TARGET_THUMB)
5472 {
cffb2a26 5473 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5474 happen if we are passed a SP (never OK for HImode/QImode) or
5475 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5476 HImode/QImode) relative address. */
cffb2a26 5477 /* ??? This should perhaps be fixed elsewhere, for instance, in
5478 fixup_stack_1, by checking for other kinds of invalid addresses,
5479 e.g. a bare reference to a virtual register. This may confuse the
5480 alpha though, which must handle this case differently. */
5481 if (GET_CODE (operands[0]) == MEM
215b30b3 5482 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5483 XEXP (operands[0], 0)))
537ffcfc 5484 operands[0]
5485 = replace_equiv_address (operands[0],
5486 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5487 if (GET_CODE (operands[1]) == MEM
5488 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5489 XEXP (operands[1], 0)))
537ffcfc 5490 operands[1]
5491 = replace_equiv_address (operands[1],
5492 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5493 }
5494
5495 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5496 {
5497 rtx reg = gen_reg_rtx (SImode);
5498
5499 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5500 operands[1] = gen_lowpart (QImode, reg);
5501 }
5502
5503 if (GET_CODE (operands[0]) == MEM)
5504 operands[1] = force_reg (QImode, operands[1]);
5505 }
5506 else if (TARGET_THUMB
5507 && GET_CODE (operands[1]) == CONST_INT
234f6557 5508 && !satisfies_constraint_I (operands[1]))
6cffc037 5509 {
674a8f0b 5510 /* Handle loading a large integer during reload. */
cffb2a26 5511
6cffc037 5512 /* Writing a constant to memory needs a scratch, which should
5513 be handled with SECONDARY_RELOADs. */
5514 gcc_assert (GET_CODE (operands[0]) == REG);
5515
5516 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5517 emit_insn (gen_movsi (operands[0], operands[1]));
5518 DONE;
cffb2a26 5519 }
5520 "
5521)
b11cae9e 5522
9c08d1fa 5523
cffb2a26 5524(define_insn "*arm_movqi_insn"
5525 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5526 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5527 "TARGET_32BIT
cffb2a26 5528 && ( register_operand (operands[0], QImode)
5529 || register_operand (operands[1], QImode))"
5565501b 5530 "@
5531 mov%?\\t%0, %1
5532 mvn%?\\t%0, #%B1
25f905c2 5533 ldr%(b%)\\t%0, %1
5534 str%(b%)\\t%1, %0"
a2cd141b 5535 [(set_attr "type" "*,*,load1,store1")
0d66636f 5536 (set_attr "predicable" "yes")]
cffb2a26 5537)
5538
25f905c2 5539(define_insn "*thumb1_movqi_insn"
cffb2a26 5540 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5541 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5542 "TARGET_THUMB1
cffb2a26 5543 && ( register_operand (operands[0], QImode)
5544 || register_operand (operands[1], QImode))"
5545 "@
5546 add\\t%0, %1, #0
5547 ldrb\\t%0, %1
5548 strb\\t%1, %0
5549 mov\\t%0, %1
5550 mov\\t%0, %1
5551 mov\\t%0, %1"
5552 [(set_attr "length" "2")
a2cd141b 5553 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5554 (set_attr "pool_range" "*,32,*,*,*,*")]
5555)
b11cae9e 5556
87b22bf7 5557(define_expand "movsf"
5558 [(set (match_operand:SF 0 "general_operand" "")
5559 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5560 "TARGET_EITHER"
87b22bf7 5561 "
25f905c2 5562 if (TARGET_32BIT)
cffb2a26 5563 {
5564 if (GET_CODE (operands[0]) == MEM)
5565 operands[1] = force_reg (SFmode, operands[1]);
5566 }
25f905c2 5567 else /* TARGET_THUMB1 */
cffb2a26 5568 {
e1ba4a27 5569 if (can_create_pseudo_p ())
cffb2a26 5570 {
5571 if (GET_CODE (operands[0]) != REG)
5572 operands[1] = force_reg (SFmode, operands[1]);
5573 }
5574 }
5575 "
5576)
5577
03d440a6 5578;; Transform a floating-point move of a constant into a core register into
5579;; an SImode operation.
cffb2a26 5580(define_split
03d440a6 5581 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 5582 (match_operand:SF 1 "immediate_operand" ""))]
25f905c2 5583 "TARGET_32BIT
cffb2a26 5584 && reload_completed
5585 && GET_CODE (operands[1]) == CONST_DOUBLE"
5586 [(set (match_dup 2) (match_dup 3))]
5587 "
5588 operands[2] = gen_lowpart (SImode, operands[0]);
5589 operands[3] = gen_lowpart (SImode, operands[1]);
5590 if (operands[2] == 0 || operands[3] == 0)
5591 FAIL;
215b30b3 5592 "
5593)
87b22bf7 5594
cffb2a26 5595(define_insn "*arm_movsf_soft_insn"
5596 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5597 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5598 "TARGET_ARM
5599 && TARGET_SOFT_FLOAT
215b30b3 5600 && (GET_CODE (operands[0]) != MEM
5601 || register_operand (operands[1], SFmode))"
9a1112d7 5602 "@
5603 mov%?\\t%0, %1
5604 ldr%?\\t%0, %1\\t%@ float
5605 str%?\\t%1, %0\\t%@ float"
cffb2a26 5606 [(set_attr "length" "4,4,4")
0d66636f 5607 (set_attr "predicable" "yes")
a2cd141b 5608 (set_attr "type" "*,load1,store1")
cffb2a26 5609 (set_attr "pool_range" "*,4096,*")
5610 (set_attr "neg_pool_range" "*,4084,*")]
5611)
5612
5613;;; ??? This should have alternatives for constants.
25f905c2 5614(define_insn "*thumb1_movsf_insn"
215b30b3 5615 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5616 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 5617 "TARGET_THUMB1
cffb2a26 5618 && ( register_operand (operands[0], SFmode)
5619 || register_operand (operands[1], SFmode))"
5620 "@
5621 add\\t%0, %1, #0
5622 ldmia\\t%1, {%0}
5623 stmia\\t%0, {%1}
5624 ldr\\t%0, %1
5625 str\\t%1, %0
5626 mov\\t%0, %1
5627 mov\\t%0, %1"
5628 [(set_attr "length" "2")
a2cd141b 5629 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 5630 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5631)
9a1112d7 5632
9c08d1fa 5633(define_expand "movdf"
87b22bf7 5634 [(set (match_operand:DF 0 "general_operand" "")
5635 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5636 "TARGET_EITHER"
9c08d1fa 5637 "
25f905c2 5638 if (TARGET_32BIT)
cffb2a26 5639 {
5640 if (GET_CODE (operands[0]) == MEM)
5641 operands[1] = force_reg (DFmode, operands[1]);
5642 }
5643 else /* TARGET_THUMB */
5644 {
e1ba4a27 5645 if (can_create_pseudo_p ())
cffb2a26 5646 {
5647 if (GET_CODE (operands[0]) != REG)
5648 operands[1] = force_reg (DFmode, operands[1]);
5649 }
5650 }
5651 "
5652)
b11cae9e 5653
9c08d1fa 5654;; Reloading a df mode value stored in integer regs to memory can require a
5655;; scratch reg.
5656(define_expand "reload_outdf"
cffb2a26 5657 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5658 (match_operand:DF 1 "s_register_operand" "r")
5659 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 5660 "TARGET_32BIT"
87b22bf7 5661 "
215b30b3 5662 {
5663 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5664
215b30b3 5665 if (code == REG)
5666 operands[2] = XEXP (operands[0], 0);
5667 else if (code == POST_INC || code == PRE_DEC)
5668 {
5669 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5670 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5671 emit_insn (gen_movdi (operands[0], operands[1]));
5672 DONE;
5673 }
5674 else if (code == PRE_INC)
5675 {
5676 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5677
215b30b3 5678 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5679 operands[2] = reg;
5680 }
5681 else if (code == POST_DEC)
5682 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5683 else
5684 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5685 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5686
788fcce0 5687 emit_insn (gen_rtx_SET (VOIDmode,
5688 replace_equiv_address (operands[0], operands[2]),
215b30b3 5689 operands[1]));
f7fbdd4a 5690
215b30b3 5691 if (code == POST_DEC)
5692 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5693
5694 DONE;
5695 }"
5696)
9c08d1fa 5697
9a1112d7 5698(define_insn "*movdf_soft_insn"
359a6e9f 5699 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5700 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 5701 "TARGET_ARM && TARGET_SOFT_FLOAT
b2778788 5702 && ( register_operand (operands[0], DFmode)
5703 || register_operand (operands[1], DFmode))"
d51f92df 5704 "*
5705 switch (which_alternative)
5706 {
5707 case 0:
5708 case 1:
5709 case 2:
5710 return \"#\";
5711 default:
5712 return output_move_double (operands);
5713 }
5714 "
359a6e9f 5715 [(set_attr "length" "8,12,16,8,8")
5716 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 5717 (set_attr "pool_range" "1020")
5718 (set_attr "neg_pool_range" "1008")]
cffb2a26 5719)
5720
5721;;; ??? This should have alternatives for constants.
5722;;; ??? This was originally identical to the movdi_insn pattern.
5723;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5724;;; thumb_reorg with a memory reference.
5725(define_insn "*thumb_movdf_insn"
215b30b3 5726 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5727 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 5728 "TARGET_THUMB1
cffb2a26 5729 && ( register_operand (operands[0], DFmode)
5730 || register_operand (operands[1], DFmode))"
5731 "*
5732 switch (which_alternative)
5733 {
5734 default:
5735 case 0:
5736 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5737 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5738 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5739 case 1:
5740 return \"ldmia\\t%1, {%0, %H0}\";
5741 case 2:
5742 return \"stmia\\t%0, {%1, %H1}\";
5743 case 3:
5744 return thumb_load_double_from_address (operands);
5745 case 4:
1a83b3ff 5746 operands[2] = gen_rtx_MEM (SImode,
5747 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5748 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5749 return \"\";
5750 case 5:
5751 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5752 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5753 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5754 }
5755 "
5756 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 5757 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 5758 (set_attr "pool_range" "*,*,*,1020,*,*")]
5759)
755eb2b4 5760
ccd90aaa 5761(define_expand "movxf"
5762 [(set (match_operand:XF 0 "general_operand" "")
5763 (match_operand:XF 1 "general_operand" ""))]
25f905c2 5764 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 5765 "
5766 if (GET_CODE (operands[0]) == MEM)
5767 operands[1] = force_reg (XFmode, operands[1]);
5768 "
5769)
5770
755eb2b4 5771;; Vector Moves
5772(define_expand "movv2si"
5773 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5774 (match_operand:V2SI 1 "general_operand" ""))]
5775 "TARGET_REALLY_IWMMXT"
5776{
5777})
5778
5779(define_expand "movv4hi"
5780 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5781 (match_operand:V4HI 1 "general_operand" ""))]
5782 "TARGET_REALLY_IWMMXT"
5783{
5784})
5785
5786(define_expand "movv8qi"
5787 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5788 (match_operand:V8QI 1 "general_operand" ""))]
5789 "TARGET_REALLY_IWMMXT"
5790{
5791})
b11cae9e 5792\f
b11cae9e 5793
9c08d1fa 5794;; load- and store-multiple insns
5795;; The arm can load/store any set of registers, provided that they are in
5796;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 5797
9c08d1fa 5798(define_expand "load_multiple"
5799 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5800 (match_operand:SI 1 "" ""))
5801 (use (match_operand:SI 2 "" ""))])]
25f905c2 5802 "TARGET_32BIT"
9580c25f 5803{
5804 HOST_WIDE_INT offset = 0;
5805
bd5b4116 5806 /* Support only fixed point registers. */
9c08d1fa 5807 if (GET_CODE (operands[2]) != CONST_INT
5808 || INTVAL (operands[2]) > 14
5809 || INTVAL (operands[2]) < 2
5810 || GET_CODE (operands[1]) != MEM
5811 || GET_CODE (operands[0]) != REG
bd5b4116 5812 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5813 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5814 FAIL;
5815
5816 operands[3]
f082f1c4 5817 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5818 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 5819 TRUE, FALSE, operands[1], &offset);
5820})
b11cae9e 5821
9c08d1fa 5822;; Load multiple with write-back
5823
2162064c 5824(define_insn "*ldmsi_postinc4"
9c08d1fa 5825 [(match_parallel 0 "load_multiple_operation"
13e9316a 5826 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5827 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5828 (const_int 16)))
5829 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5830 (mem:SI (match_dup 2)))
a0a72ac3 5831 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 5832 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5833 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5834 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5835 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5836 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 5837 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5838 "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
a2cd141b 5839 [(set_attr "type" "load4")
2162064c 5840 (set_attr "predicable" "yes")]
5841)
b11cae9e 5842
25f905c2 5843(define_insn "*ldmsi_postinc4_thumb1"
ccd90aaa 5844 [(match_parallel 0 "load_multiple_operation"
5845 [(set (match_operand:SI 1 "s_register_operand" "=l")
5846 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5847 (const_int 16)))
5848 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5849 (mem:SI (match_dup 2)))
5850 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5851 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5852 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5853 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5854 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5855 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 5856 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 5857 "ldmia\\t%1!, {%3, %4, %5, %6}"
5858 [(set_attr "type" "load4")]
5859)
5860
2162064c 5861(define_insn "*ldmsi_postinc3"
5862 [(match_parallel 0 "load_multiple_operation"
13e9316a 5863 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5864 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5865 (const_int 12)))
5866 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5867 (mem:SI (match_dup 2)))
5868 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5869 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5870 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5871 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
25f905c2 5872 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5873 "ldm%(ia%)\\t%1!, {%3, %4, %5}"
a2cd141b 5874 [(set_attr "type" "load3")
2162064c 5875 (set_attr "predicable" "yes")]
5876)
b11cae9e 5877
2162064c 5878(define_insn "*ldmsi_postinc2"
5879 [(match_parallel 0 "load_multiple_operation"
13e9316a 5880 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5881 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5882 (const_int 8)))
5883 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5884 (mem:SI (match_dup 2)))
5885 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5886 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
25f905c2 5887 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5888 "ldm%(ia%)\\t%1!, {%3, %4}"
a2cd141b 5889 [(set_attr "type" "load2")
0d66636f 5890 (set_attr "predicable" "yes")]
5891)
b11cae9e 5892
9c08d1fa 5893;; Ordinary load multiple
b11cae9e 5894
2162064c 5895(define_insn "*ldmsi4"
9c08d1fa 5896 [(match_parallel 0 "load_multiple_operation"
2162064c 5897 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5898 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5899 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5900 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5901 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5902 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5903 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5904 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
25f905c2 5905 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5906 "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
a2cd141b 5907 [(set_attr "type" "load4")
2162064c 5908 (set_attr "predicable" "yes")]
5909)
9c08d1fa 5910
2162064c 5911(define_insn "*ldmsi3"
5912 [(match_parallel 0 "load_multiple_operation"
5913 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5914 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5915 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5916 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5917 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5918 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
25f905c2 5919 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5920 "ldm%(ia%)\\t%1, {%2, %3, %4}"
a2cd141b 5921 [(set_attr "type" "load3")
2162064c 5922 (set_attr "predicable" "yes")]
5923)
9c08d1fa 5924
2162064c 5925(define_insn "*ldmsi2"
5926 [(match_parallel 0 "load_multiple_operation"
5927 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5928 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5929 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5930 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
25f905c2 5931 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
5932 "ldm%(ia%)\\t%1, {%2, %3}"
a2cd141b 5933 [(set_attr "type" "load2")
0d66636f 5934 (set_attr "predicable" "yes")]
5935)
9c08d1fa 5936
5937(define_expand "store_multiple"
5938 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5939 (match_operand:SI 1 "" ""))
5940 (use (match_operand:SI 2 "" ""))])]
25f905c2 5941 "TARGET_32BIT"
9580c25f 5942{
5943 HOST_WIDE_INT offset = 0;
5944
674a8f0b 5945 /* Support only fixed point registers. */
9c08d1fa 5946 if (GET_CODE (operands[2]) != CONST_INT
5947 || INTVAL (operands[2]) > 14
5948 || INTVAL (operands[2]) < 2
5949 || GET_CODE (operands[1]) != REG
5950 || GET_CODE (operands[0]) != MEM
bd5b4116 5951 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5952 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5953 FAIL;
5954
5955 operands[3]
f082f1c4 5956 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5957 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 5958 TRUE, FALSE, operands[0], &offset);
5959})
b11cae9e 5960
9c08d1fa 5961;; Store multiple with write-back
5962
2162064c 5963(define_insn "*stmsi_postinc4"
9c08d1fa 5964 [(match_parallel 0 "store_multiple_operation"
13e9316a 5965 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5966 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5967 (const_int 16)))
a0a72ac3 5968 (set (mem:SI (match_dup 2))
2162064c 5969 (match_operand:SI 3 "arm_hard_register_operand" ""))
5970 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5971 (match_operand:SI 4 "arm_hard_register_operand" ""))
5972 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5973 (match_operand:SI 5 "arm_hard_register_operand" ""))
5974 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5975 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 5976 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5977 "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
2162064c 5978 [(set_attr "predicable" "yes")
5979 (set_attr "type" "store4")]
5980)
b11cae9e 5981
25f905c2 5982(define_insn "*stmsi_postinc4_thumb1"
ccd90aaa 5983 [(match_parallel 0 "store_multiple_operation"
5984 [(set (match_operand:SI 1 "s_register_operand" "=l")
5985 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5986 (const_int 16)))
5987 (set (mem:SI (match_dup 2))
5988 (match_operand:SI 3 "arm_hard_register_operand" ""))
5989 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5990 (match_operand:SI 4 "arm_hard_register_operand" ""))
5991 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5992 (match_operand:SI 5 "arm_hard_register_operand" ""))
5993 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5994 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 5995 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 5996 "stmia\\t%1!, {%3, %4, %5, %6}"
5997 [(set_attr "type" "store4")]
5998)
5999
2162064c 6000(define_insn "*stmsi_postinc3"
6001 [(match_parallel 0 "store_multiple_operation"
13e9316a 6002 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6003 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6004 (const_int 12)))
6005 (set (mem:SI (match_dup 2))
6006 (match_operand:SI 3 "arm_hard_register_operand" ""))
6007 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6008 (match_operand:SI 4 "arm_hard_register_operand" ""))
6009 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6010 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6011 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6012 "stm%(ia%)\\t%1!, {%3, %4, %5}"
2162064c 6013 [(set_attr "predicable" "yes")
6014 (set_attr "type" "store3")]
6015)
9c08d1fa 6016
2162064c 6017(define_insn "*stmsi_postinc2"
6018 [(match_parallel 0 "store_multiple_operation"
13e9316a 6019 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6020 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6021 (const_int 8)))
6022 (set (mem:SI (match_dup 2))
6023 (match_operand:SI 3 "arm_hard_register_operand" ""))
6024 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6025 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6026 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6027 "stm%(ia%)\\t%1!, {%3, %4}"
0d66636f 6028 [(set_attr "predicable" "yes")
2162064c 6029 (set_attr "type" "store2")]
cffb2a26 6030)
9c08d1fa 6031
6032;; Ordinary store multiple
6033
2162064c 6034(define_insn "*stmsi4"
9c08d1fa 6035 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 6036 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 6037 (match_operand:SI 2 "arm_hard_register_operand" ""))
6038 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6039 (match_operand:SI 3 "arm_hard_register_operand" ""))
6040 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6041 (match_operand:SI 4 "arm_hard_register_operand" ""))
6042 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6043 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6044 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6045 "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
2162064c 6046 [(set_attr "predicable" "yes")
6047 (set_attr "type" "store4")]
6048)
9c08d1fa 6049
2162064c 6050(define_insn "*stmsi3"
6051 [(match_parallel 0 "store_multiple_operation"
6052 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6053 (match_operand:SI 2 "arm_hard_register_operand" ""))
6054 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6055 (match_operand:SI 3 "arm_hard_register_operand" ""))
6056 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6057 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6058 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6059 "stm%(ia%)\\t%1, {%2, %3, %4}"
2162064c 6060 [(set_attr "predicable" "yes")
6061 (set_attr "type" "store3")]
6062)
9c08d1fa 6063
2162064c 6064(define_insn "*stmsi2"
6065 [(match_parallel 0 "store_multiple_operation"
6066 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6067 (match_operand:SI 2 "arm_hard_register_operand" ""))
6068 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6069 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
25f905c2 6070 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6071 "stm%(ia%)\\t%1, {%2, %3}"
0d66636f 6072 [(set_attr "predicable" "yes")
2162064c 6073 (set_attr "type" "store2")]
cffb2a26 6074)
9c08d1fa 6075
6076;; Move a block of memory if it is word aligned and MORE than 2 words long.
6077;; We could let this apply for blocks of less than this, but it clobbers so
6078;; many registers that there is then probably a better way.
6079
008c057d 6080(define_expand "movmemqi"
34191dd1 6081 [(match_operand:BLK 0 "general_operand" "")
6082 (match_operand:BLK 1 "general_operand" "")
6083 (match_operand:SI 2 "const_int_operand" "")
6084 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6085 "TARGET_EITHER"
9c08d1fa 6086 "
25f905c2 6087 if (TARGET_32BIT)
cffb2a26 6088 {
008c057d 6089 if (arm_gen_movmemqi (operands))
cffb2a26 6090 DONE;
6091 FAIL;
6092 }
25f905c2 6093 else /* TARGET_THUMB1 */
cffb2a26 6094 {
6095 if ( INTVAL (operands[3]) != 4
6096 || INTVAL (operands[2]) > 48)
6097 FAIL;
6098
008c057d 6099 thumb_expand_movmemqi (operands);
cffb2a26 6100 DONE;
6101 }
6102 "
6103)
6104
2162064c 6105;; Thumb block-move insns
cffb2a26 6106
6107(define_insn "movmem12b"
960f3acf 6108 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6109 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6110 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6111 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6112 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6113 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6114 (set (match_operand:SI 0 "register_operand" "=l")
6115 (plus:SI (match_dup 2) (const_int 12)))
6116 (set (match_operand:SI 1 "register_operand" "=l")
6117 (plus:SI (match_dup 3) (const_int 12)))
6118 (clobber (match_scratch:SI 4 "=&l"))
6119 (clobber (match_scratch:SI 5 "=&l"))
6120 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6121 "TARGET_THUMB1"
cffb2a26 6122 "* return thumb_output_move_mem_multiple (3, operands);"
6123 [(set_attr "length" "4")
215b30b3 6124 ; This isn't entirely accurate... It loads as well, but in terms of
6125 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6126 (set_attr "type" "store3")]
6127)
6128
6129(define_insn "movmem8b"
960f3acf 6130 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6131 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6132 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6133 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6134 (set (match_operand:SI 0 "register_operand" "=l")
6135 (plus:SI (match_dup 2) (const_int 8)))
6136 (set (match_operand:SI 1 "register_operand" "=l")
6137 (plus:SI (match_dup 3) (const_int 8)))
6138 (clobber (match_scratch:SI 4 "=&l"))
6139 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6140 "TARGET_THUMB1"
cffb2a26 6141 "* return thumb_output_move_mem_multiple (2, operands);"
6142 [(set_attr "length" "4")
215b30b3 6143 ; This isn't entirely accurate... It loads as well, but in terms of
6144 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6145 (set_attr "type" "store2")]
6146)
6147
9c08d1fa 6148\f
b11cae9e 6149
341940e8 6150;; Compare & branch insns
8d232dc7 6151;; The range calculations are based as follows:
341940e8 6152;; For forward branches, the address calculation returns the address of
6153;; the next instruction. This is 2 beyond the branch instruction.
6154;; For backward branches, the address calculation returns the address of
6155;; the first instruction in this pattern (cmp). This is 2 before the branch
6156;; instruction for the shortest sequence, and 4 before the branch instruction
6157;; if we have to jump around an unconditional branch.
6158;; To the basic branch range the PC offset must be added (this is +4).
6159;; So for forward branches we have
6160;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6161;; And for backward branches we have
6162;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6163;;
6164;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6165;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6166
aeac46d4 6167(define_expand "cbranchsi4"
6168 [(set (pc) (if_then_else
6169 (match_operator 0 "arm_comparison_operator"
6170 [(match_operand:SI 1 "s_register_operand" "")
6171 (match_operand:SI 2 "nonmemory_operand" "")])
6172 (label_ref (match_operand 3 "" ""))
6173 (pc)))]
25f905c2 6174 "TARGET_THUMB1"
aeac46d4 6175 "
25f905c2 6176 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6177 {
6178 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6179 operands[3], operands[0]));
6180 DONE;
6181 }
25f905c2 6182 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6183 operands[2] = force_reg (SImode, operands[2]);
6184 ")
6185
6186(define_insn "*cbranchsi4_insn"
6187 [(set (pc) (if_then_else
6188 (match_operator 0 "arm_comparison_operator"
6189 [(match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 6190 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6191 (label_ref (match_operand 3 "" ""))
6192 (pc)))]
25f905c2 6193 "TARGET_THUMB1"
cffb2a26 6194 "*
6195 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 6196
cffb2a26 6197 switch (get_attr_length (insn))
6198 {
6199 case 4: return \"b%d0\\t%l3\";
6200 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6201 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6202 }
6203 "
6204 [(set (attr "far_jump")
6205 (if_then_else
6206 (eq_attr "length" "8")
6207 (const_string "yes")
6208 (const_string "no")))
6209 (set (attr "length")
6210 (if_then_else
6211 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6212 (le (minus (match_dup 3) (pc)) (const_int 256)))
6213 (const_int 4)
6214 (if_then_else
6215 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6216 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6217 (const_int 6)
6218 (const_int 8))))]
6219)
6220
aeac46d4 6221(define_insn "cbranchsi4_scratch"
6222 [(set (pc) (if_then_else
6223 (match_operator 4 "arm_comparison_operator"
6224 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6225 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6226 (label_ref (match_operand 3 "" ""))
6227 (pc)))
6228 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6229 "TARGET_THUMB1"
aeac46d4 6230 "*
6231 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6232
6233 switch (get_attr_length (insn))
6234 {
6235 case 4: return \"b%d4\\t%l3\";
6236 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6237 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6238 }
6239 "
6240 [(set (attr "far_jump")
6241 (if_then_else
6242 (eq_attr "length" "8")
6243 (const_string "yes")
6244 (const_string "no")))
6245 (set (attr "length")
6246 (if_then_else
6247 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6248 (le (minus (match_dup 3) (pc)) (const_int 256)))
6249 (const_int 4)
6250 (if_then_else
6251 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6252 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6253 (const_int 6)
6254 (const_int 8))))]
6255)
6256(define_insn "*movsi_cbranchsi4"
6257 [(set (pc)
6258 (if_then_else
6259 (match_operator 3 "arm_comparison_operator"
6260 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6261 (const_int 0)])
6262 (label_ref (match_operand 2 "" ""))
6263 (pc)))
6264 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6265 (match_dup 1))]
25f905c2 6266 "TARGET_THUMB1"
aeac46d4 6267 "*{
6268 if (which_alternative == 0)
6269 output_asm_insn (\"cmp\t%0, #0\", operands);
6270 else if (which_alternative == 1)
6271 output_asm_insn (\"sub\t%0, %1, #0\", operands);
6272 else
6273 {
6274 output_asm_insn (\"cmp\t%1, #0\", operands);
6275 if (which_alternative == 2)
6276 output_asm_insn (\"mov\t%0, %1\", operands);
6277 else
6278 output_asm_insn (\"str\t%1, %0\", operands);
6279 }
6280 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6281 {
6282 case 4: return \"b%d3\\t%l2\";
6283 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6284 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6285 }
6286 }"
6287 [(set (attr "far_jump")
6288 (if_then_else
6289 (ior (and (gt (symbol_ref ("which_alternative"))
6290 (const_int 1))
6291 (eq_attr "length" "8"))
6292 (eq_attr "length" "10"))
6293 (const_string "yes")
6294 (const_string "no")))
6295 (set (attr "length")
6296 (if_then_else
6297 (le (symbol_ref ("which_alternative"))
6298 (const_int 1))
6299 (if_then_else
6300 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6301 (le (minus (match_dup 2) (pc)) (const_int 256)))
6302 (const_int 4)
6303 (if_then_else
6304 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6305 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6306 (const_int 6)
6307 (const_int 8)))
6308 (if_then_else
6309 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6310 (le (minus (match_dup 2) (pc)) (const_int 256)))
6311 (const_int 6)
6312 (if_then_else
6313 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6314 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6315 (const_int 8)
6316 (const_int 10)))))]
6317)
6318
cffb2a26 6319(define_insn "*negated_cbranchsi4"
6320 [(set (pc)
6321 (if_then_else
aed179ae 6322 (match_operator 0 "equality_operator"
aeac46d4 6323 [(match_operand:SI 1 "s_register_operand" "l")
6324 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6325 (label_ref (match_operand 3 "" ""))
215b30b3 6326 (pc)))]
25f905c2 6327 "TARGET_THUMB1"
cffb2a26 6328 "*
6329 output_asm_insn (\"cmn\\t%1, %2\", operands);
6330 switch (get_attr_length (insn))
6331 {
6332 case 4: return \"b%d0\\t%l3\";
6333 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6334 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6335 }
6336 "
6337 [(set (attr "far_jump")
6338 (if_then_else
6339 (eq_attr "length" "8")
6340 (const_string "yes")
6341 (const_string "no")))
6342 (set (attr "length")
6343 (if_then_else
6344 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6345 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6346 (const_int 4)
6347 (if_then_else
341940e8 6348 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6349 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6350 (const_int 6)
6351 (const_int 8))))]
6352)
6353
58d6528b 6354(define_insn "*tbit_cbranch"
6355 [(set (pc)
6356 (if_then_else
6357 (match_operator 0 "equality_operator"
6358 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6359 (const_int 1)
6360 (match_operand:SI 2 "const_int_operand" "i"))
6361 (const_int 0)])
6362 (label_ref (match_operand 3 "" ""))
6363 (pc)))
6364 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6365 "TARGET_THUMB1"
58d6528b 6366 "*
6367 {
6368 rtx op[3];
6369 op[0] = operands[4];
6370 op[1] = operands[1];
6371 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6372
86efa74d 6373 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6374 switch (get_attr_length (insn))
6375 {
6376 case 4: return \"b%d0\\t%l3\";
6377 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6378 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6379 }
6380 }"
6381 [(set (attr "far_jump")
6382 (if_then_else
6383 (eq_attr "length" "8")
6384 (const_string "yes")
6385 (const_string "no")))
6386 (set (attr "length")
6387 (if_then_else
6388 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6389 (le (minus (match_dup 3) (pc)) (const_int 256)))
6390 (const_int 4)
6391 (if_then_else
6392 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6393 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6394 (const_int 6)
6395 (const_int 8))))]
6396)
6397
6398(define_insn "*tlobits_cbranch"
6399 [(set (pc)
6400 (if_then_else
6401 (match_operator 0 "equality_operator"
6402 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6403 (match_operand:SI 2 "const_int_operand" "i")
6404 (const_int 0))
6405 (const_int 0)])
6406 (label_ref (match_operand 3 "" ""))
6407 (pc)))
6408 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6409 "TARGET_THUMB1"
86efa74d 6410 "*
6411 {
6412 rtx op[3];
6413 op[0] = operands[4];
6414 op[1] = operands[1];
6415 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6416
58d6528b 6417 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6418 switch (get_attr_length (insn))
6419 {
6420 case 4: return \"b%d0\\t%l3\";
6421 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6422 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6423 }
6424 }"
6425 [(set (attr "far_jump")
6426 (if_then_else
6427 (eq_attr "length" "8")
6428 (const_string "yes")
6429 (const_string "no")))
6430 (set (attr "length")
6431 (if_then_else
6432 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6433 (le (minus (match_dup 3) (pc)) (const_int 256)))
6434 (const_int 4)
6435 (if_then_else
6436 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6437 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6438 (const_int 6)
6439 (const_int 8))))]
6440)
6441
aeac46d4 6442(define_insn "*tstsi3_cbranch"
58d6528b 6443 [(set (pc)
6444 (if_then_else
aeac46d4 6445 (match_operator 3 "equality_operator"
6446 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6447 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6448 (const_int 0)])
aeac46d4 6449 (label_ref (match_operand 2 "" ""))
6450 (pc)))]
25f905c2 6451 "TARGET_THUMB1"
58d6528b 6452 "*
6453 {
aeac46d4 6454 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6455 switch (get_attr_length (insn))
6456 {
aeac46d4 6457 case 4: return \"b%d3\\t%l2\";
6458 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6459 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6460 }
6461 }"
6462 [(set (attr "far_jump")
6463 (if_then_else
6464 (eq_attr "length" "8")
6465 (const_string "yes")
6466 (const_string "no")))
6467 (set (attr "length")
6468 (if_then_else
aeac46d4 6469 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6470 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6471 (const_int 4)
6472 (if_then_else
aeac46d4 6473 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6474 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6475 (const_int 6)
6476 (const_int 8))))]
6477)
6478
6479(define_insn "*andsi3_cbranch"
6480 [(set (pc)
6481 (if_then_else
6482 (match_operator 5 "equality_operator"
6483 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6484 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6485 (const_int 0)])
6486 (label_ref (match_operand 4 "" ""))
6487 (pc)))
aeac46d4 6488 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6489 (and:SI (match_dup 2) (match_dup 3)))
6490 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6491 "TARGET_THUMB1"
58d6528b 6492 "*
6493 {
6494 if (which_alternative == 0)
6495 output_asm_insn (\"and\\t%0, %3\", operands);
6496 else if (which_alternative == 1)
6497 {
6498 output_asm_insn (\"and\\t%1, %3\", operands);
6499 output_asm_insn (\"mov\\t%0, %1\", operands);
6500 }
6501 else
6502 {
6503 output_asm_insn (\"and\\t%1, %3\", operands);
6504 output_asm_insn (\"str\\t%1, %0\", operands);
6505 }
6506
6507 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6508 {
6509 case 4: return \"b%d5\\t%l4\";
6510 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6511 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6512 }
6513 }"
6514 [(set (attr "far_jump")
6515 (if_then_else
6516 (ior (and (eq (symbol_ref ("which_alternative"))
6517 (const_int 0))
6518 (eq_attr "length" "8"))
6519 (eq_attr "length" "10"))
6520 (const_string "yes")
6521 (const_string "no")))
6522 (set (attr "length")
6523 (if_then_else
6524 (eq (symbol_ref ("which_alternative"))
6525 (const_int 0))
6526 (if_then_else
6527 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6528 (le (minus (match_dup 4) (pc)) (const_int 256)))
6529 (const_int 4)
6530 (if_then_else
6531 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6532 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6533 (const_int 6)
6534 (const_int 8)))
6535 (if_then_else
6536 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6537 (le (minus (match_dup 4) (pc)) (const_int 256)))
6538 (const_int 6)
6539 (if_then_else
6540 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6541 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6542 (const_int 8)
6543 (const_int 10)))))]
6544)
6545
6546(define_insn "*orrsi3_cbranch_scratch"
6547 [(set (pc)
6548 (if_then_else
6549 (match_operator 4 "equality_operator"
6550 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6551 (match_operand:SI 2 "s_register_operand" "l"))
6552 (const_int 0)])
6553 (label_ref (match_operand 3 "" ""))
6554 (pc)))
6555 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 6556 "TARGET_THUMB1"
58d6528b 6557 "*
6558 {
6559 output_asm_insn (\"orr\\t%0, %2\", operands);
6560 switch (get_attr_length (insn))
6561 {
6562 case 4: return \"b%d4\\t%l3\";
6563 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6564 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6565 }
6566 }"
6567 [(set (attr "far_jump")
6568 (if_then_else
6569 (eq_attr "length" "8")
6570 (const_string "yes")
6571 (const_string "no")))
6572 (set (attr "length")
6573 (if_then_else
6574 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6575 (le (minus (match_dup 3) (pc)) (const_int 256)))
6576 (const_int 4)
6577 (if_then_else
6578 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6579 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6580 (const_int 6)
6581 (const_int 8))))]
6582)
6583
6584(define_insn "*orrsi3_cbranch"
6585 [(set (pc)
6586 (if_then_else
6587 (match_operator 5 "equality_operator"
6588 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6589 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6590 (const_int 0)])
6591 (label_ref (match_operand 4 "" ""))
6592 (pc)))
aeac46d4 6593 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6594 (ior:SI (match_dup 2) (match_dup 3)))
6595 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6596 "TARGET_THUMB1"
58d6528b 6597 "*
6598 {
6599 if (which_alternative == 0)
6600 output_asm_insn (\"orr\\t%0, %3\", operands);
6601 else if (which_alternative == 1)
6602 {
6603 output_asm_insn (\"orr\\t%1, %3\", operands);
6604 output_asm_insn (\"mov\\t%0, %1\", operands);
6605 }
6606 else
6607 {
6608 output_asm_insn (\"orr\\t%1, %3\", operands);
6609 output_asm_insn (\"str\\t%1, %0\", operands);
6610 }
6611
6612 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6613 {
6614 case 4: return \"b%d5\\t%l4\";
6615 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6616 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6617 }
6618 }"
6619 [(set (attr "far_jump")
6620 (if_then_else
6621 (ior (and (eq (symbol_ref ("which_alternative"))
6622 (const_int 0))
6623 (eq_attr "length" "8"))
6624 (eq_attr "length" "10"))
6625 (const_string "yes")
6626 (const_string "no")))
6627 (set (attr "length")
6628 (if_then_else
6629 (eq (symbol_ref ("which_alternative"))
6630 (const_int 0))
6631 (if_then_else
6632 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6633 (le (minus (match_dup 4) (pc)) (const_int 256)))
6634 (const_int 4)
6635 (if_then_else
6636 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6637 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6638 (const_int 6)
6639 (const_int 8)))
6640 (if_then_else
6641 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6642 (le (minus (match_dup 4) (pc)) (const_int 256)))
6643 (const_int 6)
6644 (if_then_else
6645 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6646 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6647 (const_int 8)
6648 (const_int 10)))))]
6649)
6650
6651(define_insn "*xorsi3_cbranch_scratch"
6652 [(set (pc)
6653 (if_then_else
6654 (match_operator 4 "equality_operator"
6655 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6656 (match_operand:SI 2 "s_register_operand" "l"))
6657 (const_int 0)])
6658 (label_ref (match_operand 3 "" ""))
6659 (pc)))
6660 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 6661 "TARGET_THUMB1"
58d6528b 6662 "*
6663 {
6664 output_asm_insn (\"eor\\t%0, %2\", operands);
6665 switch (get_attr_length (insn))
6666 {
6667 case 4: return \"b%d4\\t%l3\";
6668 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6669 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6670 }
6671 }"
6672 [(set (attr "far_jump")
6673 (if_then_else
6674 (eq_attr "length" "8")
6675 (const_string "yes")
6676 (const_string "no")))
6677 (set (attr "length")
6678 (if_then_else
6679 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6680 (le (minus (match_dup 3) (pc)) (const_int 256)))
6681 (const_int 4)
6682 (if_then_else
6683 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6684 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6685 (const_int 6)
6686 (const_int 8))))]
6687)
6688
6689(define_insn "*xorsi3_cbranch"
6690 [(set (pc)
6691 (if_then_else
6692 (match_operator 5 "equality_operator"
6693 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6694 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6695 (const_int 0)])
6696 (label_ref (match_operand 4 "" ""))
6697 (pc)))
aeac46d4 6698 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6699 (xor:SI (match_dup 2) (match_dup 3)))
6700 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6701 "TARGET_THUMB1"
58d6528b 6702 "*
6703 {
6704 if (which_alternative == 0)
6705 output_asm_insn (\"eor\\t%0, %3\", operands);
6706 else if (which_alternative == 1)
6707 {
6708 output_asm_insn (\"eor\\t%1, %3\", operands);
6709 output_asm_insn (\"mov\\t%0, %1\", operands);
6710 }
6711 else
6712 {
6713 output_asm_insn (\"eor\\t%1, %3\", operands);
6714 output_asm_insn (\"str\\t%1, %0\", operands);
6715 }
6716
6717 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6718 {
6719 case 4: return \"b%d5\\t%l4\";
6720 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6721 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6722 }
6723 }"
6724 [(set (attr "far_jump")
6725 (if_then_else
6726 (ior (and (eq (symbol_ref ("which_alternative"))
6727 (const_int 0))
6728 (eq_attr "length" "8"))
6729 (eq_attr "length" "10"))
6730 (const_string "yes")
6731 (const_string "no")))
6732 (set (attr "length")
6733 (if_then_else
6734 (eq (symbol_ref ("which_alternative"))
6735 (const_int 0))
6736 (if_then_else
6737 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6738 (le (minus (match_dup 4) (pc)) (const_int 256)))
6739 (const_int 4)
6740 (if_then_else
6741 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6742 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6743 (const_int 6)
6744 (const_int 8)))
6745 (if_then_else
6746 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6747 (le (minus (match_dup 4) (pc)) (const_int 256)))
6748 (const_int 6)
6749 (if_then_else
6750 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6751 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6752 (const_int 8)
6753 (const_int 10)))))]
6754)
6755
aeac46d4 6756(define_insn "*bicsi3_cbranch_scratch"
6757 [(set (pc)
6758 (if_then_else
6759 (match_operator 4 "equality_operator"
6760 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6761 (match_operand:SI 1 "s_register_operand" "0"))
6762 (const_int 0)])
6763 (label_ref (match_operand 3 "" ""))
6764 (pc)))
6765 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 6766 "TARGET_THUMB1"
aeac46d4 6767 "*
6768 {
6769 output_asm_insn (\"bic\\t%0, %2\", operands);
6770 switch (get_attr_length (insn))
6771 {
6772 case 4: return \"b%d4\\t%l3\";
6773 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6774 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6775 }
6776 }"
6777 [(set (attr "far_jump")
6778 (if_then_else
6779 (eq_attr "length" "8")
6780 (const_string "yes")
6781 (const_string "no")))
6782 (set (attr "length")
6783 (if_then_else
6784 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6785 (le (minus (match_dup 3) (pc)) (const_int 256)))
6786 (const_int 4)
6787 (if_then_else
6788 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6789 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6790 (const_int 6)
6791 (const_int 8))))]
6792)
6793
6794(define_insn "*bicsi3_cbranch"
6795 [(set (pc)
6796 (if_then_else
6797 (match_operator 5 "equality_operator"
01145ae6 6798 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6799 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 6800 (const_int 0)])
6801 (label_ref (match_operand 4 "" ""))
6802 (pc)))
01145ae6 6803 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 6804 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 6805 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
25f905c2 6806 "TARGET_THUMB1"
aeac46d4 6807 "*
6808 {
6809 if (which_alternative == 0)
6810 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 6811 else if (which_alternative <= 2)
aeac46d4 6812 {
6813 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 6814 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6815 conditions again, since we're only testing for equality. */
aeac46d4 6816 output_asm_insn (\"mov\\t%0, %1\", operands);
6817 }
6818 else
6819 {
6820 output_asm_insn (\"bic\\t%1, %3\", operands);
6821 output_asm_insn (\"str\\t%1, %0\", operands);
6822 }
6823
6824 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6825 {
6826 case 4: return \"b%d5\\t%l4\";
6827 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6828 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6829 }
6830 }"
6831 [(set (attr "far_jump")
6832 (if_then_else
6833 (ior (and (eq (symbol_ref ("which_alternative"))
6834 (const_int 0))
6835 (eq_attr "length" "8"))
6836 (eq_attr "length" "10"))
6837 (const_string "yes")
6838 (const_string "no")))
6839 (set (attr "length")
6840 (if_then_else
6841 (eq (symbol_ref ("which_alternative"))
6842 (const_int 0))
6843 (if_then_else
6844 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6845 (le (minus (match_dup 4) (pc)) (const_int 256)))
6846 (const_int 4)
6847 (if_then_else
6848 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6849 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6850 (const_int 6)
6851 (const_int 8)))
6852 (if_then_else
6853 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6854 (le (minus (match_dup 4) (pc)) (const_int 256)))
6855 (const_int 6)
6856 (if_then_else
6857 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6858 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6859 (const_int 8)
6860 (const_int 10)))))]
6861)
6862
203c488f 6863(define_insn "*cbranchne_decr1"
6864 [(set (pc)
6865 (if_then_else (match_operator 3 "equality_operator"
6866 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6867 (const_int 0)])
6868 (label_ref (match_operand 4 "" ""))
6869 (pc)))
aeac46d4 6870 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6871 (plus:SI (match_dup 2) (const_int -1)))
6872 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6873 "TARGET_THUMB1"
203c488f 6874 "*
6875 {
6876 rtx cond[2];
6877 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6878 ? GEU : LTU),
58d6528b 6879 VOIDmode, operands[2], const1_rtx);
203c488f 6880 cond[1] = operands[4];
6881
6882 if (which_alternative == 0)
6883 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6884 else if (which_alternative == 1)
6885 {
6886 /* We must provide an alternative for a hi reg because reload
6887 cannot handle output reloads on a jump instruction, but we
6888 can't subtract into that. Fortunately a mov from lo to hi
6889 does not clobber the condition codes. */
6890 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6891 output_asm_insn (\"mov\\t%0, %1\", operands);
6892 }
6893 else
6894 {
6895 /* Similarly, but the target is memory. */
6896 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6897 output_asm_insn (\"str\\t%1, %0\", operands);
6898 }
6899
6900 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6901 {
6902 case 4:
8aea555f 6903 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6904 return \"\";
6905 case 6:
8aea555f 6906 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6907 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6908 default:
8aea555f 6909 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6910 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6911 }
6912 }
6913 "
6914 [(set (attr "far_jump")
6915 (if_then_else
6916 (ior (and (eq (symbol_ref ("which_alternative"))
6917 (const_int 0))
6918 (eq_attr "length" "8"))
6919 (eq_attr "length" "10"))
6920 (const_string "yes")
6921 (const_string "no")))
6922 (set_attr_alternative "length"
6923 [
6924 ;; Alternative 0
6925 (if_then_else
6926 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6927 (le (minus (match_dup 4) (pc)) (const_int 256)))
6928 (const_int 4)
6929 (if_then_else
6930 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6931 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6932 (const_int 6)
6933 (const_int 8)))
6934 ;; Alternative 1
6935 (if_then_else
6936 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6937 (le (minus (match_dup 4) (pc)) (const_int 256)))
6938 (const_int 6)
6939 (if_then_else
6940 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6941 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6942 (const_int 8)
6943 (const_int 10)))
6944 ;; Alternative 2
6945 (if_then_else
6946 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6947 (le (minus (match_dup 4) (pc)) (const_int 256)))
6948 (const_int 6)
6949 (if_then_else
6950 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6951 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6952 (const_int 8)
6953 (const_int 10)))
6954 ;; Alternative 3
6955 (if_then_else
6956 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6957 (le (minus (match_dup 4) (pc)) (const_int 256)))
6958 (const_int 6)
6959 (if_then_else
6960 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6961 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6962 (const_int 8)
6963 (const_int 10)))])]
6964)
cffb2a26 6965
58d6528b 6966(define_insn "*addsi3_cbranch"
6967 [(set (pc)
6968 (if_then_else
6969 (match_operator 4 "comparison_operator"
6970 [(plus:SI
6971 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6972 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6973 (const_int 0)])
6974 (label_ref (match_operand 5 "" ""))
6975 (pc)))
aeac46d4 6976 (set
6977 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6978 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 6979 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
25f905c2 6980 "TARGET_THUMB1
58d6528b 6981 && (GET_CODE (operands[4]) == EQ
6982 || GET_CODE (operands[4]) == NE
6983 || GET_CODE (operands[4]) == GE
6984 || GET_CODE (operands[4]) == LT)"
6985 "*
6986 {
6987 rtx cond[3];
6988
6989
6990 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6991 cond[1] = operands[2];
6992 cond[2] = operands[3];
6993
6994 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6995 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6996 else
6997 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6998
6999 if (which_alternative >= 3
7000 && which_alternative < 4)
7001 output_asm_insn (\"mov\\t%0, %1\", operands);
7002 else if (which_alternative >= 4)
7003 output_asm_insn (\"str\\t%1, %0\", operands);
7004
7005 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7006 {
7007 case 4:
7008 return \"b%d4\\t%l5\";
7009 case 6:
7010 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7011 default:
7012 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7013 }
7014 }
7015 "
7016 [(set (attr "far_jump")
7017 (if_then_else
7018 (ior (and (lt (symbol_ref ("which_alternative"))
7019 (const_int 3))
7020 (eq_attr "length" "8"))
7021 (eq_attr "length" "10"))
7022 (const_string "yes")
7023 (const_string "no")))
7024 (set (attr "length")
7025 (if_then_else
7026 (lt (symbol_ref ("which_alternative"))
7027 (const_int 3))
7028 (if_then_else
7029 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7030 (le (minus (match_dup 5) (pc)) (const_int 256)))
7031 (const_int 4)
7032 (if_then_else
7033 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7034 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7035 (const_int 6)
7036 (const_int 8)))
7037 (if_then_else
7038 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7039 (le (minus (match_dup 5) (pc)) (const_int 256)))
7040 (const_int 6)
7041 (if_then_else
7042 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7043 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7044 (const_int 8)
7045 (const_int 10)))))]
7046)
7047
7048(define_insn "*addsi3_cbranch_scratch"
7049 [(set (pc)
7050 (if_then_else
7051 (match_operator 3 "comparison_operator"
7052 [(plus:SI
7053 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7054 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7055 (const_int 0)])
7056 (label_ref (match_operand 4 "" ""))
7057 (pc)))
7058 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7059 "TARGET_THUMB1
58d6528b 7060 && (GET_CODE (operands[3]) == EQ
7061 || GET_CODE (operands[3]) == NE
7062 || GET_CODE (operands[3]) == GE
7063 || GET_CODE (operands[3]) == LT)"
7064 "*
7065 {
7066 switch (which_alternative)
7067 {
7068 case 0:
7069 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7070 break;
7071 case 1:
7072 output_asm_insn (\"cmn\t%1, %2\", operands);
7073 break;
0f5e9701 7074 case 2:
3a445a04 7075 if (INTVAL (operands[2]) < 0)
7076 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7077 else
7078 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7079 break;
0f5e9701 7080 case 3:
3a445a04 7081 if (INTVAL (operands[2]) < 0)
7082 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7083 else
7084 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7085 break;
7086 }
7087
7088 switch (get_attr_length (insn))
7089 {
7090 case 4:
7091 return \"b%d3\\t%l4\";
7092 case 6:
7093 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7094 default:
7095 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7096 }
7097 }
7098 "
7099 [(set (attr "far_jump")
7100 (if_then_else
7101 (eq_attr "length" "8")
7102 (const_string "yes")
7103 (const_string "no")))
7104 (set (attr "length")
7105 (if_then_else
7106 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7107 (le (minus (match_dup 4) (pc)) (const_int 256)))
7108 (const_int 4)
7109 (if_then_else
7110 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7111 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7112 (const_int 6)
7113 (const_int 8))))]
7114)
7115
7116(define_insn "*subsi3_cbranch"
7117 [(set (pc)
7118 (if_then_else
7119 (match_operator 4 "comparison_operator"
7120 [(minus:SI
7121 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7122 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7123 (const_int 0)])
7124 (label_ref (match_operand 5 "" ""))
7125 (pc)))
aeac46d4 7126 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7127 (minus:SI (match_dup 2) (match_dup 3)))
7128 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7129 "TARGET_THUMB1
58d6528b 7130 && (GET_CODE (operands[4]) == EQ
7131 || GET_CODE (operands[4]) == NE
7132 || GET_CODE (operands[4]) == GE
7133 || GET_CODE (operands[4]) == LT)"
7134 "*
7135 {
7136 if (which_alternative == 0)
7137 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7138 else if (which_alternative == 1)
7139 {
7140 /* We must provide an alternative for a hi reg because reload
7141 cannot handle output reloads on a jump instruction, but we
7142 can't subtract into that. Fortunately a mov from lo to hi
7143 does not clobber the condition codes. */
7144 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7145 output_asm_insn (\"mov\\t%0, %1\", operands);
7146 }
7147 else
7148 {
7149 /* Similarly, but the target is memory. */
7150 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7151 output_asm_insn (\"str\\t%1, %0\", operands);
7152 }
7153
7154 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7155 {
7156 case 4:
7157 return \"b%d4\\t%l5\";
7158 case 6:
7159 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7160 default:
7161 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7162 }
7163 }
7164 "
7165 [(set (attr "far_jump")
7166 (if_then_else
7167 (ior (and (eq (symbol_ref ("which_alternative"))
7168 (const_int 0))
7169 (eq_attr "length" "8"))
7170 (eq_attr "length" "10"))
7171 (const_string "yes")
7172 (const_string "no")))
7173 (set (attr "length")
7174 (if_then_else
7175 (eq (symbol_ref ("which_alternative"))
7176 (const_int 0))
7177 (if_then_else
7178 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7179 (le (minus (match_dup 5) (pc)) (const_int 256)))
7180 (const_int 4)
7181 (if_then_else
7182 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7183 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7184 (const_int 6)
7185 (const_int 8)))
7186 (if_then_else
7187 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7188 (le (minus (match_dup 5) (pc)) (const_int 256)))
7189 (const_int 6)
7190 (if_then_else
7191 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7192 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7193 (const_int 8)
7194 (const_int 10)))))]
7195)
7196
7197(define_insn "*subsi3_cbranch_scratch"
7198 [(set (pc)
7199 (if_then_else
7200 (match_operator 0 "arm_comparison_operator"
7201 [(minus:SI (match_operand:SI 1 "register_operand" "l")
7202 (match_operand:SI 2 "nonmemory_operand" "l"))
7203 (const_int 0)])
7204 (label_ref (match_operand 3 "" ""))
7205 (pc)))]
25f905c2 7206 "TARGET_THUMB1
58d6528b 7207 && (GET_CODE (operands[0]) == EQ
7208 || GET_CODE (operands[0]) == NE
7209 || GET_CODE (operands[0]) == GE
7210 || GET_CODE (operands[0]) == LT)"
7211 "*
7212 output_asm_insn (\"cmp\\t%1, %2\", operands);
7213 switch (get_attr_length (insn))
7214 {
7215 case 4: return \"b%d0\\t%l3\";
7216 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7217 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7218 }
7219 "
7220 [(set (attr "far_jump")
7221 (if_then_else
7222 (eq_attr "length" "8")
7223 (const_string "yes")
7224 (const_string "no")))
7225 (set (attr "length")
7226 (if_then_else
7227 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7228 (le (minus (match_dup 3) (pc)) (const_int 256)))
7229 (const_int 4)
7230 (if_then_else
7231 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7232 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7233 (const_int 6)
7234 (const_int 8))))]
7235)
7236
9c08d1fa 7237;; Comparison and test insns
7238
7239(define_expand "cmpsi"
aea4c774 7240 [(match_operand:SI 0 "s_register_operand" "")
7241 (match_operand:SI 1 "arm_add_operand" "")]
25f905c2 7242 "TARGET_32BIT"
cffb2a26 7243 "{
7244 arm_compare_op0 = operands[0];
7245 arm_compare_op1 = operands[1];
7246 DONE;
7247 }"
7248)
b11cae9e 7249
9c08d1fa 7250(define_expand "cmpsf"
aea4c774 7251 [(match_operand:SF 0 "s_register_operand" "")
a2cd141b 7252 (match_operand:SF 1 "arm_float_compare_operand" "")]
25f905c2 7253 "TARGET_32BIT && TARGET_HARD_FLOAT"
9c08d1fa 7254 "
9c08d1fa 7255 arm_compare_op0 = operands[0];
7256 arm_compare_op1 = operands[1];
9c08d1fa 7257 DONE;
215b30b3 7258 "
7259)
b11cae9e 7260
9c08d1fa 7261(define_expand "cmpdf"
aea4c774 7262 [(match_operand:DF 0 "s_register_operand" "")
a2cd141b 7263 (match_operand:DF 1 "arm_float_compare_operand" "")]
25f905c2 7264 "TARGET_32BIT && TARGET_HARD_FLOAT"
9c08d1fa 7265 "
9c08d1fa 7266 arm_compare_op0 = operands[0];
7267 arm_compare_op1 = operands[1];
9c08d1fa 7268 DONE;
215b30b3 7269 "
7270)
b11cae9e 7271
cffb2a26 7272(define_insn "*arm_cmpsi_insn"
bd5b4116 7273 [(set (reg:CC CC_REGNUM)
aea4c774 7274 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7275 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7276 "TARGET_32BIT"
5565501b 7277 "@
aea4c774 7278 cmp%?\\t%0, %1
7279 cmn%?\\t%0, #%n1"
cffb2a26 7280 [(set_attr "conds" "set")]
7281)
b11cae9e 7282
25f905c2 7283(define_insn "*arm_cmpsi_shiftsi"
bd5b4116 7284 [(set (reg:CC CC_REGNUM)
cffb2a26 7285 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
7286 (match_operator:SI 3 "shift_operator"
aea4c774 7287 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 7288 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
7289 "TARGET_ARM"
aea4c774 7290 "cmp%?\\t%0, %1%S3"
344495ea 7291 [(set_attr "conds" "set")
331beb1a 7292 (set_attr "shift" "1")
a2cd141b 7293 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7294 (const_string "alu_shift")
7295 (const_string "alu_shift_reg")))]
0d66636f 7296)
b11cae9e 7297
25f905c2 7298(define_insn "*arm_cmpsi_shiftsi_swp"
bd5b4116 7299 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7300 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7301 [(match_operand:SI 1 "s_register_operand" "r")
7302 (match_operand:SI 2 "reg_or_int_operand" "rM")])
7303 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7304 "TARGET_ARM"
aea4c774 7305 "cmp%?\\t%0, %1%S3"
344495ea 7306 [(set_attr "conds" "set")
331beb1a 7307 (set_attr "shift" "1")
a2cd141b 7308 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7309 (const_string "alu_shift")
7310 (const_string "alu_shift_reg")))]
0d66636f 7311)
b11cae9e 7312
25f905c2 7313(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7314 [(set (reg:CC_Z CC_REGNUM)
7315 (compare:CC_Z
7316 (neg:SI (match_operator:SI 1 "shift_operator"
7317 [(match_operand:SI 2 "s_register_operand" "r")
7318 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7319 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7320 "TARGET_ARM"
aed179ae 7321 "cmn%?\\t%0, %2%S1"
344495ea 7322 [(set_attr "conds" "set")
aed179ae 7323 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7324 (const_string "alu_shift")
7325 (const_string "alu_shift_reg")))]
0d66636f 7326)
b11cae9e 7327
7d57ec45 7328;; Cirrus SF compare instruction
7329(define_insn "*cirrus_cmpsf"
7330 [(set (reg:CCFP CC_REGNUM)
7331 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7332 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7333 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7334 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7335 [(set_attr "type" "mav_farith")
7d57ec45 7336 (set_attr "cirrus" "compare")]
7337)
7338
7339;; Cirrus DF compare instruction
7340(define_insn "*cirrus_cmpdf"
7341 [(set (reg:CCFP CC_REGNUM)
7342 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7343 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7344 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7345 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7346 [(set_attr "type" "mav_farith")
7d57ec45 7347 (set_attr "cirrus" "compare")]
7348)
7349
7350;; Cirrus DI compare instruction
7351(define_expand "cmpdi"
7352 [(match_operand:DI 0 "cirrus_fp_register" "")
7353 (match_operand:DI 1 "cirrus_fp_register" "")]
a2cd141b 7354 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7355 "{
7356 arm_compare_op0 = operands[0];
7357 arm_compare_op1 = operands[1];
7358 DONE;
7359 }")
7360
7361(define_insn "*cirrus_cmpdi"
7362 [(set (reg:CC CC_REGNUM)
7363 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7364 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7365 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7366 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7367 [(set_attr "type" "mav_farith")
7d57ec45 7368 (set_attr "cirrus" "compare")]
7369)
7370
9c08d1fa 7371; This insn allows redundant compares to be removed by cse, nothing should
7372; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7373; is deleted later on. The match_dup will match the mode here, so that
7374; mode changes of the condition codes aren't lost by this even though we don't
7375; specify what they are.
7376
8a18b90c 7377(define_insn "*deleted_compare"
9c08d1fa 7378 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7379 "TARGET_32BIT"
40dbec34 7380 "\\t%@ deleted compare"
cffb2a26 7381 [(set_attr "conds" "set")
7382 (set_attr "length" "0")]
7383)
9c08d1fa 7384
7385\f
7386;; Conditional branch insns
7387
7388(define_expand "beq"
7389 [(set (pc)
7390 (if_then_else (eq (match_dup 1) (const_int 0))
7391 (label_ref (match_operand 0 "" ""))
7392 (pc)))]
25f905c2 7393 "TARGET_32BIT"
cffb2a26 7394 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7395)
5c951228 7396
9c08d1fa 7397(define_expand "bne"
7398 [(set (pc)
7399 (if_then_else (ne (match_dup 1) (const_int 0))
7400 (label_ref (match_operand 0 "" ""))
7401 (pc)))]
25f905c2 7402 "TARGET_32BIT"
cffb2a26 7403 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7404)
5c951228 7405
9c08d1fa 7406(define_expand "bgt"
7407 [(set (pc)
7408 (if_then_else (gt (match_dup 1) (const_int 0))
7409 (label_ref (match_operand 0 "" ""))
7410 (pc)))]
25f905c2 7411 "TARGET_32BIT"
cffb2a26 7412 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7413)
5c951228 7414
9c08d1fa 7415(define_expand "ble"
7416 [(set (pc)
7417 (if_then_else (le (match_dup 1) (const_int 0))
7418 (label_ref (match_operand 0 "" ""))
7419 (pc)))]
25f905c2 7420 "TARGET_32BIT"
cffb2a26 7421 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7422)
5c951228 7423
9c08d1fa 7424(define_expand "bge"
7425 [(set (pc)
7426 (if_then_else (ge (match_dup 1) (const_int 0))
7427 (label_ref (match_operand 0 "" ""))
7428 (pc)))]
25f905c2 7429 "TARGET_32BIT"
cffb2a26 7430 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7431)
5c951228 7432
9c08d1fa 7433(define_expand "blt"
7434 [(set (pc)
7435 (if_then_else (lt (match_dup 1) (const_int 0))
7436 (label_ref (match_operand 0 "" ""))
7437 (pc)))]
25f905c2 7438 "TARGET_32BIT"
cffb2a26 7439 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7440)
5c951228 7441
9c08d1fa 7442(define_expand "bgtu"
7443 [(set (pc)
7444 (if_then_else (gtu (match_dup 1) (const_int 0))
7445 (label_ref (match_operand 0 "" ""))
7446 (pc)))]
25f905c2 7447 "TARGET_32BIT"
cffb2a26 7448 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7449)
5c951228 7450
9c08d1fa 7451(define_expand "bleu"
b11cae9e 7452 [(set (pc)
9c08d1fa 7453 (if_then_else (leu (match_dup 1) (const_int 0))
7454 (label_ref (match_operand 0 "" ""))
7455 (pc)))]
25f905c2 7456 "TARGET_32BIT"
cffb2a26 7457 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7458)
b11cae9e 7459
9c08d1fa 7460(define_expand "bgeu"
b11cae9e 7461 [(set (pc)
9c08d1fa 7462 (if_then_else (geu (match_dup 1) (const_int 0))
7463 (label_ref (match_operand 0 "" ""))
7464 (pc)))]
25f905c2 7465 "TARGET_32BIT"
cffb2a26 7466 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7467)
b11cae9e 7468
9c08d1fa 7469(define_expand "bltu"
7470 [(set (pc)
7471 (if_then_else (ltu (match_dup 1) (const_int 0))
7472 (label_ref (match_operand 0 "" ""))
7473 (pc)))]
25f905c2 7474 "TARGET_32BIT"
cffb2a26 7475 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7476)
b11cae9e 7477
8fa3ba89 7478(define_expand "bunordered"
7479 [(set (pc)
7480 (if_then_else (unordered (match_dup 1) (const_int 0))
7481 (label_ref (match_operand 0 "" ""))
7482 (pc)))]
25f905c2 7483 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7484 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7485 arm_compare_op1);"
7486)
7487
7488(define_expand "bordered"
7489 [(set (pc)
7490 (if_then_else (ordered (match_dup 1) (const_int 0))
7491 (label_ref (match_operand 0 "" ""))
7492 (pc)))]
25f905c2 7493 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7494 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7495 arm_compare_op1);"
7496)
7497
7498(define_expand "bungt"
7499 [(set (pc)
7500 (if_then_else (ungt (match_dup 1) (const_int 0))
7501 (label_ref (match_operand 0 "" ""))
7502 (pc)))]
25f905c2 7503 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7504 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7505)
7506
7507(define_expand "bunlt"
7508 [(set (pc)
7509 (if_then_else (unlt (match_dup 1) (const_int 0))
7510 (label_ref (match_operand 0 "" ""))
7511 (pc)))]
25f905c2 7512 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7513 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7514)
7515
7516(define_expand "bunge"
7517 [(set (pc)
7518 (if_then_else (unge (match_dup 1) (const_int 0))
7519 (label_ref (match_operand 0 "" ""))
7520 (pc)))]
25f905c2 7521 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7522 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7523)
7524
7525(define_expand "bunle"
7526 [(set (pc)
7527 (if_then_else (unle (match_dup 1) (const_int 0))
7528 (label_ref (match_operand 0 "" ""))
7529 (pc)))]
25f905c2 7530 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7531 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7532)
7533
7534;; The following two patterns need two branch instructions, since there is
7535;; no single instruction that will handle all cases.
7536(define_expand "buneq"
7537 [(set (pc)
7538 (if_then_else (uneq (match_dup 1) (const_int 0))
7539 (label_ref (match_operand 0 "" ""))
7540 (pc)))]
25f905c2 7541 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7542 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7543)
7544
7545(define_expand "bltgt"
7546 [(set (pc)
7547 (if_then_else (ltgt (match_dup 1) (const_int 0))
7548 (label_ref (match_operand 0 "" ""))
7549 (pc)))]
25f905c2 7550 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7551 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7552)
7553
7554;;
7555;; Patterns to match conditional branch insns.
7556;;
7557
7558; Special pattern to match UNEQ.
7559(define_insn "*arm_buneq"
7560 [(set (pc)
7561 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7562 (label_ref (match_operand 0 "" ""))
7563 (pc)))]
25f905c2 7564 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7565 "*
ed29c566 7566 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7567
278b301d 7568 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7569 "
7570 [(set_attr "conds" "jump_clob")
7571 (set_attr "length" "8")]
7572)
7573
7574; Special pattern to match LTGT.
7575(define_insn "*arm_bltgt"
7576 [(set (pc)
7577 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7578 (label_ref (match_operand 0 "" ""))
7579 (pc)))]
25f905c2 7580 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7581 "*
ed29c566 7582 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7583
278b301d 7584 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7585 "
7586 [(set_attr "conds" "jump_clob")
7587 (set_attr "length" "8")]
7588)
9c08d1fa 7589
cffb2a26 7590(define_insn "*arm_cond_branch"
9c08d1fa 7591 [(set (pc)
8fa3ba89 7592 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7593 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7594 (label_ref (match_operand 0 "" ""))
7595 (pc)))]
25f905c2 7596 "TARGET_32BIT"
d75350ce 7597 "*
9c08d1fa 7598 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7599 {
7600 arm_ccfsm_state += 2;
7601 return \"\";
7602 }
e2348bcb 7603 return \"b%d1\\t%l0\";
cffb2a26 7604 "
a2cd141b 7605 [(set_attr "conds" "use")
7606 (set_attr "type" "branch")]
cffb2a26 7607)
d75350ce 7608
8fa3ba89 7609; Special pattern to match reversed UNEQ.
7610(define_insn "*arm_buneq_reversed"
7611 [(set (pc)
7612 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7613 (pc)
7614 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7615 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7616 "*
ed29c566 7617 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7618
278b301d 7619 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7620 "
7621 [(set_attr "conds" "jump_clob")
7622 (set_attr "length" "8")]
7623)
7624
7625; Special pattern to match reversed LTGT.
7626(define_insn "*arm_bltgt_reversed"
7627 [(set (pc)
7628 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7629 (pc)
7630 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7631 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7632 "*
ed29c566 7633 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7634
278b301d 7635 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7636 "
7637 [(set_attr "conds" "jump_clob")
7638 (set_attr "length" "8")]
7639)
7640
cffb2a26 7641(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7642 [(set (pc)
8fa3ba89 7643 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7644 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7645 (pc)
7646 (label_ref (match_operand 0 "" ""))))]
25f905c2 7647 "TARGET_32BIT"
d75350ce 7648 "*
9c08d1fa 7649 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7650 {
7651 arm_ccfsm_state += 2;
7652 return \"\";
7653 }
e2348bcb 7654 return \"b%D1\\t%l0\";
cffb2a26 7655 "
a2cd141b 7656 [(set_attr "conds" "use")
7657 (set_attr "type" "branch")]
cffb2a26 7658)
7659
b11cae9e 7660\f
9c08d1fa 7661
7662; scc insns
7663
7664(define_expand "seq"
7db9af5d 7665 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7666 (eq:SI (match_dup 1) (const_int 0)))]
25f905c2 7667 "TARGET_32BIT"
cffb2a26 7668 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7669)
9c08d1fa 7670
7671(define_expand "sne"
7db9af5d 7672 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7673 (ne:SI (match_dup 1) (const_int 0)))]
25f905c2 7674 "TARGET_32BIT"
cffb2a26 7675 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7676)
9c08d1fa 7677
7678(define_expand "sgt"
7db9af5d 7679 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7680 (gt:SI (match_dup 1) (const_int 0)))]
25f905c2 7681 "TARGET_32BIT"
cffb2a26 7682 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7683)
9c08d1fa 7684
7685(define_expand "sle"
7db9af5d 7686 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7687 (le:SI (match_dup 1) (const_int 0)))]
25f905c2 7688 "TARGET_32BIT"
cffb2a26 7689 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7690)
9c08d1fa 7691
7692(define_expand "sge"
7db9af5d 7693 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7694 (ge:SI (match_dup 1) (const_int 0)))]
25f905c2 7695 "TARGET_32BIT"
cffb2a26 7696 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7697)
9c08d1fa 7698
7699(define_expand "slt"
7db9af5d 7700 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7701 (lt:SI (match_dup 1) (const_int 0)))]
25f905c2 7702 "TARGET_32BIT"
cffb2a26 7703 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7704)
9c08d1fa 7705
7706(define_expand "sgtu"
7db9af5d 7707 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7708 (gtu:SI (match_dup 1) (const_int 0)))]
25f905c2 7709 "TARGET_32BIT"
cffb2a26 7710 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7711)
9c08d1fa 7712
7713(define_expand "sleu"
7db9af5d 7714 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7715 (leu:SI (match_dup 1) (const_int 0)))]
25f905c2 7716 "TARGET_32BIT"
cffb2a26 7717 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7718)
9c08d1fa 7719
7720(define_expand "sgeu"
7db9af5d 7721 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7722 (geu:SI (match_dup 1) (const_int 0)))]
25f905c2 7723 "TARGET_32BIT"
cffb2a26 7724 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7725)
9c08d1fa 7726
7727(define_expand "sltu"
7db9af5d 7728 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7729 (ltu:SI (match_dup 1) (const_int 0)))]
25f905c2 7730 "TARGET_32BIT"
cffb2a26 7731 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7732)
9c08d1fa 7733
8fa3ba89 7734(define_expand "sunordered"
7db9af5d 7735 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7736 (unordered:SI (match_dup 1) (const_int 0)))]
25f905c2 7737 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7738 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7739 arm_compare_op1);"
7740)
7741
7742(define_expand "sordered"
7db9af5d 7743 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7744 (ordered:SI (match_dup 1) (const_int 0)))]
25f905c2 7745 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7746 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7747 arm_compare_op1);"
7748)
7749
7750(define_expand "sungt"
7db9af5d 7751 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7752 (ungt:SI (match_dup 1) (const_int 0)))]
25f905c2 7753 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7754 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7755 arm_compare_op1);"
7756)
7757
7758(define_expand "sunge"
7db9af5d 7759 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7760 (unge:SI (match_dup 1) (const_int 0)))]
25f905c2 7761 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7762 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7763 arm_compare_op1);"
7764)
7765
7766(define_expand "sunlt"
7db9af5d 7767 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7768 (unlt:SI (match_dup 1) (const_int 0)))]
25f905c2 7769 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7770 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7771 arm_compare_op1);"
7772)
7773
7774(define_expand "sunle"
7db9af5d 7775 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7776 (unle:SI (match_dup 1) (const_int 0)))]
25f905c2 7777 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7778 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7779 arm_compare_op1);"
7780)
7781
7782;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7783;;; simple ARM instructions.
7784;
7785; (define_expand "suneq"
7db9af5d 7786; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7787; (uneq:SI (match_dup 1) (const_int 0)))]
25f905c2 7788; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7789; "gcc_unreachable ();"
8fa3ba89 7790; )
7791;
7792; (define_expand "sltgt"
7db9af5d 7793; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7794; (ltgt:SI (match_dup 1) (const_int 0)))]
25f905c2 7795; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7796; "gcc_unreachable ();"
8fa3ba89 7797; )
7798
f7fbdd4a 7799(define_insn "*mov_scc"
9c08d1fa 7800 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7801 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7802 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7803 "TARGET_ARM"
4d61e570 7804 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7805 [(set_attr "conds" "use")
7806 (set_attr "length" "8")]
7807)
9c08d1fa 7808
f7fbdd4a 7809(define_insn "*mov_negscc"
9c08d1fa 7810 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7811 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7812 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7813 "TARGET_ARM"
4d61e570 7814 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7815 [(set_attr "conds" "use")
7816 (set_attr "length" "8")]
7817)
9c08d1fa 7818
f7fbdd4a 7819(define_insn "*mov_notscc"
9c08d1fa 7820 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7821 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7822 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7823 "TARGET_ARM"
4d61e570 7824 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7825 [(set_attr "conds" "use")
7826 (set_attr "length" "8")]
7827)
9c08d1fa 7828
595d88b5 7829(define_expand "cstoresi4"
7830 [(set (match_operand:SI 0 "s_register_operand" "")
7831 (match_operator:SI 1 "arm_comparison_operator"
7832 [(match_operand:SI 2 "s_register_operand" "")
7833 (match_operand:SI 3 "reg_or_int_operand" "")]))]
25f905c2 7834 "TARGET_THUMB1"
595d88b5 7835 "{
7836 rtx op3, scratch, scratch2;
7837
7838 if (operands[3] == const0_rtx)
7839 {
7840 switch (GET_CODE (operands[1]))
7841 {
7842 case EQ:
25f905c2 7843 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7844 break;
7845
7846 case NE:
25f905c2 7847 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7848 break;
7849
7850 case LE:
7851 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7852 NULL_RTX, 0, OPTAB_WIDEN);
7853 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7854 NULL_RTX, 0, OPTAB_WIDEN);
7855 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7856 operands[0], 1, OPTAB_WIDEN);
7857 break;
7858
7859 case GE:
7860 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7861 NULL_RTX, 1);
7862 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7863 NULL_RTX, 1, OPTAB_WIDEN);
7864 break;
7865
7866 case GT:
7867 scratch = expand_binop (SImode, ashr_optab, operands[2],
7868 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7869 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7870 NULL_RTX, 0, OPTAB_WIDEN);
7871 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7872 0, OPTAB_WIDEN);
7873 break;
7874
7875 /* LT is handled by generic code. No need for unsigned with 0. */
7876 default:
7877 FAIL;
7878 }
7879 DONE;
7880 }
7881
7882 switch (GET_CODE (operands[1]))
7883 {
7884 case EQ:
7885 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7886 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7887 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7888 break;
7889
7890 case NE:
7891 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7892 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7893 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7894 break;
7895
7896 case LE:
7897 op3 = force_reg (SImode, operands[3]);
7898
7899 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7900 NULL_RTX, 1, OPTAB_WIDEN);
7901 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7902 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7903 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7904 op3, operands[2]));
7905 break;
7906
7907 case GE:
7908 op3 = operands[3];
25f905c2 7909 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7910 op3 = force_reg (SImode, op3);
7911 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7912 NULL_RTX, 0, OPTAB_WIDEN);
7913 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7914 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7915 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7916 operands[2], op3));
7917 break;
7918
7919 case LEU:
7920 op3 = force_reg (SImode, operands[3]);
7921 scratch = force_reg (SImode, const0_rtx);
25f905c2 7922 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7923 op3, operands[2]));
7924 break;
7925
7926 case GEU:
7927 op3 = operands[3];
25f905c2 7928 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7929 op3 = force_reg (SImode, op3);
7930 scratch = force_reg (SImode, const0_rtx);
25f905c2 7931 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7932 operands[2], op3));
7933 break;
7934
7935 case LTU:
7936 op3 = operands[3];
25f905c2 7937 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7938 op3 = force_reg (SImode, op3);
7939 scratch = gen_reg_rtx (SImode);
25f905c2 7940 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
595d88b5 7941 emit_insn (gen_negsi2 (operands[0], scratch));
7942 break;
7943
7944 case GTU:
7945 op3 = force_reg (SImode, operands[3]);
7946 scratch = gen_reg_rtx (SImode);
25f905c2 7947 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
595d88b5 7948 emit_insn (gen_negsi2 (operands[0], scratch));
7949 break;
7950
7951 /* No good sequences for GT, LT. */
7952 default:
7953 FAIL;
7954 }
7955 DONE;
7956}")
7957
25f905c2 7958(define_expand "cstoresi_eq0_thumb1"
595d88b5 7959 [(parallel
7960 [(set (match_operand:SI 0 "s_register_operand" "")
7961 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7962 (const_int 0)))
7963 (clobber (match_dup:SI 2))])]
25f905c2 7964 "TARGET_THUMB1"
595d88b5 7965 "operands[2] = gen_reg_rtx (SImode);"
7966)
7967
25f905c2 7968(define_expand "cstoresi_ne0_thumb1"
595d88b5 7969 [(parallel
7970 [(set (match_operand:SI 0 "s_register_operand" "")
7971 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7972 (const_int 0)))
7973 (clobber (match_dup:SI 2))])]
25f905c2 7974 "TARGET_THUMB1"
595d88b5 7975 "operands[2] = gen_reg_rtx (SImode);"
7976)
7977
25f905c2 7978(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7979 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7980 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7981 (const_int 0)))
7982 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7983 "TARGET_THUMB1"
595d88b5 7984 "@
7985 neg\\t%0, %1\;adc\\t%0, %0, %1
7986 neg\\t%2, %1\;adc\\t%0, %1, %2"
7987 [(set_attr "length" "4")]
7988)
7989
25f905c2 7990(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7991 [(set (match_operand:SI 0 "s_register_operand" "=l")
7992 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7993 (const_int 0)))
7994 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7995 "TARGET_THUMB1"
595d88b5 7996 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7997 [(set_attr "length" "4")]
7998)
7999
25f905c2 8000(define_insn "cstoresi_nltu_thumb1"
595d88b5 8001 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8002 (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8003 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8004 "TARGET_THUMB1"
595d88b5 8005 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8006 [(set_attr "length" "4")]
8007)
8008
8009;; Used as part of the expansion of thumb les sequence.
25f905c2 8010(define_insn "thumb1_addsi3_addgeu"
595d88b5 8011 [(set (match_operand:SI 0 "s_register_operand" "=l")
8012 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8013 (match_operand:SI 2 "s_register_operand" "l"))
8014 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8015 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8016 "TARGET_THUMB1"
595d88b5 8017 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8018 [(set_attr "length" "4")]
8019)
8020
9c08d1fa 8021\f
39b5e676 8022;; Conditional move insns
8023
8024(define_expand "movsicc"
8a18b90c 8025 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 8026 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 8027 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8028 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8029 "TARGET_32BIT"
39b5e676 8030 "
215b30b3 8031 {
8032 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8033 rtx ccreg;
8034
8035 if (code == UNEQ || code == LTGT)
8036 FAIL;
39b5e676 8037
278b301d 8038 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 8039 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8040 }"
8041)
39b5e676 8042
8043(define_expand "movsfcc"
8a18b90c 8044 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 8045 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8046 (match_operand:SF 2 "s_register_operand" "")
8047 (match_operand:SF 3 "nonmemory_operand" "")))]
25f905c2 8048 "TARGET_32BIT"
39b5e676 8049 "
215b30b3 8050 {
8051 enum rtx_code code = GET_CODE (operands[1]);
8052 rtx ccreg;
f082f1c4 8053
278b301d 8054 if (code == UNEQ || code == LTGT)
8055 FAIL;
8056
215b30b3 8057 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 8058 Otherwise, ensure it is a valid FP add operand */
8059 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8060 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 8061 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8062
215b30b3 8063 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 8064 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8065 }"
8066)
39b5e676 8067
8068(define_expand "movdfcc"
8a18b90c 8069 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 8070 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8071 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8072 (match_operand:DF 3 "arm_float_add_operand" "")))]
25f905c2 8073 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 8074 "
215b30b3 8075 {
8076 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8077 rtx ccreg;
39b5e676 8078
278b301d 8079 if (code == UNEQ || code == LTGT)
8080 FAIL;
8081
8082 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 8083 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8084 }"
8085)
39b5e676 8086
8087(define_insn "*movsicc_insn"
f082f1c4 8088 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8089 (if_then_else:SI
8fa3ba89 8090 (match_operator 3 "arm_comparison_operator"
8a18b90c 8091 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8092 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8093 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8094 "TARGET_ARM"
39b5e676 8095 "@
8a18b90c 8096 mov%D3\\t%0, %2
8097 mvn%D3\\t%0, #%B2
f082f1c4 8098 mov%d3\\t%0, %1
8099 mvn%d3\\t%0, #%B1
8a18b90c 8100 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8101 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8102 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8103 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8104 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 8105 (set_attr "conds" "use")]
8106)
39b5e676 8107
39b5e676 8108(define_insn "*movsfcc_soft_insn"
f082f1c4 8109 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8110 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8111 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8112 (match_operand:SF 1 "s_register_operand" "0,r")
8113 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8114 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8115 "@
8116 mov%D3\\t%0, %2
8117 mov%d3\\t%0, %1"
8fa3ba89 8118 [(set_attr "conds" "use")]
8119)
39b5e676 8120
39b5e676 8121\f
9c08d1fa 8122;; Jump and linkage insns
8123
cffb2a26 8124(define_expand "jump"
9c08d1fa 8125 [(set (pc)
8126 (label_ref (match_operand 0 "" "")))]
cffb2a26 8127 "TARGET_EITHER"
9c08d1fa 8128 ""
cffb2a26 8129)
8130
8131(define_insn "*arm_jump"
8132 [(set (pc)
8133 (label_ref (match_operand 0 "" "")))]
25f905c2 8134 "TARGET_32BIT"
9c08d1fa 8135 "*
0d66636f 8136 {
8137 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8138 {
8139 arm_ccfsm_state += 2;
8140 return \"\";
8141 }
8142 return \"b%?\\t%l0\";
8143 }
8144 "
8145 [(set_attr "predicable" "yes")]
8146)
9c08d1fa 8147
cffb2a26 8148(define_insn "*thumb_jump"
8149 [(set (pc)
8150 (label_ref (match_operand 0 "" "")))]
25f905c2 8151 "TARGET_THUMB1"
cffb2a26 8152 "*
8153 if (get_attr_length (insn) == 2)
8154 return \"b\\t%l0\";
8155 return \"bl\\t%l0\\t%@ far jump\";
8156 "
8157 [(set (attr "far_jump")
8158 (if_then_else
8159 (eq_attr "length" "4")
8160 (const_string "yes")
8161 (const_string "no")))
8162 (set (attr "length")
8163 (if_then_else
911ed8af 8164 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8165 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8166 (const_int 2)
8167 (const_int 4)))]
8168)
8169
d3373b54 8170(define_expand "call"
8171 [(parallel [(call (match_operand 0 "memory_operand" "")
8172 (match_operand 1 "general_operand" ""))
cffb2a26 8173 (use (match_operand 2 "" ""))
bd5b4116 8174 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8175 "TARGET_EITHER"
6c4c2133 8176 "
8177 {
bac7fc85 8178 rtx callee, pat;
bbe777ea 8179
bbe777ea 8180 /* In an untyped call, we can get NULL for operand 2. */
8181 if (operands[2] == NULL_RTX)
8182 operands[2] = const0_rtx;
8183
de55252a 8184 /* Decide if we should generate indirect calls by loading the
85c36fd1 8185 32-bit address of the callee into a register before performing the
de55252a 8186 branch and link. */
8187 callee = XEXP (operands[0], 0);
8188 if (GET_CODE (callee) == SYMBOL_REF
8189 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8190 : !REG_P (callee))
bbe777ea 8191 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8192
8193 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8194 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8195 DONE;
6c4c2133 8196 }"
8197)
d3373b54 8198
bac7fc85 8199(define_expand "call_internal"
8200 [(parallel [(call (match_operand 0 "memory_operand" "")
8201 (match_operand 1 "general_operand" ""))
8202 (use (match_operand 2 "" ""))
8203 (clobber (reg:SI LR_REGNUM))])])
8204
f1039640 8205(define_insn "*call_reg_armv5"
d3373b54 8206 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8207 (match_operand 1 "" ""))
8208 (use (match_operand 2 "" ""))
bd5b4116 8209 (clobber (reg:SI LR_REGNUM))]
f1039640 8210 "TARGET_ARM && arm_arch5"
8211 "blx%?\\t%0"
8212 [(set_attr "type" "call")]
8213)
8214
8215(define_insn "*call_reg_arm"
8216 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8217 (match_operand 1 "" ""))
8218 (use (match_operand 2 "" ""))
8219 (clobber (reg:SI LR_REGNUM))]
8220 "TARGET_ARM && !arm_arch5"
9c08d1fa 8221 "*
5565501b 8222 return output_call (operands);
cffb2a26 8223 "
8224 ;; length is worst case, normally it is only two
8225 [(set_attr "length" "12")
8226 (set_attr "type" "call")]
8227)
9c08d1fa 8228
f7fbdd4a 8229(define_insn "*call_mem"
a3c63a9d 8230 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8231 (match_operand 1 "" ""))
8232 (use (match_operand 2 "" ""))
bd5b4116 8233 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8234 "TARGET_ARM"
9c08d1fa 8235 "*
5565501b 8236 return output_call_mem (operands);
cffb2a26 8237 "
8238 [(set_attr "length" "12")
8239 (set_attr "type" "call")]
8240)
8241
25f905c2 8242(define_insn "*call_reg_thumb1_v5"
cffb2a26 8243 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8244 (match_operand 1 "" ""))
8245 (use (match_operand 2 "" ""))
bd5b4116 8246 (clobber (reg:SI LR_REGNUM))]
25f905c2 8247 "TARGET_THUMB1 && arm_arch5"
f1039640 8248 "blx\\t%0"
8249 [(set_attr "length" "2")
8250 (set_attr "type" "call")]
cffb2a26 8251)
8252
25f905c2 8253(define_insn "*call_reg_thumb1"
f1039640 8254 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8255 (match_operand 1 "" ""))
8256 (use (match_operand 2 "" ""))
bd5b4116 8257 (clobber (reg:SI LR_REGNUM))]
25f905c2 8258 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8259 "*
8260 {
150502c9 8261 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8262 return thumb_call_via_reg (operands[0]);
150502c9 8263 else if (operands[1] == const0_rtx)
f1039640 8264 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8265 else if (frame_pointer_needed)
8266 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8267 else
150502c9 8268 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8269 }"
8270 [(set_attr "type" "call")]
8271)
9c08d1fa 8272
d3373b54 8273(define_expand "call_value"
e0698af7 8274 [(parallel [(set (match_operand 0 "" "")
8275 (call (match_operand 1 "memory_operand" "")
8276 (match_operand 2 "general_operand" "")))
cffb2a26 8277 (use (match_operand 3 "" ""))
bd5b4116 8278 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8279 "TARGET_EITHER"
6c4c2133 8280 "
8281 {
bac7fc85 8282 rtx pat, callee;
bbe777ea 8283
8284 /* In an untyped call, we can get NULL for operand 2. */
8285 if (operands[3] == 0)
8286 operands[3] = const0_rtx;
8287
de55252a 8288 /* Decide if we should generate indirect calls by loading the
8289 32-bit address of the callee into a register before performing the
8290 branch and link. */
8291 callee = XEXP (operands[1], 0);
8292 if (GET_CODE (callee) == SYMBOL_REF
8293 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8294 : !REG_P (callee))
78fe751b 8295 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8296
8297 pat = gen_call_value_internal (operands[0], operands[1],
8298 operands[2], operands[3]);
8299 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8300 DONE;
6c4c2133 8301 }"
8302)
d3373b54 8303
bac7fc85 8304(define_expand "call_value_internal"
8305 [(parallel [(set (match_operand 0 "" "")
8306 (call (match_operand 1 "memory_operand" "")
8307 (match_operand 2 "general_operand" "")))
8308 (use (match_operand 3 "" ""))
8309 (clobber (reg:SI LR_REGNUM))])])
8310
f1039640 8311(define_insn "*call_value_reg_armv5"
27ed6835 8312 [(set (match_operand 0 "" "")
755eb2b4 8313 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8314 (match_operand 2 "" "")))
bbe777ea 8315 (use (match_operand 3 "" ""))
bd5b4116 8316 (clobber (reg:SI LR_REGNUM))]
f1039640 8317 "TARGET_ARM && arm_arch5"
8318 "blx%?\\t%1"
8319 [(set_attr "type" "call")]
8320)
8321
8322(define_insn "*call_value_reg_arm"
8323 [(set (match_operand 0 "" "")
8324 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8325 (match_operand 2 "" "")))
8326 (use (match_operand 3 "" ""))
8327 (clobber (reg:SI LR_REGNUM))]
8328 "TARGET_ARM && !arm_arch5"
9c08d1fa 8329 "*
215b30b3 8330 return output_call (&operands[1]);
cffb2a26 8331 "
8332 [(set_attr "length" "12")
8333 (set_attr "type" "call")]
8334)
9c08d1fa 8335
f7fbdd4a 8336(define_insn "*call_value_mem"
27ed6835 8337 [(set (match_operand 0 "" "")
a3c63a9d 8338 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8339 (match_operand 2 "" "")))
bbe777ea 8340 (use (match_operand 3 "" ""))
bd5b4116 8341 (clobber (reg:SI LR_REGNUM))]
215b30b3 8342 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8343 "*
215b30b3 8344 return output_call_mem (&operands[1]);
cffb2a26 8345 "
8346 [(set_attr "length" "12")
8347 (set_attr "type" "call")]
8348)
9c08d1fa 8349
25f905c2 8350(define_insn "*call_value_reg_thumb1_v5"
f1039640 8351 [(set (match_operand 0 "" "")
8352 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8353 (match_operand 2 "" "")))
8354 (use (match_operand 3 "" ""))
8355 (clobber (reg:SI LR_REGNUM))]
25f905c2 8356 "TARGET_THUMB1 && arm_arch5"
f1039640 8357 "blx\\t%1"
8358 [(set_attr "length" "2")
8359 (set_attr "type" "call")]
8360)
8361
25f905c2 8362(define_insn "*call_value_reg_thumb1"
f1039640 8363 [(set (match_operand 0 "" "")
8364 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8365 (match_operand 2 "" "")))
8366 (use (match_operand 3 "" ""))
8367 (clobber (reg:SI LR_REGNUM))]
25f905c2 8368 "TARGET_THUMB1 && !arm_arch5"
f1039640 8369 "*
8370 {
150502c9 8371 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8372 return thumb_call_via_reg (operands[1]);
150502c9 8373 else if (operands[2] == const0_rtx)
f1039640 8374 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8375 else if (frame_pointer_needed)
8376 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8377 else
150502c9 8378 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8379 }"
8380 [(set_attr "type" "call")]
8381)
8382
9c08d1fa 8383;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8384;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8385
f7fbdd4a 8386(define_insn "*call_symbol"
27ed6835 8387 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8388 (match_operand 1 "" ""))
bbe777ea 8389 (use (match_operand 2 "" ""))
bd5b4116 8390 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8391 "TARGET_ARM
8392 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8393 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8394 "*
8395 {
55c1e470 8396 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8397 }"
cffb2a26 8398 [(set_attr "type" "call")]
8399)
9c08d1fa 8400
f7fbdd4a 8401(define_insn "*call_value_symbol"
ccd90aaa 8402 [(set (match_operand 0 "" "")
27ed6835 8403 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8404 (match_operand:SI 2 "" "")))
bbe777ea 8405 (use (match_operand 3 "" ""))
bd5b4116 8406 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8407 "TARGET_ARM
8408 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8409 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8410 "*
8411 {
55c1e470 8412 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8413 }"
cffb2a26 8414 [(set_attr "type" "call")]
8415)
8416
8417(define_insn "*call_insn"
27ed6835 8418 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8419 (match_operand:SI 1 "" ""))
8420 (use (match_operand 2 "" ""))
bd5b4116 8421 (clobber (reg:SI LR_REGNUM))]
1c494086 8422 "TARGET_THUMB
1675c6e9 8423 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8424 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8425 "bl\\t%a0"
8426 [(set_attr "length" "4")
8427 (set_attr "type" "call")]
8428)
8429
8430(define_insn "*call_value_insn"
ccd90aaa 8431 [(set (match_operand 0 "" "")
27ed6835 8432 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8433 (match_operand 2 "" "")))
8434 (use (match_operand 3 "" ""))
bd5b4116 8435 (clobber (reg:SI LR_REGNUM))]
1c494086 8436 "TARGET_THUMB
1675c6e9 8437 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8438 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8439 "bl\\t%a1"
8440 [(set_attr "length" "4")
8441 (set_attr "type" "call")]
8442)
9c08d1fa 8443
1c494086 8444;; We may also be able to do sibcalls for Thumb, but it's much harder...
8445(define_expand "sibcall"
8446 [(parallel [(call (match_operand 0 "memory_operand" "")
8447 (match_operand 1 "general_operand" ""))
2ba80634 8448 (return)
8449 (use (match_operand 2 "" ""))])]
1c494086 8450 "TARGET_ARM"
8451 "
8452 {
8453 if (operands[2] == NULL_RTX)
8454 operands[2] = const0_rtx;
1c494086 8455 }"
8456)
8457
8458(define_expand "sibcall_value"
ccd90aaa 8459 [(parallel [(set (match_operand 0 "" "")
1c494086 8460 (call (match_operand 1 "memory_operand" "")
8461 (match_operand 2 "general_operand" "")))
2ba80634 8462 (return)
8463 (use (match_operand 3 "" ""))])]
1c494086 8464 "TARGET_ARM"
8465 "
8466 {
8467 if (operands[3] == NULL_RTX)
8468 operands[3] = const0_rtx;
1c494086 8469 }"
8470)
8471
8472(define_insn "*sibcall_insn"
8473 [(call (mem:SI (match_operand:SI 0 "" "X"))
8474 (match_operand 1 "" ""))
2ba80634 8475 (return)
8476 (use (match_operand 2 "" ""))]
1c494086 8477 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8478 "*
8479 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8480 "
8481 [(set_attr "type" "call")]
8482)
8483
8484(define_insn "*sibcall_value_insn"
ccd90aaa 8485 [(set (match_operand 0 "" "")
755eb2b4 8486 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8487 (match_operand 2 "" "")))
2ba80634 8488 (return)
8489 (use (match_operand 3 "" ""))]
1c494086 8490 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8491 "*
8492 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8493 "
8494 [(set_attr "type" "call")]
8495)
8496
9c08d1fa 8497;; Often the return insn will be the same as loading from memory, so set attr
8498(define_insn "return"
8499 [(return)]
cffb2a26 8500 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8501 "*
9c08d1fa 8502 {
cffb2a26 8503 if (arm_ccfsm_state == 2)
8504 {
8505 arm_ccfsm_state += 2;
8506 return \"\";
8507 }
5db468b7 8508 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8509 }"
a2cd141b 8510 [(set_attr "type" "load1")
755eb2b4 8511 (set_attr "length" "12")
0d66636f 8512 (set_attr "predicable" "yes")]
cffb2a26 8513)
9c08d1fa 8514
f7fbdd4a 8515(define_insn "*cond_return"
9c08d1fa 8516 [(set (pc)
8fa3ba89 8517 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8518 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8519 (return)
8520 (pc)))]
cffb2a26 8521 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8522 "*
8fa3ba89 8523 {
8524 if (arm_ccfsm_state == 2)
8525 {
8526 arm_ccfsm_state += 2;
8527 return \"\";
8528 }
8529 return output_return_instruction (operands[0], TRUE, FALSE);
8530 }"
8531 [(set_attr "conds" "use")
755eb2b4 8532 (set_attr "length" "12")
a2cd141b 8533 (set_attr "type" "load1")]
8fa3ba89 8534)
9c08d1fa 8535
f7fbdd4a 8536(define_insn "*cond_return_inverted"
9c08d1fa 8537 [(set (pc)
8fa3ba89 8538 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8539 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8540 (pc)
8541 (return)))]
cffb2a26 8542 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8543 "*
8fa3ba89 8544 {
8545 if (arm_ccfsm_state == 2)
8546 {
8547 arm_ccfsm_state += 2;
8548 return \"\";
8549 }
8550 return output_return_instruction (operands[0], TRUE, TRUE);
8551 }"
8552 [(set_attr "conds" "use")
37a1317b 8553 (set_attr "length" "12")
a2cd141b 8554 (set_attr "type" "load1")]
8fa3ba89 8555)
9c08d1fa 8556
68121397 8557;; Generate a sequence of instructions to determine if the processor is
8558;; in 26-bit or 32-bit mode, and return the appropriate return address
8559;; mask.
8560
8561(define_expand "return_addr_mask"
8562 [(set (match_dup 1)
8563 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8564 (const_int 0)))
8565 (set (match_operand:SI 0 "s_register_operand" "")
8566 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8567 (const_int -1)
8568 (const_int 67108860)))] ; 0x03fffffc
8569 "TARGET_ARM"
8570 "
62eddbd4 8571 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8572 ")
8573
8574(define_insn "*check_arch2"
8575 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8576 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8577 (const_int 0)))]
8578 "TARGET_ARM"
8579 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8580 [(set_attr "length" "8")
8581 (set_attr "conds" "set")]
8582)
8583
9c08d1fa 8584;; Call subroutine returning any type.
8585
8586(define_expand "untyped_call"
8587 [(parallel [(call (match_operand 0 "" "")
8588 (const_int 0))
8589 (match_operand 1 "" "")
8590 (match_operand 2 "" "")])]
ccd90aaa 8591 "TARGET_EITHER"
9c08d1fa 8592 "
215b30b3 8593 {
8594 int i;
ccd90aaa 8595 rtx par = gen_rtx_PARALLEL (VOIDmode,
8596 rtvec_alloc (XVECLEN (operands[2], 0)));
8597 rtx addr = gen_reg_rtx (Pmode);
8598 rtx mem;
8599 int size = 0;
9c08d1fa 8600
ccd90aaa 8601 emit_move_insn (addr, XEXP (operands[1], 0));
8602 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8603
215b30b3 8604 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8605 {
ccd90aaa 8606 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8607
ccd90aaa 8608 /* Default code only uses r0 as a return value, but we could
8609 be using anything up to 4 registers. */
8610 if (REGNO (src) == R0_REGNUM)
8611 src = gen_rtx_REG (TImode, R0_REGNUM);
8612
8613 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8614 GEN_INT (size));
8615 size += GET_MODE_SIZE (GET_MODE (src));
8616 }
8617
8618 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8619 const0_rtx));
8620
8621 size = 0;
8622
8623 for (i = 0; i < XVECLEN (par, 0); i++)
8624 {
8625 HOST_WIDE_INT offset = 0;
8626 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8627
8628 if (size != 0)
8629 emit_move_insn (addr, plus_constant (addr, size));
8630
8631 mem = change_address (mem, GET_MODE (reg), NULL);
8632 if (REGNO (reg) == R0_REGNUM)
8633 {
8634 /* On thumb we have to use a write-back instruction. */
8635 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8636 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8637 size = TARGET_ARM ? 16 : 0;
8638 }
8639 else
8640 {
8641 emit_move_insn (mem, reg);
8642 size = GET_MODE_SIZE (GET_MODE (reg));
8643 }
215b30b3 8644 }
9c08d1fa 8645
215b30b3 8646 /* The optimizer does not know that the call sets the function value
8647 registers we stored in the result block. We avoid problems by
8648 claiming that all hard registers are used and clobbered at this
8649 point. */
8650 emit_insn (gen_blockage ());
8651
8652 DONE;
8653 }"
8654)
9c08d1fa 8655
ccd90aaa 8656(define_expand "untyped_return"
8657 [(match_operand:BLK 0 "memory_operand" "")
8658 (match_operand 1 "" "")]
8659 "TARGET_EITHER"
8660 "
8661 {
8662 int i;
8663 rtx addr = gen_reg_rtx (Pmode);
8664 rtx mem;
8665 int size = 0;
8666
8667 emit_move_insn (addr, XEXP (operands[0], 0));
8668 mem = change_address (operands[0], BLKmode, addr);
8669
8670 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8671 {
8672 HOST_WIDE_INT offset = 0;
8673 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8674
8675 if (size != 0)
8676 emit_move_insn (addr, plus_constant (addr, size));
8677
8678 mem = change_address (mem, GET_MODE (reg), NULL);
8679 if (REGNO (reg) == R0_REGNUM)
8680 {
8681 /* On thumb we have to use a write-back instruction. */
8682 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8683 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8684 size = TARGET_ARM ? 16 : 0;
8685 }
8686 else
8687 {
8688 emit_move_insn (reg, mem);
8689 size = GET_MODE_SIZE (GET_MODE (reg));
8690 }
8691 }
8692
8693 /* Emit USE insns before the return. */
8694 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8695 emit_insn (gen_rtx_USE (VOIDmode,
8696 SET_DEST (XVECEXP (operands[1], 0, i))));
8697
8698 /* Construct the return. */
8699 expand_naked_return ();
8700
8701 DONE;
8702 }"
8703)
8704
9c08d1fa 8705;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8706;; all of memory. This blocks insns from being moved across this point.
8707
8708(define_insn "blockage"
e1159bbe 8709 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8710 "TARGET_EITHER"
9c08d1fa 8711 ""
cffb2a26 8712 [(set_attr "length" "0")
8713 (set_attr "type" "block")]
8714)
9c08d1fa 8715
f7fbdd4a 8716(define_expand "casesi"
8717 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8718 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8719 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8720 (match_operand:SI 3 "" "") ; table label
8721 (match_operand:SI 4 "" "")] ; Out of range label
25f905c2 8722 "TARGET_32BIT"
f7fbdd4a 8723 "
215b30b3 8724 {
8725 rtx reg;
8726 if (operands[1] != const0_rtx)
8727 {
8728 reg = gen_reg_rtx (SImode);
f7fbdd4a 8729
215b30b3 8730 emit_insn (gen_addsi3 (reg, operands[0],
8731 GEN_INT (-INTVAL (operands[1]))));
8732 operands[0] = reg;
8733 }
9c08d1fa 8734
215b30b3 8735 if (!const_ok_for_arm (INTVAL (operands[2])))
8736 operands[2] = force_reg (SImode, operands[2]);
8737
25f905c2 8738 if (TARGET_ARM)
8739 {
8740 emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
8741 operands[3], operands[4]));
8742 }
8743 else if (flag_pic)
8744 {
8745 emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
8746 operands[2], operands[3], operands[4]));
8747 }
8748 else
8749 {
8750 emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
8751 operands[3], operands[4]));
8752 }
215b30b3 8753 DONE;
8754 }"
8755)
f7fbdd4a 8756
f082f1c4 8757;; The USE in this pattern is needed to tell flow analysis that this is
8758;; a CASESI insn. It has no other purpose.
25f905c2 8759(define_insn "arm_casesi_internal"
f082f1c4 8760 [(parallel [(set (pc)
8761 (if_then_else
8762 (leu (match_operand:SI 0 "s_register_operand" "r")
8763 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8764 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8765 (label_ref (match_operand 2 "" ""))))
8766 (label_ref (match_operand 3 "" ""))))
bd5b4116 8767 (clobber (reg:CC CC_REGNUM))
f082f1c4 8768 (use (label_ref (match_dup 2)))])]
cffb2a26 8769 "TARGET_ARM"
f7fbdd4a 8770 "*
0d66636f 8771 if (flag_pic)
8772 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8773 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8774 "
8775 [(set_attr "conds" "clob")
8776 (set_attr "length" "12")]
8777)
9c08d1fa 8778
cffb2a26 8779(define_expand "indirect_jump"
9c08d1fa 8780 [(set (pc)
cffb2a26 8781 (match_operand:SI 0 "s_register_operand" ""))]
8782 "TARGET_EITHER"
25f905c2 8783 "
8784 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8785 address and use bx. */
8786 if (TARGET_THUMB2)
8787 {
8788 rtx tmp;
8789 tmp = gen_reg_rtx (SImode);
8790 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8791 operands[0] = tmp;
8792 }
8793 "
cffb2a26 8794)
8795
f1039640 8796;; NB Never uses BX.
cffb2a26 8797(define_insn "*arm_indirect_jump"
8798 [(set (pc)
8799 (match_operand:SI 0 "s_register_operand" "r"))]
8800 "TARGET_ARM"
8801 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8802 [(set_attr "predicable" "yes")]
cffb2a26 8803)
9c08d1fa 8804
f7fbdd4a 8805(define_insn "*load_indirect_jump"
9c08d1fa 8806 [(set (pc)
8807 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8808 "TARGET_ARM"
8809 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8810 [(set_attr "type" "load1")
61a2d04c 8811 (set_attr "pool_range" "4096")
8812 (set_attr "neg_pool_range" "4084")
0d66636f 8813 (set_attr "predicable" "yes")]
cffb2a26 8814)
8815
f1039640 8816;; NB Never uses BX.
25f905c2 8817(define_insn "*thumb1_indirect_jump"
cffb2a26 8818 [(set (pc)
8819 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8820 "TARGET_THUMB1"
cffb2a26 8821 "mov\\tpc, %0"
8822 [(set_attr "conds" "clob")
8823 (set_attr "length" "2")]
8824)
8825
9c08d1fa 8826\f
8827;; Misc insns
8828
8829(define_insn "nop"
8830 [(const_int 0)]
cffb2a26 8831 "TARGET_EITHER"
8832 "*
25f905c2 8833 if (TARGET_UNIFIED_ASM)
8834 return \"nop\";
cffb2a26 8835 if (TARGET_ARM)
8836 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8837 return \"mov\\tr8, r8\";
8838 "
8839 [(set (attr "length")
8840 (if_then_else (eq_attr "is_thumb" "yes")
8841 (const_int 2)
8842 (const_int 4)))]
8843)
8844
9c08d1fa 8845\f
8846;; Patterns to allow combination of arithmetic, cond code and shifts
8847
f7fbdd4a 8848(define_insn "*arith_shiftsi"
9c08d1fa 8849 [(set (match_operand:SI 0 "s_register_operand" "=r")
8850 (match_operator:SI 1 "shiftable_operator"
8851 [(match_operator:SI 3 "shift_operator"
8852 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8853 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8854 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 8855 "TARGET_ARM"
6c4c2133 8856 "%i1%?\\t%0, %2, %4%S3"
344495ea 8857 [(set_attr "predicable" "yes")
331beb1a 8858 (set_attr "shift" "4")
a2cd141b 8859 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8860 (const_string "alu_shift")
8861 (const_string "alu_shift_reg")))]
6c4c2133 8862)
9c08d1fa 8863
d7863cfe 8864(define_split
8865 [(set (match_operand:SI 0 "s_register_operand" "")
8866 (match_operator:SI 1 "shiftable_operator"
8867 [(match_operator:SI 2 "shiftable_operator"
8868 [(match_operator:SI 3 "shift_operator"
8869 [(match_operand:SI 4 "s_register_operand" "")
8870 (match_operand:SI 5 "reg_or_int_operand" "")])
8871 (match_operand:SI 6 "s_register_operand" "")])
8872 (match_operand:SI 7 "arm_rhs_operand" "")]))
8873 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8874 "TARGET_ARM"
8875 [(set (match_dup 8)
8876 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8877 (match_dup 6)]))
8878 (set (match_dup 0)
8879 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8880 "")
8881
f7fbdd4a 8882(define_insn "*arith_shiftsi_compare0"
bd5b4116 8883 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8884 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8885 [(match_operator:SI 3 "shift_operator"
8886 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8887 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8888 (match_operand:SI 2 "s_register_operand" "r")])
8889 (const_int 0)))
8890 (set (match_operand:SI 0 "s_register_operand" "=r")
8891 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8892 (match_dup 2)]))]
cffb2a26 8893 "TARGET_ARM"
25f905c2 8894 "%i1%.\\t%0, %2, %4%S3"
344495ea 8895 [(set_attr "conds" "set")
331beb1a 8896 (set_attr "shift" "4")
a2cd141b 8897 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8898 (const_string "alu_shift")
8899 (const_string "alu_shift_reg")))]
0d66636f 8900)
9c08d1fa 8901
f7fbdd4a 8902(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8903 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8904 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8905 [(match_operator:SI 3 "shift_operator"
8906 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8907 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8908 (match_operand:SI 2 "s_register_operand" "r")])
8909 (const_int 0)))
8910 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8911 "TARGET_ARM"
25f905c2 8912 "%i1%.\\t%0, %2, %4%S3"
344495ea 8913 [(set_attr "conds" "set")
331beb1a 8914 (set_attr "shift" "4")
a2cd141b 8915 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8916 (const_string "alu_shift")
8917 (const_string "alu_shift_reg")))]
0d66636f 8918)
9c08d1fa 8919
f7fbdd4a 8920(define_insn "*sub_shiftsi"
9c08d1fa 8921 [(set (match_operand:SI 0 "s_register_operand" "=r")
8922 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8923 (match_operator:SI 2 "shift_operator"
8924 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8925 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 8926 "TARGET_ARM"
6c4c2133 8927 "sub%?\\t%0, %1, %3%S2"
344495ea 8928 [(set_attr "predicable" "yes")
331beb1a 8929 (set_attr "shift" "3")
a2cd141b 8930 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8931 (const_string "alu_shift")
8932 (const_string "alu_shift_reg")))]
6c4c2133 8933)
9c08d1fa 8934
f7fbdd4a 8935(define_insn "*sub_shiftsi_compare0"
bd5b4116 8936 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8937 (compare:CC_NOOV
8938 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8939 (match_operator:SI 2 "shift_operator"
8940 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8941 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8942 (const_int 0)))
9c08d1fa 8943 (set (match_operand:SI 0 "s_register_operand" "=r")
8944 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8945 (match_dup 4)])))]
cffb2a26 8946 "TARGET_ARM"
25f905c2 8947 "sub%.\\t%0, %1, %3%S2"
344495ea 8948 [(set_attr "conds" "set")
a2cd141b 8949 (set_attr "shift" "3")
8950 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8951 (const_string "alu_shift")
8952 (const_string "alu_shift_reg")))]
0d66636f 8953)
9c08d1fa 8954
f7fbdd4a 8955(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8956 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8957 (compare:CC_NOOV
8958 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8959 (match_operator:SI 2 "shift_operator"
8960 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8961 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8962 (const_int 0)))
9c08d1fa 8963 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8964 "TARGET_ARM"
25f905c2 8965 "sub%.\\t%0, %1, %3%S2"
344495ea 8966 [(set_attr "conds" "set")
a2cd141b 8967 (set_attr "shift" "3")
8968 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8969 (const_string "alu_shift")
8970 (const_string "alu_shift_reg")))]
0d66636f 8971)
9c08d1fa 8972
9c08d1fa 8973\f
8974
f7fbdd4a 8975(define_insn "*and_scc"
9c08d1fa 8976 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8977 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8978 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8979 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8980 "TARGET_ARM"
e2348bcb 8981 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8982 [(set_attr "conds" "use")
8983 (set_attr "length" "8")]
8984)
9c08d1fa 8985
f7fbdd4a 8986(define_insn "*ior_scc"
9c08d1fa 8987 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8988 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8989 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8990 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8991 "TARGET_ARM"
e2348bcb 8992 "@
899850b0 8993 orr%d2\\t%0, %1, #1
8994 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8995 [(set_attr "conds" "use")
8996 (set_attr "length" "4,8")]
8997)
9c08d1fa 8998
f7fbdd4a 8999(define_insn "*compare_scc"
5565501b 9000 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9001 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9002 [(match_operand:SI 2 "s_register_operand" "r,r")
9003 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9004 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9005 "TARGET_ARM"
9c08d1fa 9006 "*
601f584c 9007 if (operands[3] == const0_rtx)
9008 {
9009 if (GET_CODE (operands[1]) == LT)
9010 return \"mov\\t%0, %2, lsr #31\";
9011
9012 if (GET_CODE (operands[1]) == GE)
9013 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 9014
601f584c 9015 if (GET_CODE (operands[1]) == EQ)
9016 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9017 }
e2348bcb 9018
8fa3ba89 9019 if (GET_CODE (operands[1]) == NE)
9020 {
9021 if (which_alternative == 1)
9022 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9023 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9024 }
9025 if (which_alternative == 1)
9026 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9027 else
9028 output_asm_insn (\"cmp\\t%2, %3\", operands);
9029 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9030 "
9031 [(set_attr "conds" "clob")
9032 (set_attr "length" "12")]
9033)
9c08d1fa 9034
f7fbdd4a 9035(define_insn "*cond_move"
9c08d1fa 9036 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9037 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9038 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9039 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9040 (const_int 0)])
9041 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9042 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9043 "TARGET_ARM"
9c08d1fa 9044 "*
8fa3ba89 9045 if (GET_CODE (operands[3]) == NE)
9046 {
9047 if (which_alternative != 1)
9048 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9049 if (which_alternative != 0)
9050 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9051 return \"\";
9052 }
9053 if (which_alternative != 0)
9054 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9055 if (which_alternative != 1)
9056 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9057 return \"\";
9058 "
9059 [(set_attr "conds" "use")
9060 (set_attr "length" "4,4,8")]
9061)
9c08d1fa 9062
f7fbdd4a 9063(define_insn "*cond_arith"
9c08d1fa 9064 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9065 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9066 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9067 [(match_operand:SI 2 "s_register_operand" "r,r")
9068 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9069 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9070 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9071 "TARGET_ARM"
9c08d1fa 9072 "*
8fa3ba89 9073 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9074 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9075
8fa3ba89 9076 output_asm_insn (\"cmp\\t%2, %3\", operands);
9077 if (GET_CODE (operands[5]) == AND)
9078 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9079 else if (GET_CODE (operands[5]) == MINUS)
9080 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9081 else if (which_alternative != 0)
9082 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9083 return \"%i5%d4\\t%0, %1, #1\";
9084 "
9085 [(set_attr "conds" "clob")
9086 (set_attr "length" "12")]
9087)
9c08d1fa 9088
f7fbdd4a 9089(define_insn "*cond_sub"
9c08d1fa 9090 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9091 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9092 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9093 [(match_operand:SI 2 "s_register_operand" "r,r")
9094 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9095 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9096 "TARGET_ARM"
9c08d1fa 9097 "*
8fa3ba89 9098 output_asm_insn (\"cmp\\t%2, %3\", operands);
9099 if (which_alternative != 0)
9100 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9101 return \"sub%d4\\t%0, %1, #1\";
9102 "
9103 [(set_attr "conds" "clob")
9104 (set_attr "length" "8,12")]
9105)
9c08d1fa 9106
25f905c2 9107;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 9108(define_insn "*cmp_ite0"
cffb2a26 9109 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9110 (compare
9111 (if_then_else:SI
8fa3ba89 9112 (match_operator 4 "arm_comparison_operator"
aea4c774 9113 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9114 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9115 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9116 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9117 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9118 (const_int 0))
9119 (const_int 0)))]
cffb2a26 9120 "TARGET_ARM"
9c08d1fa 9121 "*
aea4c774 9122 {
8fa3ba89 9123 static const char * const opcodes[4][2] =
9124 {
9125 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9126 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9127 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9128 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9129 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9130 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9131 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9132 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9133 };
9134 int swap =
9135 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9136
9137 return opcodes[which_alternative][swap];
9138 }"
9139 [(set_attr "conds" "set")
9140 (set_attr "length" "8")]
9141)
9c08d1fa 9142
aea4c774 9143(define_insn "*cmp_ite1"
cffb2a26 9144 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9145 (compare
9146 (if_then_else:SI
8fa3ba89 9147 (match_operator 4 "arm_comparison_operator"
aea4c774 9148 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 9149 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9150 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9151 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 9152 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 9153 (const_int 1))
9154 (const_int 0)))]
cffb2a26 9155 "TARGET_ARM"
9c08d1fa 9156 "*
9c08d1fa 9157 {
215b30b3 9158 static const char * const opcodes[4][2] =
9159 {
9160 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9161 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9162 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9163 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9164 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9165 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9166 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9167 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9168 };
9169 int swap =
9170 comparison_dominates_p (GET_CODE (operands[5]),
9171 reverse_condition (GET_CODE (operands[4])));
9172
9173 return opcodes[which_alternative][swap];
9174 }"
8fa3ba89 9175 [(set_attr "conds" "set")
9176 (set_attr "length" "8")]
9177)
9c08d1fa 9178
f6c53574 9179(define_insn "*cmp_and"
9180 [(set (match_operand 6 "dominant_cc_register" "")
9181 (compare
9182 (and:SI
9183 (match_operator 4 "arm_comparison_operator"
9184 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9185 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9186 (match_operator:SI 5 "arm_comparison_operator"
9187 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9188 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9189 (const_int 0)))]
9190 "TARGET_ARM"
9191 "*
9192 {
35823b64 9193 static const char *const opcodes[4][2] =
f6c53574 9194 {
9195 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9196 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9197 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9198 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9199 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9200 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9201 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9202 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9203 };
9204 int swap =
9205 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9206
9207 return opcodes[which_alternative][swap];
9208 }"
9209 [(set_attr "conds" "set")
9210 (set_attr "predicable" "no")
9211 (set_attr "length" "8")]
9212)
9213
9214(define_insn "*cmp_ior"
9215 [(set (match_operand 6 "dominant_cc_register" "")
9216 (compare
9217 (ior:SI
9218 (match_operator 4 "arm_comparison_operator"
9219 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9220 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9221 (match_operator:SI 5 "arm_comparison_operator"
9222 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9223 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9224 (const_int 0)))]
9225 "TARGET_ARM"
9226 "*
9227{
35823b64 9228 static const char *const opcodes[4][2] =
f6c53574 9229 {
9230 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9231 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9232 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9233 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9234 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9235 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9236 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9237 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9238 };
9239 int swap =
9240 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9241
9242 return opcodes[which_alternative][swap];
9243}
9244"
9245 [(set_attr "conds" "set")
9246 (set_attr "length" "8")]
9247)
9248
3c5afce6 9249(define_insn_and_split "*ior_scc_scc"
9250 [(set (match_operand:SI 0 "s_register_operand" "=r")
9251 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9252 [(match_operand:SI 1 "s_register_operand" "r")
9253 (match_operand:SI 2 "arm_add_operand" "rIL")])
9254 (match_operator:SI 6 "arm_comparison_operator"
9255 [(match_operand:SI 4 "s_register_operand" "r")
9256 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9257 (clobber (reg:CC CC_REGNUM))]
9258 "TARGET_ARM
9259 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9260 != CCmode)"
9261 "#"
9262 "TARGET_ARM && reload_completed"
9263 [(set (match_dup 7)
9264 (compare
9265 (ior:SI
9266 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9267 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9268 (const_int 0)))
9269 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9270 "operands[7]
9271 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9272 DOM_CC_X_OR_Y),
601f584c 9273 CC_REGNUM);"
9274 [(set_attr "conds" "clob")
9275 (set_attr "length" "16")])
9276
9277; If the above pattern is followed by a CMP insn, then the compare is
9278; redundant, since we can rework the conditional instruction that follows.
9279(define_insn_and_split "*ior_scc_scc_cmp"
9280 [(set (match_operand 0 "dominant_cc_register" "")
9281 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9282 [(match_operand:SI 1 "s_register_operand" "r")
9283 (match_operand:SI 2 "arm_add_operand" "rIL")])
9284 (match_operator:SI 6 "arm_comparison_operator"
9285 [(match_operand:SI 4 "s_register_operand" "r")
9286 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9287 (const_int 0)))
9288 (set (match_operand:SI 7 "s_register_operand" "=r")
9289 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9290 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9291 "TARGET_ARM"
9292 "#"
9293 "TARGET_ARM && reload_completed"
9294 [(set (match_dup 0)
9295 (compare
9296 (ior:SI
9297 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9298 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9299 (const_int 0)))
9300 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9301 ""
9302 [(set_attr "conds" "set")
9303 (set_attr "length" "16")])
3c5afce6 9304
9305(define_insn_and_split "*and_scc_scc"
9306 [(set (match_operand:SI 0 "s_register_operand" "=r")
9307 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9308 [(match_operand:SI 1 "s_register_operand" "r")
9309 (match_operand:SI 2 "arm_add_operand" "rIL")])
9310 (match_operator:SI 6 "arm_comparison_operator"
9311 [(match_operand:SI 4 "s_register_operand" "r")
9312 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9313 (clobber (reg:CC CC_REGNUM))]
9314 "TARGET_ARM
9315 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9316 != CCmode)"
9317 "#"
601f584c 9318 "TARGET_ARM && reload_completed
9319 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9320 != CCmode)"
3c5afce6 9321 [(set (match_dup 7)
9322 (compare
9323 (and:SI
9324 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9325 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9326 (const_int 0)))
9327 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9328 "operands[7]
9329 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9330 DOM_CC_X_AND_Y),
601f584c 9331 CC_REGNUM);"
9332 [(set_attr "conds" "clob")
9333 (set_attr "length" "16")])
9334
9335; If the above pattern is followed by a CMP insn, then the compare is
9336; redundant, since we can rework the conditional instruction that follows.
9337(define_insn_and_split "*and_scc_scc_cmp"
9338 [(set (match_operand 0 "dominant_cc_register" "")
9339 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9340 [(match_operand:SI 1 "s_register_operand" "r")
9341 (match_operand:SI 2 "arm_add_operand" "rIL")])
9342 (match_operator:SI 6 "arm_comparison_operator"
9343 [(match_operand:SI 4 "s_register_operand" "r")
9344 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9345 (const_int 0)))
9346 (set (match_operand:SI 7 "s_register_operand" "=r")
9347 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9348 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9349 "TARGET_ARM"
9350 "#"
9351 "TARGET_ARM && reload_completed"
9352 [(set (match_dup 0)
9353 (compare
9354 (and:SI
9355 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9356 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9357 (const_int 0)))
9358 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9359 ""
9360 [(set_attr "conds" "set")
9361 (set_attr "length" "16")])
9362
9363;; If there is no dominance in the comparison, then we can still save an
9364;; instruction in the AND case, since we can know that the second compare
9365;; need only zero the value if false (if true, then the value is already
9366;; correct).
9367(define_insn_and_split "*and_scc_scc_nodom"
9368 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9369 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9370 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9371 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9372 (match_operator:SI 6 "arm_comparison_operator"
9373 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9374 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9375 (clobber (reg:CC CC_REGNUM))]
9376 "TARGET_ARM
9377 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9378 == CCmode)"
9379 "#"
9380 "TARGET_ARM && reload_completed"
9381 [(parallel [(set (match_dup 0)
9382 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9383 (clobber (reg:CC CC_REGNUM))])
9384 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9385 (set (match_dup 0)
9386 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9387 (match_dup 0)
9388 (const_int 0)))]
9389 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9390 operands[4], operands[5]),
9391 CC_REGNUM);
9392 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9393 operands[5]);"
9394 [(set_attr "conds" "clob")
9395 (set_attr "length" "20")])
3c5afce6 9396
3a0bdee0 9397(define_split
9398 [(set (reg:CC_NOOV CC_REGNUM)
9399 (compare:CC_NOOV (ior:SI
9400 (and:SI (match_operand:SI 0 "s_register_operand" "")
9401 (const_int 1))
9402 (match_operator:SI 1 "comparison_operator"
9403 [(match_operand:SI 2 "s_register_operand" "")
9404 (match_operand:SI 3 "arm_add_operand" "")]))
9405 (const_int 0)))
9406 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9407 "TARGET_ARM"
9408 [(set (match_dup 4)
9409 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9410 (match_dup 0)))
9411 (set (reg:CC_NOOV CC_REGNUM)
9412 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9413 (const_int 0)))]
9414 "")
9415
9416(define_split
9417 [(set (reg:CC_NOOV CC_REGNUM)
9418 (compare:CC_NOOV (ior:SI
9419 (match_operator:SI 1 "comparison_operator"
9420 [(match_operand:SI 2 "s_register_operand" "")
9421 (match_operand:SI 3 "arm_add_operand" "")])
9422 (and:SI (match_operand:SI 0 "s_register_operand" "")
9423 (const_int 1)))
9424 (const_int 0)))
9425 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9426 "TARGET_ARM"
9427 [(set (match_dup 4)
9428 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9429 (match_dup 0)))
9430 (set (reg:CC_NOOV CC_REGNUM)
9431 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9432 (const_int 0)))]
9433 "")
25f905c2 9434;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9435
f7fbdd4a 9436(define_insn "*negscc"
9c08d1fa 9437 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9438 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9439 [(match_operand:SI 1 "s_register_operand" "r")
9440 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9441 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9442 "TARGET_ARM"
9c08d1fa 9443 "*
2ca2ec2e 9444 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9445 return \"mov\\t%0, %1, asr #31\";
9446
9c08d1fa 9447 if (GET_CODE (operands[3]) == NE)
e2348bcb 9448 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9449
e2348bcb 9450 output_asm_insn (\"cmp\\t%1, %2\", operands);
9451 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9452 return \"mvn%d3\\t%0, #0\";
215b30b3 9453 "
8fa3ba89 9454 [(set_attr "conds" "clob")
9455 (set_attr "length" "12")]
9456)
9c08d1fa 9457
9458(define_insn "movcond"
9459 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9460 (if_then_else:SI
8fa3ba89 9461 (match_operator 5 "arm_comparison_operator"
5565501b 9462 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9463 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9464 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9465 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9466 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9467 "TARGET_ARM"
9c08d1fa 9468 "*
9469 if (GET_CODE (operands[5]) == LT
9470 && (operands[4] == const0_rtx))
9471 {
5565501b 9472 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9473 {
9c08d1fa 9474 if (operands[2] == const0_rtx)
e2348bcb 9475 return \"and\\t%0, %1, %3, asr #31\";
9476 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9477 }
9478 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9479 {
9c08d1fa 9480 if (operands[1] == const0_rtx)
e2348bcb 9481 return \"bic\\t%0, %2, %3, asr #31\";
9482 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9483 }
9484 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9485 are constants. */
9c08d1fa 9486 }
e2348bcb 9487
9c08d1fa 9488 if (GET_CODE (operands[5]) == GE
9489 && (operands[4] == const0_rtx))
9490 {
9491 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9492 {
9c08d1fa 9493 if (operands[2] == const0_rtx)
e2348bcb 9494 return \"bic\\t%0, %1, %3, asr #31\";
9495 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9496 }
9497 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9498 {
9c08d1fa 9499 if (operands[1] == const0_rtx)
e2348bcb 9500 return \"and\\t%0, %2, %3, asr #31\";
9501 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9502 }
9503 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9504 are constants. */
9c08d1fa 9505 }
9506 if (GET_CODE (operands[4]) == CONST_INT
9507 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9508 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9509 else
e2348bcb 9510 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9511 if (which_alternative != 0)
e2348bcb 9512 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9513 if (which_alternative != 1)
e2348bcb 9514 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9515 return \"\";
215b30b3 9516 "
8fa3ba89 9517 [(set_attr "conds" "clob")
9518 (set_attr "length" "8,8,12")]
9519)
9c08d1fa 9520
25f905c2 9521;; ??? The patterns below need checking for Thumb-2 usefulness.
9522
8a18b90c 9523(define_insn "*ifcompare_plus_move"
9524 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9525 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9526 [(match_operand:SI 4 "s_register_operand" "r,r")
9527 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9528 (plus:SI
9529 (match_operand:SI 2 "s_register_operand" "r,r")
9530 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9531 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9532 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9533 "TARGET_ARM"
8a18b90c 9534 "#"
8fa3ba89 9535 [(set_attr "conds" "clob")
9536 (set_attr "length" "8,12")]
9537)
8a18b90c 9538
9539(define_insn "*if_plus_move"
129a2fe4 9540 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9541 (if_then_else:SI
8fa3ba89 9542 (match_operator 4 "arm_comparison_operator"
8a18b90c 9543 [(match_operand 5 "cc_register" "") (const_int 0)])
9544 (plus:SI
129a2fe4 9545 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9546 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9547 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9548 "TARGET_ARM"
8a18b90c 9549 "@
9550 add%d4\\t%0, %2, %3
9551 sub%d4\\t%0, %2, #%n3
9552 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9553 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9554 [(set_attr "conds" "use")
9555 (set_attr "length" "4,4,8,8")
9556 (set_attr "type" "*,*,*,*")]
9557)
8a18b90c 9558
9559(define_insn "*ifcompare_move_plus"
5565501b 9560 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9561 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9562 [(match_operand:SI 4 "s_register_operand" "r,r")
9563 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9564 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9565 (plus:SI
9566 (match_operand:SI 2 "s_register_operand" "r,r")
9567 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9568 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9569 "TARGET_ARM"
8a18b90c 9570 "#"
8fa3ba89 9571 [(set_attr "conds" "clob")
9572 (set_attr "length" "8,12")]
9573)
8a18b90c 9574
9575(define_insn "*if_move_plus"
129a2fe4 9576 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9577 (if_then_else:SI
8fa3ba89 9578 (match_operator 4 "arm_comparison_operator"
8a18b90c 9579 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9580 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9581 (plus:SI
129a2fe4 9582 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9583 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9584 "TARGET_ARM"
8a18b90c 9585 "@
9586 add%D4\\t%0, %2, %3
9587 sub%D4\\t%0, %2, #%n3
9588 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9589 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9590 [(set_attr "conds" "use")
9591 (set_attr "length" "4,4,8,8")
9592 (set_attr "type" "*,*,*,*")]
9593)
8a18b90c 9594
9595(define_insn "*ifcompare_arith_arith"
9596 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9597 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9598 [(match_operand:SI 5 "s_register_operand" "r")
9599 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9600 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9601 [(match_operand:SI 1 "s_register_operand" "r")
9602 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9603 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9604 [(match_operand:SI 3 "s_register_operand" "r")
9605 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9606 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9607 "TARGET_ARM"
8a18b90c 9608 "#"
8fa3ba89 9609 [(set_attr "conds" "clob")
9610 (set_attr "length" "12")]
9611)
9c08d1fa 9612
8a18b90c 9613(define_insn "*if_arith_arith"
9614 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9615 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9616 [(match_operand 8 "cc_register" "") (const_int 0)])
9617 (match_operator:SI 6 "shiftable_operator"
9618 [(match_operand:SI 1 "s_register_operand" "r")
9619 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9620 (match_operator:SI 7 "shiftable_operator"
9621 [(match_operand:SI 3 "s_register_operand" "r")
9622 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9623 "TARGET_ARM"
8a18b90c 9624 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9625 [(set_attr "conds" "use")
9626 (set_attr "length" "8")]
9627)
8a18b90c 9628
f7fbdd4a 9629(define_insn "*ifcompare_arith_move"
9c08d1fa 9630 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9631 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9632 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9633 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9634 (match_operator:SI 7 "shiftable_operator"
9635 [(match_operand:SI 4 "s_register_operand" "r,r")
9636 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9637 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9638 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9639 "TARGET_ARM"
9c08d1fa 9640 "*
9c08d1fa 9641 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9642 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9643 everything is in registers then we can do this in two instructions. */
9c08d1fa 9644 if (operands[3] == const0_rtx
9645 && GET_CODE (operands[7]) != AND
9646 && GET_CODE (operands[5]) == REG
9647 && GET_CODE (operands[1]) == REG
9648 && REGNO (operands[1]) == REGNO (operands[4])
9649 && REGNO (operands[4]) != REGNO (operands[0]))
9650 {
9651 if (GET_CODE (operands[6]) == LT)
40dbec34 9652 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9653 else if (GET_CODE (operands[6]) == GE)
40dbec34 9654 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9655 }
9656 if (GET_CODE (operands[3]) == CONST_INT
9657 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9658 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9659 else
e2348bcb 9660 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9661 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9662 if (which_alternative != 0)
129a2fe4 9663 return \"mov%D6\\t%0, %1\";
9c08d1fa 9664 return \"\";
215b30b3 9665 "
8fa3ba89 9666 [(set_attr "conds" "clob")
9667 (set_attr "length" "8,12")]
9668)
9c08d1fa 9669
8a18b90c 9670(define_insn "*if_arith_move"
129a2fe4 9671 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9672 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9673 [(match_operand 6 "cc_register" "") (const_int 0)])
9674 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9675 [(match_operand:SI 2 "s_register_operand" "r,r")
9676 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9677 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9678 "TARGET_ARM"
8a18b90c 9679 "@
9680 %I5%d4\\t%0, %2, %3
129a2fe4 9681 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9682 [(set_attr "conds" "use")
9683 (set_attr "length" "4,8")
9684 (set_attr "type" "*,*")]
9685)
8a18b90c 9686
f7fbdd4a 9687(define_insn "*ifcompare_move_arith"
9c08d1fa 9688 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9689 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9690 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9691 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9692 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9693 (match_operator:SI 7 "shiftable_operator"
9694 [(match_operand:SI 2 "s_register_operand" "r,r")
9695 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9696 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9697 "TARGET_ARM"
9c08d1fa 9698 "*
9c08d1fa 9699 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9700 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9701 everything is in registers then we can do this in two instructions */
9702 if (operands[5] == const0_rtx
9703 && GET_CODE (operands[7]) != AND
9704 && GET_CODE (operands[3]) == REG
9705 && GET_CODE (operands[1]) == REG
9706 && REGNO (operands[1]) == REGNO (operands[2])
9707 && REGNO (operands[2]) != REGNO (operands[0]))
9708 {
9709 if (GET_CODE (operands[6]) == GE)
40dbec34 9710 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9711 else if (GET_CODE (operands[6]) == LT)
40dbec34 9712 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9713 }
40dbec34 9714
9c08d1fa 9715 if (GET_CODE (operands[5]) == CONST_INT
9716 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9717 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9718 else
e2348bcb 9719 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9720
9c08d1fa 9721 if (which_alternative != 0)
129a2fe4 9722 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9723 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9724 "
8fa3ba89 9725 [(set_attr "conds" "clob")
9726 (set_attr "length" "8,12")]
9727)
9c08d1fa 9728
8a18b90c 9729(define_insn "*if_move_arith"
129a2fe4 9730 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9731 (if_then_else:SI
8fa3ba89 9732 (match_operator 4 "arm_comparison_operator"
8a18b90c 9733 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9734 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9735 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9736 [(match_operand:SI 2 "s_register_operand" "r,r")
9737 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9738 "TARGET_ARM"
8a18b90c 9739 "@
9740 %I5%D4\\t%0, %2, %3
129a2fe4 9741 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9742 [(set_attr "conds" "use")
9743 (set_attr "length" "4,8")
9744 (set_attr "type" "*,*")]
9745)
8a18b90c 9746
9747(define_insn "*ifcompare_move_not"
9c08d1fa 9748 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9749 (if_then_else:SI
8fa3ba89 9750 (match_operator 5 "arm_comparison_operator"
8a18b90c 9751 [(match_operand:SI 3 "s_register_operand" "r,r")
9752 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9753 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9754 (not:SI
9755 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9756 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9757 "TARGET_ARM"
8a18b90c 9758 "#"
8fa3ba89 9759 [(set_attr "conds" "clob")
9760 (set_attr "length" "8,12")]
9761)
9c08d1fa 9762
8a18b90c 9763(define_insn "*if_move_not"
9764 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9765 (if_then_else:SI
8fa3ba89 9766 (match_operator 4 "arm_comparison_operator"
8a18b90c 9767 [(match_operand 3 "cc_register" "") (const_int 0)])
9768 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9769 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9770 "TARGET_ARM"
8a18b90c 9771 "@
9772 mvn%D4\\t%0, %2
9773 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9774 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9775 [(set_attr "conds" "use")
9776 (set_attr "length" "4,8,8")]
9777)
8a18b90c 9778
9779(define_insn "*ifcompare_not_move"
9c08d1fa 9780 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9781 (if_then_else:SI
8fa3ba89 9782 (match_operator 5 "arm_comparison_operator"
8a18b90c 9783 [(match_operand:SI 3 "s_register_operand" "r,r")
9784 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9785 (not:SI
9786 (match_operand:SI 2 "s_register_operand" "r,r"))
9787 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9788 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9789 "TARGET_ARM"
8a18b90c 9790 "#"
8fa3ba89 9791 [(set_attr "conds" "clob")
9792 (set_attr "length" "8,12")]
9793)
9c08d1fa 9794
8a18b90c 9795(define_insn "*if_not_move"
9796 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9797 (if_then_else:SI
8fa3ba89 9798 (match_operator 4 "arm_comparison_operator"
8a18b90c 9799 [(match_operand 3 "cc_register" "") (const_int 0)])
9800 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9801 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9802 "TARGET_ARM"
8a18b90c 9803 "@
9804 mvn%d4\\t%0, %2
9805 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9806 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9807 [(set_attr "conds" "use")
9808 (set_attr "length" "4,8,8")]
9809)
8a18b90c 9810
9811(define_insn "*ifcompare_shift_move"
9c08d1fa 9812 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9813 (if_then_else:SI
8fa3ba89 9814 (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")])
9817 (match_operator:SI 7 "shift_operator"
9818 [(match_operand:SI 2 "s_register_operand" "r,r")
9819 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9820 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9821 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9822 "TARGET_ARM"
9c08d1fa 9823 "#"
8fa3ba89 9824 [(set_attr "conds" "clob")
9825 (set_attr "length" "8,12")]
9826)
9c08d1fa 9827
8a18b90c 9828(define_insn "*if_shift_move"
9829 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9830 (if_then_else:SI
8fa3ba89 9831 (match_operator 5 "arm_comparison_operator"
8a18b90c 9832 [(match_operand 6 "cc_register" "") (const_int 0)])
9833 (match_operator:SI 4 "shift_operator"
9834 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9835 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9836 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9837 "TARGET_ARM"
5565501b 9838 "@
8a18b90c 9839 mov%d5\\t%0, %2%S4
9840 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9841 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9842 [(set_attr "conds" "use")
331beb1a 9843 (set_attr "shift" "2")
a2cd141b 9844 (set_attr "length" "4,8,8")
9845 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9846 (const_string "alu_shift")
9847 (const_string "alu_shift_reg")))]
8fa3ba89 9848)
5565501b 9849
8a18b90c 9850(define_insn "*ifcompare_move_shift"
9851 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9852 (if_then_else:SI
8fa3ba89 9853 (match_operator 6 "arm_comparison_operator"
8a18b90c 9854 [(match_operand:SI 4 "s_register_operand" "r,r")
9855 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9856 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9857 (match_operator:SI 7 "shift_operator"
8a18b90c 9858 [(match_operand:SI 2 "s_register_operand" "r,r")
9859 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9860 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9861 "TARGET_ARM"
8a18b90c 9862 "#"
8fa3ba89 9863 [(set_attr "conds" "clob")
9864 (set_attr "length" "8,12")]
9865)
5565501b 9866
8a18b90c 9867(define_insn "*if_move_shift"
9868 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9869 (if_then_else:SI
8fa3ba89 9870 (match_operator 5 "arm_comparison_operator"
8a18b90c 9871 [(match_operand 6 "cc_register" "") (const_int 0)])
9872 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9873 (match_operator:SI 4 "shift_operator"
9874 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9875 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9876 "TARGET_ARM"
5565501b 9877 "@
8a18b90c 9878 mov%D5\\t%0, %2%S4
9879 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9880 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9881 [(set_attr "conds" "use")
331beb1a 9882 (set_attr "shift" "2")
a2cd141b 9883 (set_attr "length" "4,8,8")
9884 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9885 (const_string "alu_shift")
9886 (const_string "alu_shift_reg")))]
8fa3ba89 9887)
9c08d1fa 9888
f7fbdd4a 9889(define_insn "*ifcompare_shift_shift"
8a18b90c 9890 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9891 (if_then_else:SI
8fa3ba89 9892 (match_operator 7 "arm_comparison_operator"
8a18b90c 9893 [(match_operand:SI 5 "s_register_operand" "r")
9894 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9895 (match_operator:SI 8 "shift_operator"
8a18b90c 9896 [(match_operand:SI 1 "s_register_operand" "r")
9897 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9898 (match_operator:SI 9 "shift_operator"
8a18b90c 9899 [(match_operand:SI 3 "s_register_operand" "r")
9900 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9901 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9902 "TARGET_ARM"
8a18b90c 9903 "#"
8fa3ba89 9904 [(set_attr "conds" "clob")
9905 (set_attr "length" "12")]
9906)
9c08d1fa 9907
8a18b90c 9908(define_insn "*if_shift_shift"
9909 [(set (match_operand:SI 0 "s_register_operand" "=r")
9910 (if_then_else:SI
8fa3ba89 9911 (match_operator 5 "arm_comparison_operator"
8a18b90c 9912 [(match_operand 8 "cc_register" "") (const_int 0)])
9913 (match_operator:SI 6 "shift_operator"
9914 [(match_operand:SI 1 "s_register_operand" "r")
9915 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9916 (match_operator:SI 7 "shift_operator"
9917 [(match_operand:SI 3 "s_register_operand" "r")
9918 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9919 "TARGET_ARM"
8a18b90c 9920 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9921 [(set_attr "conds" "use")
331beb1a 9922 (set_attr "shift" "1")
a2cd141b 9923 (set_attr "length" "8")
9924 (set (attr "type") (if_then_else
9925 (and (match_operand 2 "const_int_operand" "")
9926 (match_operand 4 "const_int_operand" ""))
9927 (const_string "alu_shift")
9928 (const_string "alu_shift_reg")))]
8fa3ba89 9929)
8a18b90c 9930
f7fbdd4a 9931(define_insn "*ifcompare_not_arith"
8a18b90c 9932 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9933 (if_then_else:SI
8fa3ba89 9934 (match_operator 6 "arm_comparison_operator"
8a18b90c 9935 [(match_operand:SI 4 "s_register_operand" "r")
9936 (match_operand:SI 5 "arm_add_operand" "rIL")])
9937 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9938 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9939 [(match_operand:SI 2 "s_register_operand" "r")
9940 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9941 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9942 "TARGET_ARM"
8a18b90c 9943 "#"
8fa3ba89 9944 [(set_attr "conds" "clob")
9945 (set_attr "length" "12")]
9946)
9c08d1fa 9947
8a18b90c 9948(define_insn "*if_not_arith"
9949 [(set (match_operand:SI 0 "s_register_operand" "=r")
9950 (if_then_else:SI
8fa3ba89 9951 (match_operator 5 "arm_comparison_operator"
8a18b90c 9952 [(match_operand 4 "cc_register" "") (const_int 0)])
9953 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9954 (match_operator:SI 6 "shiftable_operator"
9955 [(match_operand:SI 2 "s_register_operand" "r")
9956 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9957 "TARGET_ARM"
8a18b90c 9958 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9959 [(set_attr "conds" "use")
9960 (set_attr "length" "8")]
9961)
8a18b90c 9962
9963(define_insn "*ifcompare_arith_not"
9964 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9965 (if_then_else:SI
8fa3ba89 9966 (match_operator 6 "arm_comparison_operator"
8a18b90c 9967 [(match_operand:SI 4 "s_register_operand" "r")
9968 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9969 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9970 [(match_operand:SI 2 "s_register_operand" "r")
9971 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9972 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9973 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9974 "TARGET_ARM"
8a18b90c 9975 "#"
8fa3ba89 9976 [(set_attr "conds" "clob")
9977 (set_attr "length" "12")]
9978)
9c08d1fa 9979
8a18b90c 9980(define_insn "*if_arith_not"
9981 [(set (match_operand:SI 0 "s_register_operand" "=r")
9982 (if_then_else:SI
8fa3ba89 9983 (match_operator 5 "arm_comparison_operator"
8a18b90c 9984 [(match_operand 4 "cc_register" "") (const_int 0)])
9985 (match_operator:SI 6 "shiftable_operator"
9986 [(match_operand:SI 2 "s_register_operand" "r")
9987 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9988 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9989 "TARGET_ARM"
8a18b90c 9990 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9991 [(set_attr "conds" "use")
9992 (set_attr "length" "8")]
9993)
8a18b90c 9994
f7fbdd4a 9995(define_insn "*ifcompare_neg_move"
8a18b90c 9996 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9997 (if_then_else:SI
8fa3ba89 9998 (match_operator 5 "arm_comparison_operator"
8a18b90c 9999 [(match_operand:SI 3 "s_register_operand" "r,r")
10000 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10001 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10002 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10003 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10004 "TARGET_ARM"
8a18b90c 10005 "#"
8fa3ba89 10006 [(set_attr "conds" "clob")
10007 (set_attr "length" "8,12")]
10008)
8a18b90c 10009
10010(define_insn "*if_neg_move"
10011 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10012 (if_then_else:SI
8fa3ba89 10013 (match_operator 4 "arm_comparison_operator"
8a18b90c 10014 [(match_operand 3 "cc_register" "") (const_int 0)])
10015 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10016 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10017 "TARGET_ARM"
8a18b90c 10018 "@
10019 rsb%d4\\t%0, %2, #0
10020 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10021 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10022 [(set_attr "conds" "use")
10023 (set_attr "length" "4,8,8")]
10024)
9c08d1fa 10025
f7fbdd4a 10026(define_insn "*ifcompare_move_neg"
8a18b90c 10027 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10028 (if_then_else:SI
8fa3ba89 10029 (match_operator 5 "arm_comparison_operator"
8a18b90c 10030 [(match_operand:SI 3 "s_register_operand" "r,r")
10031 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10032 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10033 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10034 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10035 "TARGET_ARM"
8a18b90c 10036 "#"
8fa3ba89 10037 [(set_attr "conds" "clob")
10038 (set_attr "length" "8,12")]
10039)
8a18b90c 10040
10041(define_insn "*if_move_neg"
10042 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10043 (if_then_else:SI
8fa3ba89 10044 (match_operator 4 "arm_comparison_operator"
8a18b90c 10045 [(match_operand 3 "cc_register" "") (const_int 0)])
10046 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10047 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10048 "TARGET_ARM"
8a18b90c 10049 "@
10050 rsb%D4\\t%0, %2, #0
10051 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10052 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10053 [(set_attr "conds" "use")
10054 (set_attr "length" "4,8,8")]
10055)
9c08d1fa 10056
f7fbdd4a 10057(define_insn "*arith_adjacentmem"
9c08d1fa 10058 [(set (match_operand:SI 0 "s_register_operand" "=r")
10059 (match_operator:SI 1 "shiftable_operator"
10060 [(match_operand:SI 2 "memory_operand" "m")
10061 (match_operand:SI 3 "memory_operand" "m")]))
10062 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10063 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10064 "*
215b30b3 10065 {
10066 rtx ldm[3];
10067 rtx arith[4];
94dee231 10068 rtx base_reg;
10069 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10070
215b30b3 10071 if (REGNO (operands[0]) > REGNO (operands[4]))
10072 {
10073 ldm[1] = operands[4];
10074 ldm[2] = operands[0];
10075 }
10076 else
10077 {
10078 ldm[1] = operands[0];
10079 ldm[2] = operands[4];
10080 }
94dee231 10081
10082 base_reg = XEXP (operands[2], 0);
10083
10084 if (!REG_P (base_reg))
10085 {
10086 val1 = INTVAL (XEXP (base_reg, 1));
10087 base_reg = XEXP (base_reg, 0);
10088 }
10089
10090 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10091 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10092
215b30b3 10093 arith[0] = operands[0];
10094 arith[3] = operands[1];
94dee231 10095
215b30b3 10096 if (val1 < val2)
10097 {
10098 arith[1] = ldm[1];
10099 arith[2] = ldm[2];
10100 }
10101 else
10102 {
10103 arith[1] = ldm[2];
10104 arith[2] = ldm[1];
10105 }
94dee231 10106
10107 ldm[0] = base_reg;
10108 if (val1 !=0 && val2 != 0)
215b30b3 10109 {
cdb1295a 10110 rtx ops[3];
10111
94dee231 10112 if (val1 == 4 || val2 == 4)
10113 /* Other val must be 8, since we know they are adjacent and neither
10114 is zero. */
25f905c2 10115 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10116 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10117 {
94dee231 10118 ldm[0] = ops[0] = operands[4];
10119 ops[1] = base_reg;
10120 ops[2] = GEN_INT (val1);
10121 output_add_immediate (ops);
10122 if (val1 < val2)
25f905c2 10123 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10124 else
25f905c2 10125 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10126 }
cdb1295a 10127 else
10128 {
10129 /* Offset is out of range for a single add, so use two ldr. */
10130 ops[0] = ldm[1];
10131 ops[1] = base_reg;
10132 ops[2] = GEN_INT (val1);
10133 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10134 ops[0] = ldm[2];
10135 ops[2] = GEN_INT (val2);
10136 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10137 }
215b30b3 10138 }
94dee231 10139 else if (val1 != 0)
215b30b3 10140 {
215b30b3 10141 if (val1 < val2)
25f905c2 10142 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10143 else
25f905c2 10144 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10145 }
10146 else
10147 {
215b30b3 10148 if (val1 < val2)
25f905c2 10149 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10150 else
25f905c2 10151 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10152 }
10153 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10154 return \"\";
10155 }"
10156 [(set_attr "length" "12")
10157 (set_attr "predicable" "yes")
a2cd141b 10158 (set_attr "type" "load1")]
215b30b3 10159)
9c08d1fa 10160
9c08d1fa 10161; This pattern is never tried by combine, so do it as a peephole
10162
a0f94409 10163(define_peephole2
372575c7 10164 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10165 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10166 (set (reg:CC CC_REGNUM)
aea4c774 10167 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10168 "TARGET_ARM"
a0f94409 10169 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10170 (set (match_dup 0) (match_dup 1))])]
10171 ""
0d66636f 10172)
9c08d1fa 10173
675d848d 10174; Peepholes to spot possible load- and store-multiples, if the ordering is
10175; reversed, check that the memory references aren't volatile.
9c08d1fa 10176
10177(define_peephole
10178 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 10179 (match_operand:SI 4 "memory_operand" "m"))
10180 (set (match_operand:SI 1 "s_register_operand" "=r")
10181 (match_operand:SI 5 "memory_operand" "m"))
9c08d1fa 10182 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 10183 (match_operand:SI 6 "memory_operand" "m"))
9c08d1fa 10184 (set (match_operand:SI 3 "s_register_operand" "=r")
aea4c774 10185 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 10186 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10187 "*
10188 return emit_ldm_seq (operands, 4);
215b30b3 10189 "
10190)
9c08d1fa 10191
10192(define_peephole
10193 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 10194 (match_operand:SI 3 "memory_operand" "m"))
10195 (set (match_operand:SI 1 "s_register_operand" "=r")
10196 (match_operand:SI 4 "memory_operand" "m"))
9c08d1fa 10197 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 10198 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 10199 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10200 "*
10201 return emit_ldm_seq (operands, 3);
215b30b3 10202 "
10203)
9c08d1fa 10204
10205(define_peephole
10206 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 10207 (match_operand:SI 2 "memory_operand" "m"))
10208 (set (match_operand:SI 1 "s_register_operand" "=r")
10209 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 10210 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10211 "*
10212 return emit_ldm_seq (operands, 2);
215b30b3 10213 "
10214)
9c08d1fa 10215
10216(define_peephole
aea4c774 10217 [(set (match_operand:SI 4 "memory_operand" "=m")
9c08d1fa 10218 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 10219 (set (match_operand:SI 5 "memory_operand" "=m")
10220 (match_operand:SI 1 "s_register_operand" "r"))
10221 (set (match_operand:SI 6 "memory_operand" "=m")
9c08d1fa 10222 (match_operand:SI 2 "s_register_operand" "r"))
aea4c774 10223 (set (match_operand:SI 7 "memory_operand" "=m")
10224 (match_operand:SI 3 "s_register_operand" "r"))]
cffb2a26 10225 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10226 "*
10227 return emit_stm_seq (operands, 4);
215b30b3 10228 "
10229)
9c08d1fa 10230
10231(define_peephole
aea4c774 10232 [(set (match_operand:SI 3 "memory_operand" "=m")
9c08d1fa 10233 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 10234 (set (match_operand:SI 4 "memory_operand" "=m")
10235 (match_operand:SI 1 "s_register_operand" "r"))
10236 (set (match_operand:SI 5 "memory_operand" "=m")
10237 (match_operand:SI 2 "s_register_operand" "r"))]
cffb2a26 10238 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10239 "*
10240 return emit_stm_seq (operands, 3);
215b30b3 10241 "
10242)
9c08d1fa 10243
10244(define_peephole
aea4c774 10245 [(set (match_operand:SI 2 "memory_operand" "=m")
9c08d1fa 10246 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 10247 (set (match_operand:SI 3 "memory_operand" "=m")
10248 (match_operand:SI 1 "s_register_operand" "r"))]
cffb2a26 10249 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10250 "*
10251 return emit_stm_seq (operands, 2);
215b30b3 10252 "
10253)
9c08d1fa 10254
9c08d1fa 10255(define_split
10256 [(set (match_operand:SI 0 "s_register_operand" "")
10257 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10258 (const_int 0))
8fa3ba89 10259 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10260 [(match_operand:SI 3 "s_register_operand" "")
10261 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10262 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10263 "TARGET_ARM"
9c08d1fa 10264 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10265 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10266 (match_dup 5)))]
215b30b3 10267 ""
10268)
9c08d1fa 10269
aea4c774 10270;; This split can be used because CC_Z mode implies that the following
10271;; branch will be an equality, or an unsigned inequality, so the sign
10272;; extension is not needed.
9c08d1fa 10273
aea4c774 10274(define_split
bd5b4116 10275 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10276 (compare:CC_Z
10277 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10278 (const_int 24))
aea4c774 10279 (match_operand 1 "const_int_operand" "")))
10280 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10281 "TARGET_ARM
10282 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10283 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10284 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10285 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10286 "
9c08d1fa 10287 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10288 "
10289)
25f905c2 10290;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10291
87b22bf7 10292(define_expand "prologue"
10293 [(clobber (const_int 0))]
cffb2a26 10294 "TARGET_EITHER"
25f905c2 10295 "if (TARGET_32BIT)
cffb2a26 10296 arm_expand_prologue ();
10297 else
25f905c2 10298 thumb1_expand_prologue ();
87b22bf7 10299 DONE;
cffb2a26 10300 "
10301)
87b22bf7 10302
56d27660 10303(define_expand "epilogue"
4c44712e 10304 [(clobber (const_int 0))]
cffb2a26 10305 "TARGET_EITHER"
56d27660 10306 "
4c44712e 10307 if (current_function_calls_eh_return)
10308 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10309 if (TARGET_THUMB1)
10310 thumb1_expand_epilogue ();
cffb2a26 10311 else if (USE_RETURN_INSN (FALSE))
56d27660 10312 {
10313 emit_jump_insn (gen_return ());
10314 DONE;
10315 }
cffb2a26 10316 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10317 gen_rtvec (1,
10318 gen_rtx_RETURN (VOIDmode)),
e1159bbe 10319 VUNSPEC_EPILOGUE));
cffb2a26 10320 DONE;
10321 "
10322)
56d27660 10323
ef5651d0 10324;; Note - although unspec_volatile's USE all hard registers,
10325;; USEs are ignored after relaod has completed. Thus we need
10326;; to add an unspec of the link register to ensure that flow
10327;; does not think that it is unused by the sibcall branch that
10328;; will replace the standard function epilogue.
1c494086 10329(define_insn "sibcall_epilogue"
ef5651d0 10330 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10331 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10332 "TARGET_32BIT"
1c494086 10333 "*
ffc9d00c 10334 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10335 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10336 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10337 "
10338;; Length is absolute worst case
10339 [(set_attr "length" "44")
defc47cf 10340 (set_attr "type" "block")
10341 ;; We don't clobber the conditions, but the potential length of this
10342 ;; operation is sufficient to make conditionalizing the sequence
10343 ;; unlikely to be profitable.
10344 (set_attr "conds" "clob")]
1c494086 10345)
10346
cffb2a26 10347(define_insn "*epilogue_insns"
e1159bbe 10348 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10349 "TARGET_EITHER"
56d27660 10350 "*
25f905c2 10351 if (TARGET_32BIT)
ffc9d00c 10352 return arm_output_epilogue (NULL);
25f905c2 10353 else /* TARGET_THUMB1 */
cffb2a26 10354 return thumb_unexpanded_epilogue ();
10355 "
215b30b3 10356 ; Length is absolute worst case
cffb2a26 10357 [(set_attr "length" "44")
defc47cf 10358 (set_attr "type" "block")
10359 ;; We don't clobber the conditions, but the potential length of this
10360 ;; operation is sufficient to make conditionalizing the sequence
10361 ;; unlikely to be profitable.
10362 (set_attr "conds" "clob")]
cffb2a26 10363)
10364
10365(define_expand "eh_epilogue"
7db9af5d 10366 [(use (match_operand:SI 0 "register_operand" ""))
10367 (use (match_operand:SI 1 "register_operand" ""))
10368 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10369 "TARGET_EITHER"
10370 "
215b30b3 10371 {
10372 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10373 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10374 {
10375 rtx ra = gen_rtx_REG (Pmode, 2);
10376
10377 emit_move_insn (ra, operands[2]);
10378 operands[2] = ra;
10379 }
5cf3595a 10380 /* This is a hack -- we may have crystalized the function type too
10381 early. */
10382 cfun->machine->func_type = 0;
215b30b3 10383 }"
10384)
56d27660 10385
9c08d1fa 10386;; This split is only used during output to reduce the number of patterns
10387;; that need assembler instructions adding to them. We allowed the setting
10388;; of the conditions to be implicit during rtl generation so that
10389;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10390;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10391;; up again here.
10392
25f905c2 10393;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10394;; conditional execution sufficient?
10395
9c08d1fa 10396(define_split
10397 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10398 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10399 [(match_operand 2 "" "") (match_operand 3 "" "")])
10400 (match_dup 0)
10401 (match_operand 4 "" "")))
bd5b4116 10402 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10403 "TARGET_ARM && reload_completed"
8fa3ba89 10404 [(set (match_dup 5) (match_dup 6))
10405 (cond_exec (match_dup 7)
10406 (set (match_dup 0) (match_dup 4)))]
10407 "
10408 {
10409 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10410 operands[2], operands[3]);
10411 enum rtx_code rc = GET_CODE (operands[1]);
10412
bd5b4116 10413 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10414 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10415 if (mode == CCFPmode || mode == CCFPEmode)
10416 rc = reverse_condition_maybe_unordered (rc);
10417 else
10418 rc = reverse_condition (rc);
10419
10420 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10421 }"
10422)
10423
10424(define_split
10425 [(set (match_operand:SI 0 "s_register_operand" "")
10426 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10427 [(match_operand 2 "" "") (match_operand 3 "" "")])
10428 (match_operand 4 "" "")
10429 (match_dup 0)))
bd5b4116 10430 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10431 "TARGET_ARM && reload_completed"
8fa3ba89 10432 [(set (match_dup 5) (match_dup 6))
10433 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10434 (set (match_dup 0) (match_dup 4)))]
10435 "
10436 {
10437 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10438 operands[2], operands[3]);
10439
bd5b4116 10440 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10441 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10442 }"
10443)
10444
10445(define_split
10446 [(set (match_operand:SI 0 "s_register_operand" "")
10447 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10448 [(match_operand 2 "" "") (match_operand 3 "" "")])
10449 (match_operand 4 "" "")
10450 (match_operand 5 "" "")))
bd5b4116 10451 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10452 "TARGET_ARM && reload_completed"
8fa3ba89 10453 [(set (match_dup 6) (match_dup 7))
10454 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10455 (set (match_dup 0) (match_dup 4)))
10456 (cond_exec (match_dup 8)
10457 (set (match_dup 0) (match_dup 5)))]
10458 "
10459 {
10460 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10461 operands[2], operands[3]);
10462 enum rtx_code rc = GET_CODE (operands[1]);
10463
bd5b4116 10464 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10465 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10466 if (mode == CCFPmode || mode == CCFPEmode)
10467 rc = reverse_condition_maybe_unordered (rc);
10468 else
10469 rc = reverse_condition (rc);
10470
10471 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10472 }"
10473)
10474
cffb2a26 10475(define_split
10476 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10477 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10478 [(match_operand:SI 2 "s_register_operand" "")
10479 (match_operand:SI 3 "arm_add_operand" "")])
10480 (match_operand:SI 4 "arm_rhs_operand" "")
10481 (not:SI
10482 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10483 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10484 "TARGET_ARM && reload_completed"
cffb2a26 10485 [(set (match_dup 6) (match_dup 7))
f6c53574 10486 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10487 (set (match_dup 0) (match_dup 4)))
10488 (cond_exec (match_dup 8)
10489 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10490 "
215b30b3 10491 {
10492 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10493 operands[2], operands[3]);
f6c53574 10494 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10495
bd5b4116 10496 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10497 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10498 if (mode == CCFPmode || mode == CCFPEmode)
10499 rc = reverse_condition_maybe_unordered (rc);
10500 else
10501 rc = reverse_condition (rc);
10502
10503 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10504 }"
10505)
cffb2a26 10506
10507(define_insn "*cond_move_not"
10508 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10509 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10510 [(match_operand 3 "cc_register" "") (const_int 0)])
10511 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10512 (not:SI
10513 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10514 "TARGET_ARM"
10515 "@
10516 mvn%D4\\t%0, %2
10517 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10518 [(set_attr "conds" "use")
10519 (set_attr "length" "4,8")]
10520)
cffb2a26 10521
9c08d1fa 10522;; The next two patterns occur when an AND operation is followed by a
10523;; scc insn sequence
10524
f7fbdd4a 10525(define_insn "*sign_extract_onebit"
9c08d1fa 10526 [(set (match_operand:SI 0 "s_register_operand" "=r")
10527 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10528 (const_int 1)
ed750274 10529 (match_operand:SI 2 "const_int_operand" "n")))
10530 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10531 "TARGET_ARM"
9c08d1fa 10532 "*
0d66636f 10533 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10534 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10535 return \"mvnne\\t%0, #0\";
10536 "
10537 [(set_attr "conds" "clob")
10538 (set_attr "length" "8")]
10539)
9c08d1fa 10540
f7fbdd4a 10541(define_insn "*not_signextract_onebit"
9c08d1fa 10542 [(set (match_operand:SI 0 "s_register_operand" "=r")
10543 (not:SI
10544 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10545 (const_int 1)
ed750274 10546 (match_operand:SI 2 "const_int_operand" "n"))))
10547 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10548 "TARGET_ARM"
9c08d1fa 10549 "*
0d66636f 10550 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10551 output_asm_insn (\"tst\\t%1, %2\", operands);
10552 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10553 return \"movne\\t%0, #0\";
10554 "
10555 [(set_attr "conds" "clob")
10556 (set_attr "length" "12")]
10557)
25f905c2 10558;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10559
0d66636f 10560;; Push multiple registers to the stack. Registers are in parallel (use ...)
10561;; expressions. For simplicity, the first register is also in the unspec
10562;; part.
f7fbdd4a 10563(define_insn "*push_multi"
87b22bf7 10564 [(match_parallel 2 "multi_register_push"
10565 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10566 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10567 UNSPEC_PUSH_MULT))])]
25f905c2 10568 "TARGET_32BIT"
87b22bf7 10569 "*
215b30b3 10570 {
10571 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10572
215b30b3 10573 /* For the StrongARM at least it is faster to
25f905c2 10574 use STR to store only a single register.
542d5028 10575 In Thumb mode always use push, and the assembler will pick
10576 something appropriate. */
25f905c2 10577 if (num_saves == 1 && TARGET_ARM)
215b30b3 10578 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10579 else
10580 {
10581 int i;
10582 char pattern[100];
ed593f11 10583
25f905c2 10584 if (TARGET_ARM)
10585 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10586 else
10587 strcpy (pattern, \"push\\t{%1\");
215b30b3 10588
6079f055 10589 for (i = 1; i < num_saves; i++)
215b30b3 10590 {
10591 strcat (pattern, \", %|\");
10592 strcat (pattern,
10593 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10594 }
10595
10596 strcat (pattern, \"}\");
10597 output_asm_insn (pattern, operands);
10598 }
10599
10600 return \"\";
10601 }"
10602 [(set_attr "type" "store4")]
10603)
f7fbdd4a 10604
4c58c898 10605(define_insn "stack_tie"
10606 [(set (mem:BLK (scratch))
10607 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10608 (match_operand:SI 1 "s_register_operand" "r")]
10609 UNSPEC_PRLG_STK))]
10610 ""
10611 ""
10612 [(set_attr "length" "0")]
10613)
10614
3398e91d 10615;; Similarly for the floating point registers
7b1d2fc4 10616(define_insn "*push_fp_multi"
10617 [(match_parallel 2 "multi_register_push"
10618 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10619 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10620 UNSPEC_PUSH_MULT))])]
25f905c2 10621 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10622 "*
215b30b3 10623 {
10624 char pattern[100];
7b1d2fc4 10625
215b30b3 10626 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10627 output_asm_insn (pattern, operands);
10628 return \"\";
10629 }"
10630 [(set_attr "type" "f_store")]
10631)
7b1d2fc4 10632
f7fbdd4a 10633;; Special patterns for dealing with the constant pool
10634
cffb2a26 10635(define_insn "align_4"
e1159bbe 10636 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10637 "TARGET_EITHER"
f7fbdd4a 10638 "*
cffb2a26 10639 assemble_align (32);
f7fbdd4a 10640 return \"\";
cffb2a26 10641 "
10642)
f7fbdd4a 10643
755eb2b4 10644(define_insn "align_8"
10645 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10646 "TARGET_EITHER"
755eb2b4 10647 "*
10648 assemble_align (64);
10649 return \"\";
10650 "
10651)
10652
cffb2a26 10653(define_insn "consttable_end"
e1159bbe 10654 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10655 "TARGET_EITHER"
f7fbdd4a 10656 "*
cffb2a26 10657 making_const_table = FALSE;
f7fbdd4a 10658 return \"\";
cffb2a26 10659 "
10660)
f7fbdd4a 10661
cffb2a26 10662(define_insn "consttable_1"
e1159bbe 10663 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10664 "TARGET_THUMB1"
f7fbdd4a 10665 "*
cffb2a26 10666 making_const_table = TRUE;
09d688ff 10667 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10668 assemble_zeros (3);
f7fbdd4a 10669 return \"\";
cffb2a26 10670 "
10671 [(set_attr "length" "4")]
10672)
f7fbdd4a 10673
cffb2a26 10674(define_insn "consttable_2"
e1159bbe 10675 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10676 "TARGET_THUMB1"
f7fbdd4a 10677 "*
cffb2a26 10678 making_const_table = TRUE;
09d688ff 10679 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10680 assemble_zeros (2);
f7fbdd4a 10681 return \"\";
cffb2a26 10682 "
10683 [(set_attr "length" "4")]
10684)
10685
10686(define_insn "consttable_4"
e1159bbe 10687 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10688 "TARGET_EITHER"
10689 "*
10690 {
10691 making_const_table = TRUE;
10692 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10693 {
10694 case MODE_FLOAT:
10695 {
badfe841 10696 REAL_VALUE_TYPE r;
10697 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10698 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10699 break;
10700 }
10701 default:
09d688ff 10702 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
cffb2a26 10703 break;
10704 }
10705 return \"\";
10706 }"
10707 [(set_attr "length" "4")]
10708)
10709
10710(define_insn "consttable_8"
e1159bbe 10711 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10712 "TARGET_EITHER"
10713 "*
10714 {
10715 making_const_table = TRUE;
10716 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10717 {
10718 case MODE_FLOAT:
10719 {
badfe841 10720 REAL_VALUE_TYPE r;
10721 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10722 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10723 break;
10724 }
10725 default:
09d688ff 10726 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10727 break;
10728 }
10729 return \"\";
10730 }"
10731 [(set_attr "length" "8")]
10732)
10733
10734;; Miscellaneous Thumb patterns
10735
fd957ef3 10736(define_expand "tablejump"
7db9af5d 10737 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10738 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10739 "TARGET_THUMB1"
fd957ef3 10740 "
10741 if (flag_pic)
10742 {
10743 /* Hopefully, CSE will eliminate this copy. */
10744 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10745 rtx reg2 = gen_reg_rtx (SImode);
10746
10747 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10748 operands[0] = reg2;
10749 }
10750 "
10751)
10752
f1039640 10753;; NB never uses BX.
25f905c2 10754(define_insn "*thumb1_tablejump"
cffb2a26 10755 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10756 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10757 "TARGET_THUMB1"
fd957ef3 10758 "mov\\t%|pc, %0"
cffb2a26 10759 [(set_attr "length" "2")]
10760)
0d66636f 10761
331beb1a 10762;; V5 Instructions,
10763
8f4be2be 10764(define_insn "clzsi2"
10765 [(set (match_operand:SI 0 "s_register_operand" "=r")
10766 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10767 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10768 "clz%?\\t%0, %1"
10769 [(set_attr "predicable" "yes")])
331beb1a 10770
e1159bbe 10771(define_expand "ffssi2"
10772 [(set (match_operand:SI 0 "s_register_operand" "")
10773 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 10774 "TARGET_32BIT && arm_arch5"
e1159bbe 10775 "
10776 {
10777 rtx t1, t2, t3;
10778
10779 t1 = gen_reg_rtx (SImode);
10780 t2 = gen_reg_rtx (SImode);
10781 t3 = gen_reg_rtx (SImode);
10782
10783 emit_insn (gen_negsi2 (t1, operands[1]));
10784 emit_insn (gen_andsi3 (t2, operands[1], t1));
8f4be2be 10785 emit_insn (gen_clzsi2 (t3, t2));
e1159bbe 10786 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10787 DONE;
10788 }"
10789)
10790
8f4be2be 10791(define_expand "ctzsi2"
10792 [(set (match_operand:SI 0 "s_register_operand" "")
10793 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 10794 "TARGET_32BIT && arm_arch5"
8f4be2be 10795 "
10796 {
10797 rtx t1, t2, t3;
10798
10799 t1 = gen_reg_rtx (SImode);
10800 t2 = gen_reg_rtx (SImode);
10801 t3 = gen_reg_rtx (SImode);
10802
10803 emit_insn (gen_negsi2 (t1, operands[1]));
10804 emit_insn (gen_andsi3 (t2, operands[1], t1));
10805 emit_insn (gen_clzsi2 (t3, t2));
10806 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10807 DONE;
10808 }"
10809)
10810
e1159bbe 10811;; V5E instructions.
331beb1a 10812
10813(define_insn "prefetch"
f4e79814 10814 [(prefetch (match_operand:SI 0 "address_operand" "p")
10815 (match_operand:SI 1 "" "")
10816 (match_operand:SI 2 "" ""))]
25f905c2 10817 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10818 "pld\\t%a0")
331beb1a 10819
0d66636f 10820;; General predication pattern
10821
10822(define_cond_exec
10823 [(match_operator 0 "arm_comparison_operator"
10824 [(match_operand 1 "cc_register" "")
10825 (const_int 0)])]
25f905c2 10826 "TARGET_32BIT"
0d66636f 10827 ""
10828)
10829
063a05c7 10830(define_insn "prologue_use"
10831 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10832 ""
10833 "%@ %0 needed for prologue"
10834)
7db9af5d 10835
4c44712e 10836
10837;; Patterns for exception handling
10838
10839(define_expand "eh_return"
10840 [(use (match_operand 0 "general_operand" ""))]
10841 "TARGET_EITHER"
10842 "
10843 {
25f905c2 10844 if (TARGET_32BIT)
4c44712e 10845 emit_insn (gen_arm_eh_return (operands[0]));
10846 else
10847 emit_insn (gen_thumb_eh_return (operands[0]));
10848 DONE;
10849 }"
10850)
10851
10852;; We can't expand this before we know where the link register is stored.
10853(define_insn_and_split "arm_eh_return"
10854 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10855 VUNSPEC_EH_RETURN)
10856 (clobber (match_scratch:SI 1 "=&r"))]
10857 "TARGET_ARM"
10858 "#"
10859 "&& reload_completed"
10860 [(const_int 0)]
10861 "
10862 {
10863 arm_set_return_address (operands[0], operands[1]);
10864 DONE;
10865 }"
10866)
10867
10868(define_insn_and_split "thumb_eh_return"
10869 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10870 VUNSPEC_EH_RETURN)
10871 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10872 "TARGET_THUMB1"
4c44712e 10873 "#"
10874 "&& reload_completed"
10875 [(const_int 0)]
10876 "
10877 {
10878 thumb_set_return_address (operands[0], operands[1]);
10879 DONE;
10880 }"
10881)
10882
f655717d 10883\f
10884;; TLS support
10885
10886(define_insn "load_tp_hard"
10887 [(set (match_operand:SI 0 "register_operand" "=r")
10888 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10889 "TARGET_HARD_TP"
10890 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10891 [(set_attr "predicable" "yes")]
10892)
10893
10894;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10895(define_insn "load_tp_soft"
10896 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10897 (clobber (reg:SI LR_REGNUM))
10898 (clobber (reg:SI IP_REGNUM))
10899 (clobber (reg:CC CC_REGNUM))]
10900 "TARGET_SOFT_TP"
10901 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10902 [(set_attr "conds" "clob")]
10903)
10904
7db9af5d 10905;; Load the FPA co-processor patterns
10906(include "fpa.md")
10907;; Load the Maverick co-processor patterns
10908(include "cirrus.md")
755eb2b4 10909;; Load the Intel Wireless Multimedia Extension patterns
10910(include "iwmmxt.md")
a2cd141b 10911;; Load the VFP co-processor patterns
10912(include "vfp.md")
25f905c2 10913;; Thumb-2 patterns
10914(include "thumb2.md")
a2cd141b 10915