]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Index: ChangeLog
[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,
afe27f3b 3;; 2001, 2002, 2003, 2004, 2005 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
9b754436 22;; the Free Software Foundation, 59 Temple Place - Suite 330,
cebb6efe 23;; Boston, MA 02111-1307, 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.
e1159bbe 93 ]
94)
95
215b30b3 96;; UNSPEC_VOLATILE Usage:
e1159bbe 97
98(define_constants
99 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
100 ; insn in the code.
101 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102 ; instruction epilogue sequence that isn't expanded
103 ; into normal RTL. Used for both normal and sibcall
104 ; epilogues.
105 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
106 ; for inlined constants.
107 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
108 ; table.
109 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
110 ; an 8-bit object.
111 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
112 ; a 16-bit object.
113 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
114 ; a 32-bit object.
115 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
116 ; a 64-bit object.
755eb2b4 117 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
118 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
119 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
120 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
121 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 123 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 124 ; handling.
e1159bbe 125 ]
126)
b11cae9e 127\f
e1159bbe 128;;---------------------------------------------------------------------------
9c08d1fa 129;; Attributes
130
215b30b3 131; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132; generating ARM code. This is used to control the length of some insn
133; patterns that share the same RTL in both ARM and Thumb code.
1c494086 134(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 135
215b30b3 136; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137; scheduling decisions for the load unit and the multiplier.
74a71f7d 138(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
9c08d1fa 139
5ecb8da7 140; IS_XSCALE is set to 'yes' when compiling for XScale.
141(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
142
331beb1a 143;; Operand number of an input operand that is shifted. Zero if the
144;; given instruction does not shift one of its input operands.
331beb1a 145(define_attr "shift" "" (const_int 0))
146
3d91c5d6 147; Floating Point Unit. If we only have floating point emulation, then there
148; is no point in scheduling the floating point insns. (Well, for best
149; performance we should try and group them together).
a2cd141b 150(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 151 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 152
094e994f 153; LENGTH of an instruction (in bytes)
154(define_attr "length" "" (const_int 4))
9c08d1fa 155
56d27660 156; POOL_RANGE is how far away from a constant pool entry that this insn
157; can be placed. If the distance is zero, then this insn will never
158; reference the pool.
cffb2a26 159; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160; before its address.
56d27660 161(define_attr "pool_range" "" (const_int 0))
cffb2a26 162(define_attr "neg_pool_range" "" (const_int 0))
56d27660 163
215b30b3 164; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 165; If such an insn references the pool, then we have no way of knowing how,
166; so use the most conservative value for pool_range.
9c08d1fa 167(define_asm_attributes
4d7a8451 168 [(set_attr "conds" "clob")
169 (set_attr "length" "4")
170 (set_attr "pool_range" "250")])
9c08d1fa 171
a2cd141b 172;; The instruction used to implement a particular pattern. This
173;; information is used by pipeline descriptions to provide accurate
174;; scheduling information.
175
176(define_attr "insn"
177 "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"
178 (const_string "other"))
179
9c08d1fa 180; TYPE attribute is used to detect floating point instructions which, if
181; running on a co-processor can run in parallel with other, basic instructions
182; If write-buffer scheduling is enabled then it can also be used in the
183; scheduling of writes.
184
185; Classification of each insn
a2cd141b 186; alu any alu instruction that doesn't hit memory or fp
187; regs or have a shifted source operand
188; alu_shift any data instruction that doesn't hit memory or fp
189; regs, but has a source operand shifted by a constant
190; alu_shift_reg any data instruction that doesn't hit memory or fp
191; regs, but has a source operand shifted by a register value
f7fbdd4a 192; mult a multiply instruction
9c08d1fa 193; block blockage insn, this blocks all functional units
194; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 195; fdivd DFmode floating point division
196; fdivs SFmode floating point division
197; fmul Floating point multiply
198; ffmul Fast floating point multiply
199; farith Floating point arithmetic (4 cycle)
200; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 201; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 202; even on a machine with an fpa.
9c08d1fa 203; f_load a floating point load from memory
204; f_store a floating point store to memory
c0e1af52 205; f_load[sd] single/double load from memeory
206; f_store[sd] single/double store to memeory
207; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 208; f_mem_r a transfer of a floating point register to a real reg via mem
209; r_mem_f the reverse of f_mem_r
210; f_2_r fast transfer float to arm (no memory needed)
211; r_2_f fast transfer arm to float
c0e1af52 212; f_cvt convert floating<->integral
a2cd141b 213; branch a branch
9c08d1fa 214; call a subroutine call
a2cd141b 215; load_byte load byte(s) from memory to arm registers
216; load1 load 1 word from memory to arm registers
217; load2 load 2 words from memory to arm registers
218; load3 load 3 words from memory to arm registers
219; load4 load 4 words from memory to arm registers
220; store store 1 word to memory from arm registers
9c08d1fa 221; store2 store 2 words
222; store3 store 3 words
a2cd141b 223; store4 store 4 (or more) words
2c6c7d8b 224; Additions for Cirrus Maverick co-processor:
225; mav_farith Floating point arithmetic (4 cycle)
226; mav_dmult Double multiplies (7 cycle)
9c08d1fa 227;
228(define_attr "type"
c0e1af52 229 "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 230 (if_then_else
231 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
232 (const_string "mult")
233 (const_string "alu")))
9c08d1fa 234
9888ad6d 235; Load scheduling, set from the arm_ld_sched variable
457275b6 236; initialized by arm_override_options()
9888ad6d 237(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 238
f7fbdd4a 239; condition codes: this one is used by final_prescan_insn to speed up
240; conditionalizing instructions. It saves having to scan the rtl to see if
241; it uses or alters the condition codes.
215b30b3 242;
f7fbdd4a 243; USE means that the condition codes are used by the insn in the process of
215b30b3 244; outputting code, this means (at present) that we can't use the insn in
245; inlined branches
246;
f7fbdd4a 247; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 248; well defined manner.
249;
f7fbdd4a 250; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 251; they are altered at all
252;
8fa3ba89 253; JUMP_CLOB is used when the condition cannot be represented by a single
215b30b3 254; instruction (UNEQ and LTGT). These cannot be predicated.
255;
f7fbdd4a 256; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 257; output of this insn
f7fbdd4a 258
259(define_attr "conds" "use,set,clob,jump_clob,nocond"
260 (if_then_else (eq_attr "type" "call")
c1a66faf 261 (const_string "clob")
f7fbdd4a 262 (const_string "nocond")))
263
215b30b3 264; Predicable means that the insn can be conditionally executed based on
265; an automatically added predicate (additional patterns are generated by
266; gen...). We default to 'no' because no Thumb patterns match this rule
267; and not all ARM patterns do.
0d66636f 268(define_attr "predicable" "no,yes" (const_string "no"))
269
129a2fe4 270; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
271; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 272; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 273; affect the schedule).
74a71f7d 274(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 275
215b30b3 276; WRITE_CONFLICT implies that a read following an unrelated write is likely
277; to stall the processor. Used with model_wbuf above.
9c08d1fa 278(define_attr "write_conflict" "no,yes"
279 (if_then_else (eq_attr "type"
a2cd141b 280 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 281 (const_string "yes")
282 (const_string "no")))
283
215b30b3 284; Classify the insns into those that take one cycle and those that take more
285; than one on the main cpu execution unit.
f7fbdd4a 286(define_attr "core_cycles" "single,multi"
287 (if_then_else (eq_attr "type"
a2cd141b 288 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 289 (const_string "single")
290 (const_string "multi")))
291
cffb2a26 292;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 293;; distant label. Only applicable to Thumb code.
cffb2a26 294(define_attr "far_jump" "yes,no" (const_string "no"))
295
d51f92df 296
297;;---------------------------------------------------------------------------
298;; Mode macros
299
300; A list of modes that are exactly 64 bits in size. We use this to expand
301; some splits that are the same for all modes when operating on ARM
302; registers.
303(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
304
305;;---------------------------------------------------------------------------
306;; Predicates
307
9c9db025 308(include "predicates.md")
309
a2cd141b 310;;---------------------------------------------------------------------------
311;; Pipeline descriptions
215b30b3 312
06469f9e 313;; Processor type. This is created automatically from arm-cores.def.
314(include "arm-tune.md")
331beb1a 315
a2cd141b 316;; True if the generic scheduling description should be used.
317
318(define_attr "generic_sched" "yes,no"
4d5cb40d 319 (const (if_then_else
c0e1af52 320 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
4d5cb40d 321 (const_string "no")
322 (const_string "yes"))))
323
c0e1af52 324(define_attr "generic_vfp" "yes,no"
325 (const (if_then_else
326 (and (eq_attr "fpu" "vfp")
327 (eq_attr "tune" "!arm1020e,arm1022e"))
328 (const_string "yes")
329 (const_string "no"))))
330
a2cd141b 331(include "arm-generic.md")
332(include "arm926ejs.md")
c0e1af52 333(include "arm1020e.md")
a2cd141b 334(include "arm1026ejs.md")
335(include "arm1136jfs.md")
3586df96 336
9c08d1fa 337\f
215b30b3 338;;---------------------------------------------------------------------------
e1159bbe 339;; Insn patterns
340;;
a0f94409 341;; Addition insns.
215b30b3 342
9c08d1fa 343;; Note: For DImode insns, there is normally no reason why operands should
344;; not be in the same register, what we don't want is for something being
345;; written to partially overlap something that is an input.
7d57ec45 346;; Cirrus 64bit additions should not be split because we have a native
347;; 64bit addition instructions.
9c08d1fa 348
cffb2a26 349(define_expand "adddi3"
350 [(parallel
215b30b3 351 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 352 (plus:DI (match_operand:DI 1 "s_register_operand" "")
353 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 354 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 355 "TARGET_EITHER"
356 "
a2cd141b 357 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 358 {
359 if (!cirrus_fp_register (operands[0], DImode))
360 operands[0] = force_reg (DImode, operands[0]);
361 if (!cirrus_fp_register (operands[1], DImode))
362 operands[1] = force_reg (DImode, operands[1]);
363 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
364 DONE;
365 }
366
cffb2a26 367 if (TARGET_THUMB)
368 {
369 if (GET_CODE (operands[1]) != REG)
370 operands[1] = force_reg (SImode, operands[1]);
371 if (GET_CODE (operands[2]) != REG)
372 operands[2] = force_reg (SImode, operands[2]);
373 }
374 "
375)
376
377(define_insn "*thumb_adddi3"
378 [(set (match_operand:DI 0 "register_operand" "=l")
379 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 380 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 381 (clobber (reg:CC CC_REGNUM))
cffb2a26 382 ]
383 "TARGET_THUMB"
384 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
385 [(set_attr "length" "4")]
386)
387
a0f94409 388(define_insn_and_split "*arm_adddi3"
cffb2a26 389 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 390 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
391 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 392 (clobber (reg:CC CC_REGNUM))]
a2cd141b 393 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 394 "#"
a0f94409 395 "TARGET_ARM && reload_completed"
396 [(parallel [(set (reg:CC_C CC_REGNUM)
397 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
398 (match_dup 1)))
399 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401 (plus:SI (match_dup 4) (match_dup 5))))]
402 "
403 {
404 operands[3] = gen_highpart (SImode, operands[0]);
405 operands[0] = gen_lowpart (SImode, operands[0]);
406 operands[4] = gen_highpart (SImode, operands[1]);
407 operands[1] = gen_lowpart (SImode, operands[1]);
408 operands[5] = gen_highpart (SImode, operands[2]);
409 operands[2] = gen_lowpart (SImode, operands[2]);
410 }"
cffb2a26 411 [(set_attr "conds" "clob")
412 (set_attr "length" "8")]
413)
9c08d1fa 414
a0f94409 415(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 416 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
417 (plus:DI (sign_extend:DI
97499065 418 (match_operand:SI 2 "s_register_operand" "r,r"))
419 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 420 (clobber (reg:CC CC_REGNUM))]
a2cd141b 421 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 422 "#"
a0f94409 423 "TARGET_ARM && reload_completed"
424 [(parallel [(set (reg:CC_C CC_REGNUM)
425 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
426 (match_dup 1)))
427 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429 (plus:SI (ashiftrt:SI (match_dup 2)
430 (const_int 31))
431 (match_dup 4))))]
432 "
433 {
434 operands[3] = gen_highpart (SImode, operands[0]);
435 operands[0] = gen_lowpart (SImode, operands[0]);
436 operands[4] = gen_highpart (SImode, operands[1]);
437 operands[1] = gen_lowpart (SImode, operands[1]);
438 operands[2] = gen_lowpart (SImode, operands[2]);
439 }"
215b30b3 440 [(set_attr "conds" "clob")
441 (set_attr "length" "8")]
442)
9c08d1fa 443
a0f94409 444(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 445 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
446 (plus:DI (zero_extend:DI
97499065 447 (match_operand:SI 2 "s_register_operand" "r,r"))
448 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 449 (clobber (reg:CC CC_REGNUM))]
a2cd141b 450 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 451 "#"
a0f94409 452 "TARGET_ARM && reload_completed"
453 [(parallel [(set (reg:CC_C CC_REGNUM)
454 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
455 (match_dup 1)))
456 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
457 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
458 (plus:SI (match_dup 4) (const_int 0))))]
459 "
460 {
461 operands[3] = gen_highpart (SImode, operands[0]);
462 operands[0] = gen_lowpart (SImode, operands[0]);
463 operands[4] = gen_highpart (SImode, operands[1]);
464 operands[1] = gen_lowpart (SImode, operands[1]);
465 operands[2] = gen_lowpart (SImode, operands[2]);
466 }"
cffb2a26 467 [(set_attr "conds" "clob")
468 (set_attr "length" "8")]
469)
b11cae9e 470
87b22bf7 471(define_expand "addsi3"
cffb2a26 472 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 473 (plus:SI (match_operand:SI 1 "s_register_operand" "")
474 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 475 "TARGET_EITHER"
87b22bf7 476 "
cffb2a26 477 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 478 {
96f57e36 479 arm_split_constant (PLUS, SImode, NULL_RTX,
480 INTVAL (operands[2]), operands[0], operands[1],
615caa51 481 optimize && !no_new_pseudos);
87b22bf7 482 DONE;
483 }
cffb2a26 484 "
485)
87b22bf7 486
5bd751ff 487; If there is a scratch available, this will be faster than synthesizing the
a0f94409 488; addition.
489(define_peephole2
490 [(match_scratch:SI 3 "r")
372575c7 491 (set (match_operand:SI 0 "arm_general_register_operand" "")
492 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 493 (match_operand:SI 2 "const_int_operand" "")))]
494 "TARGET_ARM &&
a0f94409 495 !(const_ok_for_arm (INTVAL (operands[2]))
496 || const_ok_for_arm (-INTVAL (operands[2])))
497 && const_ok_for_arm (~INTVAL (operands[2]))"
498 [(set (match_dup 3) (match_dup 2))
499 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
500 ""
501)
87b22bf7 502
a0f94409 503(define_insn_and_split "*arm_addsi3"
cffb2a26 504 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
a0f94409 505 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
87b22bf7 506 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
cffb2a26 507 "TARGET_ARM"
5565501b 508 "@
509 add%?\\t%0, %1, %2
87b22bf7 510 sub%?\\t%0, %1, #%n2
511 #"
a0f94409 512 "TARGET_ARM &&
513 GET_CODE (operands[2]) == CONST_INT
514 && !(const_ok_for_arm (INTVAL (operands[2]))
515 || const_ok_for_arm (-INTVAL (operands[2])))"
516 [(clobber (const_int 0))]
517 "
96f57e36 518 arm_split_constant (PLUS, SImode, curr_insn,
519 INTVAL (operands[2]), operands[0],
a0f94409 520 operands[1], 0);
521 DONE;
522 "
0d66636f 523 [(set_attr "length" "4,4,16")
524 (set_attr "predicable" "yes")]
cffb2a26 525)
526
527;; Register group 'k' is a single register group containing only the stack
528;; register. Trying to reload it will always fail catastrophically,
529;; so never allow those alternatives to match if reloading is needed.
530
531(define_insn "*thumb_addsi3"
532 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
533 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
534 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
535 "TARGET_THUMB"
536 "*
0d66636f 537 static const char * const asms[] =
cffb2a26 538 {
539 \"add\\t%0, %0, %2\",
540 \"sub\\t%0, %0, #%n2\",
541 \"add\\t%0, %1, %2\",
542 \"add\\t%0, %0, %2\",
543 \"add\\t%0, %0, %2\",
544 \"add\\t%0, %1, %2\",
545 \"add\\t%0, %1, %2\"
546 };
547 if ((which_alternative == 2 || which_alternative == 6)
548 && GET_CODE (operands[2]) == CONST_INT
549 && INTVAL (operands[2]) < 0)
550 return \"sub\\t%0, %1, #%n2\";
551 return asms[which_alternative];
552 "
553 [(set_attr "length" "2")]
554)
555
556;; Reloading and elimination of the frame pointer can
557;; sometimes cause this optimization to be missed.
a0f94409 558(define_peephole2
372575c7 559 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 560 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 561 (set (match_dup 0)
372575c7 562 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
cffb2a26 563 "TARGET_THUMB
cffb2a26 564 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
565 && (INTVAL (operands[1]) & 3) == 0"
372575c7 566 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 567 ""
cffb2a26 568)
b11cae9e 569
f7fbdd4a 570(define_insn "*addsi3_compare0"
bd5b4116 571 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 572 (compare:CC_NOOV
215b30b3 573 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
574 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 575 (const_int 0)))
576 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 577 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 578 "TARGET_ARM"
5565501b 579 "@
580 add%?s\\t%0, %1, %2
581 sub%?s\\t%0, %1, #%n2"
cffb2a26 582 [(set_attr "conds" "set")]
583)
9c08d1fa 584
aea4c774 585(define_insn "*addsi3_compare0_scratch"
bd5b4116 586 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 587 (compare:CC_NOOV
215b30b3 588 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
589 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 590 (const_int 0)))]
cffb2a26 591 "TARGET_ARM"
592 "@
593 cmn%?\\t%0, %1
594 cmp%?\\t%0, #%n1"
0d66636f 595 [(set_attr "conds" "set")]
596)
cffb2a26 597
aed179ae 598(define_insn "*compare_negsi_si"
599 [(set (reg:CC_Z CC_REGNUM)
600 (compare:CC_Z
601 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
602 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 603 "TARGET_ARM"
aed179ae 604 "cmn%?\\t%1, %0"
0d66636f 605 [(set_attr "conds" "set")]
606)
aea4c774 607
203c488f 608;; This is the canonicalization of addsi3_compare0_for_combiner when the
609;; addend is a constant.
610(define_insn "*cmpsi2_addneg"
611 [(set (reg:CC CC_REGNUM)
612 (compare:CC
613 (match_operand:SI 1 "s_register_operand" "r,r")
614 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
615 (set (match_operand:SI 0 "s_register_operand" "=r,r")
616 (plus:SI (match_dup 1)
617 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
618 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
619 "@
620 sub%?s\\t%0, %1, %2
621 add%?s\\t%0, %1, #%n2"
622 [(set_attr "conds" "set")]
623)
624
625;; Convert the sequence
626;; sub rd, rn, #1
627;; cmn rd, #1 (equivalent to cmp rd, #-1)
628;; bne dest
629;; into
630;; subs rd, rn, #1
631;; bcs dest ((unsigned)rn >= 1)
632;; similarly for the beq variant using bcc.
633;; This is a common looping idiom (while (n--))
634(define_peephole2
372575c7 635 [(set (match_operand:SI 0 "arm_general_register_operand" "")
636 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 637 (const_int -1)))
638 (set (match_operand 2 "cc_register" "")
639 (compare (match_dup 0) (const_int -1)))
640 (set (pc)
641 (if_then_else (match_operator 3 "equality_operator"
642 [(match_dup 2) (const_int 0)])
643 (match_operand 4 "" "")
644 (match_operand 5 "" "")))]
645 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
646 [(parallel[
647 (set (match_dup 2)
648 (compare:CC
649 (match_dup 1) (const_int 1)))
650 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
651 (set (pc)
652 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
653 (match_dup 4)
654 (match_dup 5)))]
655 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
656 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
657 ? GEU : LTU),
658 VOIDmode,
659 operands[2], const0_rtx);"
660)
661
ebcc79bc 662;; The next four insns work because they compare the result with one of
663;; the operands, and we know that the use of the condition code is
664;; either GEU or LTU, so we can use the carry flag from the addition
665;; instead of doing the compare a second time.
666(define_insn "*addsi3_compare_op1"
bd5b4116 667 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 668 (compare:CC_C
669 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
670 (match_operand:SI 2 "arm_add_operand" "rI,L"))
671 (match_dup 1)))
672 (set (match_operand:SI 0 "s_register_operand" "=r,r")
673 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 674 "TARGET_ARM"
ebcc79bc 675 "@
676 add%?s\\t%0, %1, %2
677 sub%?s\\t%0, %1, #%n2"
0d66636f 678 [(set_attr "conds" "set")]
679)
ebcc79bc 680
681(define_insn "*addsi3_compare_op2"
bd5b4116 682 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 683 (compare:CC_C
684 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
685 (match_operand:SI 2 "arm_add_operand" "rI,L"))
686 (match_dup 2)))
5565501b 687 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 688 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 689 "TARGET_ARM"
5565501b 690 "@
691 add%?s\\t%0, %1, %2
692 sub%?s\\t%0, %1, #%n2"
0d66636f 693 [(set_attr "conds" "set")]
694)
9c08d1fa 695
ebcc79bc 696(define_insn "*compare_addsi2_op0"
bd5b4116 697 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 698 (compare:CC_C
699 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
700 (match_operand:SI 1 "arm_add_operand" "rI,L"))
701 (match_dup 0)))]
cffb2a26 702 "TARGET_ARM"
ebcc79bc 703 "@
704 cmn%?\\t%0, %1
705 cmp%?\\t%0, #%n1"
0d66636f 706 [(set_attr "conds" "set")]
707)
ebcc79bc 708
709(define_insn "*compare_addsi2_op1"
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 1)))]
cffb2a26 715 "TARGET_ARM"
ebcc79bc 716 "@
717 cmn%?\\t%0, %1
718 cmp%?\\t%0, #%n1"
0d66636f 719 [(set_attr "conds" "set")]
720)
ebcc79bc 721
722(define_insn "*addsi3_carryin"
723 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 724 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 725 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
726 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
cffb2a26 727 "TARGET_ARM"
ebcc79bc 728 "adc%?\\t%0, %1, %2"
cffb2a26 729 [(set_attr "conds" "use")]
730)
ebcc79bc 731
33782ec7 732(define_insn "*addsi3_carryin_shift"
7b63a8dd 733 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 734 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 735 (plus:SI
736 (match_operator:SI 2 "shift_operator"
7b63a8dd 737 [(match_operand:SI 3 "s_register_operand" "r")
738 (match_operand:SI 4 "reg_or_int_operand" "rM")])
739 (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 740 "TARGET_ARM"
33782ec7 741 "adc%?\\t%0, %1, %3%S2"
a2cd141b 742 [(set_attr "conds" "use")
743 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
744 (const_string "alu_shift")
745 (const_string "alu_shift_reg")))]
33782ec7 746)
747
ebcc79bc 748(define_insn "*addsi3_carryin_alt1"
749 [(set (match_operand:SI 0 "s_register_operand" "=r")
750 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
751 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 752 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
cffb2a26 753 "TARGET_ARM"
ebcc79bc 754 "adc%?\\t%0, %1, %2"
cffb2a26 755 [(set_attr "conds" "use")]
756)
ebcc79bc 757
758(define_insn "*addsi3_carryin_alt2"
759 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 760 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 761 (match_operand:SI 1 "s_register_operand" "r"))
762 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 763 "TARGET_ARM"
ebcc79bc 764 "adc%?\\t%0, %1, %2"
0d66636f 765 [(set_attr "conds" "use")]
766)
ebcc79bc 767
768(define_insn "*addsi3_carryin_alt3"
769 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 770 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 771 (match_operand:SI 2 "arm_rhs_operand" "rI"))
772 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 773 "TARGET_ARM"
ebcc79bc 774 "adc%?\\t%0, %1, %2"
cffb2a26 775 [(set_attr "conds" "use")]
776)
ebcc79bc 777
9c08d1fa 778(define_insn "incscc"
779 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 780 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 781 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 782 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 783 "TARGET_ARM"
5565501b 784 "@
785 add%d2\\t%0, %1, #1
786 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 787 [(set_attr "conds" "use")
215b30b3 788 (set_attr "length" "4,8")]
789)
9c08d1fa 790
d795fb69 791; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
792(define_split
793 [(set (match_operand:SI 0 "s_register_operand" "")
794 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
795 (match_operand:SI 2 "s_register_operand" ""))
796 (const_int -1)))
797 (clobber (match_operand:SI 3 "s_register_operand" ""))]
798 "TARGET_ARM"
799 [(set (match_dup 3) (match_dup 1))
800 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
801 "
802 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
803")
804
604f3a0a 805(define_expand "addsf3"
806 [(set (match_operand:SF 0 "s_register_operand" "")
807 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 808 (match_operand:SF 2 "arm_float_add_operand" "")))]
809 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 810 "
a2cd141b 811 if (TARGET_MAVERICK
604f3a0a 812 && !cirrus_fp_register (operands[2], SFmode))
813 operands[2] = force_reg (SFmode, operands[2]);
814")
815
604f3a0a 816(define_expand "adddf3"
817 [(set (match_operand:DF 0 "s_register_operand" "")
818 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 819 (match_operand:DF 2 "arm_float_add_operand" "")))]
820 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 821 "
a2cd141b 822 if (TARGET_MAVERICK
604f3a0a 823 && !cirrus_fp_register (operands[2], DFmode))
824 operands[2] = force_reg (DFmode, operands[2]);
825")
826
cffb2a26 827(define_expand "subdi3"
828 [(parallel
829 [(set (match_operand:DI 0 "s_register_operand" "")
830 (minus:DI (match_operand:DI 1 "s_register_operand" "")
831 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 832 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 833 "TARGET_EITHER"
834 "
a2cd141b 835 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
7d57ec45 836 && TARGET_ARM
837 && cirrus_fp_register (operands[0], DImode)
838 && cirrus_fp_register (operands[1], DImode))
839 {
840 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
841 DONE;
842 }
843
cffb2a26 844 if (TARGET_THUMB)
845 {
846 if (GET_CODE (operands[1]) != REG)
847 operands[1] = force_reg (SImode, operands[1]);
848 if (GET_CODE (operands[2]) != REG)
849 operands[2] = force_reg (SImode, operands[2]);
850 }
851 "
852)
853
854(define_insn "*arm_subdi3"
855 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 856 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
857 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 858 (clobber (reg:CC CC_REGNUM))]
cffb2a26 859 "TARGET_ARM"
97499065 860 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 861 [(set_attr "conds" "clob")
862 (set_attr "length" "8")]
863)
864
865(define_insn "*thumb_subdi3"
866 [(set (match_operand:DI 0 "register_operand" "=l")
867 (minus:DI (match_operand:DI 1 "register_operand" "0")
868 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 869 (clobber (reg:CC CC_REGNUM))]
cffb2a26 870 "TARGET_THUMB"
871 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
872 [(set_attr "length" "4")]
873)
9c08d1fa 874
f7fbdd4a 875(define_insn "*subdi_di_zesidi"
cffb2a26 876 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
877 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 878 (zero_extend:DI
cffb2a26 879 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 880 (clobber (reg:CC CC_REGNUM))]
cffb2a26 881 "TARGET_ARM"
97499065 882 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 883 [(set_attr "conds" "clob")
884 (set_attr "length" "8")]
885)
9c08d1fa 886
f7fbdd4a 887(define_insn "*subdi_di_sesidi"
cffb2a26 888 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
889 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 890 (sign_extend:DI
cffb2a26 891 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 892 (clobber (reg:CC CC_REGNUM))]
cffb2a26 893 "TARGET_ARM"
97499065 894 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 895 [(set_attr "conds" "clob")
896 (set_attr "length" "8")]
897)
9c08d1fa 898
f7fbdd4a 899(define_insn "*subdi_zesidi_di"
cffb2a26 900 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 901 (minus:DI (zero_extend:DI
cffb2a26 902 (match_operand:SI 2 "s_register_operand" "r,r"))
903 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 904 (clobber (reg:CC CC_REGNUM))]
cffb2a26 905 "TARGET_ARM"
97499065 906 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 907 [(set_attr "conds" "clob")
908 (set_attr "length" "8")]
909)
9c08d1fa 910
f7fbdd4a 911(define_insn "*subdi_sesidi_di"
cffb2a26 912 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 913 (minus:DI (sign_extend:DI
cffb2a26 914 (match_operand:SI 2 "s_register_operand" "r,r"))
915 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 916 (clobber (reg:CC CC_REGNUM))]
cffb2a26 917 "TARGET_ARM"
97499065 918 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 919 [(set_attr "conds" "clob")
920 (set_attr "length" "8")]
921)
9c08d1fa 922
f7fbdd4a 923(define_insn "*subdi_zesidi_zesidi"
cffb2a26 924 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 925 (minus:DI (zero_extend:DI
cffb2a26 926 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 927 (zero_extend:DI
cffb2a26 928 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 929 (clobber (reg:CC CC_REGNUM))]
cffb2a26 930 "TARGET_ARM"
97499065 931 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
cffb2a26 932 [(set_attr "conds" "clob")
933 (set_attr "length" "8")]
934)
b11cae9e 935
87b22bf7 936(define_expand "subsi3"
cffb2a26 937 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 938 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
939 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 940 "TARGET_EITHER"
87b22bf7 941 "
942 if (GET_CODE (operands[1]) == CONST_INT)
943 {
cffb2a26 944 if (TARGET_ARM)
945 {
96f57e36 946 arm_split_constant (MINUS, SImode, NULL_RTX,
947 INTVAL (operands[1]), operands[0],
615caa51 948 operands[2], optimize && !no_new_pseudos);
cffb2a26 949 DONE;
950 }
951 else /* TARGET_THUMB */
952 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 953 }
cffb2a26 954 "
955)
87b22bf7 956
cffb2a26 957(define_insn "*thumb_subsi3_insn"
958 [(set (match_operand:SI 0 "register_operand" "=l")
959 (minus:SI (match_operand:SI 1 "register_operand" "l")
960 (match_operand:SI 2 "register_operand" "l")))]
961 "TARGET_THUMB"
962 "sub\\t%0, %1, %2"
963 [(set_attr "length" "2")]
964)
965
a0f94409 966(define_insn_and_split "*arm_subsi3_insn"
cffb2a26 967 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 968 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
969 (match_operand:SI 2 "s_register_operand" "r,r")))]
cffb2a26 970 "TARGET_ARM"
e2348bcb 971 "@
87b22bf7 972 rsb%?\\t%0, %2, %1
973 #"
a0f94409 974 "TARGET_ARM
975 && GET_CODE (operands[1]) == CONST_INT
976 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 977 [(clobber (const_int 0))]
978 "
96f57e36 979 arm_split_constant (MINUS, SImode, curr_insn,
980 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 981 DONE;
cffb2a26 982 "
a0f94409 983 [(set_attr "length" "4,16")
984 (set_attr "predicable" "yes")]
985)
986
987(define_peephole2
988 [(match_scratch:SI 3 "r")
372575c7 989 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 990 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 991 (match_operand:SI 2 "arm_general_register_operand" "")))]
a0f94409 992 "TARGET_ARM
993 && !const_ok_for_arm (INTVAL (operands[1]))
994 && const_ok_for_arm (~INTVAL (operands[1]))"
995 [(set (match_dup 3) (match_dup 1))
996 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
997 ""
cffb2a26 998)
b11cae9e 999
f7fbdd4a 1000(define_insn "*subsi3_compare0"
bd5b4116 1001 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1002 (compare:CC_NOOV
1003 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1004 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1005 (const_int 0)))
9c08d1fa 1006 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1007 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1008 "TARGET_ARM"
e2348bcb 1009 "@
40dbec34 1010 sub%?s\\t%0, %1, %2
1011 rsb%?s\\t%0, %2, %1"
cffb2a26 1012 [(set_attr "conds" "set")]
1013)
9c08d1fa 1014
1015(define_insn "decscc"
cffb2a26 1016 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1017 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1018 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1019 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1020 "TARGET_ARM"
e2348bcb 1021 "@
215b30b3 1022 sub%d2\\t%0, %1, #1
1023 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1024 [(set_attr "conds" "use")
1025 (set_attr "length" "*,8")]
1026)
9c08d1fa 1027
604f3a0a 1028(define_expand "subsf3"
1029 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1030 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1031 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1032 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1033 "
a2cd141b 1034 if (TARGET_MAVERICK)
604f3a0a 1035 {
1036 if (!cirrus_fp_register (operands[1], SFmode))
1037 operands[1] = force_reg (SFmode, operands[1]);
1038 if (!cirrus_fp_register (operands[2], SFmode))
1039 operands[2] = force_reg (SFmode, operands[2]);
1040 }
1041")
1042
604f3a0a 1043(define_expand "subdf3"
1044 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1045 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1046 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1047 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1048 "
a2cd141b 1049 if (TARGET_MAVERICK)
604f3a0a 1050 {
1051 if (!cirrus_fp_register (operands[1], DFmode))
1052 operands[1] = force_reg (DFmode, operands[1]);
1053 if (!cirrus_fp_register (operands[2], DFmode))
1054 operands[2] = force_reg (DFmode, operands[2]);
1055 }
1056")
1057
b11cae9e 1058\f
1059;; Multiplication insns
1060
cffb2a26 1061(define_expand "mulsi3"
1062 [(set (match_operand:SI 0 "s_register_operand" "")
1063 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1064 (match_operand:SI 1 "s_register_operand" "")))]
1065 "TARGET_EITHER"
1066 ""
1067)
1068
9c08d1fa 1069;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1070(define_insn "*arm_mulsi3"
1071 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1072 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1073 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
cffb2a26 1074 "TARGET_ARM"
f7fbdd4a 1075 "mul%?\\t%0, %2, %1"
a2cd141b 1076 [(set_attr "insn" "mul")
0d66636f 1077 (set_attr "predicable" "yes")]
cffb2a26 1078)
1079
215b30b3 1080; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1081; 1 and 2; are the same, because reload will make operand 0 match
1082; operand 1 without realizing that this conflicts with operand 2. We fix
1083; this by adding another alternative to match this case, and then `reload'
1084; it ourselves. This alternative must come first.
cffb2a26 1085(define_insn "*thumb_mulsi3"
1086 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1087 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1088 (match_operand:SI 2 "register_operand" "l,l,l")))]
1089 "TARGET_THUMB"
1090 "*
1091 if (which_alternative < 2)
20c4e896 1092 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1093 else
20c4e896 1094 return \"mul\\t%0, %2\";
cffb2a26 1095 "
1096 [(set_attr "length" "4,4,2")
a2cd141b 1097 (set_attr "insn" "mul")]
cffb2a26 1098)
b11cae9e 1099
f7fbdd4a 1100(define_insn "*mulsi3_compare0"
bd5b4116 1101 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1102 (compare:CC_NOOV (mult:SI
1103 (match_operand:SI 2 "s_register_operand" "r,r")
1104 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1105 (const_int 0)))
1106 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1107 (mult:SI (match_dup 2) (match_dup 1)))]
e8a4aa75 1108 "TARGET_ARM"
40dbec34 1109 "mul%?s\\t%0, %2, %1"
cffb2a26 1110 [(set_attr "conds" "set")
a2cd141b 1111 (set_attr "insn" "muls")]
cffb2a26 1112)
9c08d1fa 1113
f7fbdd4a 1114(define_insn "*mulsi_compare0_scratch"
bd5b4116 1115 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1116 (compare:CC_NOOV (mult:SI
1117 (match_operand:SI 2 "s_register_operand" "r,r")
1118 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1119 (const_int 0)))
1120 (clobber (match_scratch:SI 0 "=&r,&r"))]
e8a4aa75 1121 "TARGET_ARM"
40dbec34 1122 "mul%?s\\t%0, %2, %1"
cffb2a26 1123 [(set_attr "conds" "set")
a2cd141b 1124 (set_attr "insn" "muls")]
cffb2a26 1125)
9c08d1fa 1126
b11cae9e 1127;; Unnamed templates to match MLA instruction.
1128
f7fbdd4a 1129(define_insn "*mulsi3addsi"
9c08d1fa 1130 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1131 (plus:SI
9c08d1fa 1132 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1133 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1134 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
cffb2a26 1135 "TARGET_ARM"
f7fbdd4a 1136 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1137 [(set_attr "insn" "mla")
0d66636f 1138 (set_attr "predicable" "yes")]
1139)
b11cae9e 1140
f7fbdd4a 1141(define_insn "*mulsi3addsi_compare0"
bd5b4116 1142 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1143 (compare:CC_NOOV
1144 (plus:SI (mult:SI
1145 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1146 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1147 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1148 (const_int 0)))
9c08d1fa 1149 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1150 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1151 (match_dup 3)))]
e8a4aa75 1152 "TARGET_ARM"
40dbec34 1153 "mla%?s\\t%0, %2, %1, %3"
0d66636f 1154 [(set_attr "conds" "set")
a2cd141b 1155 (set_attr "insn" "mlas")]
0d66636f 1156)
9c08d1fa 1157
f7fbdd4a 1158(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1159 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1160 (compare:CC_NOOV
1161 (plus:SI (mult:SI
1162 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1163 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1164 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1165 (const_int 0)))
9c08d1fa 1166 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
e8a4aa75 1167 "TARGET_ARM"
40dbec34 1168 "mla%?s\\t%0, %2, %1, %3"
cffb2a26 1169 [(set_attr "conds" "set")
a2cd141b 1170 (set_attr "insn" "mlas")]
cffb2a26 1171)
f7fbdd4a 1172
efee20da 1173;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1174
1175(define_insn "*mulsidi3adddi"
fe8dbf85 1176 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1177 (plus:DI
215b30b3 1178 (mult:DI
fe8dbf85 1179 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1180 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1181 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1182 "TARGET_ARM && arm_arch3m"
fe8dbf85 1183 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1184 [(set_attr "insn" "smlal")
0d66636f 1185 (set_attr "predicable" "yes")]
1186)
82b85d08 1187
f7fbdd4a 1188(define_insn "mulsidi3"
1189 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1190 (mult:DI
1191 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1192 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1193 "TARGET_ARM && arm_arch3m"
97499065 1194 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1195 [(set_attr "insn" "smull")
0d66636f 1196 (set_attr "predicable" "yes")]
1197)
f7fbdd4a 1198
1199(define_insn "umulsidi3"
1200 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1201 (mult:DI
1202 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1203 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1204 "TARGET_ARM && arm_arch3m"
97499065 1205 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1206 [(set_attr "insn" "umull")
0d66636f 1207 (set_attr "predicable" "yes")]
1208)
b11cae9e 1209
efee20da 1210;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1211
1212(define_insn "*umulsidi3adddi"
8ead09f9 1213 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1214 (plus:DI
215b30b3 1215 (mult:DI
fe8dbf85 1216 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1217 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1218 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1219 "TARGET_ARM && arm_arch3m"
fe8dbf85 1220 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1221 [(set_attr "insn" "umlal")
0d66636f 1222 (set_attr "predicable" "yes")]
1223)
82b85d08 1224
f082f1c4 1225(define_insn "smulsi3_highpart"
1226 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1227 (truncate:SI
1228 (lshiftrt:DI
215b30b3 1229 (mult:DI
1230 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1231 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1232 (const_int 32))))
1233 (clobber (match_scratch:SI 3 "=&r,&r"))]
a2cd141b 1234 "TARGET_ARM && arm_arch3m"
f082f1c4 1235 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1236 [(set_attr "insn" "smull")
0d66636f 1237 (set_attr "predicable" "yes")]
cffb2a26 1238)
f082f1c4 1239
1240(define_insn "umulsi3_highpart"
1241 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1242 (truncate:SI
1243 (lshiftrt:DI
215b30b3 1244 (mult:DI
1245 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1246 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1247 (const_int 32))))
1248 (clobber (match_scratch:SI 3 "=&r,&r"))]
a2cd141b 1249 "TARGET_ARM && arm_arch3m"
f082f1c4 1250 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1251 [(set_attr "insn" "umull")
0d66636f 1252 (set_attr "predicable" "yes")]
cffb2a26 1253)
f082f1c4 1254
331beb1a 1255(define_insn "mulhisi3"
1256 [(set (match_operand:SI 0 "s_register_operand" "=r")
1257 (mult:SI (sign_extend:SI
1258 (match_operand:HI 1 "s_register_operand" "%r"))
1259 (sign_extend:SI
1260 (match_operand:HI 2 "s_register_operand" "r"))))]
fec538d9 1261 "TARGET_ARM && arm_arch5e"
61a2d04c 1262 "smulbb%?\\t%0, %1, %2"
a2cd141b 1263 [(set_attr "insn" "smulxy")
fec538d9 1264 (set_attr "predicable" "yes")]
1265)
1266
1267(define_insn "*mulhisi3tb"
1268 [(set (match_operand:SI 0 "s_register_operand" "=r")
1269 (mult:SI (ashiftrt:SI
1270 (match_operand:SI 1 "s_register_operand" "r")
1271 (const_int 16))
1272 (sign_extend:SI
1273 (match_operand:HI 2 "s_register_operand" "r"))))]
1274 "TARGET_ARM && arm_arch5e"
1275 "smultb%?\\t%0, %1, %2"
a2cd141b 1276 [(set_attr "insn" "smulxy")
fec538d9 1277 (set_attr "predicable" "yes")]
1278)
1279
1280(define_insn "*mulhisi3bt"
1281 [(set (match_operand:SI 0 "s_register_operand" "=r")
1282 (mult:SI (sign_extend:SI
1283 (match_operand:HI 1 "s_register_operand" "r"))
1284 (ashiftrt:SI
1285 (match_operand:SI 2 "s_register_operand" "r")
1286 (const_int 16))))]
1287 "TARGET_ARM && arm_arch5e"
1288 "smulbt%?\\t%0, %1, %2"
a2cd141b 1289 [(set_attr "insn" "smulxy")
fec538d9 1290 (set_attr "predicable" "yes")]
1291)
1292
1293(define_insn "*mulhisi3tt"
1294 [(set (match_operand:SI 0 "s_register_operand" "=r")
1295 (mult:SI (ashiftrt:SI
1296 (match_operand:SI 1 "s_register_operand" "r")
1297 (const_int 16))
1298 (ashiftrt:SI
1299 (match_operand:SI 2 "s_register_operand" "r")
1300 (const_int 16))))]
1301 "TARGET_ARM && arm_arch5e"
1302 "smultt%?\\t%0, %1, %2"
a2cd141b 1303 [(set_attr "insn" "smulxy")
fec538d9 1304 (set_attr "predicable" "yes")]
331beb1a 1305)
1306
1307(define_insn "*mulhisi3addsi"
1308 [(set (match_operand:SI 0 "s_register_operand" "=r")
1309 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1310 (mult:SI (sign_extend:SI
1311 (match_operand:HI 2 "s_register_operand" "%r"))
1312 (sign_extend:SI
1313 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1314 "TARGET_ARM && arm_arch5e"
61a2d04c 1315 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1316 [(set_attr "insn" "smlaxy")
fec538d9 1317 (set_attr "predicable" "yes")]
331beb1a 1318)
1319
1320(define_insn "*mulhidi3adddi"
1321 [(set (match_operand:DI 0 "s_register_operand" "=r")
1322 (plus:DI
1323 (match_operand:DI 1 "s_register_operand" "0")
1324 (mult:DI (sign_extend:DI
1325 (match_operand:HI 2 "s_register_operand" "%r"))
1326 (sign_extend:DI
1327 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1328 "TARGET_ARM && arm_arch5e"
331beb1a 1329 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1330 [(set_attr "insn" "smlalxy")
fec538d9 1331 (set_attr "predicable" "yes")])
331beb1a 1332
604f3a0a 1333(define_expand "mulsf3"
1334 [(set (match_operand:SF 0 "s_register_operand" "")
1335 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1336 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1337 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1338 "
a2cd141b 1339 if (TARGET_MAVERICK
604f3a0a 1340 && !cirrus_fp_register (operands[2], SFmode))
1341 operands[2] = force_reg (SFmode, operands[2]);
1342")
1343
604f3a0a 1344(define_expand "muldf3"
1345 [(set (match_operand:DF 0 "s_register_operand" "")
1346 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1347 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1348 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1349 "
a2cd141b 1350 if (TARGET_MAVERICK
604f3a0a 1351 && !cirrus_fp_register (operands[2], DFmode))
1352 operands[2] = force_reg (DFmode, operands[2]);
1353")
b11cae9e 1354\f
1355;; Division insns
1356
7db9af5d 1357(define_expand "divsf3"
1358 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1359 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1360 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1361 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1362 "")
9c08d1fa 1363
7db9af5d 1364(define_expand "divdf3"
1365 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1366 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1367 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1368 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1369 "")
b11cae9e 1370\f
1371;; Modulo insns
1372
7db9af5d 1373(define_expand "modsf3"
1374 [(set (match_operand:SF 0 "s_register_operand" "")
1375 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1376 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1377 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1378 "")
9c08d1fa 1379
7db9af5d 1380(define_expand "moddf3"
1381 [(set (match_operand:DF 0 "s_register_operand" "")
1382 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1383 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1384 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1385 "")
b11cae9e 1386\f
1387;; Boolean and,ior,xor insns
1388
f6ebffac 1389;; Split up double word logical operations
1390
1391;; Split up simple DImode logical operations. Simply perform the logical
1392;; operation on the upper and lower halves of the registers.
1393(define_split
1394 [(set (match_operand:DI 0 "s_register_operand" "")
1395 (match_operator:DI 6 "logical_binary_operator"
1396 [(match_operand:DI 1 "s_register_operand" "")
1397 (match_operand:DI 2 "s_register_operand" "")]))]
755eb2b4 1398 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1399 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1400 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1401 "
215b30b3 1402 {
1403 operands[3] = gen_highpart (SImode, operands[0]);
1404 operands[0] = gen_lowpart (SImode, operands[0]);
1405 operands[4] = gen_highpart (SImode, operands[1]);
1406 operands[1] = gen_lowpart (SImode, operands[1]);
1407 operands[5] = gen_highpart (SImode, operands[2]);
1408 operands[2] = gen_lowpart (SImode, operands[2]);
1409 }"
1410)
f6ebffac 1411
f6ebffac 1412(define_split
1413 [(set (match_operand:DI 0 "s_register_operand" "")
1414 (match_operator:DI 6 "logical_binary_operator"
1415 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416 (match_operand:DI 1 "s_register_operand" "")]))]
cffb2a26 1417 "TARGET_ARM && reload_completed"
f6ebffac 1418 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1419 (set (match_dup 3) (match_op_dup:SI 6
1420 [(ashiftrt:SI (match_dup 2) (const_int 31))
1421 (match_dup 4)]))]
1422 "
215b30b3 1423 {
1424 operands[3] = gen_highpart (SImode, operands[0]);
1425 operands[0] = gen_lowpart (SImode, operands[0]);
1426 operands[4] = gen_highpart (SImode, operands[1]);
1427 operands[1] = gen_lowpart (SImode, operands[1]);
1428 operands[5] = gen_highpart (SImode, operands[2]);
1429 operands[2] = gen_lowpart (SImode, operands[2]);
1430 }"
1431)
f6ebffac 1432
f6ebffac 1433;; The zero extend of operand 2 means we can just copy the high part of
1434;; operand1 into operand0.
1435(define_split
1436 [(set (match_operand:DI 0 "s_register_operand" "")
1437 (ior:DI
1438 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1439 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1440 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1441 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1442 (set (match_dup 3) (match_dup 4))]
1443 "
215b30b3 1444 {
1445 operands[4] = gen_highpart (SImode, operands[1]);
1446 operands[3] = gen_highpart (SImode, operands[0]);
1447 operands[0] = gen_lowpart (SImode, operands[0]);
1448 operands[1] = gen_lowpart (SImode, operands[1]);
1449 }"
1450)
f6ebffac 1451
1452;; The zero extend of operand 2 means we can just copy the high part of
1453;; operand1 into operand0.
1454(define_split
1455 [(set (match_operand:DI 0 "s_register_operand" "")
1456 (xor:DI
1457 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1458 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1459 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1460 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1461 (set (match_dup 3) (match_dup 4))]
1462 "
215b30b3 1463 {
1464 operands[4] = gen_highpart (SImode, operands[1]);
1465 operands[3] = gen_highpart (SImode, operands[0]);
1466 operands[0] = gen_lowpart (SImode, operands[0]);
1467 operands[1] = gen_lowpart (SImode, operands[1]);
1468 }"
1469)
f6ebffac 1470
b11cae9e 1471(define_insn "anddi3"
cffb2a26 1472 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1473 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1474 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 1475 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 1476 "#"
215b30b3 1477 [(set_attr "length" "8")]
1478)
b11cae9e 1479
a0f94409 1480(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1481 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1482 (and:DI (zero_extend:DI
1483 (match_operand:SI 2 "s_register_operand" "r,r"))
1484 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 1485 "TARGET_ARM"
f6ebffac 1486 "#"
a0f94409 1487 "TARGET_ARM && reload_completed"
1488 ; The zero extend of operand 2 clears the high word of the output
1489 ; operand.
1490 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1491 (set (match_dup 3) (const_int 0))]
1492 "
1493 {
1494 operands[3] = gen_highpart (SImode, operands[0]);
1495 operands[0] = gen_lowpart (SImode, operands[0]);
1496 operands[1] = gen_lowpart (SImode, operands[1]);
1497 }"
215b30b3 1498 [(set_attr "length" "8")]
1499)
b11cae9e 1500
f7fbdd4a 1501(define_insn "*anddi_sesdi_di"
cffb2a26 1502 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1503 (and:DI (sign_extend:DI
1504 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1505 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1506 "TARGET_ARM"
f6ebffac 1507 "#"
cffb2a26 1508 [(set_attr "length" "8")]
1509)
b11cae9e 1510
87b22bf7 1511(define_expand "andsi3"
cffb2a26 1512 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1513 (and:SI (match_operand:SI 1 "s_register_operand" "")
1514 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1515 "TARGET_EITHER"
87b22bf7 1516 "
cffb2a26 1517 if (TARGET_ARM)
87b22bf7 1518 {
cffb2a26 1519 if (GET_CODE (operands[2]) == CONST_INT)
1520 {
96f57e36 1521 arm_split_constant (AND, SImode, NULL_RTX,
1522 INTVAL (operands[2]), operands[0],
615caa51 1523 operands[1], optimize && !no_new_pseudos);
1524
cffb2a26 1525 DONE;
1526 }
87b22bf7 1527 }
cffb2a26 1528 else /* TARGET_THUMB */
1529 {
1530 if (GET_CODE (operands[2]) != CONST_INT)
1531 operands[2] = force_reg (SImode, operands[2]);
1532 else
1533 {
1534 int i;
1535
215b30b3 1536 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1537 {
215b30b3 1538 operands[2] = force_reg (SImode,
1539 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1540
1541 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1542
1543 DONE;
1544 }
87b22bf7 1545
cffb2a26 1546 for (i = 9; i <= 31; i++)
1547 {
1548 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1549 {
1550 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1551 const0_rtx));
1552 DONE;
1553 }
215b30b3 1554 else if ((((HOST_WIDE_INT) 1) << i) - 1
1555 == ~INTVAL (operands[2]))
cffb2a26 1556 {
1557 rtx shift = GEN_INT (i);
1558 rtx reg = gen_reg_rtx (SImode);
1559
1560 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1561 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1562
1563 DONE;
1564 }
1565 }
1566
1567 operands[2] = force_reg (SImode, operands[2]);
1568 }
215b30b3 1569 }
1570 "
cffb2a26 1571)
1572
a0f94409 1573(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1574 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1575 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1576 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
cffb2a26 1577 "TARGET_ARM"
5565501b 1578 "@
1579 and%?\\t%0, %1, %2
87b22bf7 1580 bic%?\\t%0, %1, #%B2
1581 #"
a0f94409 1582 "TARGET_ARM
1583 && GET_CODE (operands[2]) == CONST_INT
1584 && !(const_ok_for_arm (INTVAL (operands[2]))
1585 || const_ok_for_arm (~INTVAL (operands[2])))"
1586 [(clobber (const_int 0))]
1587 "
96f57e36 1588 arm_split_constant (AND, SImode, curr_insn,
1589 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1590 DONE;
1591 "
0d66636f 1592 [(set_attr "length" "4,4,16")
1593 (set_attr "predicable" "yes")]
cffb2a26 1594)
1595
1596(define_insn "*thumb_andsi3_insn"
1597 [(set (match_operand:SI 0 "register_operand" "=l")
1598 (and:SI (match_operand:SI 1 "register_operand" "%0")
1599 (match_operand:SI 2 "register_operand" "l")))]
1600 "TARGET_THUMB"
1601 "and\\t%0, %0, %2"
1602 [(set_attr "length" "2")]
1603)
87b22bf7 1604
f7fbdd4a 1605(define_insn "*andsi3_compare0"
bd5b4116 1606 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1607 (compare:CC_NOOV
1608 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1609 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1610 (const_int 0)))
cffb2a26 1611 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 1612 (and:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1613 "TARGET_ARM"
5565501b 1614 "@
1615 and%?s\\t%0, %1, %2
1616 bic%?s\\t%0, %1, #%B2"
cffb2a26 1617 [(set_attr "conds" "set")]
1618)
9c08d1fa 1619
f7fbdd4a 1620(define_insn "*andsi3_compare0_scratch"
bd5b4116 1621 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1622 (compare:CC_NOOV
1623 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1624 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1625 (const_int 0)))
dd193d7c 1626 (clobber (match_scratch:SI 2 "=X,r"))]
cffb2a26 1627 "TARGET_ARM"
5565501b 1628 "@
1629 tst%?\\t%0, %1
dd193d7c 1630 bic%?s\\t%2, %0, #%B1"
0d66636f 1631 [(set_attr "conds" "set")]
1632)
9c08d1fa 1633
f7fbdd4a 1634(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 1635 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1636 (compare:CC_NOOV (zero_extract:SI
1637 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 1638 (match_operand 1 "const_int_operand" "n")
1639 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 1640 (const_int 0)))]
cffb2a26 1641 "TARGET_ARM
1642 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1643 && INTVAL (operands[1]) > 0
1644 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1645 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 1646 "*
5c49a439 1647 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1648 << INTVAL (operands[2]));
40dbec34 1649 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 1650 return \"\";
0d66636f 1651 "
1652 [(set_attr "conds" "set")]
1653)
9c08d1fa 1654
f4462328 1655(define_insn_and_split "*ne_zeroextractsi"
c4034607 1656 [(set (match_operand:SI 0 "s_register_operand" "=r")
1657 (ne:SI (zero_extract:SI
1658 (match_operand:SI 1 "s_register_operand" "r")
1659 (match_operand:SI 2 "const_int_operand" "n")
1660 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 1661 (const_int 0)))
1662 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1663 "TARGET_ARM
1664 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1665 && INTVAL (operands[2]) > 0
1666 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1667 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 1668 "#"
1669 "TARGET_ARM
1670 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1671 && INTVAL (operands[2]) > 0
1672 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1673 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1674 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1675 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1676 (const_int 0)))
1677 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1678 (set (match_dup 0)
1679 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1680 (match_dup 0) (const_int 1)))]
1681 "
1682 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1683 << INTVAL (operands[3]));
1684 "
1685 [(set_attr "conds" "clob")
1686 (set_attr "length" "8")]
1687)
1688
1689(define_insn_and_split "*ne_zeroextractsi_shifted"
1690 [(set (match_operand:SI 0 "s_register_operand" "=r")
1691 (ne:SI (zero_extract:SI
1692 (match_operand:SI 1 "s_register_operand" "r")
1693 (match_operand:SI 2 "const_int_operand" "n")
1694 (const_int 0))
1695 (const_int 0)))
1696 (clobber (reg:CC CC_REGNUM))]
1697 "TARGET_ARM"
1698 "#"
1699 "TARGET_ARM"
1700 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1701 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1702 (const_int 0)))
1703 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1704 (set (match_dup 0)
1705 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1706 (match_dup 0) (const_int 1)))]
1707 "
1708 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1709 "
1710 [(set_attr "conds" "clob")
1711 (set_attr "length" "8")]
1712)
1713
1714(define_insn_and_split "*ite_ne_zeroextractsi"
1715 [(set (match_operand:SI 0 "s_register_operand" "=r")
1716 (if_then_else:SI (ne (zero_extract:SI
1717 (match_operand:SI 1 "s_register_operand" "r")
1718 (match_operand:SI 2 "const_int_operand" "n")
1719 (match_operand:SI 3 "const_int_operand" "n"))
1720 (const_int 0))
1721 (match_operand:SI 4 "arm_not_operand" "rIK")
1722 (const_int 0)))
1723 (clobber (reg:CC CC_REGNUM))]
1724 "TARGET_ARM
1725 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1726 && INTVAL (operands[2]) > 0
1727 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1728 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1729 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1730 "#"
1731 "TARGET_ARM
1732 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1733 && INTVAL (operands[2]) > 0
1734 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1735 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1736 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1737 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1738 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1739 (const_int 0)))
1740 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1741 (set (match_dup 0)
1742 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1743 (match_dup 0) (match_dup 4)))]
1744 "
c4034607 1745 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 1746 << INTVAL (operands[3]));
1747 "
1748 [(set_attr "conds" "clob")
1749 (set_attr "length" "8")]
1750)
1751
1752(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1753 [(set (match_operand:SI 0 "s_register_operand" "=r")
1754 (if_then_else:SI (ne (zero_extract:SI
1755 (match_operand:SI 1 "s_register_operand" "r")
1756 (match_operand:SI 2 "const_int_operand" "n")
1757 (const_int 0))
1758 (const_int 0))
1759 (match_operand:SI 3 "arm_not_operand" "rIK")
1760 (const_int 0)))
1761 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 1762 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1763 "#"
f8d7bf2f 1764 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1765 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1766 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1767 (const_int 0)))
1768 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1769 (set (match_dup 0)
1770 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1771 (match_dup 0) (match_dup 3)))]
1772 "
1773 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 1774 "
1775 [(set_attr "conds" "clob")
215b30b3 1776 (set_attr "length" "8")]
1777)
9c08d1fa 1778
58d6528b 1779(define_split
1780 [(set (match_operand:SI 0 "s_register_operand" "")
1781 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1782 (match_operand:SI 2 "const_int_operand" "")
1783 (match_operand:SI 3 "const_int_operand" "")))
1784 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1785 "TARGET_THUMB"
1786 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1787 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1788 "{
1789 HOST_WIDE_INT temp = INTVAL (operands[2]);
1790
1791 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1792 operands[3] = GEN_INT (32 - temp);
1793 }"
1794)
1795
d7863cfe 1796(define_split
1797 [(set (match_operand:SI 0 "s_register_operand" "")
1798 (match_operator:SI 1 "shiftable_operator"
1799 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1800 (match_operand:SI 3 "const_int_operand" "")
1801 (match_operand:SI 4 "const_int_operand" ""))
1802 (match_operand:SI 5 "s_register_operand" "")]))
1803 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1804 "TARGET_ARM"
1805 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1806 (set (match_dup 0)
1807 (match_op_dup 1
1808 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1809 (match_dup 5)]))]
1810 "{
1811 HOST_WIDE_INT temp = INTVAL (operands[3]);
1812
1813 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1814 operands[4] = GEN_INT (32 - temp);
1815 }"
1816)
1817
58d6528b 1818(define_split
1819 [(set (match_operand:SI 0 "s_register_operand" "")
1820 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1821 (match_operand:SI 2 "const_int_operand" "")
1822 (match_operand:SI 3 "const_int_operand" "")))]
1823 "TARGET_THUMB"
1824 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1825 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1826 "{
1827 HOST_WIDE_INT temp = INTVAL (operands[2]);
1828
1829 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1830 operands[3] = GEN_INT (32 - temp);
1831 }"
1832)
1833
d7863cfe 1834(define_split
1835 [(set (match_operand:SI 0 "s_register_operand" "")
1836 (match_operator:SI 1 "shiftable_operator"
1837 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1838 (match_operand:SI 3 "const_int_operand" "")
1839 (match_operand:SI 4 "const_int_operand" ""))
1840 (match_operand:SI 5 "s_register_operand" "")]))
1841 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1842 "TARGET_ARM"
1843 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1844 (set (match_dup 0)
1845 (match_op_dup 1
1846 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1847 (match_dup 5)]))]
1848 "{
1849 HOST_WIDE_INT temp = INTVAL (operands[3]);
1850
1851 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1852 operands[4] = GEN_INT (32 - temp);
1853 }"
1854)
1855
a42059fd 1856;;; ??? This pattern is bogus. If operand3 has bits outside the range
1857;;; represented by the bitfield, then this will produce incorrect results.
1858;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 1859;;; which have a real bit-field insert instruction, the truncation happens
1860;;; in the bit-field insert instruction itself. Since arm does not have a
1861;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 1862;;; the value before we insert. This loses some of the advantage of having
1863;;; this insv pattern, so this pattern needs to be reevalutated.
1864
8a18b90c 1865(define_expand "insv"
1866 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1867 (match_operand:SI 1 "general_operand" "")
1868 (match_operand:SI 2 "general_operand" ""))
19335226 1869 (match_operand:SI 3 "reg_or_int_operand" ""))]
cffb2a26 1870 "TARGET_ARM"
8a18b90c 1871 "
215b30b3 1872 {
1873 int start_bit = INTVAL (operands[2]);
1874 int width = INTVAL (operands[1]);
1875 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1876 rtx target, subtarget;
1877
1878 target = operands[0];
1879 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1880 subreg as the final target. */
1881 if (GET_CODE (target) == SUBREG)
1882 {
1883 subtarget = gen_reg_rtx (SImode);
1884 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1885 < GET_MODE_SIZE (SImode))
1886 target = SUBREG_REG (target);
1887 }
1888 else
1889 subtarget = target;
8a18b90c 1890
215b30b3 1891 if (GET_CODE (operands[3]) == CONST_INT)
1892 {
1893 /* Since we are inserting a known constant, we may be able to
1894 reduce the number of bits that we have to clear so that
1895 the mask becomes simple. */
1896 /* ??? This code does not check to see if the new mask is actually
1897 simpler. It may not be. */
1898 rtx op1 = gen_reg_rtx (SImode);
1899 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1900 start of this pattern. */
1901 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1902 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1903
1904 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1905 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 1906 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 1907 }
1908 else if (start_bit == 0
1909 && !(const_ok_for_arm (mask)
1910 || const_ok_for_arm (~mask)))
1911 {
1912 /* A Trick, since we are setting the bottom bits in the word,
1913 we can shift operand[3] up, operand[0] down, OR them together
1914 and rotate the result back again. This takes 3 insns, and
5910bb95 1915 the third might be mergeable into another op. */
215b30b3 1916 /* The shift up copes with the possibility that operand[3] is
1917 wider than the bitfield. */
1918 rtx op0 = gen_reg_rtx (SImode);
1919 rtx op1 = gen_reg_rtx (SImode);
1920
1921 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1922 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1923 emit_insn (gen_iorsi3 (op1, op1, op0));
1924 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1925 }
1926 else if ((width + start_bit == 32)
1927 && !(const_ok_for_arm (mask)
1928 || const_ok_for_arm (~mask)))
1929 {
1930 /* Similar trick, but slightly less efficient. */
8a18b90c 1931
215b30b3 1932 rtx op0 = gen_reg_rtx (SImode);
1933 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 1934
215b30b3 1935 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1936 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1937 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1938 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1939 }
1940 else
1941 {
1942 rtx op0 = GEN_INT (mask);
1943 rtx op1 = gen_reg_rtx (SImode);
1944 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 1945
215b30b3 1946 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1947 {
1948 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1949
215b30b3 1950 emit_insn (gen_movsi (tmp, op0));
1951 op0 = tmp;
1952 }
8a18b90c 1953
215b30b3 1954 /* Mask out any bits in operand[3] that are not needed. */
1955 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 1956
215b30b3 1957 if (GET_CODE (op0) == CONST_INT
1958 && (const_ok_for_arm (mask << start_bit)
1959 || const_ok_for_arm (~(mask << start_bit))))
1960 {
1961 op0 = GEN_INT (~(mask << start_bit));
1962 emit_insn (gen_andsi3 (op2, operands[0], op0));
1963 }
1964 else
1965 {
1966 if (GET_CODE (op0) == CONST_INT)
1967 {
1968 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1969
215b30b3 1970 emit_insn (gen_movsi (tmp, op0));
1971 op0 = tmp;
1972 }
1973
1974 if (start_bit != 0)
1975 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 1976
215b30b3 1977 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1978 }
8a18b90c 1979
215b30b3 1980 if (start_bit != 0)
1981 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 1982
215b30b3 1983 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1984 }
f082f1c4 1985
215b30b3 1986 if (subtarget != target)
1987 {
1988 /* If TARGET is still a SUBREG, then it must be wider than a word,
1989 so we must be careful only to set the subword we were asked to. */
1990 if (GET_CODE (target) == SUBREG)
1991 emit_move_insn (target, subtarget);
1992 else
1993 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1994 }
8a18b90c 1995
215b30b3 1996 DONE;
1997 }"
1998)
8a18b90c 1999
215b30b3 2000; constants for op 2 will never be given to these patterns.
a0f94409 2001(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2002 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 2003 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2004 (match_operand:DI 2 "s_register_operand" "0,r")))]
cffb2a26 2005 "TARGET_ARM"
f6ebffac 2006 "#"
755eb2b4 2007 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2008 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2009 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2010 "
2011 {
2012 operands[3] = gen_highpart (SImode, operands[0]);
2013 operands[0] = gen_lowpart (SImode, operands[0]);
2014 operands[4] = gen_highpart (SImode, operands[1]);
2015 operands[1] = gen_lowpart (SImode, operands[1]);
2016 operands[5] = gen_highpart (SImode, operands[2]);
2017 operands[2] = gen_lowpart (SImode, operands[2]);
2018 }"
0d66636f 2019 [(set_attr "length" "8")
2020 (set_attr "predicable" "yes")]
2021)
9c08d1fa 2022
a0f94409 2023(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2024 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2025 (and:DI (not:DI (zero_extend:DI
2026 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2027 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2028 "TARGET_ARM"
e2348bcb 2029 "@
97499065 2030 bic%?\\t%Q0, %Q1, %2
f6ebffac 2031 #"
a0f94409 2032 ; (not (zero_extend ...)) allows us to just copy the high word from
2033 ; operand1 to operand0.
2034 "TARGET_ARM
2035 && reload_completed
2036 && operands[0] != operands[1]"
5a097f7d 2037 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2038 (set (match_dup 3) (match_dup 4))]
2039 "
2040 {
2041 operands[3] = gen_highpart (SImode, operands[0]);
2042 operands[0] = gen_lowpart (SImode, operands[0]);
2043 operands[4] = gen_highpart (SImode, operands[1]);
2044 operands[1] = gen_lowpart (SImode, operands[1]);
2045 }"
0d66636f 2046 [(set_attr "length" "4,8")
2047 (set_attr "predicable" "yes")]
2048)
9c08d1fa 2049
a0f94409 2050(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2051 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2052 (and:DI (not:DI (sign_extend:DI
2053 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2054 (match_operand:DI 1 "s_register_operand" "0,r")))]
cffb2a26 2055 "TARGET_ARM"
f6ebffac 2056 "#"
a0f94409 2057 "TARGET_ARM && reload_completed"
5a097f7d 2058 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2059 (set (match_dup 3) (and:SI (not:SI
2060 (ashiftrt:SI (match_dup 2) (const_int 31)))
2061 (match_dup 4)))]
2062 "
2063 {
2064 operands[3] = gen_highpart (SImode, operands[0]);
2065 operands[0] = gen_lowpart (SImode, operands[0]);
2066 operands[4] = gen_highpart (SImode, operands[1]);
2067 operands[1] = gen_lowpart (SImode, operands[1]);
2068 }"
0d66636f 2069 [(set_attr "length" "8")
2070 (set_attr "predicable" "yes")]
2071)
9c08d1fa 2072
8a18b90c 2073(define_insn "andsi_notsi_si"
9c08d1fa 2074 [(set (match_operand:SI 0 "s_register_operand" "=r")
2075 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2076 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2077 "TARGET_ARM"
0d66636f 2078 "bic%?\\t%0, %1, %2"
2079 [(set_attr "predicable" "yes")]
2080)
b11cae9e 2081
cffb2a26 2082(define_insn "bicsi3"
2083 [(set (match_operand:SI 0 "register_operand" "=l")
2084 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2085 (match_operand:SI 2 "register_operand" "0")))]
2086 "TARGET_THUMB"
2087 "bic\\t%0, %0, %1"
2088 [(set_attr "length" "2")]
2089)
2090
8a18b90c 2091(define_insn "andsi_not_shiftsi_si"
a2cd141b 2092 [(set (match_operand:SI 0 "s_register_operand" "=r")
2093 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2094 [(match_operand:SI 2 "s_register_operand" "r")
2095 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2096 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2097 "TARGET_ARM"
6c4c2133 2098 "bic%?\\t%0, %1, %2%S4"
344495ea 2099 [(set_attr "predicable" "yes")
331beb1a 2100 (set_attr "shift" "2")
a2cd141b 2101 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2102 (const_string "alu_shift")
2103 (const_string "alu_shift_reg")))]
6c4c2133 2104)
8a18b90c 2105
f7fbdd4a 2106(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2107 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2108 (compare:CC_NOOV
2109 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2110 (match_operand:SI 1 "s_register_operand" "r"))
2111 (const_int 0)))
9c08d1fa 2112 (set (match_operand:SI 0 "s_register_operand" "=r")
2113 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
cffb2a26 2114 "TARGET_ARM"
40dbec34 2115 "bic%?s\\t%0, %1, %2"
0d66636f 2116 [(set_attr "conds" "set")]
2117)
9c08d1fa 2118
f7fbdd4a 2119(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2120 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2121 (compare:CC_NOOV
2122 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2123 (match_operand:SI 1 "s_register_operand" "r"))
2124 (const_int 0)))
9c08d1fa 2125 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2126 "TARGET_ARM"
40dbec34 2127 "bic%?s\\t%0, %1, %2"
0d66636f 2128 [(set_attr "conds" "set")]
2129)
9c08d1fa 2130
2131(define_insn "iordi3"
cffb2a26 2132 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2133 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2134 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2135 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 2136 "#"
0d66636f 2137 [(set_attr "length" "8")
2138 (set_attr "predicable" "yes")]
cffb2a26 2139)
9c08d1fa 2140
f7fbdd4a 2141(define_insn "*iordi_zesidi_di"
9c08d1fa 2142 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2143 (ior:DI (zero_extend:DI
2144 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2145 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2146 "TARGET_ARM"
e2348bcb 2147 "@
97499065 2148 orr%?\\t%Q0, %Q1, %2
f6ebffac 2149 #"
0d66636f 2150 [(set_attr "length" "4,8")
2151 (set_attr "predicable" "yes")]
cffb2a26 2152)
9c08d1fa 2153
f7fbdd4a 2154(define_insn "*iordi_sesidi_di"
9c08d1fa 2155 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2156 (ior:DI (sign_extend:DI
2157 (match_operand:SI 2 "s_register_operand" "r,r"))
2158 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2159 "TARGET_ARM"
f6ebffac 2160 "#"
0d66636f 2161 [(set_attr "length" "8")
2162 (set_attr "predicable" "yes")]
cffb2a26 2163)
9c08d1fa 2164
87b22bf7 2165(define_expand "iorsi3"
cffb2a26 2166 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2167 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2168 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2169 "TARGET_EITHER"
87b22bf7 2170 "
2171 if (GET_CODE (operands[2]) == CONST_INT)
2172 {
cffb2a26 2173 if (TARGET_ARM)
2174 {
96f57e36 2175 arm_split_constant (IOR, SImode, NULL_RTX,
2176 INTVAL (operands[2]), operands[0], operands[1],
615caa51 2177 optimize && !no_new_pseudos);
cffb2a26 2178 DONE;
2179 }
2180 else /* TARGET_THUMB */
2181 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2182 }
cffb2a26 2183 "
2184)
87b22bf7 2185
a0f94409 2186(define_insn_and_split "*arm_iorsi3"
cffb2a26 2187 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2188 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2189 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
cffb2a26 2190 "TARGET_ARM"
87b22bf7 2191 "@
2192 orr%?\\t%0, %1, %2
2193 #"
a0f94409 2194 "TARGET_ARM
2195 && GET_CODE (operands[2]) == CONST_INT
2196 && !const_ok_for_arm (INTVAL (operands[2]))"
2197 [(clobber (const_int 0))]
2198 "
96f57e36 2199 arm_split_constant (IOR, SImode, curr_insn,
2200 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2201 DONE;
2202 "
0d66636f 2203 [(set_attr "length" "4,16")
2204 (set_attr "predicable" "yes")]
cffb2a26 2205)
2206
2207(define_insn "*thumb_iorsi3"
2208 [(set (match_operand:SI 0 "register_operand" "=l")
2209 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2210 (match_operand:SI 2 "register_operand" "l")))]
2211 "TARGET_THUMB"
2212 "orr\\t%0, %0, %2"
2213 [(set_attr "length" "2")]
2214)
9c08d1fa 2215
a0f94409 2216(define_peephole2
2217 [(match_scratch:SI 3 "r")
372575c7 2218 (set (match_operand:SI 0 "arm_general_register_operand" "")
2219 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2220 (match_operand:SI 2 "const_int_operand" "")))]
a0f94409 2221 "TARGET_ARM
2222 && !const_ok_for_arm (INTVAL (operands[2]))
2223 && const_ok_for_arm (~INTVAL (operands[2]))"
2224 [(set (match_dup 3) (match_dup 2))
2225 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2226 ""
215b30b3 2227)
a0f94409 2228
f7fbdd4a 2229(define_insn "*iorsi3_compare0"
bd5b4116 2230 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2231 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2233 (const_int 0)))
2234 (set (match_operand:SI 0 "s_register_operand" "=r")
2235 (ior:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2236 "TARGET_ARM"
40dbec34 2237 "orr%?s\\t%0, %1, %2"
cffb2a26 2238 [(set_attr "conds" "set")]
2239)
9c08d1fa 2240
f7fbdd4a 2241(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2242 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2243 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2244 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2245 (const_int 0)))
2246 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2247 "TARGET_ARM"
40dbec34 2248 "orr%?s\\t%0, %1, %2"
0d66636f 2249 [(set_attr "conds" "set")]
2250)
9c08d1fa 2251
2252(define_insn "xordi3"
cffb2a26 2253 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2254 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2255 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2256 "TARGET_ARM && !TARGET_IWMMXT"
f6ebffac 2257 "#"
0d66636f 2258 [(set_attr "length" "8")
2259 (set_attr "predicable" "yes")]
cffb2a26 2260)
9c08d1fa 2261
f7fbdd4a 2262(define_insn "*xordi_zesidi_di"
9c08d1fa 2263 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2264 (xor:DI (zero_extend:DI
2265 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2266 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2267 "TARGET_ARM"
e2348bcb 2268 "@
97499065 2269 eor%?\\t%Q0, %Q1, %2
f6ebffac 2270 #"
0d66636f 2271 [(set_attr "length" "4,8")
2272 (set_attr "predicable" "yes")]
cffb2a26 2273)
9c08d1fa 2274
f7fbdd4a 2275(define_insn "*xordi_sesidi_di"
9c08d1fa 2276 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2277 (xor:DI (sign_extend:DI
2278 (match_operand:SI 2 "s_register_operand" "r,r"))
2279 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2280 "TARGET_ARM"
f6ebffac 2281 "#"
0d66636f 2282 [(set_attr "length" "8")
2283 (set_attr "predicable" "yes")]
cffb2a26 2284)
9c08d1fa 2285
cffb2a26 2286(define_expand "xorsi3"
2287 [(set (match_operand:SI 0 "s_register_operand" "")
2288 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2289 (match_operand:SI 2 "arm_rhs_operand" "")))]
2290 "TARGET_EITHER"
2291 "if (TARGET_THUMB)
2292 if (GET_CODE (operands[2]) == CONST_INT)
2293 operands[2] = force_reg (SImode, operands[2]);
2294 "
2295)
2296
2297(define_insn "*arm_xorsi3"
2298 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2299 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2300 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 2301 "TARGET_ARM"
2302 "eor%?\\t%0, %1, %2"
0d66636f 2303 [(set_attr "predicable" "yes")]
cffb2a26 2304)
2305
2306(define_insn "*thumb_xorsi3"
2307 [(set (match_operand:SI 0 "register_operand" "=l")
2308 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2309 (match_operand:SI 2 "register_operand" "l")))]
2310 "TARGET_THUMB"
2311 "eor\\t%0, %0, %2"
2312 [(set_attr "length" "2")]
2313)
9c08d1fa 2314
f7fbdd4a 2315(define_insn "*xorsi3_compare0"
bd5b4116 2316 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2317 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2318 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2319 (const_int 0)))
2320 (set (match_operand:SI 0 "s_register_operand" "=r")
2321 (xor:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2322 "TARGET_ARM"
40dbec34 2323 "eor%?s\\t%0, %1, %2"
0d66636f 2324 [(set_attr "conds" "set")]
2325)
9c08d1fa 2326
f7fbdd4a 2327(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2328 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2329 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2330 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2331 (const_int 0)))]
cffb2a26 2332 "TARGET_ARM"
40dbec34 2333 "teq%?\\t%0, %1"
cffb2a26 2334 [(set_attr "conds" "set")]
2335)
9c08d1fa 2336
215b30b3 2337; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2338; (NOT D) we can sometimes merge the final NOT into one of the following
2339; insns.
9c08d1fa 2340
2341(define_split
a058e94a 2342 [(set (match_operand:SI 0 "s_register_operand" "")
2343 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2344 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2345 (match_operand:SI 3 "arm_rhs_operand" "")))
2346 (clobber (match_operand:SI 4 "s_register_operand" ""))]
cffb2a26 2347 "TARGET_ARM"
9c08d1fa 2348 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2349 (not:SI (match_dup 3))))
2350 (set (match_dup 0) (not:SI (match_dup 4)))]
2351 ""
2352)
2353
f7fbdd4a 2354(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2355 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2356 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2357 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2358 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
cffb2a26 2359 "TARGET_ARM"
40dbec34 2360 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2361 [(set_attr "length" "8")
2362 (set_attr "predicable" "yes")]
cffb2a26 2363)
9c08d1fa 2364
d7863cfe 2365(define_split
2366 [(set (match_operand:SI 0 "s_register_operand" "")
2367 (match_operator:SI 1 "logical_binary_operator"
2368 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2369 (match_operand:SI 3 "const_int_operand" "")
2370 (match_operand:SI 4 "const_int_operand" ""))
2371 (match_operator:SI 9 "logical_binary_operator"
2372 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2373 (match_operand:SI 6 "const_int_operand" ""))
2374 (match_operand:SI 7 "s_register_operand" "")])]))
2375 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2376 "TARGET_ARM
2377 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2378 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2379 [(set (match_dup 8)
2380 (match_op_dup 1
2381 [(ashift:SI (match_dup 2) (match_dup 4))
2382 (match_dup 5)]))
2383 (set (match_dup 0)
2384 (match_op_dup 1
2385 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2386 (match_dup 7)]))]
2387 "
2388 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2389")
2390
2391(define_split
2392 [(set (match_operand:SI 0 "s_register_operand" "")
2393 (match_operator:SI 1 "logical_binary_operator"
2394 [(match_operator:SI 9 "logical_binary_operator"
2395 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2396 (match_operand:SI 6 "const_int_operand" ""))
2397 (match_operand:SI 7 "s_register_operand" "")])
2398 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2399 (match_operand:SI 3 "const_int_operand" "")
2400 (match_operand:SI 4 "const_int_operand" ""))]))
2401 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2402 "TARGET_ARM
2403 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2404 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2405 [(set (match_dup 8)
2406 (match_op_dup 1
2407 [(ashift:SI (match_dup 2) (match_dup 4))
2408 (match_dup 5)]))
2409 (set (match_dup 0)
2410 (match_op_dup 1
2411 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2412 (match_dup 7)]))]
2413 "
2414 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2415")
2416
2417(define_split
2418 [(set (match_operand:SI 0 "s_register_operand" "")
2419 (match_operator:SI 1 "logical_binary_operator"
2420 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2421 (match_operand:SI 3 "const_int_operand" "")
2422 (match_operand:SI 4 "const_int_operand" ""))
2423 (match_operator:SI 9 "logical_binary_operator"
2424 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2425 (match_operand:SI 6 "const_int_operand" ""))
2426 (match_operand:SI 7 "s_register_operand" "")])]))
2427 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2428 "TARGET_ARM
2429 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2430 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2431 [(set (match_dup 8)
2432 (match_op_dup 1
2433 [(ashift:SI (match_dup 2) (match_dup 4))
2434 (match_dup 5)]))
2435 (set (match_dup 0)
2436 (match_op_dup 1
2437 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2438 (match_dup 7)]))]
2439 "
2440 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2441")
2442
2443(define_split
2444 [(set (match_operand:SI 0 "s_register_operand" "")
2445 (match_operator:SI 1 "logical_binary_operator"
2446 [(match_operator:SI 9 "logical_binary_operator"
2447 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2448 (match_operand:SI 6 "const_int_operand" ""))
2449 (match_operand:SI 7 "s_register_operand" "")])
2450 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2451 (match_operand:SI 3 "const_int_operand" "")
2452 (match_operand:SI 4 "const_int_operand" ""))]))
2453 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2454 "TARGET_ARM
2455 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2456 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2457 [(set (match_dup 8)
2458 (match_op_dup 1
2459 [(ashift:SI (match_dup 2) (match_dup 4))
2460 (match_dup 5)]))
2461 (set (match_dup 0)
2462 (match_op_dup 1
2463 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2464 (match_dup 7)]))]
2465 "
2466 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2467")
9c08d1fa 2468\f
2469
2470;; Minimum and maximum insns
2471
2472(define_insn "smaxsi3"
cffb2a26 2473 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2474 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2475 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2476 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2477 "TARGET_ARM"
e2348bcb 2478 "@
2479 cmp\\t%1, %2\;movlt\\t%0, %2
2480 cmp\\t%1, %2\;movge\\t%0, %1
2481 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2482 [(set_attr "conds" "clob")
2483 (set_attr "length" "8,8,12")]
2484)
9c08d1fa 2485
2486(define_insn "sminsi3"
2487 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2488 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2489 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2490 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2491 "TARGET_ARM"
e2348bcb 2492 "@
2493 cmp\\t%1, %2\;movge\\t%0, %2
2494 cmp\\t%1, %2\;movlt\\t%0, %1
2495 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 2496 [(set_attr "conds" "clob")
2497 (set_attr "length" "8,8,12")]
2498)
9c08d1fa 2499
2500(define_insn "umaxsi3"
2501 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2502 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2503 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2504 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2505 "TARGET_ARM"
e2348bcb 2506 "@
2507 cmp\\t%1, %2\;movcc\\t%0, %2
2508 cmp\\t%1, %2\;movcs\\t%0, %1
2509 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 2510 [(set_attr "conds" "clob")
2511 (set_attr "length" "8,8,12")]
2512)
9c08d1fa 2513
2514(define_insn "uminsi3"
2515 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2516 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2517 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2518 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2519 "TARGET_ARM"
e2348bcb 2520 "@
2521 cmp\\t%1, %2\;movcs\\t%0, %2
2522 cmp\\t%1, %2\;movcc\\t%0, %1
2523 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 2524 [(set_attr "conds" "clob")
2525 (set_attr "length" "8,8,12")]
2526)
9c08d1fa 2527
8a18b90c 2528(define_insn "*store_minmaxsi"
9c08d1fa 2529 [(set (match_operand:SI 0 "memory_operand" "=m")
2530 (match_operator:SI 3 "minmax_operator"
2531 [(match_operand:SI 1 "s_register_operand" "r")
2532 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 2533 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2534 "TARGET_ARM"
9c08d1fa 2535 "*
dc55b8a9 2536 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2537 operands[1], operands[2]);
e2348bcb 2538 output_asm_insn (\"cmp\\t%1, %2\", operands);
2539 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2540 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2541 return \"\";
0d66636f 2542 "
2543 [(set_attr "conds" "clob")
2544 (set_attr "length" "12")
2545 (set_attr "type" "store1")]
2546)
9c08d1fa 2547
8a18b90c 2548; Reject the frame pointer in operand[1], since reloading this after
2549; it has been eliminated can cause carnage.
f7fbdd4a 2550(define_insn "*minmax_arithsi"
9c08d1fa 2551 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2552 (match_operator:SI 4 "shiftable_operator"
2553 [(match_operator:SI 5 "minmax_operator"
2554 [(match_operand:SI 2 "s_register_operand" "r,r")
2555 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2556 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 2557 (clobber (reg:CC CC_REGNUM))]
da45ccee 2558 "TARGET_ARM && !arm_eliminable_register (operands[1])"
9c08d1fa 2559 "*
0d66636f 2560 {
2561 enum rtx_code code = GET_CODE (operands[4]);
2562
dc55b8a9 2563 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2564 operands[2], operands[3]);
0d66636f 2565 output_asm_insn (\"cmp\\t%2, %3\", operands);
2566 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2567 if (which_alternative != 0 || operands[3] != const0_rtx
2568 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2569 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2570 return \"\";
215b30b3 2571 }"
0d66636f 2572 [(set_attr "conds" "clob")
2573 (set_attr "length" "12")]
2574)
9c08d1fa 2575
b11cae9e 2576\f
2577;; Shift and rotation insns
2578
a2cd141b 2579(define_expand "ashldi3"
2580 [(set (match_operand:DI 0 "s_register_operand" "")
2581 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2582 (match_operand:SI 2 "reg_or_int_operand" "")))]
2583 "TARGET_ARM"
2584 "
2585 if (GET_CODE (operands[2]) == CONST_INT)
2586 {
2587 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2588 {
2589 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2590 DONE;
2591 }
2592 /* Ideally we shouldn't fail here if we could know that operands[1]
2593 ends up already living in an iwmmxt register. Otherwise it's
2594 cheaper to have the alternate code being generated than moving
1d60d981 2595 values to iwmmxt regs and back. */
a2cd141b 2596 FAIL;
2597 }
2598 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2599 FAIL;
2600 "
2601)
2602
2603(define_insn "arm_ashldi3_1bit"
2604 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2605 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2606 (const_int 1)))
2607 (clobber (reg:CC CC_REGNUM))]
2608 "TARGET_ARM"
2609 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2610 [(set_attr "conds" "clob")
2611 (set_attr "length" "8")]
2612)
2613
87b22bf7 2614(define_expand "ashlsi3"
cffb2a26 2615 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2616 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2617 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2618 "TARGET_EITHER"
87b22bf7 2619 "
2620 if (GET_CODE (operands[2]) == CONST_INT
2621 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2622 {
2623 emit_insn (gen_movsi (operands[0], const0_rtx));
2624 DONE;
2625 }
cffb2a26 2626 "
2627)
2628
2629(define_insn "*thumb_ashlsi3"
2630 [(set (match_operand:SI 0 "register_operand" "=l,l")
2631 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2632 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2633 "TARGET_THUMB"
2634 "lsl\\t%0, %1, %2"
2635 [(set_attr "length" "2")]
2636)
b11cae9e 2637
a2cd141b 2638(define_expand "ashrdi3"
2639 [(set (match_operand:DI 0 "s_register_operand" "")
2640 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2641 (match_operand:SI 2 "reg_or_int_operand" "")))]
2642 "TARGET_ARM"
2643 "
2644 if (GET_CODE (operands[2]) == CONST_INT)
2645 {
2646 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2647 {
2648 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2649 DONE;
2650 }
2651 /* Ideally we shouldn't fail here if we could know that operands[1]
2652 ends up already living in an iwmmxt register. Otherwise it's
2653 cheaper to have the alternate code being generated than moving
1d60d981 2654 values to iwmmxt regs and back. */
a2cd141b 2655 FAIL;
2656 }
2657 else if (!TARGET_REALLY_IWMMXT)
2658 FAIL;
2659 "
2660)
2661
2662(define_insn "arm_ashrdi3_1bit"
2663 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2664 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2665 (const_int 1)))
2666 (clobber (reg:CC CC_REGNUM))]
2667 "TARGET_ARM"
2668 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2669 [(set_attr "conds" "clob")
2670 (set_attr "length" "8")]
2671)
2672
87b22bf7 2673(define_expand "ashrsi3"
cffb2a26 2674 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2675 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2676 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2677 "TARGET_EITHER"
87b22bf7 2678 "
2679 if (GET_CODE (operands[2]) == CONST_INT
2680 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2681 operands[2] = GEN_INT (31);
cffb2a26 2682 "
2683)
2684
2685(define_insn "*thumb_ashrsi3"
2686 [(set (match_operand:SI 0 "register_operand" "=l,l")
2687 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2688 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2689 "TARGET_THUMB"
2690 "asr\\t%0, %1, %2"
2691 [(set_attr "length" "2")]
2692)
b11cae9e 2693
a2cd141b 2694(define_expand "lshrdi3"
2695 [(set (match_operand:DI 0 "s_register_operand" "")
2696 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2697 (match_operand:SI 2 "reg_or_int_operand" "")))]
2698 "TARGET_ARM"
2699 "
2700 if (GET_CODE (operands[2]) == CONST_INT)
2701 {
2702 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2703 {
2704 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2705 DONE;
2706 }
2707 /* Ideally we shouldn't fail here if we could know that operands[1]
2708 ends up already living in an iwmmxt register. Otherwise it's
2709 cheaper to have the alternate code being generated than moving
1d60d981 2710 values to iwmmxt regs and back. */
a2cd141b 2711 FAIL;
2712 }
2713 else if (!TARGET_REALLY_IWMMXT)
2714 FAIL;
2715 "
2716)
2717
2718(define_insn "arm_lshrdi3_1bit"
2719 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2720 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2721 (const_int 1)))
2722 (clobber (reg:CC CC_REGNUM))]
2723 "TARGET_ARM"
2724 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2725 [(set_attr "conds" "clob")
2726 (set_attr "length" "8")]
2727)
2728
87b22bf7 2729(define_expand "lshrsi3"
cffb2a26 2730 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2731 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2732 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2733 "TARGET_EITHER"
87b22bf7 2734 "
2735 if (GET_CODE (operands[2]) == CONST_INT
2736 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2737 {
2738 emit_insn (gen_movsi (operands[0], const0_rtx));
2739 DONE;
2740 }
cffb2a26 2741 "
2742)
2743
2744(define_insn "*thumb_lshrsi3"
2745 [(set (match_operand:SI 0 "register_operand" "=l,l")
2746 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2747 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2748 "TARGET_THUMB"
2749 "lsr\\t%0, %1, %2"
2750 [(set_attr "length" "2")]
2751)
b11cae9e 2752
87b22bf7 2753(define_expand "rotlsi3"
cffb2a26 2754 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2755 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2756 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2757 "TARGET_ARM"
87b22bf7 2758 "
2759 if (GET_CODE (operands[2]) == CONST_INT)
2760 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2761 else
b11cae9e 2762 {
87b22bf7 2763 rtx reg = gen_reg_rtx (SImode);
2764 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2765 operands[2] = reg;
b11cae9e 2766 }
cffb2a26 2767 "
2768)
9c08d1fa 2769
87b22bf7 2770(define_expand "rotrsi3"
cffb2a26 2771 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2772 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2773 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2774 "TARGET_EITHER"
87b22bf7 2775 "
cffb2a26 2776 if (TARGET_ARM)
2777 {
2778 if (GET_CODE (operands[2]) == CONST_INT
2779 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2780 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2781 }
2782 else /* TARGET_THUMB */
2783 {
2784 if (GET_CODE (operands [2]) == CONST_INT)
2785 operands [2] = force_reg (SImode, operands[2]);
2786 }
2787 "
2788)
87b22bf7 2789
cffb2a26 2790(define_insn "*thumb_rotrsi3"
2791 [(set (match_operand:SI 0 "register_operand" "=l")
2792 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2793 (match_operand:SI 2 "register_operand" "l")))]
2794 "TARGET_THUMB"
2795 "ror\\t%0, %0, %2"
2796 [(set_attr "length" "2")]
2797)
2798
2799(define_insn "*arm_shiftsi3"
2800 [(set (match_operand:SI 0 "s_register_operand" "=r")
2801 (match_operator:SI 3 "shift_operator"
2802 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 2803 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
cffb2a26 2804 "TARGET_ARM"
6c4c2133 2805 "mov%?\\t%0, %1%S3"
344495ea 2806 [(set_attr "predicable" "yes")
331beb1a 2807 (set_attr "shift" "1")
a2cd141b 2808 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2809 (const_string "alu_shift")
2810 (const_string "alu_shift_reg")))]
6c4c2133 2811)
87b22bf7 2812
f7fbdd4a 2813(define_insn "*shiftsi3_compare0"
bd5b4116 2814 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2815 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2816 [(match_operand:SI 1 "s_register_operand" "r")
2817 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2818 (const_int 0)))
2819 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2820 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
cffb2a26 2821 "TARGET_ARM"
87b22bf7 2822 "mov%?s\\t%0, %1%S3"
344495ea 2823 [(set_attr "conds" "set")
331beb1a 2824 (set_attr "shift" "1")
a2cd141b 2825 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2826 (const_string "alu_shift")
2827 (const_string "alu_shift_reg")))]
0d66636f 2828)
9c08d1fa 2829
f7fbdd4a 2830(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 2831 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2832 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2833 [(match_operand:SI 1 "s_register_operand" "r")
2834 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2835 (const_int 0)))
2836 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2837 "TARGET_ARM"
87b22bf7 2838 "mov%?s\\t%0, %1%S3"
344495ea 2839 [(set_attr "conds" "set")
a2cd141b 2840 (set_attr "shift" "1")]
0d66636f 2841)
9c08d1fa 2842
f7fbdd4a 2843(define_insn "*notsi_shiftsi"
9c08d1fa 2844 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2845 (not:SI (match_operator:SI 3 "shift_operator"
2846 [(match_operand:SI 1 "s_register_operand" "r")
2847 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 2848 "TARGET_ARM"
6c4c2133 2849 "mvn%?\\t%0, %1%S3"
344495ea 2850 [(set_attr "predicable" "yes")
331beb1a 2851 (set_attr "shift" "1")
a2cd141b 2852 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2853 (const_string "alu_shift")
2854 (const_string "alu_shift_reg")))]
0d66636f 2855)
9c08d1fa 2856
f7fbdd4a 2857(define_insn "*notsi_shiftsi_compare0"
bd5b4116 2858 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2859 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2860 [(match_operand:SI 1 "s_register_operand" "r")
2861 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2862 (const_int 0)))
2863 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2864 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 2865 "TARGET_ARM"
87b22bf7 2866 "mvn%?s\\t%0, %1%S3"
344495ea 2867 [(set_attr "conds" "set")
331beb1a 2868 (set_attr "shift" "1")
a2cd141b 2869 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2870 (const_string "alu_shift")
2871 (const_string "alu_shift_reg")))]
0d66636f 2872)
9c08d1fa 2873
f7fbdd4a 2874(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 2875 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2876 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2877 [(match_operand:SI 1 "s_register_operand" "r")
2878 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2879 (const_int 0)))
2880 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2881 "TARGET_ARM"
87b22bf7 2882 "mvn%?s\\t%0, %1%S3"
344495ea 2883 [(set_attr "conds" "set")
331beb1a 2884 (set_attr "shift" "1")
a2cd141b 2885 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2886 (const_string "alu_shift")
2887 (const_string "alu_shift_reg")))]
0d66636f 2888)
9c08d1fa 2889
cffb2a26 2890;; We don't really have extzv, but defining this using shifts helps
2891;; to reduce register pressure later on.
2892
2893(define_expand "extzv"
2894 [(set (match_dup 4)
2895 (ashift:SI (match_operand:SI 1 "register_operand" "")
2896 (match_operand:SI 2 "const_int_operand" "")))
2897 (set (match_operand:SI 0 "register_operand" "")
2898 (lshiftrt:SI (match_dup 4)
215b30b3 2899 (match_operand:SI 3 "const_int_operand" "")))]
cffb2a26 2900 "TARGET_THUMB"
2901 "
2902 {
2903 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2904 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2905
2906 operands[3] = GEN_INT (rshift);
2907
2908 if (lshift == 0)
2909 {
2910 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2911 DONE;
2912 }
2913
2914 operands[2] = GEN_INT (lshift);
2915 operands[4] = gen_reg_rtx (SImode);
215b30b3 2916 }"
cffb2a26 2917)
2918
b11cae9e 2919\f
2920;; Unary arithmetic insns
2921
cffb2a26 2922(define_expand "negdi2"
2923 [(parallel
2924 [(set (match_operand:DI 0 "s_register_operand" "")
2925 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 2926 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 2927 "TARGET_EITHER"
2928 "
2929 if (TARGET_THUMB)
2930 {
2931 if (GET_CODE (operands[1]) != REG)
2932 operands[1] = force_reg (SImode, operands[1]);
2933 }
215b30b3 2934 "
cffb2a26 2935)
2936
2937;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2938;; The second alternative is to allow the common case of a *full* overlap.
2939(define_insn "*arm_negdi2"
2940 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2941 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 2942 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2943 "TARGET_ARM"
97499065 2944 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 2945 [(set_attr "conds" "clob")
2946 (set_attr "length" "8")]
2947)
b11cae9e 2948
cffb2a26 2949(define_insn "*thumb_negdi2"
2950 [(set (match_operand:DI 0 "register_operand" "=&l")
2951 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 2952 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2953 "TARGET_THUMB"
2954 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2955 [(set_attr "length" "6")]
2956)
2957
2958(define_expand "negsi2"
2959 [(set (match_operand:SI 0 "s_register_operand" "")
2960 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2961 "TARGET_EITHER"
b11cae9e 2962 ""
cffb2a26 2963)
2964
2965(define_insn "*arm_negsi2"
2966 [(set (match_operand:SI 0 "s_register_operand" "=r")
2967 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2968 "TARGET_ARM"
2969 "rsb%?\\t%0, %1, #0"
0d66636f 2970 [(set_attr "predicable" "yes")]
cffb2a26 2971)
2972
2973(define_insn "*thumb_negsi2"
2974 [(set (match_operand:SI 0 "register_operand" "=l")
2975 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2976 "TARGET_THUMB"
2977 "neg\\t%0, %1"
2978 [(set_attr "length" "2")]
2979)
b11cae9e 2980
604f3a0a 2981(define_expand "negsf2"
2982 [(set (match_operand:SF 0 "s_register_operand" "")
2983 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
890ab29e 2984 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 2985 ""
2986)
2987
2988(define_expand "negdf2"
2989 [(set (match_operand:DF 0 "s_register_operand" "")
2990 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
890ab29e 2991 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 2992 "")
2993
9c08d1fa 2994;; abssi2 doesn't really clobber the condition codes if a different register
2995;; is being set. To keep things simple, assume during rtl manipulations that
2996;; it does, but tell the final scan operator the truth. Similarly for
2997;; (neg (abs...))
2998
604f3a0a 2999(define_expand "abssi2"
3000 [(parallel
3001 [(set (match_operand:SI 0 "s_register_operand" "")
3002 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3003 (clobber (reg:CC CC_REGNUM))])]
3004 "TARGET_ARM"
3005 "")
3006
7d57ec45 3007(define_insn "*arm_abssi2"
722f9800 3008 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3009 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3010 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3011 "TARGET_ARM"
e2348bcb 3012 "@
3013 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3014 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3015 [(set_attr "conds" "clob,*")
331beb1a 3016 (set_attr "shift" "1")
0d66636f 3017 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3018 (set_attr "length" "8")]
3019)
9c08d1fa 3020
f7fbdd4a 3021(define_insn "*neg_abssi2"
9c08d1fa 3022 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3023 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3024 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3025 "TARGET_ARM"
e2348bcb 3026 "@
3027 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3028 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3029 [(set_attr "conds" "clob,*")
331beb1a 3030 (set_attr "shift" "1")
0d66636f 3031 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3032 (set_attr "length" "8")]
3033)
b11cae9e 3034
604f3a0a 3035(define_expand "abssf2"
3036 [(set (match_operand:SF 0 "s_register_operand" "")
3037 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3038 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3039 "")
3040
604f3a0a 3041(define_expand "absdf2"
3042 [(set (match_operand:DF 0 "s_register_operand" "")
3043 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3044 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3045 "")
3046
7db9af5d 3047(define_expand "sqrtsf2"
3048 [(set (match_operand:SF 0 "s_register_operand" "")
3049 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3050 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3051 "")
9c08d1fa 3052
7db9af5d 3053(define_expand "sqrtdf2"
3054 [(set (match_operand:DF 0 "s_register_operand" "")
3055 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3056 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3057 "")
9c08d1fa 3058
a0f94409 3059(define_insn_and_split "one_cmpldi2"
9c08d1fa 3060 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3061 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 3062 "TARGET_ARM"
f6ebffac 3063 "#"
a0f94409 3064 "TARGET_ARM && reload_completed"
3065 [(set (match_dup 0) (not:SI (match_dup 1)))
3066 (set (match_dup 2) (not:SI (match_dup 3)))]
3067 "
3068 {
3069 operands[2] = gen_highpart (SImode, operands[0]);
3070 operands[0] = gen_lowpart (SImode, operands[0]);
3071 operands[3] = gen_highpart (SImode, operands[1]);
3072 operands[1] = gen_lowpart (SImode, operands[1]);
3073 }"
0d66636f 3074 [(set_attr "length" "8")
3075 (set_attr "predicable" "yes")]
cffb2a26 3076)
b11cae9e 3077
cffb2a26 3078(define_expand "one_cmplsi2"
3079 [(set (match_operand:SI 0 "s_register_operand" "")
3080 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3081 "TARGET_EITHER"
b11cae9e 3082 ""
cffb2a26 3083)
3084
3085(define_insn "*arm_one_cmplsi2"
3086 [(set (match_operand:SI 0 "s_register_operand" "=r")
3087 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3088 "TARGET_ARM"
3089 "mvn%?\\t%0, %1"
0d66636f 3090 [(set_attr "predicable" "yes")]
cffb2a26 3091)
3092
3093(define_insn "*thumb_one_cmplsi2"
3094 [(set (match_operand:SI 0 "register_operand" "=l")
3095 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3096 "TARGET_THUMB"
3097 "mvn\\t%0, %1"
3098 [(set_attr "length" "2")]
3099)
9c08d1fa 3100
f7fbdd4a 3101(define_insn "*notsi_compare0"
bd5b4116 3102 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3103 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3104 (const_int 0)))
3105 (set (match_operand:SI 0 "s_register_operand" "=r")
3106 (not:SI (match_dup 1)))]
cffb2a26 3107 "TARGET_ARM"
40dbec34 3108 "mvn%?s\\t%0, %1"
cffb2a26 3109 [(set_attr "conds" "set")]
3110)
9c08d1fa 3111
f7fbdd4a 3112(define_insn "*notsi_compare0_scratch"
bd5b4116 3113 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3114 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3115 (const_int 0)))
3116 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3117 "TARGET_ARM"
40dbec34 3118 "mvn%?s\\t%0, %1"
cffb2a26 3119 [(set_attr "conds" "set")]
3120)
b11cae9e 3121\f
3122;; Fixed <--> Floating conversion insns
3123
604f3a0a 3124(define_expand "floatsisf2"
3125 [(set (match_operand:SF 0 "s_register_operand" "")
3126 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3127 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3128 "
a2cd141b 3129 if (TARGET_MAVERICK)
604f3a0a 3130 {
3131 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3132 DONE;
3133 }
3134")
3135
604f3a0a 3136(define_expand "floatsidf2"
3137 [(set (match_operand:DF 0 "s_register_operand" "")
3138 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3139 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3140 "
a2cd141b 3141 if (TARGET_MAVERICK)
604f3a0a 3142 {
3143 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3144 DONE;
3145 }
3146")
3147
604f3a0a 3148(define_expand "fix_truncsfsi2"
3149 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3150 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
a2cd141b 3151 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3152 "
a2cd141b 3153 if (TARGET_MAVERICK)
604f3a0a 3154 {
3155 if (!cirrus_fp_register (operands[0], SImode))
3156 operands[0] = force_reg (SImode, operands[0]);
3157 if (!cirrus_fp_register (operands[1], SFmode))
3158 operands[1] = force_reg (SFmode, operands[0]);
3159 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3160 DONE;
3161 }
3162")
3163
604f3a0a 3164(define_expand "fix_truncdfsi2"
3165 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3166 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a2cd141b 3167 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3168 "
a2cd141b 3169 if (TARGET_MAVERICK)
604f3a0a 3170 {
3171 if (!cirrus_fp_register (operands[1], DFmode))
3172 operands[1] = force_reg (DFmode, operands[0]);
3173 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3174 DONE;
3175 }
3176")
3177
f544c6d2 3178;; Truncation insns
b11cae9e 3179
604f3a0a 3180(define_expand "truncdfsf2"
3181 [(set (match_operand:SF 0 "s_register_operand" "")
3182 (float_truncate:SF
3183 (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3184 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3185 ""
3186)
b11cae9e 3187\f
9c08d1fa 3188;; Zero and sign extension instructions.
b11cae9e 3189
9c08d1fa 3190(define_insn "zero_extendsidi2"
3191 [(set (match_operand:DI 0 "s_register_operand" "=r")
3192 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3193 "TARGET_ARM"
9c08d1fa 3194 "*
0d66636f 3195 if (REGNO (operands[1])
3196 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3197 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3198 return \"mov%?\\t%R0, #0\";
3199 "
3200 [(set_attr "length" "8")
3201 (set_attr "predicable" "yes")]
3202)
9c08d1fa 3203
3204(define_insn "zero_extendqidi2"
cffb2a26 3205 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3206 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3207 "TARGET_ARM"
e2348bcb 3208 "@
97499065 3209 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3210 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3211 [(set_attr "length" "8")
0d66636f 3212 (set_attr "predicable" "yes")
a2cd141b 3213 (set_attr "type" "*,load_byte")
cffb2a26 3214 (set_attr "pool_range" "*,4092")
3215 (set_attr "neg_pool_range" "*,4084")]
3216)
9c08d1fa 3217
3218(define_insn "extendsidi2"
3219 [(set (match_operand:DI 0 "s_register_operand" "=r")
3220 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3221 "TARGET_ARM"
9c08d1fa 3222 "*
0d66636f 3223 if (REGNO (operands[1])
3224 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3225 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3226 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3227 "
3228 [(set_attr "length" "8")
331beb1a 3229 (set_attr "shift" "1")
0d66636f 3230 (set_attr "predicable" "yes")]
3231)
9c08d1fa 3232
3233(define_expand "zero_extendhisi2"
cffb2a26 3234 [(set (match_dup 2)
0d66636f 3235 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3236 (const_int 16)))
9c08d1fa 3237 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3238 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3239 "TARGET_EITHER"
9c08d1fa 3240 "
cffb2a26 3241 {
a2cd141b 3242 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3243 {
a2cd141b 3244 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3245 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3246 DONE;
cffb2a26 3247 }
cffb2a26 3248
c1a66faf 3249 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3250 {
3251 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3252 DONE;
3253 }
cffb2a26 3254
a2cd141b 3255 if (!s_register_operand (operands[1], HImode))
3256 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3257
a2cd141b 3258 if (arm_arch6)
3259 {
3260 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3261 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3262 DONE;
cffb2a26 3263 }
a2cd141b 3264
3265 operands[1] = gen_lowpart (SImode, operands[1]);
3266 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3267 }"
3268)
3269
3270(define_insn "*thumb_zero_extendhisi2"
a2cd141b 3271 [(set (match_operand:SI 0 "register_operand" "=l")
3272 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3273 "TARGET_THUMB && !arm_arch6"
cffb2a26 3274 "*
3275 rtx mem = XEXP (operands[1], 0);
3276
3277 if (GET_CODE (mem) == CONST)
3278 mem = XEXP (mem, 0);
3279
3280 if (GET_CODE (mem) == LABEL_REF)
3281 return \"ldr\\t%0, %1\";
3282
3283 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3284 {
cffb2a26 3285 rtx a = XEXP (mem, 0);
3286 rtx b = XEXP (mem, 1);
3287
3288 /* This can happen due to bugs in reload. */
3289 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3290 {
3291 rtx ops[2];
3292 ops[0] = operands[0];
3293 ops[1] = a;
3294
3295 output_asm_insn (\"mov %0, %1\", ops);
3296
3297 XEXP (mem, 0) = operands[0];
3298 }
3299
3300 else if ( GET_CODE (a) == LABEL_REF
3301 && GET_CODE (b) == CONST_INT)
3302 return \"ldr\\t%0, %1\";
25f7a26e 3303 }
cffb2a26 3304
3305 return \"ldrh\\t%0, %1\";
3306 "
3307 [(set_attr "length" "4")
a2cd141b 3308 (set_attr "type" "load_byte")
cffb2a26 3309 (set_attr "pool_range" "60")]
3310)
9c08d1fa 3311
a2cd141b 3312(define_insn "*thumb_zero_extendhisi2_v6"
3313 [(set (match_operand:SI 0 "register_operand" "=l,l")
3314 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3315 "TARGET_THUMB && arm_arch6"
3316 "*
3317 rtx mem;
3318
3319 if (which_alternative == 0)
3320 return \"uxth\\t%0, %1\";
3321
3322 mem = XEXP (operands[1], 0);
3323
3324 if (GET_CODE (mem) == CONST)
3325 mem = XEXP (mem, 0);
3326
3327 if (GET_CODE (mem) == LABEL_REF)
3328 return \"ldr\\t%0, %1\";
3329
3330 if (GET_CODE (mem) == PLUS)
3331 {
3332 rtx a = XEXP (mem, 0);
3333 rtx b = XEXP (mem, 1);
3334
3335 /* This can happen due to bugs in reload. */
3336 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3337 {
3338 rtx ops[2];
3339 ops[0] = operands[0];
3340 ops[1] = a;
3341
3342 output_asm_insn (\"mov %0, %1\", ops);
3343
3344 XEXP (mem, 0) = operands[0];
3345 }
3346
3347 else if ( GET_CODE (a) == LABEL_REF
3348 && GET_CODE (b) == CONST_INT)
3349 return \"ldr\\t%0, %1\";
3350 }
3351
3352 return \"ldrh\\t%0, %1\";
3353 "
3354 [(set_attr "length" "2,4")
3355 (set_attr "type" "alu_shift,load_byte")
3356 (set_attr "pool_range" "*,60")]
3357)
3358
cffb2a26 3359(define_insn "*arm_zero_extendhisi2"
a2cd141b 3360 [(set (match_operand:SI 0 "s_register_operand" "=r")
3361 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3362 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3363 "ldr%?h\\t%0, %1"
a2cd141b 3364 [(set_attr "type" "load_byte")
0d66636f 3365 (set_attr "predicable" "yes")
cffb2a26 3366 (set_attr "pool_range" "256")
3367 (set_attr "neg_pool_range" "244")]
3368)
f7fbdd4a 3369
a2cd141b 3370(define_insn "*arm_zero_extendhisi2_v6"
3371 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3372 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3373 "TARGET_ARM && arm_arch6"
3374 "@
3375 uxth%?\\t%0, %1
3376 ldr%?h\\t%0, %1"
3377 [(set_attr "type" "alu_shift,load_byte")
3378 (set_attr "predicable" "yes")
3379 (set_attr "pool_range" "*,256")
3380 (set_attr "neg_pool_range" "*,244")]
3381)
3382
3383(define_insn "*arm_zero_extendhisi2addsi"
3384 [(set (match_operand:SI 0 "s_register_operand" "=r")
3385 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3386 (match_operand:SI 2 "s_register_operand" "r")))]
3387 "TARGET_ARM && arm_arch6"
3388 "uxtah%?\\t%0, %2, %1"
3389 [(set_attr "type" "alu_shift")
3390 (set_attr "predicable" "yes")]
3391)
3392
206ee9a2 3393(define_split
3394 [(set (match_operand:SI 0 "s_register_operand" "")
3395 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3396 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3397 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3398 [(set (match_dup 2) (match_dup 1))
3399 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3400 "
cffb2a26 3401 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3402 FAIL;
215b30b3 3403 "
3404)
206ee9a2 3405
3406(define_split
3407 [(set (match_operand:SI 0 "s_register_operand" "")
3408 (match_operator:SI 3 "shiftable_operator"
3409 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3410 (match_operand:SI 4 "s_register_operand" "")]))
3411 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3412 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3413 [(set (match_dup 2) (match_dup 1))
3414 (set (match_dup 0)
3415 (match_op_dup 3
3416 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3417 "
cffb2a26 3418 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3419 FAIL;
215b30b3 3420 "
3421)
206ee9a2 3422
87b22bf7 3423(define_expand "zero_extendqisi2"
cffb2a26 3424 [(set (match_operand:SI 0 "s_register_operand" "")
3425 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3426 "TARGET_EITHER"
87b22bf7 3427 "
a2cd141b 3428 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 3429 {
cffb2a26 3430 if (TARGET_ARM)
3431 {
215b30b3 3432 emit_insn (gen_andsi3 (operands[0],
3433 gen_lowpart (SImode, operands[1]),
cffb2a26 3434 GEN_INT (255)));
3435 }
3436 else /* TARGET_THUMB */
3437 {
3438 rtx temp = gen_reg_rtx (SImode);
3439 rtx ops[3];
3440
3441 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3442 operands[1] = gen_lowpart (SImode, operands[1]);
3443
3444 ops[0] = temp;
3445 ops[1] = operands[1];
3446 ops[2] = GEN_INT (24);
3447
215b30b3 3448 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3449 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3450
3451 ops[0] = operands[0];
3452 ops[1] = temp;
3453 ops[2] = GEN_INT (24);
3454
215b30b3 3455 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3456 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3457 }
87b22bf7 3458 DONE;
3459 }
215b30b3 3460 "
3461)
9c08d1fa 3462
cffb2a26 3463(define_insn "*thumb_zero_extendqisi2"
a2cd141b 3464 [(set (match_operand:SI 0 "register_operand" "=l")
3465 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3466 "TARGET_THUMB && !arm_arch6"
cffb2a26 3467 "ldrb\\t%0, %1"
3468 [(set_attr "length" "2")
a2cd141b 3469 (set_attr "type" "load_byte")
cffb2a26 3470 (set_attr "pool_range" "32")]
3471)
3472
a2cd141b 3473(define_insn "*thumb_zero_extendqisi2_v6"
3474 [(set (match_operand:SI 0 "register_operand" "=l,l")
3475 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3476 "TARGET_THUMB && arm_arch6"
3477 "@
3478 uxtb\\t%0, %1
3479 ldrb\\t%0, %1"
3480 [(set_attr "length" "2,2")
3481 (set_attr "type" "alu_shift,load_byte")
3482 (set_attr "pool_range" "*,32")]
3483)
3484
cffb2a26 3485(define_insn "*arm_zero_extendqisi2"
a2cd141b 3486 [(set (match_operand:SI 0 "s_register_operand" "=r")
3487 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3488 "TARGET_ARM && !arm_arch6"
87b22bf7 3489 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 3490 [(set_attr "type" "load_byte")
0d66636f 3491 (set_attr "predicable" "yes")
cffb2a26 3492 (set_attr "pool_range" "4096")
3493 (set_attr "neg_pool_range" "4084")]
3494)
87b22bf7 3495
a2cd141b 3496(define_insn "*arm_zero_extendqisi2_v6"
3497 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3498 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3499 "TARGET_ARM && arm_arch6"
3500 "@
3501 uxtb%?\\t%0, %1
3502 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3503 [(set_attr "type" "alu_shift,load_byte")
3504 (set_attr "predicable" "yes")
3505 (set_attr "pool_range" "*,4096")
3506 (set_attr "neg_pool_range" "*,4084")]
3507)
3508
3509(define_insn "*arm_zero_extendqisi2addsi"
3510 [(set (match_operand:SI 0 "s_register_operand" "=r")
3511 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3512 (match_operand:SI 2 "s_register_operand" "r")))]
3513 "TARGET_ARM && arm_arch6"
3514 "uxtab%?\\t%0, %2, %1"
3515 [(set_attr "predicable" "yes")
3516 (set_attr "type" "alu_shift")]
3517)
3518
87b22bf7 3519(define_split
3520 [(set (match_operand:SI 0 "s_register_operand" "")
3521 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3522 (clobber (match_operand:SI 2 "s_register_operand" ""))]
9e8503e6 3523 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 3524 [(set (match_dup 2) (match_dup 1))
3525 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 3526 ""
3527)
9c08d1fa 3528
f7fbdd4a 3529(define_insn "*compareqi_eq0"
bd5b4116 3530 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 3531 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 3532 (const_int 0)))]
cffb2a26 3533 "TARGET_ARM"
87b22bf7 3534 "tst\\t%0, #255"
cffb2a26 3535 [(set_attr "conds" "set")]
3536)
b11cae9e 3537
b11cae9e 3538(define_expand "extendhisi2"
c8f69309 3539 [(set (match_dup 2)
25f7a26e 3540 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 3541 (const_int 16)))
9c08d1fa 3542 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3543 (ashiftrt:SI (match_dup 2)
3544 (const_int 16)))]
cffb2a26 3545 "TARGET_EITHER"
b11cae9e 3546 "
cffb2a26 3547 {
a2cd141b 3548 if (GET_CODE (operands[1]) == MEM)
cffb2a26 3549 {
a2cd141b 3550 if (TARGET_THUMB)
3551 {
3552 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3553 DONE;
3554 }
3555 else if (arm_arch4)
3556 {
a2cd141b 3557 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3558 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3559 DONE;
3560 }
cffb2a26 3561 }
7bd8ccc9 3562
c1a66faf 3563 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 3564 {
3565 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3566 DONE;
3567 }
a2cd141b 3568
215b30b3 3569 if (!s_register_operand (operands[1], HImode))
cffb2a26 3570 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3571
a2cd141b 3572 if (arm_arch6)
cffb2a26 3573 {
a2cd141b 3574 if (TARGET_THUMB)
3575 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3576 else
3577 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3578 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3579
cffb2a26 3580 DONE;
3581 }
a2cd141b 3582
3583 operands[1] = gen_lowpart (SImode, operands[1]);
3584 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3585 }"
3586)
3587
a2cd141b 3588(define_insn "thumb_extendhisi2"
3589 [(set (match_operand:SI 0 "register_operand" "=l")
3590 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3591 (clobber (match_scratch:SI 2 "=&l"))]
3592 "TARGET_THUMB && !arm_arch6"
cffb2a26 3593 "*
3594 {
3595 rtx ops[4];
3596 rtx mem = XEXP (operands[1], 0);
3597
3598 /* This code used to try to use 'V', and fix the address only if it was
3599 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3600 range of QImode offsets, and offsettable_address_p does a QImode
3601 address check. */
3602
3603 if (GET_CODE (mem) == CONST)
3604 mem = XEXP (mem, 0);
3605
3606 if (GET_CODE (mem) == LABEL_REF)
3607 return \"ldr\\t%0, %1\";
3608
3609 if (GET_CODE (mem) == PLUS)
3610 {
3611 rtx a = XEXP (mem, 0);
3612 rtx b = XEXP (mem, 1);
3613
3614 if (GET_CODE (a) == LABEL_REF
3615 && GET_CODE (b) == CONST_INT)
3616 return \"ldr\\t%0, %1\";
3617
3618 if (GET_CODE (b) == REG)
3619 return \"ldrsh\\t%0, %1\";
3620
3621 ops[1] = a;
3622 ops[2] = b;
3623 }
3624 else
3625 {
3626 ops[1] = mem;
3627 ops[2] = const0_rtx;
3628 }
ed29c566 3629
3630 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 3631
3632 ops[0] = operands[0];
3633 ops[3] = operands[2];
3634 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3635 return \"\";
3636 }"
3637 [(set_attr "length" "4")
a2cd141b 3638 (set_attr "type" "load_byte")
cffb2a26 3639 (set_attr "pool_range" "1020")]
3640)
25f7a26e 3641
a2cd141b 3642;; We used to have an early-clobber on the scratch register here.
3643;; However, there's a bug somewhere in reload which means that this
3644;; can be partially ignored during spill allocation if the memory
ed29c566 3645;; address also needs reloading; this causes us to die later on when
a2cd141b 3646;; we try to verify the operands. Fortunately, we don't really need
3647;; the early-clobber: we can always use operand 0 if operand 2
3648;; overlaps the address.
3649(define_insn "*thumb_extendhisi2_insn_v6"
3650 [(set (match_operand:SI 0 "register_operand" "=l,l")
3651 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3652 (clobber (match_scratch:SI 2 "=X,l"))]
3653 "TARGET_THUMB && arm_arch6"
3654 "*
3655 {
3656 rtx ops[4];
3657 rtx mem;
3658
3659 if (which_alternative == 0)
3660 return \"sxth\\t%0, %1\";
3661
3662 mem = XEXP (operands[1], 0);
3663
3664 /* This code used to try to use 'V', and fix the address only if it was
3665 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3666 range of QImode offsets, and offsettable_address_p does a QImode
3667 address check. */
3668
3669 if (GET_CODE (mem) == CONST)
3670 mem = XEXP (mem, 0);
3671
3672 if (GET_CODE (mem) == LABEL_REF)
3673 return \"ldr\\t%0, %1\";
3674
3675 if (GET_CODE (mem) == PLUS)
3676 {
3677 rtx a = XEXP (mem, 0);
3678 rtx b = XEXP (mem, 1);
3679
3680 if (GET_CODE (a) == LABEL_REF
3681 && GET_CODE (b) == CONST_INT)
3682 return \"ldr\\t%0, %1\";
3683
3684 if (GET_CODE (b) == REG)
3685 return \"ldrsh\\t%0, %1\";
3686
3687 ops[1] = a;
3688 ops[2] = b;
3689 }
3690 else
3691 {
3692 ops[1] = mem;
3693 ops[2] = const0_rtx;
3694 }
3695
ed29c566 3696 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 3697
3698 ops[0] = operands[0];
3699 if (reg_mentioned_p (operands[2], ops[1]))
3700 ops[3] = ops[0];
3701 else
3702 ops[3] = operands[2];
3703 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3704 return \"\";
3705 }"
3706 [(set_attr "length" "2,4")
3707 (set_attr "type" "alu_shift,load_byte")
3708 (set_attr "pool_range" "*,1020")]
3709)
3710
25f7a26e 3711(define_expand "extendhisi2_mem"
eab14235 3712 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 3713 (set (match_dup 3)
eab14235 3714 (zero_extend:SI (match_dup 7)))
25f7a26e 3715 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3716 (set (match_operand:SI 0 "" "")
3717 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 3718 "TARGET_ARM"
25f7a26e 3719 "
215b30b3 3720 {
3721 rtx mem1, mem2;
3722 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3723
3724 mem1 = gen_rtx_MEM (QImode, addr);
3725 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3726 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3727 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3728 operands[0] = gen_lowpart (SImode, operands[0]);
3729 operands[1] = mem1;
3730 operands[2] = gen_reg_rtx (SImode);
3731 operands[3] = gen_reg_rtx (SImode);
3732 operands[6] = gen_reg_rtx (SImode);
3733 operands[7] = mem2;
25f7a26e 3734
215b30b3 3735 if (BYTES_BIG_ENDIAN)
3736 {
3737 operands[4] = operands[2];
3738 operands[5] = operands[3];
3739 }
3740 else
3741 {
3742 operands[4] = operands[3];
3743 operands[5] = operands[2];
3744 }
3745 }"
3746)
b11cae9e 3747
a2cd141b 3748(define_insn "*arm_extendhisi2"
3749 [(set (match_operand:SI 0 "s_register_operand" "=r")
3750 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3751 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3752 "ldr%?sh\\t%0, %1"
a2cd141b 3753 [(set_attr "type" "load_byte")
0d66636f 3754 (set_attr "predicable" "yes")
cffb2a26 3755 (set_attr "pool_range" "256")
3756 (set_attr "neg_pool_range" "244")]
3757)
f7fbdd4a 3758
a2cd141b 3759(define_insn "*arm_extendhisi2_v6"
3760 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3761 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3762 "TARGET_ARM && arm_arch6"
3763 "@
3764 sxth%?\\t%0, %1
3765 ldr%?sh\\t%0, %1"
3766 [(set_attr "type" "alu_shift,load_byte")
3767 (set_attr "predicable" "yes")
3768 (set_attr "pool_range" "*,256")
3769 (set_attr "neg_pool_range" "*,244")]
3770)
3771
3772(define_insn "*arm_extendhisi2addsi"
3773 [(set (match_operand:SI 0 "s_register_operand" "=r")
3774 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3775 (match_operand:SI 2 "s_register_operand" "r")))]
3776 "TARGET_ARM && arm_arch6"
3777 "sxtah%?\\t%0, %2, %1"
3778)
3779
206ee9a2 3780(define_split
cffb2a26 3781 [(set (match_operand:SI 0 "s_register_operand" "")
206ee9a2 3782 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
cffb2a26 3783 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3784 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3785 [(set (match_dup 2) (match_dup 1))
3786 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3787 "
cffb2a26 3788 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3789 FAIL;
cffb2a26 3790 "
3791)
206ee9a2 3792
3793(define_split
cffb2a26 3794 [(set (match_operand:SI 0 "s_register_operand" "")
3795 (match_operator:SI 3 "shiftable_operator"
206ee9a2 3796 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
cffb2a26 3797 (match_operand:SI 4 "s_register_operand" "")]))
3798 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3799 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3800 [(set (match_dup 2) (match_dup 1))
3801 (set (match_dup 0)
3802 (match_op_dup 3
3803 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
cffb2a26 3804 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3805 FAIL;
206ee9a2 3806 "
cffb2a26 3807)
206ee9a2 3808
c8f69309 3809(define_expand "extendqihi2"
3810 [(set (match_dup 2)
f7fbdd4a 3811 (ashift:SI (match_operand:QI 1 "general_operand" "")
c8f69309 3812 (const_int 24)))
9c08d1fa 3813 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 3814 (ashiftrt:SI (match_dup 2)
3815 (const_int 24)))]
cffb2a26 3816 "TARGET_ARM"
c8f69309 3817 "
215b30b3 3818 {
3819 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3820 {
3821 emit_insn (gen_rtx_SET (VOIDmode,
3822 operands[0],
3823 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3824 DONE;
3825 }
3826 if (!s_register_operand (operands[1], QImode))
3827 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3828 operands[0] = gen_lowpart (SImode, operands[0]);
3829 operands[1] = gen_lowpart (SImode, operands[1]);
3830 operands[2] = gen_reg_rtx (SImode);
3831 }"
3832)
f7fbdd4a 3833
3834(define_insn "*extendqihi_insn"
b4e8a300 3835 [(set (match_operand:HI 0 "s_register_operand" "=r")
3836 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
cffb2a26 3837 "TARGET_ARM && arm_arch4"
b4e8a300 3838 "ldr%?sb\\t%0, %1"
a2cd141b 3839 [(set_attr "type" "load_byte")
0d66636f 3840 (set_attr "predicable" "yes")
cffb2a26 3841 (set_attr "pool_range" "256")
3842 (set_attr "neg_pool_range" "244")]
3843)
3fc2009e 3844
b11cae9e 3845(define_expand "extendqisi2"
c8f69309 3846 [(set (match_dup 2)
3fc2009e 3847 (ashift:SI (match_operand:QI 1 "general_operand" "")
b11cae9e 3848 (const_int 24)))
9c08d1fa 3849 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3850 (ashiftrt:SI (match_dup 2)
3851 (const_int 24)))]
cffb2a26 3852 "TARGET_EITHER"
b11cae9e 3853 "
cffb2a26 3854 {
a2cd141b 3855 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3856 {
a2cd141b 3857 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 3858 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3859 DONE;
3860 }
a2cd141b 3861
215b30b3 3862 if (!s_register_operand (operands[1], QImode))
cffb2a26 3863 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 3864
a2cd141b 3865 if (arm_arch6)
3866 {
3867 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3868 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3869 DONE;
cffb2a26 3870 }
a2cd141b 3871
3872 operands[1] = gen_lowpart (SImode, operands[1]);
3873 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3874 }"
3875)
f7fbdd4a 3876
a2cd141b 3877(define_insn "*arm_extendqisi"
3878 [(set (match_operand:SI 0 "s_register_operand" "=r")
b4e8a300 3879 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
a2cd141b 3880 "TARGET_ARM && arm_arch4 && !arm_arch6"
b4e8a300 3881 "ldr%?sb\\t%0, %1"
a2cd141b 3882 [(set_attr "type" "load_byte")
0d66636f 3883 (set_attr "predicable" "yes")
cffb2a26 3884 (set_attr "pool_range" "256")
3885 (set_attr "neg_pool_range" "244")]
3886)
3fc2009e 3887
a2cd141b 3888(define_insn "*arm_extendqisi_v6"
3889 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
b4e8a300 3890 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
a2cd141b 3891 "TARGET_ARM && arm_arch6"
b4e8a300 3892 "@
3893 sxtb%?\\t%0, %1
3894 ldr%?sb\\t%0, %1"
a2cd141b 3895 [(set_attr "type" "alu_shift,load_byte")
3896 (set_attr "predicable" "yes")
a2cd141b 3897 (set_attr "pool_range" "*,256")
3898 (set_attr "neg_pool_range" "*,244")]
3899)
3900
3901(define_insn "*arm_extendqisi2addsi"
3902 [(set (match_operand:SI 0 "s_register_operand" "=r")
3903 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3904 (match_operand:SI 2 "s_register_operand" "r")))]
3905 "TARGET_ARM && arm_arch6"
3906 "sxtab%?\\t%0, %2, %1"
3907 [(set_attr "type" "alu_shift")
3908 (set_attr "predicable" "yes")]
3909)
3910
a2cd141b 3911(define_insn "*thumb_extendqisi2"
3912 [(set (match_operand:SI 0 "register_operand" "=l,l")
3913 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3914 "TARGET_THUMB && !arm_arch6"
cffb2a26 3915 "*
3916 {
3917 rtx ops[3];
3918 rtx mem = XEXP (operands[1], 0);
3919
3920 if (GET_CODE (mem) == CONST)
3921 mem = XEXP (mem, 0);
3922
3923 if (GET_CODE (mem) == LABEL_REF)
3924 return \"ldr\\t%0, %1\";
3925
3926 if (GET_CODE (mem) == PLUS
3927 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3928 return \"ldr\\t%0, %1\";
3929
3930 if (which_alternative == 0)
3931 return \"ldrsb\\t%0, %1\";
3932
3933 ops[0] = operands[0];
3934
3935 if (GET_CODE (mem) == PLUS)
3936 {
3937 rtx a = XEXP (mem, 0);
3938 rtx b = XEXP (mem, 1);
3939
3940 ops[1] = a;
3941 ops[2] = b;
3942
3943 if (GET_CODE (a) == REG)
3944 {
3945 if (GET_CODE (b) == REG)
3946 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3947 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 3948 {
3949 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3950 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3951 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3952 }
cffb2a26 3953 else
3954 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3955 }
cffb2a26 3956 else
3957 {
ed29c566 3958 gcc_assert (GET_CODE (b) == REG);
cffb2a26 3959 if (REGNO (b) == REGNO (ops[0]))
215b30b3 3960 {
3961 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3962 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3963 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3964 }
cffb2a26 3965 else
3966 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3967 }
3968 }
3969 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3970 {
215b30b3 3971 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3972 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3973 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 3974 }
3975 else
3976 {
3977 ops[1] = mem;
3978 ops[2] = const0_rtx;
3979
3980 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3981 }
3982 return \"\";
3983 }"
3984 [(set_attr "length" "2,6")
a2cd141b 3985 (set_attr "type" "load_byte,load_byte")
cffb2a26 3986 (set_attr "pool_range" "32,32")]
3987)
3988
a2cd141b 3989(define_insn "*thumb_extendqisi2_v6"
3990 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3991 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3992 "TARGET_THUMB && arm_arch6"
3993 "*
3994 {
3995 rtx ops[3];
3996 rtx mem;
3997
3998 if (which_alternative == 0)
3999 return \"sxtb\\t%0, %1\";
4000
4001 mem = XEXP (operands[1], 0);
4002
4003 if (GET_CODE (mem) == CONST)
4004 mem = XEXP (mem, 0);
4005
4006 if (GET_CODE (mem) == LABEL_REF)
4007 return \"ldr\\t%0, %1\";
4008
4009 if (GET_CODE (mem) == PLUS
4010 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4011 return \"ldr\\t%0, %1\";
4012
4013 if (which_alternative == 0)
4014 return \"ldrsb\\t%0, %1\";
4015
4016 ops[0] = operands[0];
4017
4018 if (GET_CODE (mem) == PLUS)
4019 {
4020 rtx a = XEXP (mem, 0);
4021 rtx b = XEXP (mem, 1);
4022
4023 ops[1] = a;
4024 ops[2] = b;
4025
4026 if (GET_CODE (a) == REG)
4027 {
4028 if (GET_CODE (b) == REG)
4029 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4030 else if (REGNO (a) == REGNO (ops[0]))
4031 {
4032 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4033 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4034 }
4035 else
4036 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4037 }
a2cd141b 4038 else
4039 {
ed29c566 4040 gcc_assert (GET_CODE (b) == REG);
a2cd141b 4041 if (REGNO (b) == REGNO (ops[0]))
4042 {
4043 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4044 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4045 }
4046 else
4047 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4048 }
4049 }
4050 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4051 {
4052 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4053 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4054 }
4055 else
4056 {
4057 ops[1] = mem;
4058 ops[2] = const0_rtx;
4059
4060 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4061 }
4062 return \"\";
4063 }"
4064 [(set_attr "length" "2,2,4")
4065 (set_attr "type" "alu_shift,load_byte,load_byte")
4066 (set_attr "pool_range" "*,32,32")]
4067)
4068
caedf871 4069(define_expand "extendsfdf2"
4070 [(set (match_operand:DF 0 "s_register_operand" "")
4071 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 4072 "TARGET_ARM && TARGET_HARD_FLOAT"
caedf871 4073 ""
4074)
b11cae9e 4075\f
4076;; Move insns (including loads and stores)
4077
4078;; XXX Just some ideas about movti.
9c08d1fa 4079;; I don't think these are a good idea on the arm, there just aren't enough
4080;; registers
b11cae9e 4081;;(define_expand "loadti"
9c08d1fa 4082;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4083;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4084;; "" "")
4085
4086;;(define_expand "storeti"
4087;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4088;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4089;; "" "")
4090
4091;;(define_expand "movti"
4092;; [(set (match_operand:TI 0 "general_operand" "")
4093;; (match_operand:TI 1 "general_operand" ""))]
4094;; ""
4095;; "
4096;;{
4097;; rtx insn;
4098;;
4099;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4100;; operands[1] = copy_to_reg (operands[1]);
4101;; if (GET_CODE (operands[0]) == MEM)
4102;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4103;; else if (GET_CODE (operands[1]) == MEM)
4104;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4105;; else
4106;; FAIL;
4107;;
4108;; emit_insn (insn);
4109;; DONE;
4110;;}")
4111
a2f10574 4112;; Recognize garbage generated above.
b11cae9e 4113
4114;;(define_insn ""
4115;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4116;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4117;; ""
4118;; "*
4119;; {
4120;; register mem = (which_alternative < 3);
0d66636f 4121;; register const char *template;
b11cae9e 4122;;
4123;; operands[mem] = XEXP (operands[mem], 0);
4124;; switch (which_alternative)
4125;; {
4126;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4127;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4128;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4129;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4130;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4131;; case 5: template = \"stmia\\t%0, %M1\"; break;
4132;; }
e2348bcb 4133;; output_asm_insn (template, operands);
4134;; return \"\";
b11cae9e 4135;; }")
4136
cffb2a26 4137(define_expand "movdi"
4138 [(set (match_operand:DI 0 "general_operand" "")
4139 (match_operand:DI 1 "general_operand" ""))]
4140 "TARGET_EITHER"
4141 "
4142 if (TARGET_THUMB)
4143 {
215b30b3 4144 if (!no_new_pseudos)
cffb2a26 4145 {
4146 if (GET_CODE (operands[0]) != REG)
4147 operands[1] = force_reg (DImode, operands[1]);
4148 }
4149 }
4150 "
4151)
b11cae9e 4152
cffb2a26 4153(define_insn "*arm_movdi"
d51f92df 4154 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4155 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4156 "TARGET_ARM
4157 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4158 && !TARGET_IWMMXT"
b11cae9e 4159 "*
d51f92df 4160 switch (which_alternative)
4161 {
4162 case 0:
4163 case 1:
4164 case 2:
4165 return \"#\";
4166 default:
4167 return output_move_double (operands);
4168 }
cffb2a26 4169 "
359a6e9f 4170 [(set_attr "length" "8,12,16,8,8")
4171 (set_attr "type" "*,*,*,load2,store2")
4172 (set_attr "pool_range" "*,*,*,1020,*")
4173 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4174)
4175
d51f92df 4176(define_split
4177 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4178 (match_operand:ANY64 1 "const_double_operand" ""))]
4179 "TARGET_ARM
4180 && reload_completed
4181 && (arm_const_double_inline_cost (operands[1])
4182 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4183 [(const_int 0)]
4184 "
4185 arm_split_constant (SET, SImode, curr_insn,
4186 INTVAL (gen_lowpart (SImode, operands[1])),
4187 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4188 arm_split_constant (SET, SImode, curr_insn,
4189 INTVAL (gen_highpart_mode (SImode,
4190 GET_MODE (operands[0]),
4191 operands[1])),
4192 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4193 DONE;
4194 "
4195)
4196
e5ba9289 4197; If optimizing for size, or if we have load delay slots, then
4198; we want to split the constant into two separate operations.
4199; In both cases this may split a trivial part into a single data op
4200; leaving a single complex constant to load. We can also get longer
4201; offsets in a LDR which means we get better chances of sharing the pool
4202; entries. Finally, we can normally do a better job of scheduling
4203; LDR instructions than we can with LDM.
4204; This pattern will only match if the one above did not.
4205(define_split
4206 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4207 (match_operand:ANY64 1 "const_double_operand" ""))]
4208 "TARGET_ARM && reload_completed
4209 && arm_const_double_by_parts (operands[1])"
4210 [(set (match_dup 0) (match_dup 1))
4211 (set (match_dup 2) (match_dup 3))]
4212 "
4213 operands[2] = gen_highpart (SImode, operands[0]);
4214 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4215 operands[1]);
4216 operands[0] = gen_lowpart (SImode, operands[0]);
4217 operands[1] = gen_lowpart (SImode, operands[1]);
4218 "
4219)
4220
d51f92df 4221(define_split
4222 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4223 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4224 "TARGET_EITHER && reload_completed"
4225 [(set (match_dup 0) (match_dup 1))
4226 (set (match_dup 2) (match_dup 3))]
4227 "
4228 operands[2] = gen_highpart (SImode, operands[0]);
4229 operands[3] = gen_highpart (SImode, operands[1]);
4230 operands[0] = gen_lowpart (SImode, operands[0]);
4231 operands[1] = gen_lowpart (SImode, operands[1]);
4232
4233 /* Handle a partial overlap. */
4234 if (rtx_equal_p (operands[0], operands[3]))
4235 {
4236 rtx tmp0 = operands[0];
4237 rtx tmp1 = operands[1];
4238
4239 operands[0] = operands[2];
4240 operands[1] = operands[3];
4241 operands[2] = tmp0;
4242 operands[3] = tmp1;
4243 }
4244 "
4245)
4246
a8a3b539 4247;; We can't actually do base+index doubleword loads if the index and
4248;; destination overlap. Split here so that we at least have chance to
4249;; schedule.
4250(define_split
4251 [(set (match_operand:DI 0 "s_register_operand" "")
4252 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4253 (match_operand:SI 2 "s_register_operand" ""))))]
4254 "TARGET_LDRD
4255 && reg_overlap_mentioned_p (operands[0], operands[1])
4256 && reg_overlap_mentioned_p (operands[0], operands[2])"
4257 [(set (match_dup 4)
4258 (plus:SI (match_dup 1)
4259 (match_dup 2)))
4260 (set (match_dup 0)
4261 (mem:DI (match_dup 4)))]
4262 "
4263 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4264 "
4265)
4266
cffb2a26 4267;;; ??? This should have alternatives for constants.
4268;;; ??? This was originally identical to the movdf_insn pattern.
4269;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4270;;; thumb_reorg with a memory reference.
4271(define_insn "*thumb_movdi_insn"
215b30b3 4272 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4273 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
cffb2a26 4274 "TARGET_THUMB
a2cd141b 4275 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4276 && ( register_operand (operands[0], DImode)
4277 || register_operand (operands[1], DImode))"
4278 "*
4279 {
4280 switch (which_alternative)
4281 {
4282 default:
4283 case 0:
4284 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4285 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4286 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4287 case 1:
4288 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4289 case 2:
4290 operands[1] = GEN_INT (- INTVAL (operands[1]));
4291 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4292 case 3:
4293 return \"ldmia\\t%1, {%0, %H0}\";
4294 case 4:
4295 return \"stmia\\t%0, {%1, %H1}\";
4296 case 5:
4297 return thumb_load_double_from_address (operands);
4298 case 6:
1a83b3ff 4299 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4300 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4301 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4302 return \"\";
4303 case 7:
4304 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4305 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4306 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4307 }
4308 }"
4309 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4310 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4311 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4312)
b11cae9e 4313
9c08d1fa 4314(define_expand "movsi"
4315 [(set (match_operand:SI 0 "general_operand" "")
4316 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4317 "TARGET_EITHER"
9c08d1fa 4318 "
cffb2a26 4319 if (TARGET_ARM)
9c08d1fa 4320 {
674a8f0b 4321 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4322 if (GET_CODE (operands[0]) == MEM)
4323 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4324 if (arm_general_register_operand (operands[0], SImode)
4325 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4326 && !(const_ok_for_arm (INTVAL (operands[1]))
4327 || const_ok_for_arm (~INTVAL (operands[1]))))
4328 {
96f57e36 4329 arm_split_constant (SET, SImode, NULL_RTX,
4330 INTVAL (operands[1]), operands[0], NULL_RTX,
615caa51 4331 optimize && !no_new_pseudos);
cffb2a26 4332 DONE;
4333 }
4334 }
674a8f0b 4335 else /* TARGET_THUMB.... */
cffb2a26 4336 {
215b30b3 4337 if (!no_new_pseudos)
cffb2a26 4338 {
4339 if (GET_CODE (operands[0]) != REG)
4340 operands[1] = force_reg (SImode, operands[1]);
4341 }
9c08d1fa 4342 }
af1b847e 4343
bbe777ea 4344 if (flag_pic
4345 && (CONSTANT_P (operands[1])
4346 || symbol_mentioned_p (operands[1])
4347 || label_mentioned_p (operands[1])))
849170fd 4348 operands[1] = legitimize_pic_address (operands[1], SImode,
935d87ee 4349 (no_new_pseudos ? operands[0] : 0));
215b30b3 4350 "
4351)
9c08d1fa 4352
cffb2a26 4353(define_insn "*arm_movsi_insn"
215b30b3 4354 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4355 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
755eb2b4 4356 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 4357 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 4358 && ( register_operand (operands[0], SImode)
4359 || register_operand (operands[1], SImode))"
f7fbdd4a 4360 "@
4361 mov%?\\t%0, %1
4362 mvn%?\\t%0, #%B1
4363 ldr%?\\t%0, %1
4364 str%?\\t%1, %0"
a2cd141b 4365 [(set_attr "type" "*,*,load1,store1")
0d66636f 4366 (set_attr "predicable" "yes")
cffb2a26 4367 (set_attr "pool_range" "*,*,4096,*")
4368 (set_attr "neg_pool_range" "*,*,4084,*")]
4369)
87b22bf7 4370
4371(define_split
a2cd141b 4372 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 4373 (match_operand:SI 1 "const_int_operand" ""))]
cffb2a26 4374 "TARGET_ARM
215b30b3 4375 && (!(const_ok_for_arm (INTVAL (operands[1]))
4376 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 4377 [(clobber (const_int 0))]
4378 "
96f57e36 4379 arm_split_constant (SET, SImode, NULL_RTX,
4380 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 4381 DONE;
215b30b3 4382 "
4383)
9c08d1fa 4384
cffb2a26 4385(define_insn "*thumb_movsi_insn"
215b30b3 4386 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4387 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
cffb2a26 4388 "TARGET_THUMB
4389 && ( register_operand (operands[0], SImode)
4390 || register_operand (operands[1], SImode))"
4391 "@
4392 mov %0, %1
4393 mov %0, %1
4394 #
4395 #
4396 ldmia\\t%1, {%0}
4397 stmia\\t%0, {%1}
4398 ldr\\t%0, %1
4399 str\\t%1, %0
4400 mov\\t%0, %1"
4401 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 4402 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 4403 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4404)
4405
4406(define_split
4407 [(set (match_operand:SI 0 "register_operand" "")
4408 (match_operand:SI 1 "const_int_operand" ""))]
4409 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4410 [(set (match_dup 0) (match_dup 1))
4411 (set (match_dup 0) (neg:SI (match_dup 0)))]
4412 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4413)
4414
4415(define_split
4416 [(set (match_operand:SI 0 "register_operand" "")
4417 (match_operand:SI 1 "const_int_operand" ""))]
4418 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4419 [(set (match_dup 0) (match_dup 1))
4420 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4421 "
4422 {
4423 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4424 unsigned HOST_WIDE_INT mask = 0xff;
4425 int i;
4426
4427 for (i = 0; i < 25; i++)
4428 if ((val & (mask << i)) == val)
4429 break;
4430
f5b3169c 4431 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 4432 if (i == 0)
4433 FAIL;
4434
4435 operands[1] = GEN_INT (val >> i);
4436 operands[2] = GEN_INT (i);
4437 }"
4438)
4439
67336bcf 4440;; When generating pic, we need to load the symbol offset into a register.
4441;; So that the optimizer does not confuse this with a normal symbol load
4442;; we use an unspec. The offset will be loaded from a constant pool entry,
4443;; since that is the only type of relocation we can use.
4444
4445;; The rather odd constraints on the following are to force reload to leave
4446;; the insn alone, and to force the minipool generation pass to then move
4447;; the GOT symbol to memory.
849170fd 4448
8c4d8060 4449(define_insn "pic_load_addr_arm"
849170fd 4450 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4451 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4452 "TARGET_ARM && flag_pic"
67336bcf 4453 "ldr%?\\t%0, %1"
a2cd141b 4454 [(set_attr "type" "load1")
8c4d8060 4455 (set (attr "pool_range") (const_int 4096))
4456 (set (attr "neg_pool_range") (const_int 4084))]
4457)
4458
4459(define_insn "pic_load_addr_thumb"
4460 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 4461 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4462 "TARGET_THUMB && flag_pic"
4463 "ldr\\t%0, %1"
a2cd141b 4464 [(set_attr "type" "load1")
8c4d8060 4465 (set (attr "pool_range") (const_int 1024))]
cffb2a26 4466)
849170fd 4467
4468;; This variant is used for AOF assembly, since it needs to mention the
4469;; pic register in the rtl.
4470(define_expand "pic_load_addr_based"
7db9af5d 4471 [(set (match_operand:SI 0 "s_register_operand" "")
e1159bbe 4472 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
cffb2a26 4473 "TARGET_ARM && flag_pic"
4474 "operands[2] = pic_offset_table_rtx;"
4475)
849170fd 4476
4477(define_insn "*pic_load_addr_based_insn"
4478 [(set (match_operand:SI 0 "s_register_operand" "=r")
4479 (unspec:SI [(match_operand 1 "" "")
e1159bbe 4480 (match_operand 2 "s_register_operand" "r")]
4481 UNSPEC_PIC_SYM))]
cffb2a26 4482 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
849170fd 4483 "*
4484#ifdef AOF_ASSEMBLER
4485 operands[1] = aof_pic_entry (operands[1]);
4486#endif
4487 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4488 return \"\";
cffb2a26 4489 "
a2cd141b 4490 [(set_attr "type" "load1")
cffb2a26 4491 (set (attr "pool_range")
4492 (if_then_else (eq_attr "is_thumb" "yes")
4493 (const_int 1024)
4494 (const_int 4096)))
4495 (set (attr "neg_pool_range")
4496 (if_then_else (eq_attr "is_thumb" "yes")
4497 (const_int 0)
4498 (const_int 4084)))]
4499)
4500
4501(define_insn "pic_add_dot_plus_four"
4502 [(set (match_operand:SI 0 "register_operand" "+r")
2c96dc5a 4503 (unspec:SI [(plus:SI (match_dup 0)
4504 (const (plus:SI (pc) (const_int 4))))]
4505 UNSPEC_PIC_BASE))
cffb2a26 4506 (use (label_ref (match_operand 1 "" "")))]
4507 "TARGET_THUMB && flag_pic"
4508 "*
805e22b2 4509 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
cffb2a26 4510 CODE_LABEL_NUMBER (operands[1]));
4511 return \"add\\t%0, %|pc\";
4512 "
4513 [(set_attr "length" "2")]
4514)
849170fd 4515
4516(define_insn "pic_add_dot_plus_eight"
6c4c2133 4517 [(set (match_operand:SI 0 "register_operand" "+r")
2c96dc5a 4518 (unspec:SI [(plus:SI (match_dup 0)
4519 (const (plus:SI (pc) (const_int 8))))]
4520 UNSPEC_PIC_BASE))
c4034607 4521 (use (label_ref (match_operand 1 "" "")))]
cffb2a26 4522 "TARGET_ARM && flag_pic"
c4034607 4523 "*
805e22b2 4524 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
0d66636f 4525 CODE_LABEL_NUMBER (operands[1]));
4526 return \"add%?\\t%0, %|pc, %0\";
cffb2a26 4527 "
0d66636f 4528 [(set_attr "predicable" "yes")]
cffb2a26 4529)
849170fd 4530
95373f08 4531(define_expand "builtin_setjmp_receiver"
4532 [(label_ref (match_operand 0 "" ""))]
4533 "flag_pic"
4534 "
4535{
b935b306 4536 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4537 register. */
4538 arm_load_pic_register (3);
95373f08 4539 DONE;
4540}")
4541
9c08d1fa 4542;; If copying one reg to another we can set the condition codes according to
4543;; its value. Such a move is common after a return from subroutine and the
4544;; result is being tested against zero.
4545
f7fbdd4a 4546(define_insn "*movsi_compare0"
bd5b4116 4547 [(set (reg:CC CC_REGNUM)
cffb2a26 4548 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4549 (const_int 0)))
4550 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4551 (match_dup 1))]
4552 "TARGET_ARM"
e2348bcb 4553 "@
40dbec34 4554 cmp%?\\t%0, #0
4555 sub%?s\\t%0, %1, #0"
cffb2a26 4556 [(set_attr "conds" "set")]
4557)
b11cae9e 4558
b11cae9e 4559;; Subroutine to store a half word from a register into memory.
4560;; Operand 0 is the source register (HImode)
c8f69309 4561;; Operand 1 is the destination address in a register (SImode)
b11cae9e 4562
9c08d1fa 4563;; In both this routine and the next, we must be careful not to spill
01cc3b75 4564;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 4565;; can generate unrecognizable rtl.
4566
b11cae9e 4567(define_expand "storehi"
c8f69309 4568 [;; store the low byte
f082f1c4 4569 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 4570 ;; extract the high byte
c8f69309 4571 (set (match_dup 2)
4572 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 4573 ;; store the high byte
787f8210 4574 (set (match_dup 4) (match_dup 5))]
cffb2a26 4575 "TARGET_ARM"
b11cae9e 4576 "
215b30b3 4577 {
537ffcfc 4578 rtx op1 = operands[1];
4579 rtx addr = XEXP (op1, 0);
215b30b3 4580 enum rtx_code code = GET_CODE (addr);
4581
4582 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4583 || code == MINUS)
537ffcfc 4584 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 4585
537ffcfc 4586 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4587 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4588 operands[3] = gen_lowpart (QImode, operands[0]);
4589 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 4590 operands[2] = gen_reg_rtx (SImode);
4591 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4592 }"
4593)
b11cae9e 4594
c7597b5d 4595(define_expand "storehi_bigend"
f082f1c4 4596 [(set (match_dup 4) (match_dup 3))
c7597b5d 4597 (set (match_dup 2)
4598 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 4599 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 4600 "TARGET_ARM"
b11cae9e 4601 "
215b30b3 4602 {
537ffcfc 4603 rtx op1 = operands[1];
4604 rtx addr = XEXP (op1, 0);
215b30b3 4605 enum rtx_code code = GET_CODE (addr);
4606
4607 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4608 || code == MINUS)
537ffcfc 4609 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 4610
537ffcfc 4611 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4612 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4613 operands[3] = gen_lowpart (QImode, operands[0]);
4614 operands[0] = gen_lowpart (SImode, operands[0]);
4615 operands[2] = gen_reg_rtx (SImode);
787f8210 4616 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4617 }"
4618)
c7597b5d 4619
4620;; Subroutine to store a half word integer constant into memory.
4621(define_expand "storeinthi"
f082f1c4 4622 [(set (match_operand 0 "" "")
787f8210 4623 (match_operand 1 "" ""))
9e8503e6 4624 (set (match_dup 3) (match_dup 2))]
cffb2a26 4625 "TARGET_ARM"
c7597b5d 4626 "
215b30b3 4627 {
4628 HOST_WIDE_INT value = INTVAL (operands[1]);
4629 rtx addr = XEXP (operands[0], 0);
537ffcfc 4630 rtx op0 = operands[0];
215b30b3 4631 enum rtx_code code = GET_CODE (addr);
c7597b5d 4632
215b30b3 4633 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4634 || code == MINUS)
537ffcfc 4635 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 4636
215b30b3 4637 operands[1] = gen_reg_rtx (SImode);
4638 if (BYTES_BIG_ENDIAN)
4639 {
4640 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4641 if ((value & 255) == ((value >> 8) & 255))
4642 operands[2] = operands[1];
4643 else
4644 {
4645 operands[2] = gen_reg_rtx (SImode);
4646 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4647 }
4648 }
4649 else
4650 {
4651 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4652 if ((value & 255) == ((value >> 8) & 255))
4653 operands[2] = operands[1];
4654 else
4655 {
4656 operands[2] = gen_reg_rtx (SImode);
4657 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4658 }
4659 }
c7597b5d 4660
537ffcfc 4661 operands[3] = adjust_address (op0, QImode, 1);
e513d163 4662 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 4663 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 4664 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 4665 }"
4666)
b11cae9e 4667
f7fbdd4a 4668(define_expand "storehi_single_op"
4669 [(set (match_operand:HI 0 "memory_operand" "")
4670 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4671 "TARGET_ARM && arm_arch4"
f7fbdd4a 4672 "
215b30b3 4673 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 4674 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 4675 "
4676)
f7fbdd4a 4677
b11cae9e 4678(define_expand "movhi"
4679 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 4680 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4681 "TARGET_EITHER"
b11cae9e 4682 "
cffb2a26 4683 if (TARGET_ARM)
b11cae9e 4684 {
215b30b3 4685 if (!no_new_pseudos)
cffb2a26 4686 {
4687 if (GET_CODE (operands[0]) == MEM)
b11cae9e 4688 {
cffb2a26 4689 if (arm_arch4)
4690 {
4691 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4692 DONE;
4693 }
4694 if (GET_CODE (operands[1]) == CONST_INT)
4695 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 4696 else
cffb2a26 4697 {
4698 if (GET_CODE (operands[1]) == MEM)
4699 operands[1] = force_reg (HImode, operands[1]);
4700 if (BYTES_BIG_ENDIAN)
4701 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4702 else
4703 emit_insn (gen_storehi (operands[1], operands[0]));
4704 }
4705 DONE;
b11cae9e 4706 }
cffb2a26 4707 /* Sign extend a constant, and keep it in an SImode reg. */
4708 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 4709 {
cffb2a26 4710 rtx reg = gen_reg_rtx (SImode);
4711 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4712
4713 /* If the constant is already valid, leave it alone. */
215b30b3 4714 if (!const_ok_for_arm (val))
cffb2a26 4715 {
4716 /* If setting all the top bits will make the constant
4717 loadable in a single instruction, then set them.
4718 Otherwise, sign extend the number. */
4719
215b30b3 4720 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 4721 val |= ~0xffff;
4722 else if (val & 0x8000)
4723 val |= ~0xffff;
4724 }
4725
4726 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 4727 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 4728 }
615caa51 4729 else if (arm_arch4 && optimize && !no_new_pseudos
0045890a 4730 && GET_CODE (operands[1]) == MEM)
4731 {
4732 rtx reg = gen_reg_rtx (SImode);
4733
4734 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4735 operands[1] = gen_lowpart (HImode, reg);
4736 }
215b30b3 4737 else if (!arm_arch4)
f7fbdd4a 4738 {
cffb2a26 4739 if (GET_CODE (operands[1]) == MEM)
4740 {
c1a66faf 4741 rtx base;
4742 rtx offset = const0_rtx;
4743 rtx reg = gen_reg_rtx (SImode);
4744
4745 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4746 || (GET_CODE (base) == PLUS
4747 && (GET_CODE (offset = XEXP (base, 1))
4748 == CONST_INT)
4749 && ((INTVAL(offset) & 1) != 1)
4750 && GET_CODE (base = XEXP (base, 0)) == REG))
4751 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 4752 {
c1a66faf 4753 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4754 rtx new;
4755
4756 new = gen_rtx_MEM (SImode,
4757 plus_constant (base, new_offset));
4758 MEM_COPY_ATTRIBUTES (new, operands[1]);
4759 emit_insn (gen_movsi (reg, new));
4760 if (((INTVAL (offset) & 2) != 0)
4761 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4762 {
4763 rtx reg2 = gen_reg_rtx (SImode);
4764
4765 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4766 reg = reg2;
4767 }
206ee9a2 4768 }
c1a66faf 4769 else
4770 emit_insn (gen_movhi_bytes (reg, operands[1]));
4771
4772 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 4773 }
4774 }
4775 }
674a8f0b 4776 /* Handle loading a large integer during reload. */
cffb2a26 4777 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4778 && !const_ok_for_arm (INTVAL (operands[1]))
4779 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 4780 {
4781 /* Writing a constant to memory needs a scratch, which should
4782 be handled with SECONDARY_RELOADs. */
ed29c566 4783 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 4784
4785 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4786 emit_insn (gen_movsi (operands[0], operands[1]));
4787 DONE;
4788 }
4789 }
4790 else /* TARGET_THUMB */
4791 {
215b30b3 4792 if (!no_new_pseudos)
cffb2a26 4793 {
4794 if (GET_CODE (operands[0]) != REG)
4795 operands[1] = force_reg (HImode, operands[1]);
4796
4797 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 4798 happen if we are passed a SP (never OK for HImode/QImode) or
4799 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4800 HImode/QImode) relative address. */
cffb2a26 4801 /* ??? This should perhaps be fixed elsewhere, for instance, in
4802 fixup_stack_1, by checking for other kinds of invalid addresses,
4803 e.g. a bare reference to a virtual register. This may confuse the
4804 alpha though, which must handle this case differently. */
4805 if (GET_CODE (operands[0]) == MEM
215b30b3 4806 && !memory_address_p (GET_MODE (operands[0]),
4807 XEXP (operands[0], 0)))
537ffcfc 4808 operands[0]
4809 = replace_equiv_address (operands[0],
4810 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 4811
4812 if (GET_CODE (operands[1]) == MEM
215b30b3 4813 && !memory_address_p (GET_MODE (operands[1]),
4814 XEXP (operands[1], 0)))
537ffcfc 4815 operands[1]
4816 = replace_equiv_address (operands[1],
4817 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 4818 }
674a8f0b 4819 /* Handle loading a large integer during reload. */
cffb2a26 4820 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4821 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
cffb2a26 4822 {
4823 /* Writing a constant to memory needs a scratch, which should
4824 be handled with SECONDARY_RELOADs. */
ed29c566 4825 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 4826
1a83b3ff 4827 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 4828 emit_insn (gen_movsi (operands[0], operands[1]));
4829 DONE;
4830 }
b11cae9e 4831 }
cffb2a26 4832 "
4833)
4834
4835(define_insn "*thumb_movhi_insn"
a941568e 4836 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4837 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
cffb2a26 4838 "TARGET_THUMB
4839 && ( register_operand (operands[0], HImode)
4840 || register_operand (operands[1], HImode))"
4841 "*
4842 switch (which_alternative)
d79300ac 4843 {
cffb2a26 4844 case 0: return \"add %0, %1, #0\";
4845 case 2: return \"strh %1, %0\";
4846 case 3: return \"mov %0, %1\";
4847 case 4: return \"mov %0, %1\";
4848 case 5: return \"mov %0, %1\";
ed29c566 4849 default: gcc_unreachable ();
cffb2a26 4850 case 1:
4851 /* The stack pointer can end up being taken as an index register.
4852 Catch this case here and deal with it. */
4853 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4854 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4855 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4856 {
4857 rtx ops[2];
4858 ops[0] = operands[0];
4859 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4860
4861 output_asm_insn (\"mov %0, %1\", ops);
4862
4863 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4864
4865 }
4866 return \"ldrh %0, %1\";
4867 }"
4868 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 4869 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 4870)
d79300ac 4871
b11cae9e 4872
25f7a26e 4873(define_expand "movhi_bytes"
eab14235 4874 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4875 (set (match_dup 3)
eab14235 4876 (zero_extend:SI (match_dup 6)))
25f7a26e 4877 (set (match_operand:SI 0 "" "")
4878 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 4879 "TARGET_ARM"
25f7a26e 4880 "
215b30b3 4881 {
4882 rtx mem1, mem2;
4883 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4884
4885 mem1 = gen_rtx_MEM (QImode, addr);
4886 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4887 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4888 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4889 operands[0] = gen_lowpart (SImode, operands[0]);
4890 operands[1] = mem1;
4891 operands[2] = gen_reg_rtx (SImode);
4892 operands[3] = gen_reg_rtx (SImode);
4893 operands[6] = mem2;
25f7a26e 4894
215b30b3 4895 if (BYTES_BIG_ENDIAN)
4896 {
4897 operands[4] = operands[2];
4898 operands[5] = operands[3];
4899 }
4900 else
4901 {
4902 operands[4] = operands[3];
4903 operands[5] = operands[2];
4904 }
4905 }"
4906)
25f7a26e 4907
c7597b5d 4908(define_expand "movhi_bigend"
4909 [(set (match_dup 2)
4910 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4911 (const_int 16)))
4912 (set (match_dup 3)
4913 (ashiftrt:SI (match_dup 2) (const_int 16)))
4914 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 4915 (match_dup 4))]
cffb2a26 4916 "TARGET_ARM"
c7597b5d 4917 "
4918 operands[2] = gen_reg_rtx (SImode);
4919 operands[3] = gen_reg_rtx (SImode);
787f8210 4920 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 4921 "
4922)
b11cae9e 4923
a2f10574 4924;; Pattern to recognize insn generated default case above
f7fbdd4a 4925(define_insn "*movhi_insn_arch4"
cffb2a26 4926 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 4927 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 4928 "TARGET_ARM
4929 && arm_arch4
f7fbdd4a 4930 && (GET_CODE (operands[1]) != CONST_INT
4931 || const_ok_for_arm (INTVAL (operands[1]))
4932 || const_ok_for_arm (~INTVAL (operands[1])))"
4933 "@
4934 mov%?\\t%0, %1\\t%@ movhi
4935 mvn%?\\t%0, #%B1\\t%@ movhi
aed179ae 4936 str%?h\\t%1, %0\\t%@ movhi
cffb2a26 4937 ldr%?h\\t%0, %1\\t%@ movhi"
a2cd141b 4938 [(set_attr "type" "*,*,store1,load1")
0d66636f 4939 (set_attr "predicable" "yes")
cffb2a26 4940 (set_attr "pool_range" "*,*,*,256")
4941 (set_attr "neg_pool_range" "*,*,*,244")]
4942)
f7fbdd4a 4943
f7fbdd4a 4944(define_insn "*movhi_bytes"
25f7a26e 4945 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4946 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 4947 "TARGET_ARM"
25f7a26e 4948 "@
4949 mov%?\\t%0, %1\\t%@ movhi
0d66636f 4950 mvn%?\\t%0, #%B1\\t%@ movhi"
4951 [(set_attr "predicable" "yes")]
4952)
25f7a26e 4953
cffb2a26 4954(define_insn "thumb_movhi_clobber"
4955 [(set (match_operand:HI 0 "memory_operand" "=m")
4956 (match_operand:HI 1 "register_operand" "l"))
4957 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4958 "TARGET_THUMB"
344495ea 4959 "*
ed29c566 4960 gcc_unreachable ();"
cffb2a26 4961)
4962
bc5c7e08 4963;; We use a DImode scratch because we may occasionally need an additional
4964;; temporary if the address isn't offsettable -- push_reload doesn't seem
4965;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 4966(define_expand "reload_outhi"
cffb2a26 4967 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 4968 (match_operand:HI 1 "s_register_operand" "r")
4969 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 4970 "TARGET_EITHER"
4971 "if (TARGET_ARM)
4972 arm_reload_out_hi (operands);
4973 else
4974 thumb_reload_out_hi (operands);
d3373b54 4975 DONE;
cffb2a26 4976 "
4977)
d3373b54 4978
25f7a26e 4979(define_expand "reload_inhi"
4980 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 4981 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 4982 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 4983 "TARGET_EITHER"
25f7a26e 4984 "
cffb2a26 4985 if (TARGET_ARM)
4986 arm_reload_in_hi (operands);
4987 else
4988 thumb_reload_out_hi (operands);
25f7a26e 4989 DONE;
4990")
4991
9c08d1fa 4992(define_expand "movqi"
4993 [(set (match_operand:QI 0 "general_operand" "")
4994 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 4995 "TARGET_EITHER"
9c08d1fa 4996 "
cffb2a26 4997 if (TARGET_ARM)
9c08d1fa 4998 {
cffb2a26 4999 /* Everything except mem = const or mem = mem can be done easily */
c7597b5d 5000
935d87ee 5001 if (!no_new_pseudos)
cffb2a26 5002 {
5003 if (GET_CODE (operands[1]) == CONST_INT)
5004 {
5005 rtx reg = gen_reg_rtx (SImode);
5006
5007 emit_insn (gen_movsi (reg, operands[1]));
9e8503e6 5008 operands[1] = gen_lowpart (QImode, reg);
cffb2a26 5009 }
0045890a 5010 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5011 {
5012 rtx reg = gen_reg_rtx (SImode);
5013
5014 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5015 operands[1] = gen_lowpart (QImode, reg);
5016 }
5017 if (GET_CODE (operands[0]) == MEM)
5018 operands[1] = force_reg (QImode, operands[1]);
5019 }
b11cae9e 5020 }
cffb2a26 5021 else /* TARGET_THUMB */
5022 {
215b30b3 5023 if (!no_new_pseudos)
cffb2a26 5024 {
5025 if (GET_CODE (operands[0]) != REG)
5026 operands[1] = force_reg (QImode, operands[1]);
5027
5028 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5029 happen if we are passed a SP (never OK for HImode/QImode) or
5030 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5031 HImode/QImode) relative address. */
cffb2a26 5032 /* ??? This should perhaps be fixed elsewhere, for instance, in
5033 fixup_stack_1, by checking for other kinds of invalid addresses,
5034 e.g. a bare reference to a virtual register. This may confuse the
5035 alpha though, which must handle this case differently. */
5036 if (GET_CODE (operands[0]) == MEM
215b30b3 5037 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5038 XEXP (operands[0], 0)))
537ffcfc 5039 operands[0]
5040 = replace_equiv_address (operands[0],
5041 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5042 if (GET_CODE (operands[1]) == MEM
5043 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5044 XEXP (operands[1], 0)))
537ffcfc 5045 operands[1]
5046 = replace_equiv_address (operands[1],
5047 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 5048 }
674a8f0b 5049 /* Handle loading a large integer during reload. */
cffb2a26 5050 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5051 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
cffb2a26 5052 {
5053 /* Writing a constant to memory needs a scratch, which should
5054 be handled with SECONDARY_RELOADs. */
ed29c566 5055 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5056
9e8503e6 5057 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5058 emit_insn (gen_movsi (operands[0], operands[1]));
5059 DONE;
5060 }
5061 }
5062 "
5063)
b11cae9e 5064
9c08d1fa 5065
cffb2a26 5066(define_insn "*arm_movqi_insn"
5067 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5068 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
cffb2a26 5069 "TARGET_ARM
5070 && ( register_operand (operands[0], QImode)
5071 || register_operand (operands[1], QImode))"
5565501b 5072 "@
5073 mov%?\\t%0, %1
5074 mvn%?\\t%0, #%B1
5075 ldr%?b\\t%0, %1
5076 str%?b\\t%1, %0"
a2cd141b 5077 [(set_attr "type" "*,*,load1,store1")
0d66636f 5078 (set_attr "predicable" "yes")]
cffb2a26 5079)
5080
5081(define_insn "*thumb_movqi_insn"
5082 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5083 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
cffb2a26 5084 "TARGET_THUMB
5085 && ( register_operand (operands[0], QImode)
5086 || register_operand (operands[1], QImode))"
5087 "@
5088 add\\t%0, %1, #0
5089 ldrb\\t%0, %1
5090 strb\\t%1, %0
5091 mov\\t%0, %1
5092 mov\\t%0, %1
5093 mov\\t%0, %1"
5094 [(set_attr "length" "2")
a2cd141b 5095 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5096 (set_attr "pool_range" "*,32,*,*,*,*")]
5097)
b11cae9e 5098
87b22bf7 5099(define_expand "movsf"
5100 [(set (match_operand:SF 0 "general_operand" "")
5101 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5102 "TARGET_EITHER"
87b22bf7 5103 "
cffb2a26 5104 if (TARGET_ARM)
5105 {
5106 if (GET_CODE (operands[0]) == MEM)
5107 operands[1] = force_reg (SFmode, operands[1]);
5108 }
5109 else /* TARGET_THUMB */
5110 {
215b30b3 5111 if (!no_new_pseudos)
cffb2a26 5112 {
5113 if (GET_CODE (operands[0]) != REG)
5114 operands[1] = force_reg (SFmode, operands[1]);
5115 }
5116 }
5117 "
5118)
5119
5120(define_split
5121 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5122 (match_operand:SF 1 "immediate_operand" ""))]
5123 "TARGET_ARM
a2cd141b 5124 && !(TARGET_HARD_FLOAT && TARGET_FPA)
cffb2a26 5125 && reload_completed
5126 && GET_CODE (operands[1]) == CONST_DOUBLE"
5127 [(set (match_dup 2) (match_dup 3))]
5128 "
5129 operands[2] = gen_lowpart (SImode, operands[0]);
5130 operands[3] = gen_lowpart (SImode, operands[1]);
5131 if (operands[2] == 0 || operands[3] == 0)
5132 FAIL;
215b30b3 5133 "
5134)
87b22bf7 5135
cffb2a26 5136(define_insn "*arm_movsf_soft_insn"
5137 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5138 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5139 "TARGET_ARM
5140 && TARGET_SOFT_FLOAT
215b30b3 5141 && (GET_CODE (operands[0]) != MEM
5142 || register_operand (operands[1], SFmode))"
9a1112d7 5143 "@
5144 mov%?\\t%0, %1
5145 ldr%?\\t%0, %1\\t%@ float
5146 str%?\\t%1, %0\\t%@ float"
cffb2a26 5147 [(set_attr "length" "4,4,4")
0d66636f 5148 (set_attr "predicable" "yes")
a2cd141b 5149 (set_attr "type" "*,load1,store1")
cffb2a26 5150 (set_attr "pool_range" "*,4096,*")
5151 (set_attr "neg_pool_range" "*,4084,*")]
5152)
5153
5154;;; ??? This should have alternatives for constants.
5155(define_insn "*thumb_movsf_insn"
215b30b3 5156 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5157 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
cffb2a26 5158 "TARGET_THUMB
5159 && ( register_operand (operands[0], SFmode)
5160 || register_operand (operands[1], SFmode))"
5161 "@
5162 add\\t%0, %1, #0
5163 ldmia\\t%1, {%0}
5164 stmia\\t%0, {%1}
5165 ldr\\t%0, %1
5166 str\\t%1, %0
5167 mov\\t%0, %1
5168 mov\\t%0, %1"
5169 [(set_attr "length" "2")
a2cd141b 5170 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 5171 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5172)
9a1112d7 5173
9c08d1fa 5174(define_expand "movdf"
87b22bf7 5175 [(set (match_operand:DF 0 "general_operand" "")
5176 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5177 "TARGET_EITHER"
9c08d1fa 5178 "
cffb2a26 5179 if (TARGET_ARM)
5180 {
5181 if (GET_CODE (operands[0]) == MEM)
5182 operands[1] = force_reg (DFmode, operands[1]);
5183 }
5184 else /* TARGET_THUMB */
5185 {
215b30b3 5186 if (!no_new_pseudos)
cffb2a26 5187 {
5188 if (GET_CODE (operands[0]) != REG)
5189 operands[1] = force_reg (DFmode, operands[1]);
5190 }
5191 }
5192 "
5193)
b11cae9e 5194
9c08d1fa 5195;; Reloading a df mode value stored in integer regs to memory can require a
5196;; scratch reg.
5197(define_expand "reload_outdf"
cffb2a26 5198 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5199 (match_operand:DF 1 "s_register_operand" "r")
5200 (match_operand:SI 2 "s_register_operand" "=&r")]
cffb2a26 5201 "TARGET_ARM"
87b22bf7 5202 "
215b30b3 5203 {
5204 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5205
215b30b3 5206 if (code == REG)
5207 operands[2] = XEXP (operands[0], 0);
5208 else if (code == POST_INC || code == PRE_DEC)
5209 {
5210 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5211 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5212 emit_insn (gen_movdi (operands[0], operands[1]));
5213 DONE;
5214 }
5215 else if (code == PRE_INC)
5216 {
5217 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5218
215b30b3 5219 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5220 operands[2] = reg;
5221 }
5222 else if (code == POST_DEC)
5223 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5224 else
5225 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5226 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5227
215b30b3 5228 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5229 operands[1]));
f7fbdd4a 5230
215b30b3 5231 if (code == POST_DEC)
5232 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5233
5234 DONE;
5235 }"
5236)
9c08d1fa 5237
9a1112d7 5238(define_insn "*movdf_soft_insn"
359a6e9f 5239 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5240 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 5241 "TARGET_ARM && TARGET_SOFT_FLOAT
5242 "
d51f92df 5243 "*
5244 switch (which_alternative)
5245 {
5246 case 0:
5247 case 1:
5248 case 2:
5249 return \"#\";
5250 default:
5251 return output_move_double (operands);
5252 }
5253 "
359a6e9f 5254 [(set_attr "length" "8,12,16,8,8")
5255 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 5256 (set_attr "pool_range" "1020")
5257 (set_attr "neg_pool_range" "1008")]
cffb2a26 5258)
5259
5260;;; ??? This should have alternatives for constants.
5261;;; ??? This was originally identical to the movdi_insn pattern.
5262;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5263;;; thumb_reorg with a memory reference.
5264(define_insn "*thumb_movdf_insn"
215b30b3 5265 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5266 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
cffb2a26 5267 "TARGET_THUMB
5268 && ( register_operand (operands[0], DFmode)
5269 || register_operand (operands[1], DFmode))"
5270 "*
5271 switch (which_alternative)
5272 {
5273 default:
5274 case 0:
5275 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5276 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5277 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5278 case 1:
5279 return \"ldmia\\t%1, {%0, %H0}\";
5280 case 2:
5281 return \"stmia\\t%0, {%1, %H1}\";
5282 case 3:
5283 return thumb_load_double_from_address (operands);
5284 case 4:
1a83b3ff 5285 operands[2] = gen_rtx_MEM (SImode,
5286 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5287 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5288 return \"\";
5289 case 5:
5290 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5291 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5292 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5293 }
5294 "
5295 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 5296 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 5297 (set_attr "pool_range" "*,*,*,1020,*,*")]
5298)
755eb2b4 5299
ccd90aaa 5300(define_expand "movxf"
5301 [(set (match_operand:XF 0 "general_operand" "")
5302 (match_operand:XF 1 "general_operand" ""))]
5303 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5304 "
5305 if (GET_CODE (operands[0]) == MEM)
5306 operands[1] = force_reg (XFmode, operands[1]);
5307 "
5308)
5309
755eb2b4 5310;; Vector Moves
5311(define_expand "movv2si"
5312 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5313 (match_operand:V2SI 1 "general_operand" ""))]
5314 "TARGET_REALLY_IWMMXT"
5315{
5316})
5317
5318(define_expand "movv4hi"
5319 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5320 (match_operand:V4HI 1 "general_operand" ""))]
5321 "TARGET_REALLY_IWMMXT"
5322{
5323})
5324
5325(define_expand "movv8qi"
5326 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5327 (match_operand:V8QI 1 "general_operand" ""))]
5328 "TARGET_REALLY_IWMMXT"
5329{
5330})
b11cae9e 5331\f
b11cae9e 5332
9c08d1fa 5333;; load- and store-multiple insns
5334;; The arm can load/store any set of registers, provided that they are in
5335;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 5336
9c08d1fa 5337(define_expand "load_multiple"
5338 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5339 (match_operand:SI 1 "" ""))
5340 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5341 "TARGET_ARM"
9580c25f 5342{
5343 HOST_WIDE_INT offset = 0;
5344
bd5b4116 5345 /* Support only fixed point registers. */
9c08d1fa 5346 if (GET_CODE (operands[2]) != CONST_INT
5347 || INTVAL (operands[2]) > 14
5348 || INTVAL (operands[2]) < 2
5349 || GET_CODE (operands[1]) != MEM
5350 || GET_CODE (operands[0]) != REG
bd5b4116 5351 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5352 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5353 FAIL;
5354
5355 operands[3]
f082f1c4 5356 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5357 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 5358 TRUE, FALSE, operands[1], &offset);
5359})
b11cae9e 5360
9c08d1fa 5361;; Load multiple with write-back
5362
2162064c 5363(define_insn "*ldmsi_postinc4"
9c08d1fa 5364 [(match_parallel 0 "load_multiple_operation"
13e9316a 5365 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5366 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5367 (const_int 16)))
5368 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5369 (mem:SI (match_dup 2)))
a0a72ac3 5370 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 5371 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5372 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5373 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5374 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5375 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5376 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5377 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
a2cd141b 5378 [(set_attr "type" "load4")
2162064c 5379 (set_attr "predicable" "yes")]
5380)
b11cae9e 5381
ccd90aaa 5382(define_insn "*ldmsi_postinc4_thumb"
5383 [(match_parallel 0 "load_multiple_operation"
5384 [(set (match_operand:SI 1 "s_register_operand" "=l")
5385 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5386 (const_int 16)))
5387 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5388 (mem:SI (match_dup 2)))
5389 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5390 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5391 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5392 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5393 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5394 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5395 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5396 "ldmia\\t%1!, {%3, %4, %5, %6}"
5397 [(set_attr "type" "load4")]
5398)
5399
2162064c 5400(define_insn "*ldmsi_postinc3"
5401 [(match_parallel 0 "load_multiple_operation"
13e9316a 5402 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5403 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5404 (const_int 12)))
5405 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5406 (mem:SI (match_dup 2)))
5407 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5408 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5409 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5410 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5411 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5412 "ldm%?ia\\t%1!, {%3, %4, %5}"
a2cd141b 5413 [(set_attr "type" "load3")
2162064c 5414 (set_attr "predicable" "yes")]
5415)
b11cae9e 5416
2162064c 5417(define_insn "*ldmsi_postinc2"
5418 [(match_parallel 0 "load_multiple_operation"
13e9316a 5419 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5420 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5421 (const_int 8)))
5422 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5423 (mem:SI (match_dup 2)))
5424 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5425 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5426 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5427 "ldm%?ia\\t%1!, {%3, %4}"
a2cd141b 5428 [(set_attr "type" "load2")
0d66636f 5429 (set_attr "predicable" "yes")]
5430)
b11cae9e 5431
9c08d1fa 5432;; Ordinary load multiple
b11cae9e 5433
2162064c 5434(define_insn "*ldmsi4"
9c08d1fa 5435 [(match_parallel 0 "load_multiple_operation"
2162064c 5436 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5437 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5438 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5439 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5440 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5441 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5442 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5443 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5444 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5445 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
a2cd141b 5446 [(set_attr "type" "load4")
2162064c 5447 (set_attr "predicable" "yes")]
5448)
9c08d1fa 5449
2162064c 5450(define_insn "*ldmsi3"
5451 [(match_parallel 0 "load_multiple_operation"
5452 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5453 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5454 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5455 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5456 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5457 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5458 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5459 "ldm%?ia\\t%1, {%2, %3, %4}"
a2cd141b 5460 [(set_attr "type" "load3")
2162064c 5461 (set_attr "predicable" "yes")]
5462)
9c08d1fa 5463
2162064c 5464(define_insn "*ldmsi2"
5465 [(match_parallel 0 "load_multiple_operation"
5466 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5467 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5468 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5469 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5470 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5471 "ldm%?ia\\t%1, {%2, %3}"
a2cd141b 5472 [(set_attr "type" "load2")
0d66636f 5473 (set_attr "predicable" "yes")]
5474)
9c08d1fa 5475
5476(define_expand "store_multiple"
5477 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5478 (match_operand:SI 1 "" ""))
5479 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5480 "TARGET_ARM"
9580c25f 5481{
5482 HOST_WIDE_INT offset = 0;
5483
674a8f0b 5484 /* Support only fixed point registers. */
9c08d1fa 5485 if (GET_CODE (operands[2]) != CONST_INT
5486 || INTVAL (operands[2]) > 14
5487 || INTVAL (operands[2]) < 2
5488 || GET_CODE (operands[1]) != REG
5489 || GET_CODE (operands[0]) != MEM
bd5b4116 5490 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5491 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5492 FAIL;
5493
5494 operands[3]
f082f1c4 5495 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5496 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 5497 TRUE, FALSE, operands[0], &offset);
5498})
b11cae9e 5499
9c08d1fa 5500;; Store multiple with write-back
5501
2162064c 5502(define_insn "*stmsi_postinc4"
9c08d1fa 5503 [(match_parallel 0 "store_multiple_operation"
13e9316a 5504 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5505 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5506 (const_int 16)))
a0a72ac3 5507 (set (mem:SI (match_dup 2))
2162064c 5508 (match_operand:SI 3 "arm_hard_register_operand" ""))
5509 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5510 (match_operand:SI 4 "arm_hard_register_operand" ""))
5511 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5512 (match_operand:SI 5 "arm_hard_register_operand" ""))
5513 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5514 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5515 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5516 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5517 [(set_attr "predicable" "yes")
5518 (set_attr "type" "store4")]
5519)
b11cae9e 5520
ccd90aaa 5521(define_insn "*stmsi_postinc4_thumb"
5522 [(match_parallel 0 "store_multiple_operation"
5523 [(set (match_operand:SI 1 "s_register_operand" "=l")
5524 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5525 (const_int 16)))
5526 (set (mem:SI (match_dup 2))
5527 (match_operand:SI 3 "arm_hard_register_operand" ""))
5528 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5529 (match_operand:SI 4 "arm_hard_register_operand" ""))
5530 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5531 (match_operand:SI 5 "arm_hard_register_operand" ""))
5532 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5533 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5534 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5535 "stmia\\t%1!, {%3, %4, %5, %6}"
5536 [(set_attr "type" "store4")]
5537)
5538
2162064c 5539(define_insn "*stmsi_postinc3"
5540 [(match_parallel 0 "store_multiple_operation"
13e9316a 5541 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5542 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5543 (const_int 12)))
5544 (set (mem:SI (match_dup 2))
5545 (match_operand:SI 3 "arm_hard_register_operand" ""))
5546 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5547 (match_operand:SI 4 "arm_hard_register_operand" ""))
5548 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5549 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5550 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5551 "stm%?ia\\t%1!, {%3, %4, %5}"
5552 [(set_attr "predicable" "yes")
5553 (set_attr "type" "store3")]
5554)
9c08d1fa 5555
2162064c 5556(define_insn "*stmsi_postinc2"
5557 [(match_parallel 0 "store_multiple_operation"
13e9316a 5558 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5559 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5560 (const_int 8)))
5561 (set (mem:SI (match_dup 2))
5562 (match_operand:SI 3 "arm_hard_register_operand" ""))
5563 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5564 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5565 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5566 "stm%?ia\\t%1!, {%3, %4}"
0d66636f 5567 [(set_attr "predicable" "yes")
2162064c 5568 (set_attr "type" "store2")]
cffb2a26 5569)
9c08d1fa 5570
5571;; Ordinary store multiple
5572
2162064c 5573(define_insn "*stmsi4"
9c08d1fa 5574 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 5575 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 5576 (match_operand:SI 2 "arm_hard_register_operand" ""))
5577 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5578 (match_operand:SI 3 "arm_hard_register_operand" ""))
5579 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5580 (match_operand:SI 4 "arm_hard_register_operand" ""))
5581 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5582 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5583 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5584 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5585 [(set_attr "predicable" "yes")
5586 (set_attr "type" "store4")]
5587)
9c08d1fa 5588
2162064c 5589(define_insn "*stmsi3"
5590 [(match_parallel 0 "store_multiple_operation"
5591 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5592 (match_operand:SI 2 "arm_hard_register_operand" ""))
5593 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5594 (match_operand:SI 3 "arm_hard_register_operand" ""))
5595 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5596 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5597 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5598 "stm%?ia\\t%1, {%2, %3, %4}"
5599 [(set_attr "predicable" "yes")
5600 (set_attr "type" "store3")]
5601)
9c08d1fa 5602
2162064c 5603(define_insn "*stmsi2"
5604 [(match_parallel 0 "store_multiple_operation"
5605 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5606 (match_operand:SI 2 "arm_hard_register_operand" ""))
5607 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5608 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5609 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5610 "stm%?ia\\t%1, {%2, %3}"
0d66636f 5611 [(set_attr "predicable" "yes")
2162064c 5612 (set_attr "type" "store2")]
cffb2a26 5613)
9c08d1fa 5614
5615;; Move a block of memory if it is word aligned and MORE than 2 words long.
5616;; We could let this apply for blocks of less than this, but it clobbers so
5617;; many registers that there is then probably a better way.
5618
008c057d 5619(define_expand "movmemqi"
34191dd1 5620 [(match_operand:BLK 0 "general_operand" "")
5621 (match_operand:BLK 1 "general_operand" "")
5622 (match_operand:SI 2 "const_int_operand" "")
5623 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 5624 "TARGET_EITHER"
9c08d1fa 5625 "
cffb2a26 5626 if (TARGET_ARM)
5627 {
008c057d 5628 if (arm_gen_movmemqi (operands))
cffb2a26 5629 DONE;
5630 FAIL;
5631 }
5632 else /* TARGET_THUMB */
5633 {
5634 if ( INTVAL (operands[3]) != 4
5635 || INTVAL (operands[2]) > 48)
5636 FAIL;
5637
008c057d 5638 thumb_expand_movmemqi (operands);
cffb2a26 5639 DONE;
5640 }
5641 "
5642)
5643
2162064c 5644;; Thumb block-move insns
cffb2a26 5645
5646(define_insn "movmem12b"
960f3acf 5647 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5648 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5649 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5650 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5651 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5652 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5653 (set (match_operand:SI 0 "register_operand" "=l")
5654 (plus:SI (match_dup 2) (const_int 12)))
5655 (set (match_operand:SI 1 "register_operand" "=l")
5656 (plus:SI (match_dup 3) (const_int 12)))
5657 (clobber (match_scratch:SI 4 "=&l"))
5658 (clobber (match_scratch:SI 5 "=&l"))
5659 (clobber (match_scratch:SI 6 "=&l"))]
cffb2a26 5660 "TARGET_THUMB"
5661 "* return thumb_output_move_mem_multiple (3, operands);"
5662 [(set_attr "length" "4")
215b30b3 5663 ; This isn't entirely accurate... It loads as well, but in terms of
5664 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5665 (set_attr "type" "store3")]
5666)
5667
5668(define_insn "movmem8b"
960f3acf 5669 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5670 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5671 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5672 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5673 (set (match_operand:SI 0 "register_operand" "=l")
5674 (plus:SI (match_dup 2) (const_int 8)))
5675 (set (match_operand:SI 1 "register_operand" "=l")
5676 (plus:SI (match_dup 3) (const_int 8)))
5677 (clobber (match_scratch:SI 4 "=&l"))
5678 (clobber (match_scratch:SI 5 "=&l"))]
cffb2a26 5679 "TARGET_THUMB"
5680 "* return thumb_output_move_mem_multiple (2, operands);"
5681 [(set_attr "length" "4")
215b30b3 5682 ; This isn't entirely accurate... It loads as well, but in terms of
5683 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5684 (set_attr "type" "store2")]
5685)
5686
9c08d1fa 5687\f
b11cae9e 5688
341940e8 5689;; Compare & branch insns
8d232dc7 5690;; The range calculations are based as follows:
341940e8 5691;; For forward branches, the address calculation returns the address of
5692;; the next instruction. This is 2 beyond the branch instruction.
5693;; For backward branches, the address calculation returns the address of
5694;; the first instruction in this pattern (cmp). This is 2 before the branch
5695;; instruction for the shortest sequence, and 4 before the branch instruction
5696;; if we have to jump around an unconditional branch.
5697;; To the basic branch range the PC offset must be added (this is +4).
5698;; So for forward branches we have
5699;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5700;; And for backward branches we have
5701;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5702;;
5703;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5704;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 5705
aeac46d4 5706(define_expand "cbranchsi4"
5707 [(set (pc) (if_then_else
5708 (match_operator 0 "arm_comparison_operator"
5709 [(match_operand:SI 1 "s_register_operand" "")
5710 (match_operand:SI 2 "nonmemory_operand" "")])
5711 (label_ref (match_operand 3 "" ""))
5712 (pc)))]
5713 "TARGET_THUMB"
5714 "
5715 if (thumb_cmpneg_operand (operands[2], SImode))
5716 {
5717 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5718 operands[3], operands[0]));
5719 DONE;
5720 }
5721 if (!thumb_cmp_operand (operands[2], SImode))
5722 operands[2] = force_reg (SImode, operands[2]);
5723 ")
5724
5725(define_insn "*cbranchsi4_insn"
5726 [(set (pc) (if_then_else
5727 (match_operator 0 "arm_comparison_operator"
5728 [(match_operand:SI 1 "s_register_operand" "l,*h")
5729 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5730 (label_ref (match_operand 3 "" ""))
5731 (pc)))]
cffb2a26 5732 "TARGET_THUMB"
5733 "*
5734 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 5735
cffb2a26 5736 switch (get_attr_length (insn))
5737 {
5738 case 4: return \"b%d0\\t%l3\";
5739 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5740 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5741 }
5742 "
5743 [(set (attr "far_jump")
5744 (if_then_else
5745 (eq_attr "length" "8")
5746 (const_string "yes")
5747 (const_string "no")))
5748 (set (attr "length")
5749 (if_then_else
5750 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5751 (le (minus (match_dup 3) (pc)) (const_int 256)))
5752 (const_int 4)
5753 (if_then_else
5754 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 5755 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5756 (const_int 6)
5757 (const_int 8))))]
5758)
5759
aeac46d4 5760(define_insn "cbranchsi4_scratch"
5761 [(set (pc) (if_then_else
5762 (match_operator 4 "arm_comparison_operator"
5763 [(match_operand:SI 1 "s_register_operand" "l,0")
5764 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5765 (label_ref (match_operand 3 "" ""))
5766 (pc)))
5767 (clobber (match_scratch:SI 0 "=l,l"))]
5768 "TARGET_THUMB"
5769 "*
5770 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5771
5772 switch (get_attr_length (insn))
5773 {
5774 case 4: return \"b%d4\\t%l3\";
5775 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5776 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5777 }
5778 "
5779 [(set (attr "far_jump")
5780 (if_then_else
5781 (eq_attr "length" "8")
5782 (const_string "yes")
5783 (const_string "no")))
5784 (set (attr "length")
5785 (if_then_else
5786 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5787 (le (minus (match_dup 3) (pc)) (const_int 256)))
5788 (const_int 4)
5789 (if_then_else
5790 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5791 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5792 (const_int 6)
5793 (const_int 8))))]
5794)
5795(define_insn "*movsi_cbranchsi4"
5796 [(set (pc)
5797 (if_then_else
5798 (match_operator 3 "arm_comparison_operator"
5799 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5800 (const_int 0)])
5801 (label_ref (match_operand 2 "" ""))
5802 (pc)))
5803 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5804 (match_dup 1))]
5805 "TARGET_THUMB"
5806 "*{
5807 if (which_alternative == 0)
5808 output_asm_insn (\"cmp\t%0, #0\", operands);
5809 else if (which_alternative == 1)
5810 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5811 else
5812 {
5813 output_asm_insn (\"cmp\t%1, #0\", operands);
5814 if (which_alternative == 2)
5815 output_asm_insn (\"mov\t%0, %1\", operands);
5816 else
5817 output_asm_insn (\"str\t%1, %0\", operands);
5818 }
5819 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5820 {
5821 case 4: return \"b%d3\\t%l2\";
5822 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5823 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5824 }
5825 }"
5826 [(set (attr "far_jump")
5827 (if_then_else
5828 (ior (and (gt (symbol_ref ("which_alternative"))
5829 (const_int 1))
5830 (eq_attr "length" "8"))
5831 (eq_attr "length" "10"))
5832 (const_string "yes")
5833 (const_string "no")))
5834 (set (attr "length")
5835 (if_then_else
5836 (le (symbol_ref ("which_alternative"))
5837 (const_int 1))
5838 (if_then_else
5839 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5840 (le (minus (match_dup 2) (pc)) (const_int 256)))
5841 (const_int 4)
5842 (if_then_else
5843 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5844 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5845 (const_int 6)
5846 (const_int 8)))
5847 (if_then_else
5848 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5849 (le (minus (match_dup 2) (pc)) (const_int 256)))
5850 (const_int 6)
5851 (if_then_else
5852 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5853 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5854 (const_int 8)
5855 (const_int 10)))))]
5856)
5857
cffb2a26 5858(define_insn "*negated_cbranchsi4"
5859 [(set (pc)
5860 (if_then_else
aed179ae 5861 (match_operator 0 "equality_operator"
aeac46d4 5862 [(match_operand:SI 1 "s_register_operand" "l")
5863 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5864 (label_ref (match_operand 3 "" ""))
215b30b3 5865 (pc)))]
cffb2a26 5866 "TARGET_THUMB"
5867 "*
5868 output_asm_insn (\"cmn\\t%1, %2\", operands);
5869 switch (get_attr_length (insn))
5870 {
5871 case 4: return \"b%d0\\t%l3\";
5872 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5873 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5874 }
5875 "
5876 [(set (attr "far_jump")
5877 (if_then_else
5878 (eq_attr "length" "8")
5879 (const_string "yes")
5880 (const_string "no")))
5881 (set (attr "length")
5882 (if_then_else
5883 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 5884 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 5885 (const_int 4)
5886 (if_then_else
341940e8 5887 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5888 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5889 (const_int 6)
5890 (const_int 8))))]
5891)
5892
58d6528b 5893(define_insn "*tbit_cbranch"
5894 [(set (pc)
5895 (if_then_else
5896 (match_operator 0 "equality_operator"
5897 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5898 (const_int 1)
5899 (match_operand:SI 2 "const_int_operand" "i"))
5900 (const_int 0)])
5901 (label_ref (match_operand 3 "" ""))
5902 (pc)))
5903 (clobber (match_scratch:SI 4 "=l"))]
5904 "TARGET_THUMB"
5905 "*
5906 {
5907 rtx op[3];
5908 op[0] = operands[4];
5909 op[1] = operands[1];
5910 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5911
5912 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5913 switch (get_attr_length (insn))
5914 {
5915 case 4: return \"b%d0\\t%l3\";
5916 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5917 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5918 }
5919 }"
5920 [(set (attr "far_jump")
5921 (if_then_else
5922 (eq_attr "length" "8")
5923 (const_string "yes")
5924 (const_string "no")))
5925 (set (attr "length")
5926 (if_then_else
5927 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5928 (le (minus (match_dup 3) (pc)) (const_int 256)))
5929 (const_int 4)
5930 (if_then_else
5931 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5932 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5933 (const_int 6)
5934 (const_int 8))))]
5935)
5936
aeac46d4 5937(define_insn "*tstsi3_cbranch"
58d6528b 5938 [(set (pc)
5939 (if_then_else
aeac46d4 5940 (match_operator 3 "equality_operator"
5941 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5942 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 5943 (const_int 0)])
aeac46d4 5944 (label_ref (match_operand 2 "" ""))
5945 (pc)))]
58d6528b 5946 "TARGET_THUMB"
5947 "*
5948 {
aeac46d4 5949 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 5950 switch (get_attr_length (insn))
5951 {
aeac46d4 5952 case 4: return \"b%d3\\t%l2\";
5953 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5954 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 5955 }
5956 }"
5957 [(set (attr "far_jump")
5958 (if_then_else
5959 (eq_attr "length" "8")
5960 (const_string "yes")
5961 (const_string "no")))
5962 (set (attr "length")
5963 (if_then_else
aeac46d4 5964 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5965 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 5966 (const_int 4)
5967 (if_then_else
aeac46d4 5968 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5969 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 5970 (const_int 6)
5971 (const_int 8))))]
5972)
5973
5974(define_insn "*andsi3_cbranch"
5975 [(set (pc)
5976 (if_then_else
5977 (match_operator 5 "equality_operator"
5978 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5979 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5980 (const_int 0)])
5981 (label_ref (match_operand 4 "" ""))
5982 (pc)))
aeac46d4 5983 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 5984 (and:SI (match_dup 2) (match_dup 3)))
5985 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5986 "TARGET_THUMB"
5987 "*
5988 {
5989 if (which_alternative == 0)
5990 output_asm_insn (\"and\\t%0, %3\", operands);
5991 else if (which_alternative == 1)
5992 {
5993 output_asm_insn (\"and\\t%1, %3\", operands);
5994 output_asm_insn (\"mov\\t%0, %1\", operands);
5995 }
5996 else
5997 {
5998 output_asm_insn (\"and\\t%1, %3\", operands);
5999 output_asm_insn (\"str\\t%1, %0\", operands);
6000 }
6001
6002 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6003 {
6004 case 4: return \"b%d5\\t%l4\";
6005 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6006 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6007 }
6008 }"
6009 [(set (attr "far_jump")
6010 (if_then_else
6011 (ior (and (eq (symbol_ref ("which_alternative"))
6012 (const_int 0))
6013 (eq_attr "length" "8"))
6014 (eq_attr "length" "10"))
6015 (const_string "yes")
6016 (const_string "no")))
6017 (set (attr "length")
6018 (if_then_else
6019 (eq (symbol_ref ("which_alternative"))
6020 (const_int 0))
6021 (if_then_else
6022 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6023 (le (minus (match_dup 4) (pc)) (const_int 256)))
6024 (const_int 4)
6025 (if_then_else
6026 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6027 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6028 (const_int 6)
6029 (const_int 8)))
6030 (if_then_else
6031 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6032 (le (minus (match_dup 4) (pc)) (const_int 256)))
6033 (const_int 6)
6034 (if_then_else
6035 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6036 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6037 (const_int 8)
6038 (const_int 10)))))]
6039)
6040
6041(define_insn "*orrsi3_cbranch_scratch"
6042 [(set (pc)
6043 (if_then_else
6044 (match_operator 4 "equality_operator"
6045 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6046 (match_operand:SI 2 "s_register_operand" "l"))
6047 (const_int 0)])
6048 (label_ref (match_operand 3 "" ""))
6049 (pc)))
6050 (clobber (match_scratch:SI 0 "=l"))]
6051 "TARGET_THUMB"
6052 "*
6053 {
6054 output_asm_insn (\"orr\\t%0, %2\", operands);
6055 switch (get_attr_length (insn))
6056 {
6057 case 4: return \"b%d4\\t%l3\";
6058 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6059 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6060 }
6061 }"
6062 [(set (attr "far_jump")
6063 (if_then_else
6064 (eq_attr "length" "8")
6065 (const_string "yes")
6066 (const_string "no")))
6067 (set (attr "length")
6068 (if_then_else
6069 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6070 (le (minus (match_dup 3) (pc)) (const_int 256)))
6071 (const_int 4)
6072 (if_then_else
6073 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6074 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6075 (const_int 6)
6076 (const_int 8))))]
6077)
6078
6079(define_insn "*orrsi3_cbranch"
6080 [(set (pc)
6081 (if_then_else
6082 (match_operator 5 "equality_operator"
6083 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6084 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6085 (const_int 0)])
6086 (label_ref (match_operand 4 "" ""))
6087 (pc)))
aeac46d4 6088 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6089 (ior:SI (match_dup 2) (match_dup 3)))
6090 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6091 "TARGET_THUMB"
6092 "*
6093 {
6094 if (which_alternative == 0)
6095 output_asm_insn (\"orr\\t%0, %3\", operands);
6096 else if (which_alternative == 1)
6097 {
6098 output_asm_insn (\"orr\\t%1, %3\", operands);
6099 output_asm_insn (\"mov\\t%0, %1\", operands);
6100 }
6101 else
6102 {
6103 output_asm_insn (\"orr\\t%1, %3\", operands);
6104 output_asm_insn (\"str\\t%1, %0\", operands);
6105 }
6106
6107 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6108 {
6109 case 4: return \"b%d5\\t%l4\";
6110 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6111 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6112 }
6113 }"
6114 [(set (attr "far_jump")
6115 (if_then_else
6116 (ior (and (eq (symbol_ref ("which_alternative"))
6117 (const_int 0))
6118 (eq_attr "length" "8"))
6119 (eq_attr "length" "10"))
6120 (const_string "yes")
6121 (const_string "no")))
6122 (set (attr "length")
6123 (if_then_else
6124 (eq (symbol_ref ("which_alternative"))
6125 (const_int 0))
6126 (if_then_else
6127 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6128 (le (minus (match_dup 4) (pc)) (const_int 256)))
6129 (const_int 4)
6130 (if_then_else
6131 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6132 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6133 (const_int 6)
6134 (const_int 8)))
6135 (if_then_else
6136 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6137 (le (minus (match_dup 4) (pc)) (const_int 256)))
6138 (const_int 6)
6139 (if_then_else
6140 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6141 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6142 (const_int 8)
6143 (const_int 10)))))]
6144)
6145
6146(define_insn "*xorsi3_cbranch_scratch"
6147 [(set (pc)
6148 (if_then_else
6149 (match_operator 4 "equality_operator"
6150 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6151 (match_operand:SI 2 "s_register_operand" "l"))
6152 (const_int 0)])
6153 (label_ref (match_operand 3 "" ""))
6154 (pc)))
6155 (clobber (match_scratch:SI 0 "=l"))]
6156 "TARGET_THUMB"
6157 "*
6158 {
6159 output_asm_insn (\"eor\\t%0, %2\", operands);
6160 switch (get_attr_length (insn))
6161 {
6162 case 4: return \"b%d4\\t%l3\";
6163 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6164 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6165 }
6166 }"
6167 [(set (attr "far_jump")
6168 (if_then_else
6169 (eq_attr "length" "8")
6170 (const_string "yes")
6171 (const_string "no")))
6172 (set (attr "length")
6173 (if_then_else
6174 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6175 (le (minus (match_dup 3) (pc)) (const_int 256)))
6176 (const_int 4)
6177 (if_then_else
6178 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6179 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6180 (const_int 6)
6181 (const_int 8))))]
6182)
6183
6184(define_insn "*xorsi3_cbranch"
6185 [(set (pc)
6186 (if_then_else
6187 (match_operator 5 "equality_operator"
6188 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6189 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6190 (const_int 0)])
6191 (label_ref (match_operand 4 "" ""))
6192 (pc)))
aeac46d4 6193 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6194 (xor:SI (match_dup 2) (match_dup 3)))
6195 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6196 "TARGET_THUMB"
6197 "*
6198 {
6199 if (which_alternative == 0)
6200 output_asm_insn (\"eor\\t%0, %3\", operands);
6201 else if (which_alternative == 1)
6202 {
6203 output_asm_insn (\"eor\\t%1, %3\", operands);
6204 output_asm_insn (\"mov\\t%0, %1\", operands);
6205 }
6206 else
6207 {
6208 output_asm_insn (\"eor\\t%1, %3\", operands);
6209 output_asm_insn (\"str\\t%1, %0\", operands);
6210 }
6211
6212 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6213 {
6214 case 4: return \"b%d5\\t%l4\";
6215 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6216 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6217 }
6218 }"
6219 [(set (attr "far_jump")
6220 (if_then_else
6221 (ior (and (eq (symbol_ref ("which_alternative"))
6222 (const_int 0))
6223 (eq_attr "length" "8"))
6224 (eq_attr "length" "10"))
6225 (const_string "yes")
6226 (const_string "no")))
6227 (set (attr "length")
6228 (if_then_else
6229 (eq (symbol_ref ("which_alternative"))
6230 (const_int 0))
6231 (if_then_else
6232 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6233 (le (minus (match_dup 4) (pc)) (const_int 256)))
6234 (const_int 4)
6235 (if_then_else
6236 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6237 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6238 (const_int 6)
6239 (const_int 8)))
6240 (if_then_else
6241 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6242 (le (minus (match_dup 4) (pc)) (const_int 256)))
6243 (const_int 6)
6244 (if_then_else
6245 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6246 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6247 (const_int 8)
6248 (const_int 10)))))]
6249)
6250
aeac46d4 6251(define_insn "*bicsi3_cbranch_scratch"
6252 [(set (pc)
6253 (if_then_else
6254 (match_operator 4 "equality_operator"
6255 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6256 (match_operand:SI 1 "s_register_operand" "0"))
6257 (const_int 0)])
6258 (label_ref (match_operand 3 "" ""))
6259 (pc)))
6260 (clobber (match_scratch:SI 0 "=l"))]
6261 "TARGET_THUMB"
6262 "*
6263 {
6264 output_asm_insn (\"bic\\t%0, %2\", operands);
6265 switch (get_attr_length (insn))
6266 {
6267 case 4: return \"b%d4\\t%l3\";
6268 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6269 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6270 }
6271 }"
6272 [(set (attr "far_jump")
6273 (if_then_else
6274 (eq_attr "length" "8")
6275 (const_string "yes")
6276 (const_string "no")))
6277 (set (attr "length")
6278 (if_then_else
6279 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6280 (le (minus (match_dup 3) (pc)) (const_int 256)))
6281 (const_int 4)
6282 (if_then_else
6283 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6284 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6285 (const_int 6)
6286 (const_int 8))))]
6287)
6288
6289(define_insn "*bicsi3_cbranch"
6290 [(set (pc)
6291 (if_then_else
6292 (match_operator 5 "equality_operator"
01145ae6 6293 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6294 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 6295 (const_int 0)])
6296 (label_ref (match_operand 4 "" ""))
6297 (pc)))
01145ae6 6298 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 6299 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 6300 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
aeac46d4 6301 "TARGET_THUMB"
6302 "*
6303 {
6304 if (which_alternative == 0)
6305 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 6306 else if (which_alternative <= 2)
aeac46d4 6307 {
6308 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 6309 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6310 conditions again, since we're only testing for equality. */
aeac46d4 6311 output_asm_insn (\"mov\\t%0, %1\", operands);
6312 }
6313 else
6314 {
6315 output_asm_insn (\"bic\\t%1, %3\", operands);
6316 output_asm_insn (\"str\\t%1, %0\", operands);
6317 }
6318
6319 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6320 {
6321 case 4: return \"b%d5\\t%l4\";
6322 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6323 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6324 }
6325 }"
6326 [(set (attr "far_jump")
6327 (if_then_else
6328 (ior (and (eq (symbol_ref ("which_alternative"))
6329 (const_int 0))
6330 (eq_attr "length" "8"))
6331 (eq_attr "length" "10"))
6332 (const_string "yes")
6333 (const_string "no")))
6334 (set (attr "length")
6335 (if_then_else
6336 (eq (symbol_ref ("which_alternative"))
6337 (const_int 0))
6338 (if_then_else
6339 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6340 (le (minus (match_dup 4) (pc)) (const_int 256)))
6341 (const_int 4)
6342 (if_then_else
6343 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6344 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6345 (const_int 6)
6346 (const_int 8)))
6347 (if_then_else
6348 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6349 (le (minus (match_dup 4) (pc)) (const_int 256)))
6350 (const_int 6)
6351 (if_then_else
6352 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6353 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6354 (const_int 8)
6355 (const_int 10)))))]
6356)
6357
203c488f 6358(define_insn "*cbranchne_decr1"
6359 [(set (pc)
6360 (if_then_else (match_operator 3 "equality_operator"
6361 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6362 (const_int 0)])
6363 (label_ref (match_operand 4 "" ""))
6364 (pc)))
aeac46d4 6365 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6366 (plus:SI (match_dup 2) (const_int -1)))
6367 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6368 "TARGET_THUMB"
6369 "*
6370 {
6371 rtx cond[2];
6372 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6373 ? GEU : LTU),
58d6528b 6374 VOIDmode, operands[2], const1_rtx);
203c488f 6375 cond[1] = operands[4];
6376
6377 if (which_alternative == 0)
6378 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6379 else if (which_alternative == 1)
6380 {
6381 /* We must provide an alternative for a hi reg because reload
6382 cannot handle output reloads on a jump instruction, but we
6383 can't subtract into that. Fortunately a mov from lo to hi
6384 does not clobber the condition codes. */
6385 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6386 output_asm_insn (\"mov\\t%0, %1\", operands);
6387 }
6388 else
6389 {
6390 /* Similarly, but the target is memory. */
6391 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6392 output_asm_insn (\"str\\t%1, %0\", operands);
6393 }
6394
6395 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6396 {
6397 case 4:
8aea555f 6398 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6399 return \"\";
6400 case 6:
8aea555f 6401 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6402 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6403 default:
8aea555f 6404 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6405 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6406 }
6407 }
6408 "
6409 [(set (attr "far_jump")
6410 (if_then_else
6411 (ior (and (eq (symbol_ref ("which_alternative"))
6412 (const_int 0))
6413 (eq_attr "length" "8"))
6414 (eq_attr "length" "10"))
6415 (const_string "yes")
6416 (const_string "no")))
6417 (set_attr_alternative "length"
6418 [
6419 ;; Alternative 0
6420 (if_then_else
6421 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6422 (le (minus (match_dup 4) (pc)) (const_int 256)))
6423 (const_int 4)
6424 (if_then_else
6425 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6426 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6427 (const_int 6)
6428 (const_int 8)))
6429 ;; Alternative 1
6430 (if_then_else
6431 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6432 (le (minus (match_dup 4) (pc)) (const_int 256)))
6433 (const_int 6)
6434 (if_then_else
6435 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6436 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6437 (const_int 8)
6438 (const_int 10)))
6439 ;; Alternative 2
6440 (if_then_else
6441 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6442 (le (minus (match_dup 4) (pc)) (const_int 256)))
6443 (const_int 6)
6444 (if_then_else
6445 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6446 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6447 (const_int 8)
6448 (const_int 10)))
6449 ;; Alternative 3
6450 (if_then_else
6451 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6452 (le (minus (match_dup 4) (pc)) (const_int 256)))
6453 (const_int 6)
6454 (if_then_else
6455 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6456 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6457 (const_int 8)
6458 (const_int 10)))])]
6459)
cffb2a26 6460
58d6528b 6461(define_insn "*addsi3_cbranch"
6462 [(set (pc)
6463 (if_then_else
6464 (match_operator 4 "comparison_operator"
6465 [(plus:SI
6466 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6467 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6468 (const_int 0)])
6469 (label_ref (match_operand 5 "" ""))
6470 (pc)))
aeac46d4 6471 (set
6472 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6473 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 6474 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6475 "TARGET_THUMB
6476 && (GET_CODE (operands[4]) == EQ
6477 || GET_CODE (operands[4]) == NE
6478 || GET_CODE (operands[4]) == GE
6479 || GET_CODE (operands[4]) == LT)"
6480 "*
6481 {
6482 rtx cond[3];
6483
6484
6485 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6486 cond[1] = operands[2];
6487 cond[2] = operands[3];
6488
6489 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6490 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6491 else
6492 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6493
6494 if (which_alternative >= 3
6495 && which_alternative < 4)
6496 output_asm_insn (\"mov\\t%0, %1\", operands);
6497 else if (which_alternative >= 4)
6498 output_asm_insn (\"str\\t%1, %0\", operands);
6499
6500 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6501 {
6502 case 4:
6503 return \"b%d4\\t%l5\";
6504 case 6:
6505 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6506 default:
6507 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6508 }
6509 }
6510 "
6511 [(set (attr "far_jump")
6512 (if_then_else
6513 (ior (and (lt (symbol_ref ("which_alternative"))
6514 (const_int 3))
6515 (eq_attr "length" "8"))
6516 (eq_attr "length" "10"))
6517 (const_string "yes")
6518 (const_string "no")))
6519 (set (attr "length")
6520 (if_then_else
6521 (lt (symbol_ref ("which_alternative"))
6522 (const_int 3))
6523 (if_then_else
6524 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6525 (le (minus (match_dup 5) (pc)) (const_int 256)))
6526 (const_int 4)
6527 (if_then_else
6528 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6529 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6530 (const_int 6)
6531 (const_int 8)))
6532 (if_then_else
6533 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6534 (le (minus (match_dup 5) (pc)) (const_int 256)))
6535 (const_int 6)
6536 (if_then_else
6537 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6538 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6539 (const_int 8)
6540 (const_int 10)))))]
6541)
6542
6543(define_insn "*addsi3_cbranch_scratch"
6544 [(set (pc)
6545 (if_then_else
6546 (match_operator 3 "comparison_operator"
6547 [(plus:SI
6548 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 6549 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 6550 (const_int 0)])
6551 (label_ref (match_operand 4 "" ""))
6552 (pc)))
6553 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6554 "TARGET_THUMB
6555 && (GET_CODE (operands[3]) == EQ
6556 || GET_CODE (operands[3]) == NE
6557 || GET_CODE (operands[3]) == GE
6558 || GET_CODE (operands[3]) == LT)"
6559 "*
6560 {
6561 switch (which_alternative)
6562 {
6563 case 0:
6564 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6565 break;
6566 case 1:
6567 output_asm_insn (\"cmn\t%1, %2\", operands);
6568 break;
0f5e9701 6569 case 2:
3a445a04 6570 if (INTVAL (operands[2]) < 0)
6571 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6572 else
6573 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 6574 break;
0f5e9701 6575 case 3:
3a445a04 6576 if (INTVAL (operands[2]) < 0)
6577 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6578 else
6579 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 6580 break;
6581 }
6582
6583 switch (get_attr_length (insn))
6584 {
6585 case 4:
6586 return \"b%d3\\t%l4\";
6587 case 6:
6588 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6589 default:
6590 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6591 }
6592 }
6593 "
6594 [(set (attr "far_jump")
6595 (if_then_else
6596 (eq_attr "length" "8")
6597 (const_string "yes")
6598 (const_string "no")))
6599 (set (attr "length")
6600 (if_then_else
6601 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6602 (le (minus (match_dup 4) (pc)) (const_int 256)))
6603 (const_int 4)
6604 (if_then_else
6605 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6606 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6607 (const_int 6)
6608 (const_int 8))))]
6609)
6610
6611(define_insn "*subsi3_cbranch"
6612 [(set (pc)
6613 (if_then_else
6614 (match_operator 4 "comparison_operator"
6615 [(minus:SI
6616 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6617 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6618 (const_int 0)])
6619 (label_ref (match_operand 5 "" ""))
6620 (pc)))
aeac46d4 6621 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6622 (minus:SI (match_dup 2) (match_dup 3)))
6623 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6624 "TARGET_THUMB
6625 && (GET_CODE (operands[4]) == EQ
6626 || GET_CODE (operands[4]) == NE
6627 || GET_CODE (operands[4]) == GE
6628 || GET_CODE (operands[4]) == LT)"
6629 "*
6630 {
6631 if (which_alternative == 0)
6632 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6633 else if (which_alternative == 1)
6634 {
6635 /* We must provide an alternative for a hi reg because reload
6636 cannot handle output reloads on a jump instruction, but we
6637 can't subtract into that. Fortunately a mov from lo to hi
6638 does not clobber the condition codes. */
6639 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6640 output_asm_insn (\"mov\\t%0, %1\", operands);
6641 }
6642 else
6643 {
6644 /* Similarly, but the target is memory. */
6645 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6646 output_asm_insn (\"str\\t%1, %0\", operands);
6647 }
6648
6649 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6650 {
6651 case 4:
6652 return \"b%d4\\t%l5\";
6653 case 6:
6654 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6655 default:
6656 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6657 }
6658 }
6659 "
6660 [(set (attr "far_jump")
6661 (if_then_else
6662 (ior (and (eq (symbol_ref ("which_alternative"))
6663 (const_int 0))
6664 (eq_attr "length" "8"))
6665 (eq_attr "length" "10"))
6666 (const_string "yes")
6667 (const_string "no")))
6668 (set (attr "length")
6669 (if_then_else
6670 (eq (symbol_ref ("which_alternative"))
6671 (const_int 0))
6672 (if_then_else
6673 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6674 (le (minus (match_dup 5) (pc)) (const_int 256)))
6675 (const_int 4)
6676 (if_then_else
6677 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6678 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6679 (const_int 6)
6680 (const_int 8)))
6681 (if_then_else
6682 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6683 (le (minus (match_dup 5) (pc)) (const_int 256)))
6684 (const_int 6)
6685 (if_then_else
6686 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6687 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6688 (const_int 8)
6689 (const_int 10)))))]
6690)
6691
6692(define_insn "*subsi3_cbranch_scratch"
6693 [(set (pc)
6694 (if_then_else
6695 (match_operator 0 "arm_comparison_operator"
6696 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6697 (match_operand:SI 2 "nonmemory_operand" "l"))
6698 (const_int 0)])
6699 (label_ref (match_operand 3 "" ""))
6700 (pc)))]
6701 "TARGET_THUMB
6702 && (GET_CODE (operands[0]) == EQ
6703 || GET_CODE (operands[0]) == NE
6704 || GET_CODE (operands[0]) == GE
6705 || GET_CODE (operands[0]) == LT)"
6706 "*
6707 output_asm_insn (\"cmp\\t%1, %2\", operands);
6708 switch (get_attr_length (insn))
6709 {
6710 case 4: return \"b%d0\\t%l3\";
6711 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6712 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6713 }
6714 "
6715 [(set (attr "far_jump")
6716 (if_then_else
6717 (eq_attr "length" "8")
6718 (const_string "yes")
6719 (const_string "no")))
6720 (set (attr "length")
6721 (if_then_else
6722 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6723 (le (minus (match_dup 3) (pc)) (const_int 256)))
6724 (const_int 4)
6725 (if_then_else
6726 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6727 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6728 (const_int 6)
6729 (const_int 8))))]
6730)
6731
9c08d1fa 6732;; Comparison and test insns
6733
6734(define_expand "cmpsi"
aea4c774 6735 [(match_operand:SI 0 "s_register_operand" "")
6736 (match_operand:SI 1 "arm_add_operand" "")]
cffb2a26 6737 "TARGET_ARM"
6738 "{
6739 arm_compare_op0 = operands[0];
6740 arm_compare_op1 = operands[1];
6741 DONE;
6742 }"
6743)
b11cae9e 6744
9c08d1fa 6745(define_expand "cmpsf"
aea4c774 6746 [(match_operand:SF 0 "s_register_operand" "")
a2cd141b 6747 (match_operand:SF 1 "arm_float_compare_operand" "")]
6748 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6749 "
9c08d1fa 6750 arm_compare_op0 = operands[0];
6751 arm_compare_op1 = operands[1];
9c08d1fa 6752 DONE;
215b30b3 6753 "
6754)
b11cae9e 6755
9c08d1fa 6756(define_expand "cmpdf"
aea4c774 6757 [(match_operand:DF 0 "s_register_operand" "")
a2cd141b 6758 (match_operand:DF 1 "arm_float_compare_operand" "")]
6759 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6760 "
9c08d1fa 6761 arm_compare_op0 = operands[0];
6762 arm_compare_op1 = operands[1];
9c08d1fa 6763 DONE;
215b30b3 6764 "
6765)
b11cae9e 6766
cffb2a26 6767(define_insn "*arm_cmpsi_insn"
bd5b4116 6768 [(set (reg:CC CC_REGNUM)
aea4c774 6769 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 6770 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6771 "TARGET_ARM"
5565501b 6772 "@
aea4c774 6773 cmp%?\\t%0, %1
6774 cmn%?\\t%0, #%n1"
cffb2a26 6775 [(set_attr "conds" "set")]
6776)
b11cae9e 6777
aea4c774 6778(define_insn "*cmpsi_shiftsi"
bd5b4116 6779 [(set (reg:CC CC_REGNUM)
cffb2a26 6780 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6781 (match_operator:SI 3 "shift_operator"
aea4c774 6782 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 6783 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6784 "TARGET_ARM"
aea4c774 6785 "cmp%?\\t%0, %1%S3"
344495ea 6786 [(set_attr "conds" "set")
331beb1a 6787 (set_attr "shift" "1")
a2cd141b 6788 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6789 (const_string "alu_shift")
6790 (const_string "alu_shift_reg")))]
0d66636f 6791)
b11cae9e 6792
aea4c774 6793(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6794 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6795 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6796 [(match_operand:SI 1 "s_register_operand" "r")
6797 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6798 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6799 "TARGET_ARM"
aea4c774 6800 "cmp%?\\t%0, %1%S3"
344495ea 6801 [(set_attr "conds" "set")
331beb1a 6802 (set_attr "shift" "1")
a2cd141b 6803 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6804 (const_string "alu_shift")
6805 (const_string "alu_shift_reg")))]
0d66636f 6806)
b11cae9e 6807
aed179ae 6808(define_insn "*cmpsi_negshiftsi_si"
6809 [(set (reg:CC_Z CC_REGNUM)
6810 (compare:CC_Z
6811 (neg:SI (match_operator:SI 1 "shift_operator"
6812 [(match_operand:SI 2 "s_register_operand" "r")
6813 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6814 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6815 "TARGET_ARM"
aed179ae 6816 "cmn%?\\t%0, %2%S1"
344495ea 6817 [(set_attr "conds" "set")
aed179ae 6818 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6819 (const_string "alu_shift")
6820 (const_string "alu_shift_reg")))]
0d66636f 6821)
b11cae9e 6822
7d57ec45 6823;; Cirrus SF compare instruction
6824(define_insn "*cirrus_cmpsf"
6825 [(set (reg:CCFP CC_REGNUM)
6826 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6827 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 6828 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6829 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 6830 [(set_attr "type" "mav_farith")
7d57ec45 6831 (set_attr "cirrus" "compare")]
6832)
6833
6834;; Cirrus DF compare instruction
6835(define_insn "*cirrus_cmpdf"
6836 [(set (reg:CCFP CC_REGNUM)
6837 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6838 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 6839 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6840 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 6841 [(set_attr "type" "mav_farith")
7d57ec45 6842 (set_attr "cirrus" "compare")]
6843)
6844
6845;; Cirrus DI compare instruction
6846(define_expand "cmpdi"
6847 [(match_operand:DI 0 "cirrus_fp_register" "")
6848 (match_operand:DI 1 "cirrus_fp_register" "")]
a2cd141b 6849 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6850 "{
6851 arm_compare_op0 = operands[0];
6852 arm_compare_op1 = operands[1];
6853 DONE;
6854 }")
6855
6856(define_insn "*cirrus_cmpdi"
6857 [(set (reg:CC CC_REGNUM)
6858 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6859 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 6860 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6861 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 6862 [(set_attr "type" "mav_farith")
7d57ec45 6863 (set_attr "cirrus" "compare")]
6864)
6865
9c08d1fa 6866; This insn allows redundant compares to be removed by cse, nothing should
6867; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6868; is deleted later on. The match_dup will match the mode here, so that
6869; mode changes of the condition codes aren't lost by this even though we don't
6870; specify what they are.
6871
8a18b90c 6872(define_insn "*deleted_compare"
9c08d1fa 6873 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
cffb2a26 6874 "TARGET_ARM"
40dbec34 6875 "\\t%@ deleted compare"
cffb2a26 6876 [(set_attr "conds" "set")
6877 (set_attr "length" "0")]
6878)
9c08d1fa 6879
6880\f
6881;; Conditional branch insns
6882
6883(define_expand "beq"
6884 [(set (pc)
6885 (if_then_else (eq (match_dup 1) (const_int 0))
6886 (label_ref (match_operand 0 "" ""))
6887 (pc)))]
cffb2a26 6888 "TARGET_ARM"
6889 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6890)
5c951228 6891
9c08d1fa 6892(define_expand "bne"
6893 [(set (pc)
6894 (if_then_else (ne (match_dup 1) (const_int 0))
6895 (label_ref (match_operand 0 "" ""))
6896 (pc)))]
cffb2a26 6897 "TARGET_ARM"
6898 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6899)
5c951228 6900
9c08d1fa 6901(define_expand "bgt"
6902 [(set (pc)
6903 (if_then_else (gt (match_dup 1) (const_int 0))
6904 (label_ref (match_operand 0 "" ""))
6905 (pc)))]
cffb2a26 6906 "TARGET_ARM"
6907 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6908)
5c951228 6909
9c08d1fa 6910(define_expand "ble"
6911 [(set (pc)
6912 (if_then_else (le (match_dup 1) (const_int 0))
6913 (label_ref (match_operand 0 "" ""))
6914 (pc)))]
cffb2a26 6915 "TARGET_ARM"
6916 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6917)
5c951228 6918
9c08d1fa 6919(define_expand "bge"
6920 [(set (pc)
6921 (if_then_else (ge (match_dup 1) (const_int 0))
6922 (label_ref (match_operand 0 "" ""))
6923 (pc)))]
cffb2a26 6924 "TARGET_ARM"
6925 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6926)
5c951228 6927
9c08d1fa 6928(define_expand "blt"
6929 [(set (pc)
6930 (if_then_else (lt (match_dup 1) (const_int 0))
6931 (label_ref (match_operand 0 "" ""))
6932 (pc)))]
cffb2a26 6933 "TARGET_ARM"
6934 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6935)
5c951228 6936
9c08d1fa 6937(define_expand "bgtu"
6938 [(set (pc)
6939 (if_then_else (gtu (match_dup 1) (const_int 0))
6940 (label_ref (match_operand 0 "" ""))
6941 (pc)))]
cffb2a26 6942 "TARGET_ARM"
6943 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6944)
5c951228 6945
9c08d1fa 6946(define_expand "bleu"
b11cae9e 6947 [(set (pc)
9c08d1fa 6948 (if_then_else (leu (match_dup 1) (const_int 0))
6949 (label_ref (match_operand 0 "" ""))
6950 (pc)))]
cffb2a26 6951 "TARGET_ARM"
6952 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6953)
b11cae9e 6954
9c08d1fa 6955(define_expand "bgeu"
b11cae9e 6956 [(set (pc)
9c08d1fa 6957 (if_then_else (geu (match_dup 1) (const_int 0))
6958 (label_ref (match_operand 0 "" ""))
6959 (pc)))]
cffb2a26 6960 "TARGET_ARM"
6961 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6962)
b11cae9e 6963
9c08d1fa 6964(define_expand "bltu"
6965 [(set (pc)
6966 (if_then_else (ltu (match_dup 1) (const_int 0))
6967 (label_ref (match_operand 0 "" ""))
6968 (pc)))]
cffb2a26 6969 "TARGET_ARM"
6970 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6971)
b11cae9e 6972
8fa3ba89 6973(define_expand "bunordered"
6974 [(set (pc)
6975 (if_then_else (unordered (match_dup 1) (const_int 0))
6976 (label_ref (match_operand 0 "" ""))
6977 (pc)))]
c0e1af52 6978 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 6979 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6980 arm_compare_op1);"
6981)
6982
6983(define_expand "bordered"
6984 [(set (pc)
6985 (if_then_else (ordered (match_dup 1) (const_int 0))
6986 (label_ref (match_operand 0 "" ""))
6987 (pc)))]
c0e1af52 6988 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 6989 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6990 arm_compare_op1);"
6991)
6992
6993(define_expand "bungt"
6994 [(set (pc)
6995 (if_then_else (ungt (match_dup 1) (const_int 0))
6996 (label_ref (match_operand 0 "" ""))
6997 (pc)))]
c0e1af52 6998 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 6999 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7000)
7001
7002(define_expand "bunlt"
7003 [(set (pc)
7004 (if_then_else (unlt (match_dup 1) (const_int 0))
7005 (label_ref (match_operand 0 "" ""))
7006 (pc)))]
c0e1af52 7007 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7008 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7009)
7010
7011(define_expand "bunge"
7012 [(set (pc)
7013 (if_then_else (unge (match_dup 1) (const_int 0))
7014 (label_ref (match_operand 0 "" ""))
7015 (pc)))]
c0e1af52 7016 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7017 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7018)
7019
7020(define_expand "bunle"
7021 [(set (pc)
7022 (if_then_else (unle (match_dup 1) (const_int 0))
7023 (label_ref (match_operand 0 "" ""))
7024 (pc)))]
c0e1af52 7025 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7026 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7027)
7028
7029;; The following two patterns need two branch instructions, since there is
7030;; no single instruction that will handle all cases.
7031(define_expand "buneq"
7032 [(set (pc)
7033 (if_then_else (uneq (match_dup 1) (const_int 0))
7034 (label_ref (match_operand 0 "" ""))
7035 (pc)))]
c0e1af52 7036 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7037 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7038)
7039
7040(define_expand "bltgt"
7041 [(set (pc)
7042 (if_then_else (ltgt (match_dup 1) (const_int 0))
7043 (label_ref (match_operand 0 "" ""))
7044 (pc)))]
c0e1af52 7045 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7046 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7047)
7048
7049;;
7050;; Patterns to match conditional branch insns.
7051;;
7052
7053; Special pattern to match UNEQ.
7054(define_insn "*arm_buneq"
7055 [(set (pc)
7056 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7057 (label_ref (match_operand 0 "" ""))
7058 (pc)))]
c0e1af52 7059 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7060 "*
ed29c566 7061 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7062
278b301d 7063 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7064 "
7065 [(set_attr "conds" "jump_clob")
7066 (set_attr "length" "8")]
7067)
7068
7069; Special pattern to match LTGT.
7070(define_insn "*arm_bltgt"
7071 [(set (pc)
7072 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7073 (label_ref (match_operand 0 "" ""))
7074 (pc)))]
c0e1af52 7075 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7076 "*
ed29c566 7077 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7078
278b301d 7079 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7080 "
7081 [(set_attr "conds" "jump_clob")
7082 (set_attr "length" "8")]
7083)
9c08d1fa 7084
cffb2a26 7085(define_insn "*arm_cond_branch"
9c08d1fa 7086 [(set (pc)
8fa3ba89 7087 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7088 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7089 (label_ref (match_operand 0 "" ""))
7090 (pc)))]
cffb2a26 7091 "TARGET_ARM"
d75350ce 7092 "*
9c08d1fa 7093 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7094 {
7095 arm_ccfsm_state += 2;
7096 return \"\";
7097 }
e2348bcb 7098 return \"b%d1\\t%l0\";
cffb2a26 7099 "
a2cd141b 7100 [(set_attr "conds" "use")
7101 (set_attr "type" "branch")]
cffb2a26 7102)
d75350ce 7103
8fa3ba89 7104; Special pattern to match reversed UNEQ.
7105(define_insn "*arm_buneq_reversed"
7106 [(set (pc)
7107 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7108 (pc)
7109 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7110 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7111 "*
ed29c566 7112 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7113
278b301d 7114 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7115 "
7116 [(set_attr "conds" "jump_clob")
7117 (set_attr "length" "8")]
7118)
7119
7120; Special pattern to match reversed LTGT.
7121(define_insn "*arm_bltgt_reversed"
7122 [(set (pc)
7123 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7124 (pc)
7125 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7126 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7127 "*
ed29c566 7128 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7129
278b301d 7130 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7131 "
7132 [(set_attr "conds" "jump_clob")
7133 (set_attr "length" "8")]
7134)
7135
cffb2a26 7136(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7137 [(set (pc)
8fa3ba89 7138 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7139 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7140 (pc)
7141 (label_ref (match_operand 0 "" ""))))]
cffb2a26 7142 "TARGET_ARM"
d75350ce 7143 "*
9c08d1fa 7144 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7145 {
7146 arm_ccfsm_state += 2;
7147 return \"\";
7148 }
e2348bcb 7149 return \"b%D1\\t%l0\";
cffb2a26 7150 "
a2cd141b 7151 [(set_attr "conds" "use")
7152 (set_attr "type" "branch")]
cffb2a26 7153)
7154
b11cae9e 7155\f
9c08d1fa 7156
7157; scc insns
7158
7159(define_expand "seq"
7db9af5d 7160 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7161 (eq:SI (match_dup 1) (const_int 0)))]
cffb2a26 7162 "TARGET_ARM"
7163 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7164)
9c08d1fa 7165
7166(define_expand "sne"
7db9af5d 7167 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7168 (ne:SI (match_dup 1) (const_int 0)))]
cffb2a26 7169 "TARGET_ARM"
7170 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7171)
9c08d1fa 7172
7173(define_expand "sgt"
7db9af5d 7174 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7175 (gt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7176 "TARGET_ARM"
7177 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7178)
9c08d1fa 7179
7180(define_expand "sle"
7db9af5d 7181 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7182 (le:SI (match_dup 1) (const_int 0)))]
cffb2a26 7183 "TARGET_ARM"
7184 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7185)
9c08d1fa 7186
7187(define_expand "sge"
7db9af5d 7188 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7189 (ge:SI (match_dup 1) (const_int 0)))]
cffb2a26 7190 "TARGET_ARM"
7191 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7192)
9c08d1fa 7193
7194(define_expand "slt"
7db9af5d 7195 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7196 (lt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7197 "TARGET_ARM"
7198 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7199)
9c08d1fa 7200
7201(define_expand "sgtu"
7db9af5d 7202 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7203 (gtu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7204 "TARGET_ARM"
7205 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7206)
9c08d1fa 7207
7208(define_expand "sleu"
7db9af5d 7209 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7210 (leu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7211 "TARGET_ARM"
7212 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7213)
9c08d1fa 7214
7215(define_expand "sgeu"
7db9af5d 7216 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7217 (geu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7218 "TARGET_ARM"
7219 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7220)
9c08d1fa 7221
7222(define_expand "sltu"
7db9af5d 7223 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7224 (ltu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7225 "TARGET_ARM"
7226 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7227)
9c08d1fa 7228
8fa3ba89 7229(define_expand "sunordered"
7db9af5d 7230 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7231 (unordered:SI (match_dup 1) (const_int 0)))]
c0e1af52 7232 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7233 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7234 arm_compare_op1);"
7235)
7236
7237(define_expand "sordered"
7db9af5d 7238 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7239 (ordered:SI (match_dup 1) (const_int 0)))]
c0e1af52 7240 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7241 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7242 arm_compare_op1);"
7243)
7244
7245(define_expand "sungt"
7db9af5d 7246 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7247 (ungt:SI (match_dup 1) (const_int 0)))]
c0e1af52 7248 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7249 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7250 arm_compare_op1);"
7251)
7252
7253(define_expand "sunge"
7db9af5d 7254 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7255 (unge:SI (match_dup 1) (const_int 0)))]
c0e1af52 7256 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7257 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7258 arm_compare_op1);"
7259)
7260
7261(define_expand "sunlt"
7db9af5d 7262 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7263 (unlt:SI (match_dup 1) (const_int 0)))]
c0e1af52 7264 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7265 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7266 arm_compare_op1);"
7267)
7268
7269(define_expand "sunle"
7db9af5d 7270 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7271 (unle:SI (match_dup 1) (const_int 0)))]
c0e1af52 7272 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7273 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7274 arm_compare_op1);"
7275)
7276
7277;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7278;;; simple ARM instructions.
7279;
7280; (define_expand "suneq"
7db9af5d 7281; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7282; (uneq:SI (match_dup 1) (const_int 0)))]
c0e1af52 7283; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7284; "gcc_unreachable ();"
8fa3ba89 7285; )
7286;
7287; (define_expand "sltgt"
7db9af5d 7288; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7289; (ltgt:SI (match_dup 1) (const_int 0)))]
c0e1af52 7290; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7291; "gcc_unreachable ();"
8fa3ba89 7292; )
7293
f7fbdd4a 7294(define_insn "*mov_scc"
9c08d1fa 7295 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7296 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7297 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7298 "TARGET_ARM"
4d61e570 7299 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7300 [(set_attr "conds" "use")
7301 (set_attr "length" "8")]
7302)
9c08d1fa 7303
f7fbdd4a 7304(define_insn "*mov_negscc"
9c08d1fa 7305 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7306 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7307 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7308 "TARGET_ARM"
4d61e570 7309 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7310 [(set_attr "conds" "use")
7311 (set_attr "length" "8")]
7312)
9c08d1fa 7313
f7fbdd4a 7314(define_insn "*mov_notscc"
9c08d1fa 7315 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7316 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7317 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7318 "TARGET_ARM"
4d61e570 7319 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7320 [(set_attr "conds" "use")
7321 (set_attr "length" "8")]
7322)
9c08d1fa 7323
7324\f
39b5e676 7325;; Conditional move insns
7326
7327(define_expand "movsicc"
8a18b90c 7328 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7329 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7330 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7331 (match_operand:SI 3 "arm_not_operand" "")))]
cffb2a26 7332 "TARGET_ARM"
39b5e676 7333 "
215b30b3 7334 {
7335 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7336 rtx ccreg;
7337
7338 if (code == UNEQ || code == LTGT)
7339 FAIL;
39b5e676 7340
278b301d 7341 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7342 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7343 }"
7344)
39b5e676 7345
7346(define_expand "movsfcc"
8a18b90c 7347 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7348 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7349 (match_operand:SF 2 "s_register_operand" "")
7350 (match_operand:SF 3 "nonmemory_operand" "")))]
cffb2a26 7351 "TARGET_ARM"
39b5e676 7352 "
215b30b3 7353 {
7354 enum rtx_code code = GET_CODE (operands[1]);
7355 rtx ccreg;
f082f1c4 7356
278b301d 7357 if (code == UNEQ || code == LTGT)
7358 FAIL;
7359
215b30b3 7360 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7361 Otherwise, ensure it is a valid FP add operand */
7362 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7363 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7364 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7365
215b30b3 7366 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7367 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7368 }"
7369)
39b5e676 7370
7371(define_expand "movdfcc"
8a18b90c 7372 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7373 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7374 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7375 (match_operand:DF 3 "arm_float_add_operand" "")))]
7376 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 7377 "
215b30b3 7378 {
7379 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7380 rtx ccreg;
39b5e676 7381
278b301d 7382 if (code == UNEQ || code == LTGT)
7383 FAIL;
7384
7385 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7386 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7387 }"
7388)
39b5e676 7389
7390(define_insn "*movsicc_insn"
f082f1c4 7391 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7392 (if_then_else:SI
8fa3ba89 7393 (match_operator 3 "arm_comparison_operator"
8a18b90c 7394 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7395 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7396 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7397 "TARGET_ARM"
39b5e676 7398 "@
8a18b90c 7399 mov%D3\\t%0, %2
7400 mvn%D3\\t%0, #%B2
f082f1c4 7401 mov%d3\\t%0, %1
7402 mvn%d3\\t%0, #%B1
8a18b90c 7403 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7404 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7405 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7406 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7407 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 7408 (set_attr "conds" "use")]
7409)
39b5e676 7410
39b5e676 7411(define_insn "*movsfcc_soft_insn"
f082f1c4 7412 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7413 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7414 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7415 (match_operand:SF 1 "s_register_operand" "0,r")
7416 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7417 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7418 "@
7419 mov%D3\\t%0, %2
7420 mov%d3\\t%0, %1"
8fa3ba89 7421 [(set_attr "conds" "use")]
7422)
39b5e676 7423
39b5e676 7424\f
9c08d1fa 7425;; Jump and linkage insns
7426
cffb2a26 7427(define_expand "jump"
9c08d1fa 7428 [(set (pc)
7429 (label_ref (match_operand 0 "" "")))]
cffb2a26 7430 "TARGET_EITHER"
9c08d1fa 7431 ""
cffb2a26 7432)
7433
7434(define_insn "*arm_jump"
7435 [(set (pc)
7436 (label_ref (match_operand 0 "" "")))]
7437 "TARGET_ARM"
9c08d1fa 7438 "*
0d66636f 7439 {
7440 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7441 {
7442 arm_ccfsm_state += 2;
7443 return \"\";
7444 }
7445 return \"b%?\\t%l0\";
7446 }
7447 "
7448 [(set_attr "predicable" "yes")]
7449)
9c08d1fa 7450
cffb2a26 7451(define_insn "*thumb_jump"
7452 [(set (pc)
7453 (label_ref (match_operand 0 "" "")))]
7454 "TARGET_THUMB"
7455 "*
7456 if (get_attr_length (insn) == 2)
7457 return \"b\\t%l0\";
7458 return \"bl\\t%l0\\t%@ far jump\";
7459 "
7460 [(set (attr "far_jump")
7461 (if_then_else
7462 (eq_attr "length" "4")
7463 (const_string "yes")
7464 (const_string "no")))
7465 (set (attr "length")
7466 (if_then_else
911ed8af 7467 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7468 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7469 (const_int 2)
7470 (const_int 4)))]
7471)
7472
d3373b54 7473(define_expand "call"
7474 [(parallel [(call (match_operand 0 "memory_operand" "")
7475 (match_operand 1 "general_operand" ""))
cffb2a26 7476 (use (match_operand 2 "" ""))
bd5b4116 7477 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7478 "TARGET_EITHER"
6c4c2133 7479 "
7480 {
78fe751b 7481 rtx callee;
bbe777ea 7482
bbe777ea 7483 /* In an untyped call, we can get NULL for operand 2. */
7484 if (operands[2] == NULL_RTX)
7485 operands[2] = const0_rtx;
7486
78fe751b 7487 /* This is to decide if we should generate indirect calls by loading the
7488 32 bit address of the callee into a register before performing the
7489 branch and link. operand[2] encodes the long_call/short_call
7490 attribute of the function being called. This attribute is set whenever
7491 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7492 is used, and the short_call attribute can also be set if function is
7493 declared as static or if it has already been defined in the current
7494 compilation unit. See arm.c and arm.h for info about this. The third
7495 parameter to arm_is_longcall_p is used to tell it which pattern
7496 invoked it. */
7497 callee = XEXP (operands[0], 0);
7498
bbe777ea 7499 if (GET_CODE (callee) != REG
7500 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7501 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6c4c2133 7502 }"
7503)
d3373b54 7504
f1039640 7505(define_insn "*call_reg_armv5"
d3373b54 7506 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7507 (match_operand 1 "" ""))
7508 (use (match_operand 2 "" ""))
bd5b4116 7509 (clobber (reg:SI LR_REGNUM))]
f1039640 7510 "TARGET_ARM && arm_arch5"
7511 "blx%?\\t%0"
7512 [(set_attr "type" "call")]
7513)
7514
7515(define_insn "*call_reg_arm"
7516 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7517 (match_operand 1 "" ""))
7518 (use (match_operand 2 "" ""))
7519 (clobber (reg:SI LR_REGNUM))]
7520 "TARGET_ARM && !arm_arch5"
9c08d1fa 7521 "*
5565501b 7522 return output_call (operands);
cffb2a26 7523 "
7524 ;; length is worst case, normally it is only two
7525 [(set_attr "length" "12")
7526 (set_attr "type" "call")]
7527)
9c08d1fa 7528
f7fbdd4a 7529(define_insn "*call_mem"
6c4c2133 7530 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
cffb2a26 7531 (match_operand 1 "" ""))
7532 (use (match_operand 2 "" ""))
bd5b4116 7533 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7534 "TARGET_ARM"
9c08d1fa 7535 "*
5565501b 7536 return output_call_mem (operands);
cffb2a26 7537 "
7538 [(set_attr "length" "12")
7539 (set_attr "type" "call")]
7540)
7541
f1039640 7542(define_insn "*call_reg_thumb_v5"
cffb2a26 7543 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7544 (match_operand 1 "" ""))
7545 (use (match_operand 2 "" ""))
bd5b4116 7546 (clobber (reg:SI LR_REGNUM))]
f1039640 7547 "TARGET_THUMB && arm_arch5"
7548 "blx\\t%0"
7549 [(set_attr "length" "2")
7550 (set_attr "type" "call")]
cffb2a26 7551)
7552
f1039640 7553(define_insn "*call_reg_thumb"
7554 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7555 (match_operand 1 "" ""))
7556 (use (match_operand 2 "" ""))
bd5b4116 7557 (clobber (reg:SI LR_REGNUM))]
f1039640 7558 "TARGET_THUMB && !arm_arch5"
cffb2a26 7559 "*
7560 {
150502c9 7561 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7562 return thumb_call_via_reg (operands[0]);
150502c9 7563 else if (operands[1] == const0_rtx)
f1039640 7564 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7565 else if (frame_pointer_needed)
7566 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7567 else
150502c9 7568 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7569 }"
7570 [(set_attr "type" "call")]
7571)
9c08d1fa 7572
d3373b54 7573(define_expand "call_value"
e0698af7 7574 [(parallel [(set (match_operand 0 "" "")
7575 (call (match_operand 1 "memory_operand" "")
7576 (match_operand 2 "general_operand" "")))
cffb2a26 7577 (use (match_operand 3 "" ""))
bd5b4116 7578 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7579 "TARGET_EITHER"
6c4c2133 7580 "
7581 {
bbe777ea 7582 rtx callee = XEXP (operands[1], 0);
7583
7584 /* In an untyped call, we can get NULL for operand 2. */
7585 if (operands[3] == 0)
7586 operands[3] = const0_rtx;
7587
7588 /* See the comment in define_expand \"call\". */
7589 if (GET_CODE (callee) != REG
7590 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
78fe751b 7591 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6c4c2133 7592 }"
7593)
d3373b54 7594
f1039640 7595(define_insn "*call_value_reg_armv5"
27ed6835 7596 [(set (match_operand 0 "" "")
755eb2b4 7597 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7598 (match_operand 2 "" "")))
bbe777ea 7599 (use (match_operand 3 "" ""))
bd5b4116 7600 (clobber (reg:SI LR_REGNUM))]
f1039640 7601 "TARGET_ARM && arm_arch5"
7602 "blx%?\\t%1"
7603 [(set_attr "type" "call")]
7604)
7605
7606(define_insn "*call_value_reg_arm"
7607 [(set (match_operand 0 "" "")
7608 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7609 (match_operand 2 "" "")))
7610 (use (match_operand 3 "" ""))
7611 (clobber (reg:SI LR_REGNUM))]
7612 "TARGET_ARM && !arm_arch5"
9c08d1fa 7613 "*
215b30b3 7614 return output_call (&operands[1]);
cffb2a26 7615 "
7616 [(set_attr "length" "12")
7617 (set_attr "type" "call")]
7618)
9c08d1fa 7619
f7fbdd4a 7620(define_insn "*call_value_mem"
27ed6835 7621 [(set (match_operand 0 "" "")
755eb2b4 7622 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
cffb2a26 7623 (match_operand 2 "" "")))
bbe777ea 7624 (use (match_operand 3 "" ""))
bd5b4116 7625 (clobber (reg:SI LR_REGNUM))]
215b30b3 7626 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7627 "*
215b30b3 7628 return output_call_mem (&operands[1]);
cffb2a26 7629 "
7630 [(set_attr "length" "12")
7631 (set_attr "type" "call")]
7632)
9c08d1fa 7633
f1039640 7634(define_insn "*call_value_reg_thumb_v5"
7635 [(set (match_operand 0 "" "")
7636 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7637 (match_operand 2 "" "")))
7638 (use (match_operand 3 "" ""))
7639 (clobber (reg:SI LR_REGNUM))]
7640 "TARGET_THUMB && arm_arch5"
7641 "blx\\t%1"
7642 [(set_attr "length" "2")
7643 (set_attr "type" "call")]
7644)
7645
7646(define_insn "*call_value_reg_thumb"
7647 [(set (match_operand 0 "" "")
7648 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7649 (match_operand 2 "" "")))
7650 (use (match_operand 3 "" ""))
7651 (clobber (reg:SI LR_REGNUM))]
7652 "TARGET_THUMB && !arm_arch5"
7653 "*
7654 {
150502c9 7655 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7656 return thumb_call_via_reg (operands[1]);
150502c9 7657 else if (operands[2] == const0_rtx)
f1039640 7658 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7659 else if (frame_pointer_needed)
7660 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7661 else
150502c9 7662 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 7663 }"
7664 [(set_attr "type" "call")]
7665)
7666
9c08d1fa 7667;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7668;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7669
f7fbdd4a 7670(define_insn "*call_symbol"
27ed6835 7671 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7672 (match_operand 1 "" ""))
bbe777ea 7673 (use (match_operand 2 "" ""))
bd5b4116 7674 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7675 "TARGET_ARM
7676 && (GET_CODE (operands[0]) == SYMBOL_REF)
215b30b3 7677 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6ebaa29d 7678 "*
7679 {
55c1e470 7680 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7681 }"
cffb2a26 7682 [(set_attr "type" "call")]
7683)
9c08d1fa 7684
f7fbdd4a 7685(define_insn "*call_value_symbol"
ccd90aaa 7686 [(set (match_operand 0 "" "")
27ed6835 7687 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7688 (match_operand:SI 2 "" "")))
bbe777ea 7689 (use (match_operand 3 "" ""))
bd5b4116 7690 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7691 "TARGET_ARM
7692 && (GET_CODE (operands[1]) == SYMBOL_REF)
215b30b3 7693 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6ebaa29d 7694 "*
7695 {
55c1e470 7696 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7697 }"
cffb2a26 7698 [(set_attr "type" "call")]
7699)
7700
7701(define_insn "*call_insn"
27ed6835 7702 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7703 (match_operand:SI 1 "" ""))
7704 (use (match_operand 2 "" ""))
bd5b4116 7705 (clobber (reg:SI LR_REGNUM))]
1c494086 7706 "TARGET_THUMB
1675c6e9 7707 && GET_CODE (operands[0]) == SYMBOL_REF
7708 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
cffb2a26 7709 "bl\\t%a0"
7710 [(set_attr "length" "4")
7711 (set_attr "type" "call")]
7712)
7713
7714(define_insn "*call_value_insn"
ccd90aaa 7715 [(set (match_operand 0 "" "")
27ed6835 7716 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 7717 (match_operand 2 "" "")))
7718 (use (match_operand 3 "" ""))
bd5b4116 7719 (clobber (reg:SI LR_REGNUM))]
1c494086 7720 "TARGET_THUMB
1675c6e9 7721 && GET_CODE (operands[1]) == SYMBOL_REF
7722 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
cffb2a26 7723 "bl\\t%a1"
7724 [(set_attr "length" "4")
7725 (set_attr "type" "call")]
7726)
9c08d1fa 7727
1c494086 7728;; We may also be able to do sibcalls for Thumb, but it's much harder...
7729(define_expand "sibcall"
7730 [(parallel [(call (match_operand 0 "memory_operand" "")
7731 (match_operand 1 "general_operand" ""))
2ba80634 7732 (return)
7733 (use (match_operand 2 "" ""))])]
1c494086 7734 "TARGET_ARM"
7735 "
7736 {
7737 if (operands[2] == NULL_RTX)
7738 operands[2] = const0_rtx;
1c494086 7739 }"
7740)
7741
7742(define_expand "sibcall_value"
ccd90aaa 7743 [(parallel [(set (match_operand 0 "" "")
1c494086 7744 (call (match_operand 1 "memory_operand" "")
7745 (match_operand 2 "general_operand" "")))
2ba80634 7746 (return)
7747 (use (match_operand 3 "" ""))])]
1c494086 7748 "TARGET_ARM"
7749 "
7750 {
7751 if (operands[3] == NULL_RTX)
7752 operands[3] = const0_rtx;
1c494086 7753 }"
7754)
7755
7756(define_insn "*sibcall_insn"
7757 [(call (mem:SI (match_operand:SI 0 "" "X"))
7758 (match_operand 1 "" ""))
2ba80634 7759 (return)
7760 (use (match_operand 2 "" ""))]
1c494086 7761 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7762 "*
7763 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7764 "
7765 [(set_attr "type" "call")]
7766)
7767
7768(define_insn "*sibcall_value_insn"
ccd90aaa 7769 [(set (match_operand 0 "" "")
755eb2b4 7770 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 7771 (match_operand 2 "" "")))
2ba80634 7772 (return)
7773 (use (match_operand 3 "" ""))]
1c494086 7774 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7775 "*
7776 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7777 "
7778 [(set_attr "type" "call")]
7779)
7780
9c08d1fa 7781;; Often the return insn will be the same as loading from memory, so set attr
7782(define_insn "return"
7783 [(return)]
cffb2a26 7784 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7785 "*
9c08d1fa 7786 {
cffb2a26 7787 if (arm_ccfsm_state == 2)
7788 {
7789 arm_ccfsm_state += 2;
7790 return \"\";
7791 }
5db468b7 7792 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 7793 }"
a2cd141b 7794 [(set_attr "type" "load1")
755eb2b4 7795 (set_attr "length" "12")
0d66636f 7796 (set_attr "predicable" "yes")]
cffb2a26 7797)
9c08d1fa 7798
f7fbdd4a 7799(define_insn "*cond_return"
9c08d1fa 7800 [(set (pc)
8fa3ba89 7801 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7802 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7803 (return)
7804 (pc)))]
cffb2a26 7805 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7806 "*
8fa3ba89 7807 {
7808 if (arm_ccfsm_state == 2)
7809 {
7810 arm_ccfsm_state += 2;
7811 return \"\";
7812 }
7813 return output_return_instruction (operands[0], TRUE, FALSE);
7814 }"
7815 [(set_attr "conds" "use")
755eb2b4 7816 (set_attr "length" "12")
a2cd141b 7817 (set_attr "type" "load1")]
8fa3ba89 7818)
9c08d1fa 7819
f7fbdd4a 7820(define_insn "*cond_return_inverted"
9c08d1fa 7821 [(set (pc)
8fa3ba89 7822 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7823 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7824 (pc)
7825 (return)))]
cffb2a26 7826 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7827 "*
8fa3ba89 7828 {
7829 if (arm_ccfsm_state == 2)
7830 {
7831 arm_ccfsm_state += 2;
7832 return \"\";
7833 }
7834 return output_return_instruction (operands[0], TRUE, TRUE);
7835 }"
7836 [(set_attr "conds" "use")
37a1317b 7837 (set_attr "length" "12")
a2cd141b 7838 (set_attr "type" "load1")]
8fa3ba89 7839)
9c08d1fa 7840
68121397 7841;; Generate a sequence of instructions to determine if the processor is
7842;; in 26-bit or 32-bit mode, and return the appropriate return address
7843;; mask.
7844
7845(define_expand "return_addr_mask"
7846 [(set (match_dup 1)
7847 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7848 (const_int 0)))
7849 (set (match_operand:SI 0 "s_register_operand" "")
7850 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7851 (const_int -1)
7852 (const_int 67108860)))] ; 0x03fffffc
7853 "TARGET_ARM"
7854 "
62eddbd4 7855 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7856 ")
7857
7858(define_insn "*check_arch2"
7859 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7860 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7861 (const_int 0)))]
7862 "TARGET_ARM"
7863 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7864 [(set_attr "length" "8")
7865 (set_attr "conds" "set")]
7866)
7867
9c08d1fa 7868;; Call subroutine returning any type.
7869
7870(define_expand "untyped_call"
7871 [(parallel [(call (match_operand 0 "" "")
7872 (const_int 0))
7873 (match_operand 1 "" "")
7874 (match_operand 2 "" "")])]
ccd90aaa 7875 "TARGET_EITHER"
9c08d1fa 7876 "
215b30b3 7877 {
7878 int i;
ccd90aaa 7879 rtx par = gen_rtx_PARALLEL (VOIDmode,
7880 rtvec_alloc (XVECLEN (operands[2], 0)));
7881 rtx addr = gen_reg_rtx (Pmode);
7882 rtx mem;
7883 int size = 0;
9c08d1fa 7884
ccd90aaa 7885 emit_move_insn (addr, XEXP (operands[1], 0));
7886 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7887
215b30b3 7888 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7889 {
ccd90aaa 7890 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7891
ccd90aaa 7892 /* Default code only uses r0 as a return value, but we could
7893 be using anything up to 4 registers. */
7894 if (REGNO (src) == R0_REGNUM)
7895 src = gen_rtx_REG (TImode, R0_REGNUM);
7896
7897 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7898 GEN_INT (size));
7899 size += GET_MODE_SIZE (GET_MODE (src));
7900 }
7901
7902 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7903 const0_rtx));
7904
7905 size = 0;
7906
7907 for (i = 0; i < XVECLEN (par, 0); i++)
7908 {
7909 HOST_WIDE_INT offset = 0;
7910 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7911
7912 if (size != 0)
7913 emit_move_insn (addr, plus_constant (addr, size));
7914
7915 mem = change_address (mem, GET_MODE (reg), NULL);
7916 if (REGNO (reg) == R0_REGNUM)
7917 {
7918 /* On thumb we have to use a write-back instruction. */
7919 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7920 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7921 size = TARGET_ARM ? 16 : 0;
7922 }
7923 else
7924 {
7925 emit_move_insn (mem, reg);
7926 size = GET_MODE_SIZE (GET_MODE (reg));
7927 }
215b30b3 7928 }
9c08d1fa 7929
215b30b3 7930 /* The optimizer does not know that the call sets the function value
7931 registers we stored in the result block. We avoid problems by
7932 claiming that all hard registers are used and clobbered at this
7933 point. */
7934 emit_insn (gen_blockage ());
7935
7936 DONE;
7937 }"
7938)
9c08d1fa 7939
ccd90aaa 7940(define_expand "untyped_return"
7941 [(match_operand:BLK 0 "memory_operand" "")
7942 (match_operand 1 "" "")]
7943 "TARGET_EITHER"
7944 "
7945 {
7946 int i;
7947 rtx addr = gen_reg_rtx (Pmode);
7948 rtx mem;
7949 int size = 0;
7950
7951 emit_move_insn (addr, XEXP (operands[0], 0));
7952 mem = change_address (operands[0], BLKmode, addr);
7953
7954 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7955 {
7956 HOST_WIDE_INT offset = 0;
7957 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7958
7959 if (size != 0)
7960 emit_move_insn (addr, plus_constant (addr, size));
7961
7962 mem = change_address (mem, GET_MODE (reg), NULL);
7963 if (REGNO (reg) == R0_REGNUM)
7964 {
7965 /* On thumb we have to use a write-back instruction. */
7966 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7967 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7968 size = TARGET_ARM ? 16 : 0;
7969 }
7970 else
7971 {
7972 emit_move_insn (reg, mem);
7973 size = GET_MODE_SIZE (GET_MODE (reg));
7974 }
7975 }
7976
7977 /* Emit USE insns before the return. */
7978 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7979 emit_insn (gen_rtx_USE (VOIDmode,
7980 SET_DEST (XVECEXP (operands[1], 0, i))));
7981
7982 /* Construct the return. */
7983 expand_naked_return ();
7984
7985 DONE;
7986 }"
7987)
7988
9c08d1fa 7989;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7990;; all of memory. This blocks insns from being moved across this point.
7991
7992(define_insn "blockage"
e1159bbe 7993 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 7994 "TARGET_EITHER"
9c08d1fa 7995 ""
cffb2a26 7996 [(set_attr "length" "0")
7997 (set_attr "type" "block")]
7998)
9c08d1fa 7999
f7fbdd4a 8000(define_expand "casesi"
8001 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8002 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8003 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8004 (match_operand:SI 3 "" "") ; table label
8005 (match_operand:SI 4 "" "")] ; Out of range label
cffb2a26 8006 "TARGET_ARM"
f7fbdd4a 8007 "
215b30b3 8008 {
8009 rtx reg;
8010 if (operands[1] != const0_rtx)
8011 {
8012 reg = gen_reg_rtx (SImode);
f7fbdd4a 8013
215b30b3 8014 emit_insn (gen_addsi3 (reg, operands[0],
8015 GEN_INT (-INTVAL (operands[1]))));
8016 operands[0] = reg;
8017 }
9c08d1fa 8018
215b30b3 8019 if (!const_ok_for_arm (INTVAL (operands[2])))
8020 operands[2] = force_reg (SImode, operands[2]);
8021
8022 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8023 operands[4]));
8024 DONE;
8025 }"
8026)
f7fbdd4a 8027
f082f1c4 8028;; The USE in this pattern is needed to tell flow analysis that this is
8029;; a CASESI insn. It has no other purpose.
f7fbdd4a 8030(define_insn "casesi_internal"
f082f1c4 8031 [(parallel [(set (pc)
8032 (if_then_else
8033 (leu (match_operand:SI 0 "s_register_operand" "r")
8034 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8035 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8036 (label_ref (match_operand 2 "" ""))))
8037 (label_ref (match_operand 3 "" ""))))
bd5b4116 8038 (clobber (reg:CC CC_REGNUM))
f082f1c4 8039 (use (label_ref (match_dup 2)))])]
cffb2a26 8040 "TARGET_ARM"
f7fbdd4a 8041 "*
0d66636f 8042 if (flag_pic)
8043 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8044 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8045 "
8046 [(set_attr "conds" "clob")
8047 (set_attr "length" "12")]
8048)
9c08d1fa 8049
cffb2a26 8050(define_expand "indirect_jump"
9c08d1fa 8051 [(set (pc)
cffb2a26 8052 (match_operand:SI 0 "s_register_operand" ""))]
8053 "TARGET_EITHER"
9c08d1fa 8054 ""
cffb2a26 8055)
8056
f1039640 8057;; NB Never uses BX.
cffb2a26 8058(define_insn "*arm_indirect_jump"
8059 [(set (pc)
8060 (match_operand:SI 0 "s_register_operand" "r"))]
8061 "TARGET_ARM"
8062 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8063 [(set_attr "predicable" "yes")]
cffb2a26 8064)
9c08d1fa 8065
f7fbdd4a 8066(define_insn "*load_indirect_jump"
9c08d1fa 8067 [(set (pc)
8068 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8069 "TARGET_ARM"
8070 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8071 [(set_attr "type" "load1")
61a2d04c 8072 (set_attr "pool_range" "4096")
8073 (set_attr "neg_pool_range" "4084")
0d66636f 8074 (set_attr "predicable" "yes")]
cffb2a26 8075)
8076
f1039640 8077;; NB Never uses BX.
cffb2a26 8078(define_insn "*thumb_indirect_jump"
8079 [(set (pc)
8080 (match_operand:SI 0 "register_operand" "l*r"))]
8081 "TARGET_THUMB"
8082 "mov\\tpc, %0"
8083 [(set_attr "conds" "clob")
8084 (set_attr "length" "2")]
8085)
8086
9c08d1fa 8087\f
8088;; Misc insns
8089
8090(define_insn "nop"
8091 [(const_int 0)]
cffb2a26 8092 "TARGET_EITHER"
8093 "*
8094 if (TARGET_ARM)
8095 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8096 return \"mov\\tr8, r8\";
8097 "
8098 [(set (attr "length")
8099 (if_then_else (eq_attr "is_thumb" "yes")
8100 (const_int 2)
8101 (const_int 4)))]
8102)
8103
9c08d1fa 8104\f
8105;; Patterns to allow combination of arithmetic, cond code and shifts
8106
f7fbdd4a 8107(define_insn "*arith_shiftsi"
9c08d1fa 8108 [(set (match_operand:SI 0 "s_register_operand" "=r")
8109 (match_operator:SI 1 "shiftable_operator"
8110 [(match_operator:SI 3 "shift_operator"
8111 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8112 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8113 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 8114 "TARGET_ARM"
6c4c2133 8115 "%i1%?\\t%0, %2, %4%S3"
344495ea 8116 [(set_attr "predicable" "yes")
331beb1a 8117 (set_attr "shift" "4")
a2cd141b 8118 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8119 (const_string "alu_shift")
8120 (const_string "alu_shift_reg")))]
6c4c2133 8121)
9c08d1fa 8122
d7863cfe 8123(define_split
8124 [(set (match_operand:SI 0 "s_register_operand" "")
8125 (match_operator:SI 1 "shiftable_operator"
8126 [(match_operator:SI 2 "shiftable_operator"
8127 [(match_operator:SI 3 "shift_operator"
8128 [(match_operand:SI 4 "s_register_operand" "")
8129 (match_operand:SI 5 "reg_or_int_operand" "")])
8130 (match_operand:SI 6 "s_register_operand" "")])
8131 (match_operand:SI 7 "arm_rhs_operand" "")]))
8132 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8133 "TARGET_ARM"
8134 [(set (match_dup 8)
8135 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8136 (match_dup 6)]))
8137 (set (match_dup 0)
8138 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8139 "")
8140
f7fbdd4a 8141(define_insn "*arith_shiftsi_compare0"
bd5b4116 8142 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8143 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8144 [(match_operator:SI 3 "shift_operator"
8145 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8146 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8147 (match_operand:SI 2 "s_register_operand" "r")])
8148 (const_int 0)))
8149 (set (match_operand:SI 0 "s_register_operand" "=r")
8150 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8151 (match_dup 2)]))]
cffb2a26 8152 "TARGET_ARM"
87b22bf7 8153 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8154 [(set_attr "conds" "set")
331beb1a 8155 (set_attr "shift" "4")
a2cd141b 8156 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8157 (const_string "alu_shift")
8158 (const_string "alu_shift_reg")))]
0d66636f 8159)
9c08d1fa 8160
f7fbdd4a 8161(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8162 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8163 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8164 [(match_operator:SI 3 "shift_operator"
8165 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8166 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8167 (match_operand:SI 2 "s_register_operand" "r")])
8168 (const_int 0)))
8169 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8170 "TARGET_ARM"
87b22bf7 8171 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8172 [(set_attr "conds" "set")
331beb1a 8173 (set_attr "shift" "4")
a2cd141b 8174 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8175 (const_string "alu_shift")
8176 (const_string "alu_shift_reg")))]
0d66636f 8177)
9c08d1fa 8178
f7fbdd4a 8179(define_insn "*sub_shiftsi"
9c08d1fa 8180 [(set (match_operand:SI 0 "s_register_operand" "=r")
8181 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8182 (match_operator:SI 2 "shift_operator"
8183 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8184 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 8185 "TARGET_ARM"
6c4c2133 8186 "sub%?\\t%0, %1, %3%S2"
344495ea 8187 [(set_attr "predicable" "yes")
331beb1a 8188 (set_attr "shift" "3")
a2cd141b 8189 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8190 (const_string "alu_shift")
8191 (const_string "alu_shift_reg")))]
6c4c2133 8192)
9c08d1fa 8193
f7fbdd4a 8194(define_insn "*sub_shiftsi_compare0"
bd5b4116 8195 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8196 (compare:CC_NOOV
8197 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8198 (match_operator:SI 2 "shift_operator"
8199 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8200 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8201 (const_int 0)))
9c08d1fa 8202 (set (match_operand:SI 0 "s_register_operand" "=r")
8203 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8204 (match_dup 4)])))]
cffb2a26 8205 "TARGET_ARM"
87b22bf7 8206 "sub%?s\\t%0, %1, %3%S2"
344495ea 8207 [(set_attr "conds" "set")
a2cd141b 8208 (set_attr "shift" "3")
8209 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8210 (const_string "alu_shift")
8211 (const_string "alu_shift_reg")))]
0d66636f 8212)
9c08d1fa 8213
f7fbdd4a 8214(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8215 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8216 (compare:CC_NOOV
8217 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8218 (match_operator:SI 2 "shift_operator"
8219 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8220 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8221 (const_int 0)))
9c08d1fa 8222 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8223 "TARGET_ARM"
87b22bf7 8224 "sub%?s\\t%0, %1, %3%S2"
344495ea 8225 [(set_attr "conds" "set")
a2cd141b 8226 (set_attr "shift" "3")
8227 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8228 (const_string "alu_shift")
8229 (const_string "alu_shift_reg")))]
0d66636f 8230)
9c08d1fa 8231
9c08d1fa 8232\f
8233
f7fbdd4a 8234(define_insn "*and_scc"
9c08d1fa 8235 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8236 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8237 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8238 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8239 "TARGET_ARM"
e2348bcb 8240 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8241 [(set_attr "conds" "use")
8242 (set_attr "length" "8")]
8243)
9c08d1fa 8244
f7fbdd4a 8245(define_insn "*ior_scc"
9c08d1fa 8246 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8247 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8248 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8249 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8250 "TARGET_ARM"
e2348bcb 8251 "@
899850b0 8252 orr%d2\\t%0, %1, #1
8253 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8254 [(set_attr "conds" "use")
8255 (set_attr "length" "4,8")]
8256)
9c08d1fa 8257
f7fbdd4a 8258(define_insn "*compare_scc"
5565501b 8259 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8260 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8261 [(match_operand:SI 2 "s_register_operand" "r,r")
8262 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8263 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8264 "TARGET_ARM"
9c08d1fa 8265 "*
601f584c 8266 if (operands[3] == const0_rtx)
8267 {
8268 if (GET_CODE (operands[1]) == LT)
8269 return \"mov\\t%0, %2, lsr #31\";
8270
8271 if (GET_CODE (operands[1]) == GE)
8272 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 8273
601f584c 8274 if (GET_CODE (operands[1]) == EQ)
8275 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8276 }
e2348bcb 8277
8fa3ba89 8278 if (GET_CODE (operands[1]) == NE)
8279 {
8280 if (which_alternative == 1)
8281 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8282 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8283 }
8284 if (which_alternative == 1)
8285 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8286 else
8287 output_asm_insn (\"cmp\\t%2, %3\", operands);
8288 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8289 "
8290 [(set_attr "conds" "clob")
8291 (set_attr "length" "12")]
8292)
9c08d1fa 8293
f7fbdd4a 8294(define_insn "*cond_move"
9c08d1fa 8295 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8296 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8297 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8298 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8299 (const_int 0)])
8300 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8301 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8302 "TARGET_ARM"
9c08d1fa 8303 "*
8fa3ba89 8304 if (GET_CODE (operands[3]) == NE)
8305 {
8306 if (which_alternative != 1)
8307 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8308 if (which_alternative != 0)
8309 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8310 return \"\";
8311 }
8312 if (which_alternative != 0)
8313 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8314 if (which_alternative != 1)
8315 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8316 return \"\";
8317 "
8318 [(set_attr "conds" "use")
8319 (set_attr "length" "4,4,8")]
8320)
9c08d1fa 8321
f7fbdd4a 8322(define_insn "*cond_arith"
9c08d1fa 8323 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8324 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8325 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8326 [(match_operand:SI 2 "s_register_operand" "r,r")
8327 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8328 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8329 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8330 "TARGET_ARM"
9c08d1fa 8331 "*
8fa3ba89 8332 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8333 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8334
8fa3ba89 8335 output_asm_insn (\"cmp\\t%2, %3\", operands);
8336 if (GET_CODE (operands[5]) == AND)
8337 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8338 else if (GET_CODE (operands[5]) == MINUS)
8339 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8340 else if (which_alternative != 0)
8341 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8342 return \"%i5%d4\\t%0, %1, #1\";
8343 "
8344 [(set_attr "conds" "clob")
8345 (set_attr "length" "12")]
8346)
9c08d1fa 8347
f7fbdd4a 8348(define_insn "*cond_sub"
9c08d1fa 8349 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8350 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8351 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8352 [(match_operand:SI 2 "s_register_operand" "r,r")
8353 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8354 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8355 "TARGET_ARM"
9c08d1fa 8356 "*
8fa3ba89 8357 output_asm_insn (\"cmp\\t%2, %3\", operands);
8358 if (which_alternative != 0)
8359 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8360 return \"sub%d4\\t%0, %1, #1\";
8361 "
8362 [(set_attr "conds" "clob")
8363 (set_attr "length" "8,12")]
8364)
9c08d1fa 8365
aea4c774 8366(define_insn "*cmp_ite0"
cffb2a26 8367 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8368 (compare
8369 (if_then_else:SI
8fa3ba89 8370 (match_operator 4 "arm_comparison_operator"
aea4c774 8371 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8372 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8373 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8374 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8375 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8376 (const_int 0))
8377 (const_int 0)))]
cffb2a26 8378 "TARGET_ARM"
9c08d1fa 8379 "*
aea4c774 8380 {
8fa3ba89 8381 static const char * const opcodes[4][2] =
8382 {
8383 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8384 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8385 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8386 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8387 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8388 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8389 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8390 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8391 };
8392 int swap =
8393 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8394
8395 return opcodes[which_alternative][swap];
8396 }"
8397 [(set_attr "conds" "set")
8398 (set_attr "length" "8")]
8399)
9c08d1fa 8400
aea4c774 8401(define_insn "*cmp_ite1"
cffb2a26 8402 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8403 (compare
8404 (if_then_else:SI
8fa3ba89 8405 (match_operator 4 "arm_comparison_operator"
aea4c774 8406 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8407 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8408 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8409 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8410 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8411 (const_int 1))
8412 (const_int 0)))]
cffb2a26 8413 "TARGET_ARM"
9c08d1fa 8414 "*
9c08d1fa 8415 {
215b30b3 8416 static const char * const opcodes[4][2] =
8417 {
8418 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8419 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8420 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8421 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8422 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8423 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8424 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8425 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8426 };
8427 int swap =
8428 comparison_dominates_p (GET_CODE (operands[5]),
8429 reverse_condition (GET_CODE (operands[4])));
8430
8431 return opcodes[which_alternative][swap];
8432 }"
8fa3ba89 8433 [(set_attr "conds" "set")
8434 (set_attr "length" "8")]
8435)
9c08d1fa 8436
f6c53574 8437(define_insn "*cmp_and"
8438 [(set (match_operand 6 "dominant_cc_register" "")
8439 (compare
8440 (and:SI
8441 (match_operator 4 "arm_comparison_operator"
8442 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8443 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8444 (match_operator:SI 5 "arm_comparison_operator"
8445 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8446 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8447 (const_int 0)))]
8448 "TARGET_ARM"
8449 "*
8450 {
35823b64 8451 static const char *const opcodes[4][2] =
f6c53574 8452 {
8453 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8454 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8455 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8456 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8457 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8458 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8459 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8460 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8461 };
8462 int swap =
8463 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8464
8465 return opcodes[which_alternative][swap];
8466 }"
8467 [(set_attr "conds" "set")
8468 (set_attr "predicable" "no")
8469 (set_attr "length" "8")]
8470)
8471
8472(define_insn "*cmp_ior"
8473 [(set (match_operand 6 "dominant_cc_register" "")
8474 (compare
8475 (ior:SI
8476 (match_operator 4 "arm_comparison_operator"
8477 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8478 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8479 (match_operator:SI 5 "arm_comparison_operator"
8480 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8481 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8482 (const_int 0)))]
8483 "TARGET_ARM"
8484 "*
8485{
35823b64 8486 static const char *const opcodes[4][2] =
f6c53574 8487 {
8488 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8489 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8490 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8491 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8492 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8493 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8494 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8495 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8496 };
8497 int swap =
8498 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8499
8500 return opcodes[which_alternative][swap];
8501}
8502"
8503 [(set_attr "conds" "set")
8504 (set_attr "length" "8")]
8505)
8506
3c5afce6 8507(define_insn_and_split "*ior_scc_scc"
8508 [(set (match_operand:SI 0 "s_register_operand" "=r")
8509 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8510 [(match_operand:SI 1 "s_register_operand" "r")
8511 (match_operand:SI 2 "arm_add_operand" "rIL")])
8512 (match_operator:SI 6 "arm_comparison_operator"
8513 [(match_operand:SI 4 "s_register_operand" "r")
8514 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8515 (clobber (reg:CC CC_REGNUM))]
8516 "TARGET_ARM
8517 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8518 != CCmode)"
8519 "#"
8520 "TARGET_ARM && reload_completed"
8521 [(set (match_dup 7)
8522 (compare
8523 (ior:SI
8524 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8525 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8526 (const_int 0)))
8527 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8528 "operands[7]
8529 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8530 DOM_CC_X_OR_Y),
601f584c 8531 CC_REGNUM);"
8532 [(set_attr "conds" "clob")
8533 (set_attr "length" "16")])
8534
8535; If the above pattern is followed by a CMP insn, then the compare is
8536; redundant, since we can rework the conditional instruction that follows.
8537(define_insn_and_split "*ior_scc_scc_cmp"
8538 [(set (match_operand 0 "dominant_cc_register" "")
8539 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8540 [(match_operand:SI 1 "s_register_operand" "r")
8541 (match_operand:SI 2 "arm_add_operand" "rIL")])
8542 (match_operator:SI 6 "arm_comparison_operator"
8543 [(match_operand:SI 4 "s_register_operand" "r")
8544 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8545 (const_int 0)))
8546 (set (match_operand:SI 7 "s_register_operand" "=r")
8547 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8548 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8549 "TARGET_ARM"
8550 "#"
8551 "TARGET_ARM && reload_completed"
8552 [(set (match_dup 0)
8553 (compare
8554 (ior:SI
8555 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8556 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8557 (const_int 0)))
8558 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8559 ""
8560 [(set_attr "conds" "set")
8561 (set_attr "length" "16")])
3c5afce6 8562
8563(define_insn_and_split "*and_scc_scc"
8564 [(set (match_operand:SI 0 "s_register_operand" "=r")
8565 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8566 [(match_operand:SI 1 "s_register_operand" "r")
8567 (match_operand:SI 2 "arm_add_operand" "rIL")])
8568 (match_operator:SI 6 "arm_comparison_operator"
8569 [(match_operand:SI 4 "s_register_operand" "r")
8570 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8571 (clobber (reg:CC CC_REGNUM))]
8572 "TARGET_ARM
8573 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8574 != CCmode)"
8575 "#"
601f584c 8576 "TARGET_ARM && reload_completed
8577 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8578 != CCmode)"
3c5afce6 8579 [(set (match_dup 7)
8580 (compare
8581 (and:SI
8582 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8583 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8584 (const_int 0)))
8585 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8586 "operands[7]
8587 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8588 DOM_CC_X_AND_Y),
601f584c 8589 CC_REGNUM);"
8590 [(set_attr "conds" "clob")
8591 (set_attr "length" "16")])
8592
8593; If the above pattern is followed by a CMP insn, then the compare is
8594; redundant, since we can rework the conditional instruction that follows.
8595(define_insn_and_split "*and_scc_scc_cmp"
8596 [(set (match_operand 0 "dominant_cc_register" "")
8597 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8598 [(match_operand:SI 1 "s_register_operand" "r")
8599 (match_operand:SI 2 "arm_add_operand" "rIL")])
8600 (match_operator:SI 6 "arm_comparison_operator"
8601 [(match_operand:SI 4 "s_register_operand" "r")
8602 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8603 (const_int 0)))
8604 (set (match_operand:SI 7 "s_register_operand" "=r")
8605 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8606 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8607 "TARGET_ARM"
8608 "#"
8609 "TARGET_ARM && reload_completed"
8610 [(set (match_dup 0)
8611 (compare
8612 (and:SI
8613 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8614 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8615 (const_int 0)))
8616 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8617 ""
8618 [(set_attr "conds" "set")
8619 (set_attr "length" "16")])
8620
8621;; If there is no dominance in the comparison, then we can still save an
8622;; instruction in the AND case, since we can know that the second compare
8623;; need only zero the value if false (if true, then the value is already
8624;; correct).
8625(define_insn_and_split "*and_scc_scc_nodom"
8626 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8627 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8628 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8629 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8630 (match_operator:SI 6 "arm_comparison_operator"
8631 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8632 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8633 (clobber (reg:CC CC_REGNUM))]
8634 "TARGET_ARM
8635 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8636 == CCmode)"
8637 "#"
8638 "TARGET_ARM && reload_completed"
8639 [(parallel [(set (match_dup 0)
8640 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8641 (clobber (reg:CC CC_REGNUM))])
8642 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8643 (set (match_dup 0)
8644 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8645 (match_dup 0)
8646 (const_int 0)))]
8647 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8648 operands[4], operands[5]),
8649 CC_REGNUM);
8650 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8651 operands[5]);"
8652 [(set_attr "conds" "clob")
8653 (set_attr "length" "20")])
3c5afce6 8654
3a0bdee0 8655(define_split
8656 [(set (reg:CC_NOOV CC_REGNUM)
8657 (compare:CC_NOOV (ior:SI
8658 (and:SI (match_operand:SI 0 "s_register_operand" "")
8659 (const_int 1))
8660 (match_operator:SI 1 "comparison_operator"
8661 [(match_operand:SI 2 "s_register_operand" "")
8662 (match_operand:SI 3 "arm_add_operand" "")]))
8663 (const_int 0)))
8664 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8665 "TARGET_ARM"
8666 [(set (match_dup 4)
8667 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8668 (match_dup 0)))
8669 (set (reg:CC_NOOV CC_REGNUM)
8670 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8671 (const_int 0)))]
8672 "")
8673
8674(define_split
8675 [(set (reg:CC_NOOV CC_REGNUM)
8676 (compare:CC_NOOV (ior:SI
8677 (match_operator:SI 1 "comparison_operator"
8678 [(match_operand:SI 2 "s_register_operand" "")
8679 (match_operand:SI 3 "arm_add_operand" "")])
8680 (and:SI (match_operand:SI 0 "s_register_operand" "")
8681 (const_int 1)))
8682 (const_int 0)))
8683 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8684 "TARGET_ARM"
8685 [(set (match_dup 4)
8686 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8687 (match_dup 0)))
8688 (set (reg:CC_NOOV CC_REGNUM)
8689 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8690 (const_int 0)))]
8691 "")
8692
f7fbdd4a 8693(define_insn "*negscc"
9c08d1fa 8694 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8695 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 8696 [(match_operand:SI 1 "s_register_operand" "r")
8697 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 8698 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8699 "TARGET_ARM"
9c08d1fa 8700 "*
f0e75574 8701 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
e2348bcb 8702 return \"mov\\t%0, %1, asr #31\";
8703
9c08d1fa 8704 if (GET_CODE (operands[3]) == NE)
e2348bcb 8705 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8706
9c08d1fa 8707 if (GET_CODE (operands[3]) == GT)
e2348bcb 8708 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8709
8710 output_asm_insn (\"cmp\\t%1, %2\", operands);
8711 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8712 return \"mvn%d3\\t%0, #0\";
215b30b3 8713 "
8fa3ba89 8714 [(set_attr "conds" "clob")
8715 (set_attr "length" "12")]
8716)
9c08d1fa 8717
8718(define_insn "movcond"
8719 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 8720 (if_then_else:SI
8fa3ba89 8721 (match_operator 5 "arm_comparison_operator"
5565501b 8722 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8723 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8724 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8725 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 8726 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8727 "TARGET_ARM"
9c08d1fa 8728 "*
8729 if (GET_CODE (operands[5]) == LT
8730 && (operands[4] == const0_rtx))
8731 {
5565501b 8732 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 8733 {
9c08d1fa 8734 if (operands[2] == const0_rtx)
e2348bcb 8735 return \"and\\t%0, %1, %3, asr #31\";
8736 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 8737 }
8738 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8739 {
9c08d1fa 8740 if (operands[1] == const0_rtx)
e2348bcb 8741 return \"bic\\t%0, %2, %3, asr #31\";
8742 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 8743 }
8744 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8745 are constants. */
9c08d1fa 8746 }
e2348bcb 8747
9c08d1fa 8748 if (GET_CODE (operands[5]) == GE
8749 && (operands[4] == const0_rtx))
8750 {
8751 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8752 {
9c08d1fa 8753 if (operands[2] == const0_rtx)
e2348bcb 8754 return \"bic\\t%0, %1, %3, asr #31\";
8755 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 8756 }
8757 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8758 {
9c08d1fa 8759 if (operands[1] == const0_rtx)
e2348bcb 8760 return \"and\\t%0, %2, %3, asr #31\";
8761 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 8762 }
8763 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8764 are constants. */
9c08d1fa 8765 }
8766 if (GET_CODE (operands[4]) == CONST_INT
8767 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 8768 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 8769 else
e2348bcb 8770 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 8771 if (which_alternative != 0)
e2348bcb 8772 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 8773 if (which_alternative != 1)
e2348bcb 8774 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 8775 return \"\";
215b30b3 8776 "
8fa3ba89 8777 [(set_attr "conds" "clob")
8778 (set_attr "length" "8,8,12")]
8779)
9c08d1fa 8780
8a18b90c 8781(define_insn "*ifcompare_plus_move"
8782 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8783 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8784 [(match_operand:SI 4 "s_register_operand" "r,r")
8785 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8786 (plus:SI
8787 (match_operand:SI 2 "s_register_operand" "r,r")
8788 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 8789 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8790 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8791 "TARGET_ARM"
8a18b90c 8792 "#"
8fa3ba89 8793 [(set_attr "conds" "clob")
8794 (set_attr "length" "8,12")]
8795)
8a18b90c 8796
8797(define_insn "*if_plus_move"
129a2fe4 8798 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8799 (if_then_else:SI
8fa3ba89 8800 (match_operator 4 "arm_comparison_operator"
8a18b90c 8801 [(match_operand 5 "cc_register" "") (const_int 0)])
8802 (plus:SI
129a2fe4 8803 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8804 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8805 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 8806 "TARGET_ARM"
8a18b90c 8807 "@
8808 add%d4\\t%0, %2, %3
8809 sub%d4\\t%0, %2, #%n3
8810 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 8811 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 8812 [(set_attr "conds" "use")
8813 (set_attr "length" "4,4,8,8")
8814 (set_attr "type" "*,*,*,*")]
8815)
8a18b90c 8816
8817(define_insn "*ifcompare_move_plus"
5565501b 8818 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8819 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8820 [(match_operand:SI 4 "s_register_operand" "r,r")
8821 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8822 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8823 (plus:SI
8824 (match_operand:SI 2 "s_register_operand" "r,r")
8825 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 8826 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8827 "TARGET_ARM"
8a18b90c 8828 "#"
8fa3ba89 8829 [(set_attr "conds" "clob")
8830 (set_attr "length" "8,12")]
8831)
8a18b90c 8832
8833(define_insn "*if_move_plus"
129a2fe4 8834 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8835 (if_then_else:SI
8fa3ba89 8836 (match_operator 4 "arm_comparison_operator"
8a18b90c 8837 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 8838 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 8839 (plus:SI
129a2fe4 8840 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8841 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 8842 "TARGET_ARM"
8a18b90c 8843 "@
8844 add%D4\\t%0, %2, %3
8845 sub%D4\\t%0, %2, #%n3
8846 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 8847 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 8848 [(set_attr "conds" "use")
8849 (set_attr "length" "4,4,8,8")
8850 (set_attr "type" "*,*,*,*")]
8851)
8a18b90c 8852
8853(define_insn "*ifcompare_arith_arith"
8854 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8855 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 8856 [(match_operand:SI 5 "s_register_operand" "r")
8857 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 8858 (match_operator:SI 8 "shiftable_operator"
8a18b90c 8859 [(match_operand:SI 1 "s_register_operand" "r")
8860 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 8861 (match_operator:SI 7 "shiftable_operator"
8a18b90c 8862 [(match_operand:SI 3 "s_register_operand" "r")
8863 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 8864 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8865 "TARGET_ARM"
8a18b90c 8866 "#"
8fa3ba89 8867 [(set_attr "conds" "clob")
8868 (set_attr "length" "12")]
8869)
9c08d1fa 8870
8a18b90c 8871(define_insn "*if_arith_arith"
8872 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8873 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 8874 [(match_operand 8 "cc_register" "") (const_int 0)])
8875 (match_operator:SI 6 "shiftable_operator"
8876 [(match_operand:SI 1 "s_register_operand" "r")
8877 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8878 (match_operator:SI 7 "shiftable_operator"
8879 [(match_operand:SI 3 "s_register_operand" "r")
8880 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 8881 "TARGET_ARM"
8a18b90c 8882 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 8883 [(set_attr "conds" "use")
8884 (set_attr "length" "8")]
8885)
8a18b90c 8886
f7fbdd4a 8887(define_insn "*ifcompare_arith_move"
9c08d1fa 8888 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8889 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8890 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 8891 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 8892 (match_operator:SI 7 "shiftable_operator"
8893 [(match_operand:SI 4 "s_register_operand" "r,r")
8894 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 8895 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8896 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8897 "TARGET_ARM"
9c08d1fa 8898 "*
9c08d1fa 8899 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8900 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 8901 everything is in registers then we can do this in two instructions. */
9c08d1fa 8902 if (operands[3] == const0_rtx
8903 && GET_CODE (operands[7]) != AND
8904 && GET_CODE (operands[5]) == REG
8905 && GET_CODE (operands[1]) == REG
8906 && REGNO (operands[1]) == REGNO (operands[4])
8907 && REGNO (operands[4]) != REGNO (operands[0]))
8908 {
8909 if (GET_CODE (operands[6]) == LT)
40dbec34 8910 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8911 else if (GET_CODE (operands[6]) == GE)
40dbec34 8912 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8913 }
8914 if (GET_CODE (operands[3]) == CONST_INT
8915 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 8916 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 8917 else
e2348bcb 8918 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 8919 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 8920 if (which_alternative != 0)
129a2fe4 8921 return \"mov%D6\\t%0, %1\";
9c08d1fa 8922 return \"\";
215b30b3 8923 "
8fa3ba89 8924 [(set_attr "conds" "clob")
8925 (set_attr "length" "8,12")]
8926)
9c08d1fa 8927
8a18b90c 8928(define_insn "*if_arith_move"
129a2fe4 8929 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8930 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 8931 [(match_operand 6 "cc_register" "") (const_int 0)])
8932 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8933 [(match_operand:SI 2 "s_register_operand" "r,r")
8934 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8935 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 8936 "TARGET_ARM"
8a18b90c 8937 "@
8938 %I5%d4\\t%0, %2, %3
129a2fe4 8939 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 8940 [(set_attr "conds" "use")
8941 (set_attr "length" "4,8")
8942 (set_attr "type" "*,*")]
8943)
8a18b90c 8944
f7fbdd4a 8945(define_insn "*ifcompare_move_arith"
9c08d1fa 8946 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8947 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8948 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 8949 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8950 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 8951 (match_operator:SI 7 "shiftable_operator"
8952 [(match_operand:SI 2 "s_register_operand" "r,r")
8953 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8954 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8955 "TARGET_ARM"
9c08d1fa 8956 "*
9c08d1fa 8957 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8958 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 8959 everything is in registers then we can do this in two instructions */
8960 if (operands[5] == const0_rtx
8961 && GET_CODE (operands[7]) != AND
8962 && GET_CODE (operands[3]) == REG
8963 && GET_CODE (operands[1]) == REG
8964 && REGNO (operands[1]) == REGNO (operands[2])
8965 && REGNO (operands[2]) != REGNO (operands[0]))
8966 {
8967 if (GET_CODE (operands[6]) == GE)
40dbec34 8968 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8969 else if (GET_CODE (operands[6]) == LT)
40dbec34 8970 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8971 }
40dbec34 8972
9c08d1fa 8973 if (GET_CODE (operands[5]) == CONST_INT
8974 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 8975 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 8976 else
e2348bcb 8977 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 8978
9c08d1fa 8979 if (which_alternative != 0)
129a2fe4 8980 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 8981 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 8982 "
8fa3ba89 8983 [(set_attr "conds" "clob")
8984 (set_attr "length" "8,12")]
8985)
9c08d1fa 8986
8a18b90c 8987(define_insn "*if_move_arith"
129a2fe4 8988 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 8989 (if_then_else:SI
8fa3ba89 8990 (match_operator 4 "arm_comparison_operator"
8a18b90c 8991 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 8992 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8993 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8994 [(match_operand:SI 2 "s_register_operand" "r,r")
8995 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 8996 "TARGET_ARM"
8a18b90c 8997 "@
8998 %I5%D4\\t%0, %2, %3
129a2fe4 8999 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9000 [(set_attr "conds" "use")
9001 (set_attr "length" "4,8")
9002 (set_attr "type" "*,*")]
9003)
8a18b90c 9004
9005(define_insn "*ifcompare_move_not"
9c08d1fa 9006 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9007 (if_then_else:SI
8fa3ba89 9008 (match_operator 5 "arm_comparison_operator"
8a18b90c 9009 [(match_operand:SI 3 "s_register_operand" "r,r")
9010 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9011 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9012 (not:SI
9013 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9014 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9015 "TARGET_ARM"
8a18b90c 9016 "#"
8fa3ba89 9017 [(set_attr "conds" "clob")
9018 (set_attr "length" "8,12")]
9019)
9c08d1fa 9020
8a18b90c 9021(define_insn "*if_move_not"
9022 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9023 (if_then_else:SI
8fa3ba89 9024 (match_operator 4 "arm_comparison_operator"
8a18b90c 9025 [(match_operand 3 "cc_register" "") (const_int 0)])
9026 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9027 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9028 "TARGET_ARM"
8a18b90c 9029 "@
9030 mvn%D4\\t%0, %2
9031 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9032 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9033 [(set_attr "conds" "use")
9034 (set_attr "length" "4,8,8")]
9035)
8a18b90c 9036
9037(define_insn "*ifcompare_not_move"
9c08d1fa 9038 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9039 (if_then_else:SI
8fa3ba89 9040 (match_operator 5 "arm_comparison_operator"
8a18b90c 9041 [(match_operand:SI 3 "s_register_operand" "r,r")
9042 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9043 (not:SI
9044 (match_operand:SI 2 "s_register_operand" "r,r"))
9045 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9046 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9047 "TARGET_ARM"
8a18b90c 9048 "#"
8fa3ba89 9049 [(set_attr "conds" "clob")
9050 (set_attr "length" "8,12")]
9051)
9c08d1fa 9052
8a18b90c 9053(define_insn "*if_not_move"
9054 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9055 (if_then_else:SI
8fa3ba89 9056 (match_operator 4 "arm_comparison_operator"
8a18b90c 9057 [(match_operand 3 "cc_register" "") (const_int 0)])
9058 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9059 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9060 "TARGET_ARM"
8a18b90c 9061 "@
9062 mvn%d4\\t%0, %2
9063 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9064 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9065 [(set_attr "conds" "use")
9066 (set_attr "length" "4,8,8")]
9067)
8a18b90c 9068
9069(define_insn "*ifcompare_shift_move"
9c08d1fa 9070 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9071 (if_then_else:SI
8fa3ba89 9072 (match_operator 6 "arm_comparison_operator"
8a18b90c 9073 [(match_operand:SI 4 "s_register_operand" "r,r")
9074 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9075 (match_operator:SI 7 "shift_operator"
9076 [(match_operand:SI 2 "s_register_operand" "r,r")
9077 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9078 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9079 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9080 "TARGET_ARM"
9c08d1fa 9081 "#"
8fa3ba89 9082 [(set_attr "conds" "clob")
9083 (set_attr "length" "8,12")]
9084)
9c08d1fa 9085
8a18b90c 9086(define_insn "*if_shift_move"
9087 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9088 (if_then_else:SI
8fa3ba89 9089 (match_operator 5 "arm_comparison_operator"
8a18b90c 9090 [(match_operand 6 "cc_register" "") (const_int 0)])
9091 (match_operator:SI 4 "shift_operator"
9092 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9093 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9094 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9095 "TARGET_ARM"
5565501b 9096 "@
8a18b90c 9097 mov%d5\\t%0, %2%S4
9098 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9099 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9100 [(set_attr "conds" "use")
331beb1a 9101 (set_attr "shift" "2")
a2cd141b 9102 (set_attr "length" "4,8,8")
9103 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9104 (const_string "alu_shift")
9105 (const_string "alu_shift_reg")))]
8fa3ba89 9106)
5565501b 9107
8a18b90c 9108(define_insn "*ifcompare_move_shift"
9109 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9110 (if_then_else:SI
8fa3ba89 9111 (match_operator 6 "arm_comparison_operator"
8a18b90c 9112 [(match_operand:SI 4 "s_register_operand" "r,r")
9113 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9114 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9115 (match_operator:SI 7 "shift_operator"
8a18b90c 9116 [(match_operand:SI 2 "s_register_operand" "r,r")
9117 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9118 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9119 "TARGET_ARM"
8a18b90c 9120 "#"
8fa3ba89 9121 [(set_attr "conds" "clob")
9122 (set_attr "length" "8,12")]
9123)
5565501b 9124
8a18b90c 9125(define_insn "*if_move_shift"
9126 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9127 (if_then_else:SI
8fa3ba89 9128 (match_operator 5 "arm_comparison_operator"
8a18b90c 9129 [(match_operand 6 "cc_register" "") (const_int 0)])
9130 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9131 (match_operator:SI 4 "shift_operator"
9132 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9133 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9134 "TARGET_ARM"
5565501b 9135 "@
8a18b90c 9136 mov%D5\\t%0, %2%S4
9137 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9138 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9139 [(set_attr "conds" "use")
331beb1a 9140 (set_attr "shift" "2")
a2cd141b 9141 (set_attr "length" "4,8,8")
9142 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9143 (const_string "alu_shift")
9144 (const_string "alu_shift_reg")))]
8fa3ba89 9145)
9c08d1fa 9146
f7fbdd4a 9147(define_insn "*ifcompare_shift_shift"
8a18b90c 9148 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9149 (if_then_else:SI
8fa3ba89 9150 (match_operator 7 "arm_comparison_operator"
8a18b90c 9151 [(match_operand:SI 5 "s_register_operand" "r")
9152 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9153 (match_operator:SI 8 "shift_operator"
8a18b90c 9154 [(match_operand:SI 1 "s_register_operand" "r")
9155 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9156 (match_operator:SI 9 "shift_operator"
8a18b90c 9157 [(match_operand:SI 3 "s_register_operand" "r")
9158 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9159 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9160 "TARGET_ARM"
8a18b90c 9161 "#"
8fa3ba89 9162 [(set_attr "conds" "clob")
9163 (set_attr "length" "12")]
9164)
9c08d1fa 9165
8a18b90c 9166(define_insn "*if_shift_shift"
9167 [(set (match_operand:SI 0 "s_register_operand" "=r")
9168 (if_then_else:SI
8fa3ba89 9169 (match_operator 5 "arm_comparison_operator"
8a18b90c 9170 [(match_operand 8 "cc_register" "") (const_int 0)])
9171 (match_operator:SI 6 "shift_operator"
9172 [(match_operand:SI 1 "s_register_operand" "r")
9173 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9174 (match_operator:SI 7 "shift_operator"
9175 [(match_operand:SI 3 "s_register_operand" "r")
9176 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9177 "TARGET_ARM"
8a18b90c 9178 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9179 [(set_attr "conds" "use")
331beb1a 9180 (set_attr "shift" "1")
a2cd141b 9181 (set_attr "length" "8")
9182 (set (attr "type") (if_then_else
9183 (and (match_operand 2 "const_int_operand" "")
9184 (match_operand 4 "const_int_operand" ""))
9185 (const_string "alu_shift")
9186 (const_string "alu_shift_reg")))]
8fa3ba89 9187)
8a18b90c 9188
f7fbdd4a 9189(define_insn "*ifcompare_not_arith"
8a18b90c 9190 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9191 (if_then_else:SI
8fa3ba89 9192 (match_operator 6 "arm_comparison_operator"
8a18b90c 9193 [(match_operand:SI 4 "s_register_operand" "r")
9194 (match_operand:SI 5 "arm_add_operand" "rIL")])
9195 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9196 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9197 [(match_operand:SI 2 "s_register_operand" "r")
9198 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9199 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9200 "TARGET_ARM"
8a18b90c 9201 "#"
8fa3ba89 9202 [(set_attr "conds" "clob")
9203 (set_attr "length" "12")]
9204)
9c08d1fa 9205
8a18b90c 9206(define_insn "*if_not_arith"
9207 [(set (match_operand:SI 0 "s_register_operand" "=r")
9208 (if_then_else:SI
8fa3ba89 9209 (match_operator 5 "arm_comparison_operator"
8a18b90c 9210 [(match_operand 4 "cc_register" "") (const_int 0)])
9211 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9212 (match_operator:SI 6 "shiftable_operator"
9213 [(match_operand:SI 2 "s_register_operand" "r")
9214 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9215 "TARGET_ARM"
8a18b90c 9216 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9217 [(set_attr "conds" "use")
9218 (set_attr "length" "8")]
9219)
8a18b90c 9220
9221(define_insn "*ifcompare_arith_not"
9222 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9223 (if_then_else:SI
8fa3ba89 9224 (match_operator 6 "arm_comparison_operator"
8a18b90c 9225 [(match_operand:SI 4 "s_register_operand" "r")
9226 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9227 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9228 [(match_operand:SI 2 "s_register_operand" "r")
9229 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9230 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9231 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9232 "TARGET_ARM"
8a18b90c 9233 "#"
8fa3ba89 9234 [(set_attr "conds" "clob")
9235 (set_attr "length" "12")]
9236)
9c08d1fa 9237
8a18b90c 9238(define_insn "*if_arith_not"
9239 [(set (match_operand:SI 0 "s_register_operand" "=r")
9240 (if_then_else:SI
8fa3ba89 9241 (match_operator 5 "arm_comparison_operator"
8a18b90c 9242 [(match_operand 4 "cc_register" "") (const_int 0)])
9243 (match_operator:SI 6 "shiftable_operator"
9244 [(match_operand:SI 2 "s_register_operand" "r")
9245 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9246 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9247 "TARGET_ARM"
8a18b90c 9248 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9249 [(set_attr "conds" "use")
9250 (set_attr "length" "8")]
9251)
8a18b90c 9252
f7fbdd4a 9253(define_insn "*ifcompare_neg_move"
8a18b90c 9254 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9255 (if_then_else:SI
8fa3ba89 9256 (match_operator 5 "arm_comparison_operator"
8a18b90c 9257 [(match_operand:SI 3 "s_register_operand" "r,r")
9258 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9259 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9260 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9261 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9262 "TARGET_ARM"
8a18b90c 9263 "#"
8fa3ba89 9264 [(set_attr "conds" "clob")
9265 (set_attr "length" "8,12")]
9266)
8a18b90c 9267
9268(define_insn "*if_neg_move"
9269 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9270 (if_then_else:SI
8fa3ba89 9271 (match_operator 4 "arm_comparison_operator"
8a18b90c 9272 [(match_operand 3 "cc_register" "") (const_int 0)])
9273 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9274 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9275 "TARGET_ARM"
8a18b90c 9276 "@
9277 rsb%d4\\t%0, %2, #0
9278 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9279 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9280 [(set_attr "conds" "use")
9281 (set_attr "length" "4,8,8")]
9282)
9c08d1fa 9283
f7fbdd4a 9284(define_insn "*ifcompare_move_neg"
8a18b90c 9285 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9286 (if_then_else:SI
8fa3ba89 9287 (match_operator 5 "arm_comparison_operator"
8a18b90c 9288 [(match_operand:SI 3 "s_register_operand" "r,r")
9289 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9290 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9291 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9292 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9293 "TARGET_ARM"
8a18b90c 9294 "#"
8fa3ba89 9295 [(set_attr "conds" "clob")
9296 (set_attr "length" "8,12")]
9297)
8a18b90c 9298
9299(define_insn "*if_move_neg"
9300 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9301 (if_then_else:SI
8fa3ba89 9302 (match_operator 4 "arm_comparison_operator"
8a18b90c 9303 [(match_operand 3 "cc_register" "") (const_int 0)])
9304 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9305 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9306 "TARGET_ARM"
8a18b90c 9307 "@
9308 rsb%D4\\t%0, %2, #0
9309 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9310 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9311 [(set_attr "conds" "use")
9312 (set_attr "length" "4,8,8")]
9313)
9c08d1fa 9314
f7fbdd4a 9315(define_insn "*arith_adjacentmem"
9c08d1fa 9316 [(set (match_operand:SI 0 "s_register_operand" "=r")
9317 (match_operator:SI 1 "shiftable_operator"
9318 [(match_operand:SI 2 "memory_operand" "m")
9319 (match_operand:SI 3 "memory_operand" "m")]))
9320 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9321 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9322 "*
215b30b3 9323 {
9324 rtx ldm[3];
9325 rtx arith[4];
94dee231 9326 rtx base_reg;
9327 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9328
215b30b3 9329 if (REGNO (operands[0]) > REGNO (operands[4]))
9330 {
9331 ldm[1] = operands[4];
9332 ldm[2] = operands[0];
9333 }
9334 else
9335 {
9336 ldm[1] = operands[0];
9337 ldm[2] = operands[4];
9338 }
94dee231 9339
9340 base_reg = XEXP (operands[2], 0);
9341
9342 if (!REG_P (base_reg))
9343 {
9344 val1 = INTVAL (XEXP (base_reg, 1));
9345 base_reg = XEXP (base_reg, 0);
9346 }
9347
9348 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9349 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9350
215b30b3 9351 arith[0] = operands[0];
9352 arith[3] = operands[1];
94dee231 9353
215b30b3 9354 if (val1 < val2)
9355 {
9356 arith[1] = ldm[1];
9357 arith[2] = ldm[2];
9358 }
9359 else
9360 {
9361 arith[1] = ldm[2];
9362 arith[2] = ldm[1];
9363 }
94dee231 9364
9365 ldm[0] = base_reg;
9366 if (val1 !=0 && val2 != 0)
215b30b3 9367 {
94dee231 9368 if (val1 == 4 || val2 == 4)
9369 /* Other val must be 8, since we know they are adjacent and neither
9370 is zero. */
9371 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
215b30b3 9372 else
94dee231 9373 {
9374 rtx ops[3];
9375
9376 ldm[0] = ops[0] = operands[4];
9377 ops[1] = base_reg;
9378 ops[2] = GEN_INT (val1);
9379 output_add_immediate (ops);
9380 if (val1 < val2)
9381 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9382 else
9383 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9384 }
215b30b3 9385 }
94dee231 9386 else if (val1 != 0)
215b30b3 9387 {
215b30b3 9388 if (val1 < val2)
9389 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9390 else
9391 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9392 }
9393 else
9394 {
215b30b3 9395 if (val1 < val2)
9396 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9397 else
9398 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9399 }
9400 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9401 return \"\";
9402 }"
9403 [(set_attr "length" "12")
9404 (set_attr "predicable" "yes")
a2cd141b 9405 (set_attr "type" "load1")]
215b30b3 9406)
9c08d1fa 9407
9408;; the arm can support extended pre-inc instructions
9409
9410;; In all these cases, we use operands 0 and 1 for the register being
9411;; incremented because those are the operands that local-alloc will
9412;; tie and these are the pair most likely to be tieable (and the ones
9413;; that will benefit the most).
9414
9415;; We reject the frame pointer if it occurs anywhere in these patterns since
9416;; elimination will cause too many headaches.
9417
f7fbdd4a 9418(define_insn "*strqi_preinc"
9c08d1fa 9419 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9420 (match_operand:SI 2 "index_operand" "rJ")))
9421 (match_operand:QI 3 "s_register_operand" "r"))
9422 (set (match_operand:SI 0 "s_register_operand" "=r")
9423 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9424 "TARGET_ARM
da45ccee 9425 && !arm_eliminable_register (operands[0])
9426 && !arm_eliminable_register (operands[1])
9427 && !arm_eliminable_register (operands[2])"
40dbec34 9428 "str%?b\\t%3, [%0, %2]!"
0d66636f 9429 [(set_attr "type" "store1")
9430 (set_attr "predicable" "yes")]
9431)
9c08d1fa 9432
f7fbdd4a 9433(define_insn "*strqi_predec"
9c08d1fa 9434 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9435 (match_operand:SI 2 "s_register_operand" "r")))
9436 (match_operand:QI 3 "s_register_operand" "r"))
9437 (set (match_operand:SI 0 "s_register_operand" "=r")
9438 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9439 "TARGET_ARM
da45ccee 9440 && !arm_eliminable_register (operands[0])
9441 && !arm_eliminable_register (operands[1])
9442 && !arm_eliminable_register (operands[2])"
40dbec34 9443 "str%?b\\t%3, [%0, -%2]!"
0d66636f 9444 [(set_attr "type" "store1")
9445 (set_attr "predicable" "yes")]
9446)
9c08d1fa 9447
f7fbdd4a 9448(define_insn "*loadqi_preinc"
9c08d1fa 9449 [(set (match_operand:QI 3 "s_register_operand" "=r")
9450 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9451 (match_operand:SI 2 "index_operand" "rJ"))))
9452 (set (match_operand:SI 0 "s_register_operand" "=r")
9453 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9454 "TARGET_ARM
da45ccee 9455 && !arm_eliminable_register (operands[0])
9456 && !arm_eliminable_register (operands[1])
9457 && !arm_eliminable_register (operands[2])"
40dbec34 9458 "ldr%?b\\t%3, [%0, %2]!"
a2cd141b 9459 [(set_attr "type" "load_byte")
0d66636f 9460 (set_attr "predicable" "yes")]
9461)
9c08d1fa 9462
f7fbdd4a 9463(define_insn "*loadqi_predec"
9c08d1fa 9464 [(set (match_operand:QI 3 "s_register_operand" "=r")
9465 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9466 (match_operand:SI 2 "s_register_operand" "r"))))
9467 (set (match_operand:SI 0 "s_register_operand" "=r")
9468 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9469 "TARGET_ARM
da45ccee 9470 && !arm_eliminable_register (operands[0])
9471 && !arm_eliminable_register (operands[1])
9472 && !arm_eliminable_register (operands[2])"
40dbec34 9473 "ldr%?b\\t%3, [%0, -%2]!"
a2cd141b 9474 [(set_attr "type" "load_byte")
0d66636f 9475 (set_attr "predicable" "yes")]
9476)
9c08d1fa 9477
f7fbdd4a 9478(define_insn "*loadqisi_preinc"
9c08d1fa 9479 [(set (match_operand:SI 3 "s_register_operand" "=r")
9480 (zero_extend:SI
9481 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9482 (match_operand:SI 2 "index_operand" "rJ")))))
9483 (set (match_operand:SI 0 "s_register_operand" "=r")
9484 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9485 "TARGET_ARM
da45ccee 9486 && !arm_eliminable_register (operands[0])
9487 && !arm_eliminable_register (operands[1])
9488 && !arm_eliminable_register (operands[2])"
40dbec34 9489 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
a2cd141b 9490 [(set_attr "type" "load_byte")
0d66636f 9491 (set_attr "predicable" "yes")]
9492)
9c08d1fa 9493
f7fbdd4a 9494(define_insn "*loadqisi_predec"
9c08d1fa 9495 [(set (match_operand:SI 3 "s_register_operand" "=r")
9496 (zero_extend:SI
9497 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9498 (match_operand:SI 2 "s_register_operand" "r")))))
9499 (set (match_operand:SI 0 "s_register_operand" "=r")
9500 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9501 "TARGET_ARM
da45ccee 9502 && !arm_eliminable_register (operands[0])
9503 && !arm_eliminable_register (operands[1])
9504 && !arm_eliminable_register (operands[2])"
40dbec34 9505 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
a2cd141b 9506 [(set_attr "type" "load_byte")
0d66636f 9507 (set_attr "predicable" "yes")]
9508)
9c08d1fa 9509
f7fbdd4a 9510(define_insn "*strsi_preinc"
9c08d1fa 9511 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9512 (match_operand:SI 2 "index_operand" "rJ")))
9513 (match_operand:SI 3 "s_register_operand" "r"))
9514 (set (match_operand:SI 0 "s_register_operand" "=r")
9515 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9516 "TARGET_ARM
da45ccee 9517 && !arm_eliminable_register (operands[0])
9518 && !arm_eliminable_register (operands[1])
9519 && !arm_eliminable_register (operands[2])"
40dbec34 9520 "str%?\\t%3, [%0, %2]!"
0d66636f 9521 [(set_attr "type" "store1")
9522 (set_attr "predicable" "yes")]
9523)
9c08d1fa 9524
cbd60e74 9525(define_insn "*strsi_predec"
9c08d1fa 9526 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9527 (match_operand:SI 2 "s_register_operand" "r")))
9528 (match_operand:SI 3 "s_register_operand" "r"))
9529 (set (match_operand:SI 0 "s_register_operand" "=r")
9530 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9531 "TARGET_ARM
da45ccee 9532 && !arm_eliminable_register (operands[0])
9533 && !arm_eliminable_register (operands[1])
9534 && !arm_eliminable_register (operands[2])"
40dbec34 9535 "str%?\\t%3, [%0, -%2]!"
0d66636f 9536 [(set_attr "type" "store1")
9537 (set_attr "predicable" "yes")]
9538)
9c08d1fa 9539
f7fbdd4a 9540(define_insn "*loadsi_preinc"
9c08d1fa 9541 [(set (match_operand:SI 3 "s_register_operand" "=r")
9542 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9543 (match_operand:SI 2 "index_operand" "rJ"))))
9544 (set (match_operand:SI 0 "s_register_operand" "=r")
9545 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9546 "TARGET_ARM
da45ccee 9547 && !arm_eliminable_register (operands[0])
9548 && !arm_eliminable_register (operands[1])
9549 && !arm_eliminable_register (operands[2])"
40dbec34 9550 "ldr%?\\t%3, [%0, %2]!"
a2cd141b 9551 [(set_attr "type" "load1")
0d66636f 9552 (set_attr "predicable" "yes")]
9553)
9c08d1fa 9554
f7fbdd4a 9555(define_insn "*loadsi_predec"
9c08d1fa 9556 [(set (match_operand:SI 3 "s_register_operand" "=r")
9557 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9558 (match_operand:SI 2 "s_register_operand" "r"))))
9559 (set (match_operand:SI 0 "s_register_operand" "=r")
9560 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9561 "TARGET_ARM
da45ccee 9562 && !arm_eliminable_register (operands[0])
9563 && !arm_eliminable_register (operands[1])
9564 && !arm_eliminable_register (operands[2])"
40dbec34 9565 "ldr%?\\t%3, [%0, -%2]!"
a2cd141b 9566 [(set_attr "type" "load1")
0d66636f 9567 (set_attr "predicable" "yes")]
9568)
9c08d1fa 9569
f7fbdd4a 9570(define_insn "*strqi_shiftpreinc"
9c08d1fa 9571 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9572 [(match_operand:SI 3 "s_register_operand" "r")
9573 (match_operand:SI 4 "const_shift_operand" "n")])
9574 (match_operand:SI 1 "s_register_operand" "0")))
9575 (match_operand:QI 5 "s_register_operand" "r"))
9576 (set (match_operand:SI 0 "s_register_operand" "=r")
9577 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9578 (match_dup 1)))]
cffb2a26 9579 "TARGET_ARM
da45ccee 9580 && !arm_eliminable_register (operands[0])
9581 && !arm_eliminable_register (operands[1])
9582 && !arm_eliminable_register (operands[3])"
87b22bf7 9583 "str%?b\\t%5, [%0, %3%S2]!"
0d66636f 9584 [(set_attr "type" "store1")
9585 (set_attr "predicable" "yes")]
9586)
9c08d1fa 9587
f7fbdd4a 9588(define_insn "*strqi_shiftpredec"
9c08d1fa 9589 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9590 (match_operator:SI 2 "shift_operator"
9591 [(match_operand:SI 3 "s_register_operand" "r")
9592 (match_operand:SI 4 "const_shift_operand" "n")])))
9593 (match_operand:QI 5 "s_register_operand" "r"))
9594 (set (match_operand:SI 0 "s_register_operand" "=r")
9595 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9596 (match_dup 4)])))]
cffb2a26 9597 "TARGET_ARM
da45ccee 9598 && !arm_eliminable_register (operands[0])
9599 && !arm_eliminable_register (operands[1])
9600 && !arm_eliminable_register (operands[3])"
87b22bf7 9601 "str%?b\\t%5, [%0, -%3%S2]!"
0d66636f 9602 [(set_attr "type" "store1")
9603 (set_attr "predicable" "yes")]
9604)
9c08d1fa 9605
f7fbdd4a 9606(define_insn "*loadqi_shiftpreinc"
9c08d1fa 9607 [(set (match_operand:QI 5 "s_register_operand" "=r")
9608 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9609 [(match_operand:SI 3 "s_register_operand" "r")
9610 (match_operand:SI 4 "const_shift_operand" "n")])
9611 (match_operand:SI 1 "s_register_operand" "0"))))
9612 (set (match_operand:SI 0 "s_register_operand" "=r")
9613 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9614 (match_dup 1)))]
cffb2a26 9615 "TARGET_ARM
da45ccee 9616 && !arm_eliminable_register (operands[0])
9617 && !arm_eliminable_register (operands[1])
9618 && !arm_eliminable_register (operands[3])"
87b22bf7 9619 "ldr%?b\\t%5, [%0, %3%S2]!"
a2cd141b 9620 [(set_attr "type" "load_byte")
0d66636f 9621 (set_attr "predicable" "yes")]
9622)
9c08d1fa 9623
f7fbdd4a 9624(define_insn "*loadqi_shiftpredec"
9c08d1fa 9625 [(set (match_operand:QI 5 "s_register_operand" "=r")
9626 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9627 (match_operator:SI 2 "shift_operator"
9628 [(match_operand:SI 3 "s_register_operand" "r")
9629 (match_operand:SI 4 "const_shift_operand" "n")]))))
9630 (set (match_operand:SI 0 "s_register_operand" "=r")
9631 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9632 (match_dup 4)])))]
cffb2a26 9633 "TARGET_ARM
da45ccee 9634 && !arm_eliminable_register (operands[0])
9635 && !arm_eliminable_register (operands[1])
9636 && !arm_eliminable_register (operands[3])"
87b22bf7 9637 "ldr%?b\\t%5, [%0, -%3%S2]!"
a2cd141b 9638 [(set_attr "type" "load_byte")
0d66636f 9639 (set_attr "predicable" "yes")]
9640)
9c08d1fa 9641
f7fbdd4a 9642(define_insn "*strsi_shiftpreinc"
9c08d1fa 9643 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9644 [(match_operand:SI 3 "s_register_operand" "r")
9645 (match_operand:SI 4 "const_shift_operand" "n")])
9646 (match_operand:SI 1 "s_register_operand" "0")))
9647 (match_operand:SI 5 "s_register_operand" "r"))
9648 (set (match_operand:SI 0 "s_register_operand" "=r")
9649 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9650 (match_dup 1)))]
cffb2a26 9651 "TARGET_ARM
da45ccee 9652 && !arm_eliminable_register (operands[0])
9653 && !arm_eliminable_register (operands[1])
9654 && !arm_eliminable_register (operands[3])"
87b22bf7 9655 "str%?\\t%5, [%0, %3%S2]!"
0d66636f 9656 [(set_attr "type" "store1")
9657 (set_attr "predicable" "yes")]
9658)
9c08d1fa 9659
f7fbdd4a 9660(define_insn "*strsi_shiftpredec"
9c08d1fa 9661 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9662 (match_operator:SI 2 "shift_operator"
9663 [(match_operand:SI 3 "s_register_operand" "r")
9664 (match_operand:SI 4 "const_shift_operand" "n")])))
9665 (match_operand:SI 5 "s_register_operand" "r"))
9666 (set (match_operand:SI 0 "s_register_operand" "=r")
9667 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9668 (match_dup 4)])))]
cffb2a26 9669 "TARGET_ARM
da45ccee 9670 && !arm_eliminable_register (operands[0])
9671 && !arm_eliminable_register (operands[1])
9672 && !arm_eliminable_register (operands[3])"
87b22bf7 9673 "str%?\\t%5, [%0, -%3%S2]!"
0d66636f 9674 [(set_attr "type" "store1")
9675 (set_attr "predicable" "yes")]
9676)
9c08d1fa 9677
cbd60e74 9678(define_insn "*loadsi_shiftpreinc"
9c08d1fa 9679 [(set (match_operand:SI 5 "s_register_operand" "=r")
9680 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9681 [(match_operand:SI 3 "s_register_operand" "r")
9682 (match_operand:SI 4 "const_shift_operand" "n")])
9683 (match_operand:SI 1 "s_register_operand" "0"))))
9684 (set (match_operand:SI 0 "s_register_operand" "=r")
9685 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9686 (match_dup 1)))]
cffb2a26 9687 "TARGET_ARM
da45ccee 9688 && !arm_eliminable_register (operands[0])
9689 && !arm_eliminable_register (operands[1])
9690 && !arm_eliminable_register (operands[3])"
87b22bf7 9691 "ldr%?\\t%5, [%0, %3%S2]!"
a2cd141b 9692 [(set_attr "type" "load1")
0d66636f 9693 (set_attr "predicable" "yes")]
9694)
9c08d1fa 9695
cbd60e74 9696(define_insn "*loadsi_shiftpredec"
9c08d1fa 9697 [(set (match_operand:SI 5 "s_register_operand" "=r")
9698 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9699 (match_operator:SI 2 "shift_operator"
9700 [(match_operand:SI 3 "s_register_operand" "r")
9701 (match_operand:SI 4 "const_shift_operand" "n")]))))
9702 (set (match_operand:SI 0 "s_register_operand" "=r")
9703 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9704 (match_dup 4)])))]
cffb2a26 9705 "TARGET_ARM
da45ccee 9706 && !arm_eliminable_register (operands[0])
9707 && !arm_eliminable_register (operands[1])
9708 && !arm_eliminable_register (operands[3])"
87b22bf7 9709 "ldr%?\\t%5, [%0, -%3%S2]!"
a2cd141b 9710 [(set_attr "type" "load1")
0d66636f 9711 (set_attr "predicable" "yes")])
9c08d1fa 9712
9c08d1fa 9713; It can also support extended post-inc expressions, but combine doesn't
9714; try these....
9715; It doesn't seem worth adding peepholes for anything but the most common
9716; cases since, unlike combine, the increment must immediately follow the load
9717; for this pattern to match.
fc40f3ac 9718; We must watch to see that the source/destination register isn't also the
9719; same as the base address register, and that if the index is a register,
9720; that it is not the same as the base address register. In such cases the
e3e08e7f 9721; instruction that we would generate would have UNPREDICTABLE behavior so
fc40f3ac 9722; we cannot use it.
9c08d1fa 9723
9724(define_peephole
9725 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9726 (match_operand:QI 2 "s_register_operand" "r"))
9727 (set (match_dup 0)
9728 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 9729 "TARGET_ARM
9730 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9731 && (GET_CODE (operands[1]) != REG
9732 || (REGNO (operands[1]) != REGNO (operands[0])))"
9733 "str%?b\\t%2, [%0], %1"
9734)
9c08d1fa 9735
9736(define_peephole
9737 [(set (match_operand:QI 0 "s_register_operand" "=r")
9738 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9739 (set (match_dup 1)
9740 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
fc40f3ac 9741 "TARGET_ARM
9742 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 9743 && (GET_CODE (operands[2]) != REG
9744 || REGNO(operands[0]) != REGNO (operands[2]))"
9745 "ldr%?b\\t%0, [%1], %2"
9746)
9c08d1fa 9747
9748(define_peephole
9749 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9750 (match_operand:SI 2 "s_register_operand" "r"))
9751 (set (match_dup 0)
9752 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 9753 "TARGET_ARM
9754 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9755 && (GET_CODE (operands[1]) != REG
9756 || (REGNO (operands[1]) != REGNO (operands[0])))"
9757 "str%?\\t%2, [%0], %1"
9758)
9c08d1fa 9759
9c08d1fa 9760(define_peephole
9761 [(set (match_operand:SI 0 "s_register_operand" "=r")
9762 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9763 (set (match_dup 1)
9764 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
cffb2a26 9765 "TARGET_ARM
fc40f3ac 9766 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 9767 && (GET_CODE (operands[2]) != REG
9768 || REGNO(operands[0]) != REGNO (operands[2]))"
9769 "ldr%?\\t%0, [%1], %2"
9770)
9c08d1fa 9771
c7597b5d 9772(define_peephole
9773 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9774 (match_operand:SI 1 "index_operand" "rJ")))
9775 (match_operand:QI 2 "s_register_operand" "r"))
9776 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
fc40f3ac 9777 "TARGET_ARM
9778 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9779 && (GET_CODE (operands[1]) != REG
9780 || (REGNO (operands[1]) != REGNO (operands[0])))"
9781 "str%?b\\t%2, [%0, %1]!"
9782)
c7597b5d 9783
9784(define_peephole
9785 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9786 [(match_operand:SI 0 "s_register_operand" "r")
87b22bf7 9787 (match_operand:SI 1 "const_int_operand" "n")])
c7597b5d 9788 (match_operand:SI 2 "s_register_operand" "+r")))
9789 (match_operand:QI 3 "s_register_operand" "r"))
9790 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9791 (match_dup 2)))]
fc40f3ac 9792 "TARGET_ARM
9793 && (REGNO (operands[3]) != REGNO (operands[2]))
9794 && (REGNO (operands[0]) != REGNO (operands[2]))"
215b30b3 9795 "str%?b\\t%3, [%2, %0%S4]!"
9796)
c7597b5d 9797
9c08d1fa 9798; This pattern is never tried by combine, so do it as a peephole
9799
a0f94409 9800(define_peephole2
372575c7 9801 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9802 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9803 (set (reg:CC CC_REGNUM)
aea4c774 9804 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9805 "TARGET_ARM"
a0f94409 9806 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9807 (set (match_dup 0) (match_dup 1))])]
9808 ""
0d66636f 9809)
9c08d1fa 9810
675d848d 9811; Peepholes to spot possible load- and store-multiples, if the ordering is
9812; reversed, check that the memory references aren't volatile.
9c08d1fa 9813
9814(define_peephole
9815 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9816 (match_operand:SI 4 "memory_operand" "m"))
9817 (set (match_operand:SI 1 "s_register_operand" "=r")
9818 (match_operand:SI 5 "memory_operand" "m"))
9c08d1fa 9819 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9820 (match_operand:SI 6 "memory_operand" "m"))
9c08d1fa 9821 (set (match_operand:SI 3 "s_register_operand" "=r")
aea4c774 9822 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 9823 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9824 "*
9825 return emit_ldm_seq (operands, 4);
215b30b3 9826 "
9827)
9c08d1fa 9828
9829(define_peephole
9830 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9831 (match_operand:SI 3 "memory_operand" "m"))
9832 (set (match_operand:SI 1 "s_register_operand" "=r")
9833 (match_operand:SI 4 "memory_operand" "m"))
9c08d1fa 9834 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9835 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 9836 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9837 "*
9838 return emit_ldm_seq (operands, 3);
215b30b3 9839 "
9840)
9c08d1fa 9841
9842(define_peephole
9843 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9844 (match_operand:SI 2 "memory_operand" "m"))
9845 (set (match_operand:SI 1 "s_register_operand" "=r")
9846 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 9847 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9848 "*
9849 return emit_ldm_seq (operands, 2);
215b30b3 9850 "
9851)
9c08d1fa 9852
9853(define_peephole
aea4c774 9854 [(set (match_operand:SI 4 "memory_operand" "=m")
9c08d1fa 9855 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9856 (set (match_operand:SI 5 "memory_operand" "=m")
9857 (match_operand:SI 1 "s_register_operand" "r"))
9858 (set (match_operand:SI 6 "memory_operand" "=m")
9c08d1fa 9859 (match_operand:SI 2 "s_register_operand" "r"))
aea4c774 9860 (set (match_operand:SI 7 "memory_operand" "=m")
9861 (match_operand:SI 3 "s_register_operand" "r"))]
cffb2a26 9862 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9863 "*
9864 return emit_stm_seq (operands, 4);
215b30b3 9865 "
9866)
9c08d1fa 9867
9868(define_peephole
aea4c774 9869 [(set (match_operand:SI 3 "memory_operand" "=m")
9c08d1fa 9870 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9871 (set (match_operand:SI 4 "memory_operand" "=m")
9872 (match_operand:SI 1 "s_register_operand" "r"))
9873 (set (match_operand:SI 5 "memory_operand" "=m")
9874 (match_operand:SI 2 "s_register_operand" "r"))]
cffb2a26 9875 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9876 "*
9877 return emit_stm_seq (operands, 3);
215b30b3 9878 "
9879)
9c08d1fa 9880
9881(define_peephole
aea4c774 9882 [(set (match_operand:SI 2 "memory_operand" "=m")
9c08d1fa 9883 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9884 (set (match_operand:SI 3 "memory_operand" "=m")
9885 (match_operand:SI 1 "s_register_operand" "r"))]
cffb2a26 9886 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9887 "*
9888 return emit_stm_seq (operands, 2);
215b30b3 9889 "
9890)
9c08d1fa 9891
9c08d1fa 9892(define_split
9893 [(set (match_operand:SI 0 "s_register_operand" "")
9894 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9895 (const_int 0))
8fa3ba89 9896 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9897 [(match_operand:SI 3 "s_register_operand" "")
9898 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9899 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9900 "TARGET_ARM"
9c08d1fa 9901 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9902 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9903 (match_dup 5)))]
215b30b3 9904 ""
9905)
9c08d1fa 9906
aea4c774 9907;; This split can be used because CC_Z mode implies that the following
9908;; branch will be an equality, or an unsigned inequality, so the sign
9909;; extension is not needed.
9c08d1fa 9910
aea4c774 9911(define_split
bd5b4116 9912 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9913 (compare:CC_Z
9914 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9915 (const_int 24))
aea4c774 9916 (match_operand 1 "const_int_operand" "")))
9917 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9918 "TARGET_ARM
9919 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9920 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9921 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9922 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9923 "
9c08d1fa 9924 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9925 "
9926)
9c08d1fa 9927
87b22bf7 9928(define_expand "prologue"
9929 [(clobber (const_int 0))]
cffb2a26 9930 "TARGET_EITHER"
9931 "if (TARGET_ARM)
9932 arm_expand_prologue ();
9933 else
9934 thumb_expand_prologue ();
87b22bf7 9935 DONE;
cffb2a26 9936 "
9937)
87b22bf7 9938
56d27660 9939(define_expand "epilogue"
4c44712e 9940 [(clobber (const_int 0))]
cffb2a26 9941 "TARGET_EITHER"
56d27660 9942 "
4c44712e 9943 if (current_function_calls_eh_return)
9944 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
cffb2a26 9945 if (TARGET_THUMB)
9946 thumb_expand_epilogue ();
9947 else if (USE_RETURN_INSN (FALSE))
56d27660 9948 {
9949 emit_jump_insn (gen_return ());
9950 DONE;
9951 }
cffb2a26 9952 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9953 gen_rtvec (1,
9954 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9955 VUNSPEC_EPILOGUE));
cffb2a26 9956 DONE;
9957 "
9958)
56d27660 9959
ef5651d0 9960;; Note - although unspec_volatile's USE all hard registers,
9961;; USEs are ignored after relaod has completed. Thus we need
9962;; to add an unspec of the link register to ensure that flow
9963;; does not think that it is unused by the sibcall branch that
9964;; will replace the standard function epilogue.
1c494086 9965(define_insn "sibcall_epilogue"
ef5651d0 9966 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9967 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
1c494086 9968 "TARGET_ARM"
9969 "*
ffc9d00c 9970 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9971 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9972 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9973 "
9974;; Length is absolute worst case
9975 [(set_attr "length" "44")
defc47cf 9976 (set_attr "type" "block")
9977 ;; We don't clobber the conditions, but the potential length of this
9978 ;; operation is sufficient to make conditionalizing the sequence
9979 ;; unlikely to be profitable.
9980 (set_attr "conds" "clob")]
1c494086 9981)
9982
cffb2a26 9983(define_insn "*epilogue_insns"
e1159bbe 9984 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9985 "TARGET_EITHER"
56d27660 9986 "*
cffb2a26 9987 if (TARGET_ARM)
ffc9d00c 9988 return arm_output_epilogue (NULL);
cffb2a26 9989 else /* TARGET_THUMB */
9990 return thumb_unexpanded_epilogue ();
9991 "
215b30b3 9992 ; Length is absolute worst case
cffb2a26 9993 [(set_attr "length" "44")
defc47cf 9994 (set_attr "type" "block")
9995 ;; We don't clobber the conditions, but the potential length of this
9996 ;; operation is sufficient to make conditionalizing the sequence
9997 ;; unlikely to be profitable.
9998 (set_attr "conds" "clob")]
cffb2a26 9999)
10000
10001(define_expand "eh_epilogue"
7db9af5d 10002 [(use (match_operand:SI 0 "register_operand" ""))
10003 (use (match_operand:SI 1 "register_operand" ""))
10004 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10005 "TARGET_EITHER"
10006 "
215b30b3 10007 {
10008 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10009 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10010 {
10011 rtx ra = gen_rtx_REG (Pmode, 2);
10012
10013 emit_move_insn (ra, operands[2]);
10014 operands[2] = ra;
10015 }
5cf3595a 10016 /* This is a hack -- we may have crystalized the function type too
10017 early. */
10018 cfun->machine->func_type = 0;
215b30b3 10019 }"
10020)
56d27660 10021
9c08d1fa 10022;; This split is only used during output to reduce the number of patterns
10023;; that need assembler instructions adding to them. We allowed the setting
10024;; of the conditions to be implicit during rtl generation so that
10025;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10026;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10027;; up again here.
10028
10029(define_split
10030 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10031 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10032 [(match_operand 2 "" "") (match_operand 3 "" "")])
10033 (match_dup 0)
10034 (match_operand 4 "" "")))
bd5b4116 10035 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10036 "TARGET_ARM && reload_completed"
8fa3ba89 10037 [(set (match_dup 5) (match_dup 6))
10038 (cond_exec (match_dup 7)
10039 (set (match_dup 0) (match_dup 4)))]
10040 "
10041 {
10042 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10043 operands[2], operands[3]);
10044 enum rtx_code rc = GET_CODE (operands[1]);
10045
bd5b4116 10046 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10047 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10048 if (mode == CCFPmode || mode == CCFPEmode)
10049 rc = reverse_condition_maybe_unordered (rc);
10050 else
10051 rc = reverse_condition (rc);
10052
10053 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10054 }"
10055)
10056
10057(define_split
10058 [(set (match_operand:SI 0 "s_register_operand" "")
10059 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10060 [(match_operand 2 "" "") (match_operand 3 "" "")])
10061 (match_operand 4 "" "")
10062 (match_dup 0)))
bd5b4116 10063 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10064 "TARGET_ARM && reload_completed"
8fa3ba89 10065 [(set (match_dup 5) (match_dup 6))
10066 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10067 (set (match_dup 0) (match_dup 4)))]
10068 "
10069 {
10070 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10071 operands[2], operands[3]);
10072
bd5b4116 10073 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10074 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10075 }"
10076)
10077
10078(define_split
10079 [(set (match_operand:SI 0 "s_register_operand" "")
10080 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10081 [(match_operand 2 "" "") (match_operand 3 "" "")])
10082 (match_operand 4 "" "")
10083 (match_operand 5 "" "")))
bd5b4116 10084 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10085 "TARGET_ARM && reload_completed"
8fa3ba89 10086 [(set (match_dup 6) (match_dup 7))
10087 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10088 (set (match_dup 0) (match_dup 4)))
10089 (cond_exec (match_dup 8)
10090 (set (match_dup 0) (match_dup 5)))]
10091 "
10092 {
10093 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10094 operands[2], operands[3]);
10095 enum rtx_code rc = GET_CODE (operands[1]);
10096
bd5b4116 10097 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10098 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10099 if (mode == CCFPmode || mode == CCFPEmode)
10100 rc = reverse_condition_maybe_unordered (rc);
10101 else
10102 rc = reverse_condition (rc);
10103
10104 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10105 }"
10106)
10107
cffb2a26 10108(define_split
10109 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10110 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10111 [(match_operand:SI 2 "s_register_operand" "")
10112 (match_operand:SI 3 "arm_add_operand" "")])
10113 (match_operand:SI 4 "arm_rhs_operand" "")
10114 (not:SI
10115 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10116 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10117 "TARGET_ARM && reload_completed"
cffb2a26 10118 [(set (match_dup 6) (match_dup 7))
f6c53574 10119 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10120 (set (match_dup 0) (match_dup 4)))
10121 (cond_exec (match_dup 8)
10122 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10123 "
215b30b3 10124 {
10125 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10126 operands[2], operands[3]);
f6c53574 10127 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10128
bd5b4116 10129 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10130 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10131 if (mode == CCFPmode || mode == CCFPEmode)
10132 rc = reverse_condition_maybe_unordered (rc);
10133 else
10134 rc = reverse_condition (rc);
10135
10136 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10137 }"
10138)
cffb2a26 10139
10140(define_insn "*cond_move_not"
10141 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10142 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10143 [(match_operand 3 "cc_register" "") (const_int 0)])
10144 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10145 (not:SI
10146 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10147 "TARGET_ARM"
10148 "@
10149 mvn%D4\\t%0, %2
10150 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10151 [(set_attr "conds" "use")
10152 (set_attr "length" "4,8")]
10153)
cffb2a26 10154
9c08d1fa 10155;; The next two patterns occur when an AND operation is followed by a
10156;; scc insn sequence
10157
f7fbdd4a 10158(define_insn "*sign_extract_onebit"
9c08d1fa 10159 [(set (match_operand:SI 0 "s_register_operand" "=r")
10160 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10161 (const_int 1)
ed750274 10162 (match_operand:SI 2 "const_int_operand" "n")))
10163 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10164 "TARGET_ARM"
9c08d1fa 10165 "*
0d66636f 10166 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10167 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10168 return \"mvnne\\t%0, #0\";
10169 "
10170 [(set_attr "conds" "clob")
10171 (set_attr "length" "8")]
10172)
9c08d1fa 10173
f7fbdd4a 10174(define_insn "*not_signextract_onebit"
9c08d1fa 10175 [(set (match_operand:SI 0 "s_register_operand" "=r")
10176 (not:SI
10177 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10178 (const_int 1)
ed750274 10179 (match_operand:SI 2 "const_int_operand" "n"))))
10180 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10181 "TARGET_ARM"
9c08d1fa 10182 "*
0d66636f 10183 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10184 output_asm_insn (\"tst\\t%1, %2\", operands);
10185 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10186 return \"movne\\t%0, #0\";
10187 "
10188 [(set_attr "conds" "clob")
10189 (set_attr "length" "12")]
10190)
87b22bf7 10191
0d66636f 10192;; Push multiple registers to the stack. Registers are in parallel (use ...)
10193;; expressions. For simplicity, the first register is also in the unspec
10194;; part.
f7fbdd4a 10195(define_insn "*push_multi"
87b22bf7 10196 [(match_parallel 2 "multi_register_push"
10197 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10198 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10199 UNSPEC_PUSH_MULT))])]
cffb2a26 10200 "TARGET_ARM"
87b22bf7 10201 "*
215b30b3 10202 {
10203 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10204
215b30b3 10205 /* For the StrongARM at least it is faster to
10206 use STR to store only a single register. */
6079f055 10207 if (num_saves == 1)
215b30b3 10208 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10209 else
10210 {
10211 int i;
10212 char pattern[100];
ed593f11 10213
215b30b3 10214 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10215
6079f055 10216 for (i = 1; i < num_saves; i++)
215b30b3 10217 {
10218 strcat (pattern, \", %|\");
10219 strcat (pattern,
10220 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10221 }
10222
10223 strcat (pattern, \"}\");
10224 output_asm_insn (pattern, operands);
10225 }
10226
10227 return \"\";
10228 }"
10229 [(set_attr "type" "store4")]
10230)
f7fbdd4a 10231
4c58c898 10232(define_insn "stack_tie"
10233 [(set (mem:BLK (scratch))
10234 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10235 (match_operand:SI 1 "s_register_operand" "r")]
10236 UNSPEC_PRLG_STK))]
10237 ""
10238 ""
10239 [(set_attr "length" "0")]
10240)
10241
3398e91d 10242;; Similarly for the floating point registers
7b1d2fc4 10243(define_insn "*push_fp_multi"
10244 [(match_parallel 2 "multi_register_push"
10245 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10246 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10247 UNSPEC_PUSH_MULT))])]
a2cd141b 10248 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10249 "*
215b30b3 10250 {
10251 char pattern[100];
7b1d2fc4 10252
215b30b3 10253 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10254 output_asm_insn (pattern, operands);
10255 return \"\";
10256 }"
10257 [(set_attr "type" "f_store")]
10258)
7b1d2fc4 10259
f7fbdd4a 10260;; Special patterns for dealing with the constant pool
10261
cffb2a26 10262(define_insn "align_4"
e1159bbe 10263 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10264 "TARGET_EITHER"
f7fbdd4a 10265 "*
cffb2a26 10266 assemble_align (32);
f7fbdd4a 10267 return \"\";
cffb2a26 10268 "
10269)
f7fbdd4a 10270
755eb2b4 10271(define_insn "align_8"
10272 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10273 "TARGET_EITHER"
755eb2b4 10274 "*
10275 assemble_align (64);
10276 return \"\";
10277 "
10278)
10279
cffb2a26 10280(define_insn "consttable_end"
e1159bbe 10281 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10282 "TARGET_EITHER"
f7fbdd4a 10283 "*
cffb2a26 10284 making_const_table = FALSE;
f7fbdd4a 10285 return \"\";
cffb2a26 10286 "
10287)
f7fbdd4a 10288
cffb2a26 10289(define_insn "consttable_1"
e1159bbe 10290 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
cffb2a26 10291 "TARGET_THUMB"
f7fbdd4a 10292 "*
cffb2a26 10293 making_const_table = TRUE;
09d688ff 10294 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10295 assemble_zeros (3);
f7fbdd4a 10296 return \"\";
cffb2a26 10297 "
10298 [(set_attr "length" "4")]
10299)
f7fbdd4a 10300
cffb2a26 10301(define_insn "consttable_2"
e1159bbe 10302 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
cffb2a26 10303 "TARGET_THUMB"
f7fbdd4a 10304 "*
cffb2a26 10305 making_const_table = TRUE;
09d688ff 10306 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10307 assemble_zeros (2);
f7fbdd4a 10308 return \"\";
cffb2a26 10309 "
10310 [(set_attr "length" "4")]
10311)
10312
10313(define_insn "consttable_4"
e1159bbe 10314 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10315 "TARGET_EITHER"
10316 "*
10317 {
10318 making_const_table = TRUE;
10319 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10320 {
10321 case MODE_FLOAT:
10322 {
badfe841 10323 REAL_VALUE_TYPE r;
10324 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10325 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10326 break;
10327 }
10328 default:
09d688ff 10329 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
cffb2a26 10330 break;
10331 }
10332 return \"\";
10333 }"
10334 [(set_attr "length" "4")]
10335)
10336
10337(define_insn "consttable_8"
e1159bbe 10338 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10339 "TARGET_EITHER"
10340 "*
10341 {
10342 making_const_table = TRUE;
10343 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10344 {
10345 case MODE_FLOAT:
10346 {
badfe841 10347 REAL_VALUE_TYPE r;
10348 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10349 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10350 break;
10351 }
10352 default:
09d688ff 10353 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10354 break;
10355 }
10356 return \"\";
10357 }"
10358 [(set_attr "length" "8")]
10359)
10360
10361;; Miscellaneous Thumb patterns
10362
fd957ef3 10363(define_expand "tablejump"
7db9af5d 10364 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10365 (use (label_ref (match_operand 1 "" "")))])]
10366 "TARGET_THUMB"
10367 "
10368 if (flag_pic)
10369 {
10370 /* Hopefully, CSE will eliminate this copy. */
10371 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10372 rtx reg2 = gen_reg_rtx (SImode);
10373
10374 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10375 operands[0] = reg2;
10376 }
10377 "
10378)
10379
f1039640 10380;; NB never uses BX.
fd957ef3 10381(define_insn "*thumb_tablejump"
cffb2a26 10382 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10383 (use (label_ref (match_operand 1 "" "")))]
10384 "TARGET_THUMB"
fd957ef3 10385 "mov\\t%|pc, %0"
cffb2a26 10386 [(set_attr "length" "2")]
10387)
0d66636f 10388
331beb1a 10389;; V5 Instructions,
10390
8f4be2be 10391(define_insn "clzsi2"
10392 [(set (match_operand:SI 0 "s_register_operand" "=r")
10393 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
e1159bbe 10394 "TARGET_ARM && arm_arch5"
ee7cbe0e 10395 "clz%?\\t%0, %1"
10396 [(set_attr "predicable" "yes")])
331beb1a 10397
e1159bbe 10398(define_expand "ffssi2"
10399 [(set (match_operand:SI 0 "s_register_operand" "")
10400 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10401 "TARGET_ARM && arm_arch5"
10402 "
10403 {
10404 rtx t1, t2, t3;
10405
10406 t1 = gen_reg_rtx (SImode);
10407 t2 = gen_reg_rtx (SImode);
10408 t3 = gen_reg_rtx (SImode);
10409
10410 emit_insn (gen_negsi2 (t1, operands[1]));
10411 emit_insn (gen_andsi3 (t2, operands[1], t1));
8f4be2be 10412 emit_insn (gen_clzsi2 (t3, t2));
e1159bbe 10413 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10414 DONE;
10415 }"
10416)
10417
8f4be2be 10418(define_expand "ctzsi2"
10419 [(set (match_operand:SI 0 "s_register_operand" "")
10420 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10421 "TARGET_ARM && arm_arch5"
10422 "
10423 {
10424 rtx t1, t2, t3;
10425
10426 t1 = gen_reg_rtx (SImode);
10427 t2 = gen_reg_rtx (SImode);
10428 t3 = gen_reg_rtx (SImode);
10429
10430 emit_insn (gen_negsi2 (t1, operands[1]));
10431 emit_insn (gen_andsi3 (t2, operands[1], t1));
10432 emit_insn (gen_clzsi2 (t3, t2));
10433 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10434 DONE;
10435 }"
10436)
10437
e1159bbe 10438;; V5E instructions.
331beb1a 10439
10440(define_insn "prefetch"
f4e79814 10441 [(prefetch (match_operand:SI 0 "address_operand" "p")
10442 (match_operand:SI 1 "" "")
10443 (match_operand:SI 2 "" ""))]
e1159bbe 10444 "TARGET_ARM && arm_arch5e"
bcb7a8f6 10445 "pld\\t%a0")
331beb1a 10446
0d66636f 10447;; General predication pattern
10448
10449(define_cond_exec
10450 [(match_operator 0 "arm_comparison_operator"
10451 [(match_operand 1 "cc_register" "")
10452 (const_int 0)])]
10453 "TARGET_ARM"
10454 ""
10455)
10456
063a05c7 10457(define_insn "prologue_use"
10458 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10459 ""
10460 "%@ %0 needed for prologue"
10461)
7db9af5d 10462
4c44712e 10463
10464;; Patterns for exception handling
10465
10466(define_expand "eh_return"
10467 [(use (match_operand 0 "general_operand" ""))]
10468 "TARGET_EITHER"
10469 "
10470 {
10471 if (TARGET_ARM)
10472 emit_insn (gen_arm_eh_return (operands[0]));
10473 else
10474 emit_insn (gen_thumb_eh_return (operands[0]));
10475 DONE;
10476 }"
10477)
10478
10479;; We can't expand this before we know where the link register is stored.
10480(define_insn_and_split "arm_eh_return"
10481 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10482 VUNSPEC_EH_RETURN)
10483 (clobber (match_scratch:SI 1 "=&r"))]
10484 "TARGET_ARM"
10485 "#"
10486 "&& reload_completed"
10487 [(const_int 0)]
10488 "
10489 {
10490 arm_set_return_address (operands[0], operands[1]);
10491 DONE;
10492 }"
10493)
10494
10495(define_insn_and_split "thumb_eh_return"
10496 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10497 VUNSPEC_EH_RETURN)
10498 (clobber (match_scratch:SI 1 "=&l"))]
10499 "TARGET_THUMB"
10500 "#"
10501 "&& reload_completed"
10502 [(const_int 0)]
10503 "
10504 {
10505 thumb_set_return_address (operands[0], operands[1]);
10506 DONE;
10507 }"
10508)
10509
7db9af5d 10510;; Load the FPA co-processor patterns
10511(include "fpa.md")
10512;; Load the Maverick co-processor patterns
10513(include "cirrus.md")
755eb2b4 10514;; Load the Intel Wireless Multimedia Extension patterns
10515(include "iwmmxt.md")
a2cd141b 10516;; Load the VFP co-processor patterns
10517(include "vfp.md")
10518