]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* config/rs6000/rs6000.c: Annotate cache line size field in all
[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,
038d1e19 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
b11cae9e 4;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 5;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 6;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 7
acf6ed70 8;; This file is part of GCC.
b11cae9e 9
acf6ed70 10;; GCC is free software; you can redistribute it and/or modify it
11;; under the terms of the GNU General Public License as published
038d1e19 12;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 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
038d1e19 21;; along with GCC; see the file COPYING3. If not see
22;; <http://www.gnu.org/licenses/>.
b11cae9e 23
24;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25
9c08d1fa 26\f
e1159bbe 27;;---------------------------------------------------------------------------
28;; Constants
29
30;; Register numbers
31(define_constants
ccd90aaa 32 [(R0_REGNUM 0) ; First CORE register
33 (IP_REGNUM 12) ; Scratch register
e1159bbe 34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
ccd90aaa 38 (LAST_ARM_REGNUM 15) ;
39 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
40 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
e1159bbe 41 ]
42)
3c5afce6 43;; 3rd operand to select_dominance_cc_mode
44(define_constants
45 [(DOM_CC_X_AND_Y 0)
46 (DOM_CC_NX_OR_Y 1)
47 (DOM_CC_X_OR_Y 2)
48 ]
49)
e1159bbe 50
9c08d1fa 51;; UNSPEC Usage:
8a18b90c 52;; Note: sin and cos are no-longer used.
d98a3884 53;; Unspec constants for Neon are defined in neon.md.
e1159bbe 54
55(define_constants
56 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
60 ; operand 0 is the result,
61 ; operand 1 the parameter.
62 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63 ; operand 0 is the first register,
64 ; subsequent registers are in parallel (use ...)
65 ; expressions.
66 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
67 ; usage, that is, we will add the pic_register
68 ; value to it before trying to dereference it.
2c96dc5a 69 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
70 ; GLOBAL_OFFSET_TABLE. The operation is fully
71 ; described by the RTL but must be wrapped to
72 ; prevent combine from trying to rip it apart.
73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
e1159bbe 74 ; being scheduled before the stack adjustment insn.
063a05c7 75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
79 ; register to "use".
68121397 80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
8d232dc7 81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
f655717d 93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
6cdcb15c 94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95 ; instruction stream.
25f905c2 96 (UNSPEC_STACK_ALIGN 20) ; Doubleword aligned stack pointer. Used to
97 ; generate correct unwind information.
bac7fc85 98 (UNSPEC_PIC_OFFSET 22) ; A symbolic 12-bit OFFSET that has been treated
99 ; correctly for PIC usage.
e1159bbe 100 ]
101)
102
215b30b3 103;; UNSPEC_VOLATILE Usage:
e1159bbe 104
105(define_constants
106 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
107 ; insn in the code.
108 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
109 ; instruction epilogue sequence that isn't expanded
110 ; into normal RTL. Used for both normal and sibcall
111 ; epilogues.
112 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
113 ; for inlined constants.
114 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
115 ; table.
116 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
117 ; an 8-bit object.
118 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
119 ; a 16-bit object.
120 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
121 ; a 32-bit object.
122 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
123 ; a 64-bit object.
d98a3884 124 (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
125 ; a 128-bit object.
126 (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
127 (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
128 (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
129 (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
130 (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
131 (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 132 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 133 ; handling.
e1159bbe 134 ]
135)
b11cae9e 136\f
e1159bbe 137;;---------------------------------------------------------------------------
9c08d1fa 138;; Attributes
139
215b30b3 140; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
141; generating ARM code. This is used to control the length of some insn
142; patterns that share the same RTL in both ARM and Thumb code.
1c494086 143(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 144
215b30b3 145; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
146; scheduling decisions for the load unit and the multiplier.
74a71f7d 147(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
9c08d1fa 148
5ecb8da7 149; IS_XSCALE is set to 'yes' when compiling for XScale.
150(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
151
331beb1a 152;; Operand number of an input operand that is shifted. Zero if the
153;; given instruction does not shift one of its input operands.
331beb1a 154(define_attr "shift" "" (const_int 0))
155
3d91c5d6 156; Floating Point Unit. If we only have floating point emulation, then there
157; is no point in scheduling the floating point insns. (Well, for best
158; performance we should try and group them together).
a2cd141b 159(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 160 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 161
094e994f 162; LENGTH of an instruction (in bytes)
163(define_attr "length" "" (const_int 4))
9c08d1fa 164
56d27660 165; POOL_RANGE is how far away from a constant pool entry that this insn
166; can be placed. If the distance is zero, then this insn will never
167; reference the pool.
cffb2a26 168; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
169; before its address.
56d27660 170(define_attr "pool_range" "" (const_int 0))
cffb2a26 171(define_attr "neg_pool_range" "" (const_int 0))
56d27660 172
215b30b3 173; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 174; If such an insn references the pool, then we have no way of knowing how,
175; so use the most conservative value for pool_range.
9c08d1fa 176(define_asm_attributes
4d7a8451 177 [(set_attr "conds" "clob")
178 (set_attr "length" "4")
179 (set_attr "pool_range" "250")])
9c08d1fa 180
a2cd141b 181;; The instruction used to implement a particular pattern. This
182;; information is used by pipeline descriptions to provide accurate
183;; scheduling information.
184
185(define_attr "insn"
bcaec148 186 "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,other"
a2cd141b 187 (const_string "other"))
188
9c08d1fa 189; TYPE attribute is used to detect floating point instructions which, if
190; running on a co-processor can run in parallel with other, basic instructions
191; If write-buffer scheduling is enabled then it can also be used in the
192; scheduling of writes.
193
194; Classification of each insn
a2cd141b 195; alu any alu instruction that doesn't hit memory or fp
196; regs or have a shifted source operand
197; alu_shift any data instruction that doesn't hit memory or fp
198; regs, but has a source operand shifted by a constant
199; alu_shift_reg any data instruction that doesn't hit memory or fp
200; regs, but has a source operand shifted by a register value
f7fbdd4a 201; mult a multiply instruction
9c08d1fa 202; block blockage insn, this blocks all functional units
203; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 204; fdivd DFmode floating point division
205; fdivs SFmode floating point division
206; fmul Floating point multiply
207; ffmul Fast floating point multiply
208; farith Floating point arithmetic (4 cycle)
209; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 210; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 211; even on a machine with an fpa.
9c08d1fa 212; f_load a floating point load from memory
213; f_store a floating point store to memory
9aff9709 214; f_load[sd] single/double load from memory
215; f_store[sd] single/double store to memory
c0e1af52 216; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 217; f_mem_r a transfer of a floating point register to a real reg via mem
218; r_mem_f the reverse of f_mem_r
219; f_2_r fast transfer float to arm (no memory needed)
220; r_2_f fast transfer arm to float
c0e1af52 221; f_cvt convert floating<->integral
a2cd141b 222; branch a branch
9c08d1fa 223; call a subroutine call
a2cd141b 224; load_byte load byte(s) from memory to arm registers
225; load1 load 1 word from memory to arm registers
226; load2 load 2 words from memory to arm registers
227; load3 load 3 words from memory to arm registers
228; load4 load 4 words from memory to arm registers
229; store store 1 word to memory from arm registers
9c08d1fa 230; store2 store 2 words
231; store3 store 3 words
a2cd141b 232; store4 store 4 (or more) words
2c6c7d8b 233; Additions for Cirrus Maverick co-processor:
234; mav_farith Floating point arithmetic (4 cycle)
235; mav_dmult Double multiplies (7 cycle)
9c08d1fa 236;
bcaec148 237
9c08d1fa 238(define_attr "type"
bcaec148 239 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
a2cd141b 240 (if_then_else
241 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
242 (const_string "mult")
243 (const_string "alu")))
9c08d1fa 244
9888ad6d 245; Load scheduling, set from the arm_ld_sched variable
457275b6 246; initialized by arm_override_options()
9888ad6d 247(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 248
f7fbdd4a 249; condition codes: this one is used by final_prescan_insn to speed up
250; conditionalizing instructions. It saves having to scan the rtl to see if
251; it uses or alters the condition codes.
215b30b3 252;
f7fbdd4a 253; USE means that the condition codes are used by the insn in the process of
215b30b3 254; outputting code, this means (at present) that we can't use the insn in
255; inlined branches
256;
f7fbdd4a 257; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 258; well defined manner.
259;
f7fbdd4a 260; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 261; they are altered at all
262;
8fa3ba89 263; JUMP_CLOB is used when the condition cannot be represented by a single
215b30b3 264; instruction (UNEQ and LTGT). These cannot be predicated.
265;
f7fbdd4a 266; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 267; output of this insn
f7fbdd4a 268
269(define_attr "conds" "use,set,clob,jump_clob,nocond"
270 (if_then_else (eq_attr "type" "call")
c1a66faf 271 (const_string "clob")
f7fbdd4a 272 (const_string "nocond")))
273
215b30b3 274; Predicable means that the insn can be conditionally executed based on
275; an automatically added predicate (additional patterns are generated by
276; gen...). We default to 'no' because no Thumb patterns match this rule
277; and not all ARM patterns do.
0d66636f 278(define_attr "predicable" "no,yes" (const_string "no"))
279
129a2fe4 280; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
281; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 282; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 283; affect the schedule).
74a71f7d 284(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 285
215b30b3 286; WRITE_CONFLICT implies that a read following an unrelated write is likely
287; to stall the processor. Used with model_wbuf above.
9c08d1fa 288(define_attr "write_conflict" "no,yes"
289 (if_then_else (eq_attr "type"
a2cd141b 290 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 291 (const_string "yes")
292 (const_string "no")))
293
215b30b3 294; Classify the insns into those that take one cycle and those that take more
295; than one on the main cpu execution unit.
f7fbdd4a 296(define_attr "core_cycles" "single,multi"
297 (if_then_else (eq_attr "type"
a2cd141b 298 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 299 (const_string "single")
300 (const_string "multi")))
301
cffb2a26 302;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 303;; distant label. Only applicable to Thumb code.
cffb2a26 304(define_attr "far_jump" "yes,no" (const_string "no"))
305
d51f92df 306
25f905c2 307;; The number of machine instructions this pattern expands to.
308;; Used for Thumb-2 conditional execution.
309(define_attr "ce_count" "" (const_int 1))
310
d51f92df 311;;---------------------------------------------------------------------------
fd781bb2 312;; Mode iterators
d51f92df 313
314; A list of modes that are exactly 64 bits in size. We use this to expand
315; some splits that are the same for all modes when operating on ARM
316; registers.
fd781bb2 317(define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
d51f92df 318
319;;---------------------------------------------------------------------------
320;; Predicates
321
9c9db025 322(include "predicates.md")
234f6557 323(include "constraints.md")
9c9db025 324
a2cd141b 325;;---------------------------------------------------------------------------
326;; Pipeline descriptions
215b30b3 327
06469f9e 328;; Processor type. This is created automatically from arm-cores.def.
329(include "arm-tune.md")
331beb1a 330
a2cd141b 331;; True if the generic scheduling description should be used.
332
333(define_attr "generic_sched" "yes,no"
4d5cb40d 334 (const (if_then_else
bcaec148 335 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8")
4d5cb40d 336 (const_string "no")
337 (const_string "yes"))))
338
c0e1af52 339(define_attr "generic_vfp" "yes,no"
340 (const (if_then_else
341 (and (eq_attr "fpu" "vfp")
bcaec148 342 (eq_attr "tune" "!arm1020e,arm1022e,cortexa8"))
c0e1af52 343 (const_string "yes")
344 (const_string "no"))))
345
a2cd141b 346(include "arm-generic.md")
347(include "arm926ejs.md")
c0e1af52 348(include "arm1020e.md")
a2cd141b 349(include "arm1026ejs.md")
350(include "arm1136jfs.md")
bcaec148 351(include "cortex-a8.md")
3586df96 352
9c08d1fa 353\f
215b30b3 354;;---------------------------------------------------------------------------
e1159bbe 355;; Insn patterns
356;;
a0f94409 357;; Addition insns.
215b30b3 358
9c08d1fa 359;; Note: For DImode insns, there is normally no reason why operands should
360;; not be in the same register, what we don't want is for something being
361;; written to partially overlap something that is an input.
7d57ec45 362;; Cirrus 64bit additions should not be split because we have a native
363;; 64bit addition instructions.
9c08d1fa 364
cffb2a26 365(define_expand "adddi3"
366 [(parallel
215b30b3 367 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 368 (plus:DI (match_operand:DI 1 "s_register_operand" "")
369 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 370 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 371 "TARGET_EITHER"
372 "
a2cd141b 373 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 374 {
375 if (!cirrus_fp_register (operands[0], DImode))
376 operands[0] = force_reg (DImode, operands[0]);
377 if (!cirrus_fp_register (operands[1], DImode))
378 operands[1] = force_reg (DImode, operands[1]);
379 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
380 DONE;
381 }
382
25f905c2 383 if (TARGET_THUMB1)
cffb2a26 384 {
385 if (GET_CODE (operands[1]) != REG)
386 operands[1] = force_reg (SImode, operands[1]);
387 if (GET_CODE (operands[2]) != REG)
388 operands[2] = force_reg (SImode, operands[2]);
389 }
390 "
391)
392
25f905c2 393(define_insn "*thumb1_adddi3"
cffb2a26 394 [(set (match_operand:DI 0 "register_operand" "=l")
395 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 396 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 397 (clobber (reg:CC CC_REGNUM))
cffb2a26 398 ]
25f905c2 399 "TARGET_THUMB1"
cffb2a26 400 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
401 [(set_attr "length" "4")]
402)
403
a0f94409 404(define_insn_and_split "*arm_adddi3"
cffb2a26 405 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 406 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
407 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 408 (clobber (reg:CC CC_REGNUM))]
25f905c2 409 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 410 "#"
25f905c2 411 "TARGET_32BIT && reload_completed"
a0f94409 412 [(parallel [(set (reg:CC_C CC_REGNUM)
413 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
414 (match_dup 1)))
415 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
416 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
417 (plus:SI (match_dup 4) (match_dup 5))))]
418 "
419 {
420 operands[3] = gen_highpart (SImode, operands[0]);
421 operands[0] = gen_lowpart (SImode, operands[0]);
422 operands[4] = gen_highpart (SImode, operands[1]);
423 operands[1] = gen_lowpart (SImode, operands[1]);
424 operands[5] = gen_highpart (SImode, operands[2]);
425 operands[2] = gen_lowpart (SImode, operands[2]);
426 }"
cffb2a26 427 [(set_attr "conds" "clob")
428 (set_attr "length" "8")]
429)
9c08d1fa 430
a0f94409 431(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 432 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
433 (plus:DI (sign_extend:DI
97499065 434 (match_operand:SI 2 "s_register_operand" "r,r"))
435 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 436 (clobber (reg:CC CC_REGNUM))]
25f905c2 437 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 438 "#"
25f905c2 439 "TARGET_32BIT && reload_completed"
a0f94409 440 [(parallel [(set (reg:CC_C CC_REGNUM)
441 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
442 (match_dup 1)))
443 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
444 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
445 (plus:SI (ashiftrt:SI (match_dup 2)
446 (const_int 31))
447 (match_dup 4))))]
448 "
449 {
450 operands[3] = gen_highpart (SImode, operands[0]);
451 operands[0] = gen_lowpart (SImode, operands[0]);
452 operands[4] = gen_highpart (SImode, operands[1]);
453 operands[1] = gen_lowpart (SImode, operands[1]);
454 operands[2] = gen_lowpart (SImode, operands[2]);
455 }"
215b30b3 456 [(set_attr "conds" "clob")
457 (set_attr "length" "8")]
458)
9c08d1fa 459
a0f94409 460(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 461 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
462 (plus:DI (zero_extend:DI
97499065 463 (match_operand:SI 2 "s_register_operand" "r,r"))
464 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 465 (clobber (reg:CC CC_REGNUM))]
25f905c2 466 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 467 "#"
25f905c2 468 "TARGET_32BIT && reload_completed"
a0f94409 469 [(parallel [(set (reg:CC_C CC_REGNUM)
470 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
471 (match_dup 1)))
472 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
473 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
474 (plus:SI (match_dup 4) (const_int 0))))]
475 "
476 {
477 operands[3] = gen_highpart (SImode, operands[0]);
478 operands[0] = gen_lowpart (SImode, operands[0]);
479 operands[4] = gen_highpart (SImode, operands[1]);
480 operands[1] = gen_lowpart (SImode, operands[1]);
481 operands[2] = gen_lowpart (SImode, operands[2]);
482 }"
cffb2a26 483 [(set_attr "conds" "clob")
484 (set_attr "length" "8")]
485)
b11cae9e 486
87b22bf7 487(define_expand "addsi3"
cffb2a26 488 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 489 (plus:SI (match_operand:SI 1 "s_register_operand" "")
490 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 491 "TARGET_EITHER"
87b22bf7 492 "
25f905c2 493 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 494 {
96f57e36 495 arm_split_constant (PLUS, SImode, NULL_RTX,
496 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 497 optimize && can_create_pseudo_p ());
87b22bf7 498 DONE;
499 }
cffb2a26 500 "
501)
87b22bf7 502
5bd751ff 503; If there is a scratch available, this will be faster than synthesizing the
a0f94409 504; addition.
505(define_peephole2
506 [(match_scratch:SI 3 "r")
372575c7 507 (set (match_operand:SI 0 "arm_general_register_operand" "")
508 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 509 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 510 "TARGET_32BIT &&
a0f94409 511 !(const_ok_for_arm (INTVAL (operands[2]))
512 || const_ok_for_arm (-INTVAL (operands[2])))
513 && const_ok_for_arm (~INTVAL (operands[2]))"
514 [(set (match_dup 3) (match_dup 2))
515 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
516 ""
517)
87b22bf7 518
a0f94409 519(define_insn_and_split "*arm_addsi3"
cffb2a26 520 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
a0f94409 521 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
87b22bf7 522 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
25f905c2 523 "TARGET_32BIT"
5565501b 524 "@
525 add%?\\t%0, %1, %2
87b22bf7 526 sub%?\\t%0, %1, #%n2
527 #"
25f905c2 528 "TARGET_32BIT &&
a0f94409 529 GET_CODE (operands[2]) == CONST_INT
530 && !(const_ok_for_arm (INTVAL (operands[2]))
531 || const_ok_for_arm (-INTVAL (operands[2])))"
532 [(clobber (const_int 0))]
533 "
96f57e36 534 arm_split_constant (PLUS, SImode, curr_insn,
535 INTVAL (operands[2]), operands[0],
a0f94409 536 operands[1], 0);
537 DONE;
538 "
0d66636f 539 [(set_attr "length" "4,4,16")
540 (set_attr "predicable" "yes")]
cffb2a26 541)
542
543;; Register group 'k' is a single register group containing only the stack
544;; register. Trying to reload it will always fail catastrophically,
545;; so never allow those alternatives to match if reloading is needed.
546
25f905c2 547(define_insn "*thumb1_addsi3"
cffb2a26 548 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
549 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
550 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
25f905c2 551 "TARGET_THUMB1"
cffb2a26 552 "*
0d66636f 553 static const char * const asms[] =
cffb2a26 554 {
555 \"add\\t%0, %0, %2\",
556 \"sub\\t%0, %0, #%n2\",
557 \"add\\t%0, %1, %2\",
558 \"add\\t%0, %0, %2\",
559 \"add\\t%0, %0, %2\",
560 \"add\\t%0, %1, %2\",
561 \"add\\t%0, %1, %2\"
562 };
563 if ((which_alternative == 2 || which_alternative == 6)
564 && GET_CODE (operands[2]) == CONST_INT
565 && INTVAL (operands[2]) < 0)
566 return \"sub\\t%0, %1, #%n2\";
567 return asms[which_alternative];
568 "
569 [(set_attr "length" "2")]
570)
571
572;; Reloading and elimination of the frame pointer can
573;; sometimes cause this optimization to be missed.
a0f94409 574(define_peephole2
372575c7 575 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 576 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 577 (set (match_dup 0)
372575c7 578 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 579 "TARGET_THUMB1
cffb2a26 580 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
581 && (INTVAL (operands[1]) & 3) == 0"
372575c7 582 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 583 ""
cffb2a26 584)
b11cae9e 585
25f905c2 586;; ??? Make Thumb-2 variants which prefer low regs
f7fbdd4a 587(define_insn "*addsi3_compare0"
bd5b4116 588 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 589 (compare:CC_NOOV
215b30b3 590 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
591 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 592 (const_int 0)))
593 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 594 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 595 "TARGET_32BIT"
5565501b 596 "@
25f905c2 597 add%.\\t%0, %1, %2
598 sub%.\\t%0, %1, #%n2"
cffb2a26 599 [(set_attr "conds" "set")]
600)
9c08d1fa 601
aea4c774 602(define_insn "*addsi3_compare0_scratch"
bd5b4116 603 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 604 (compare:CC_NOOV
215b30b3 605 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
606 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 607 (const_int 0)))]
25f905c2 608 "TARGET_32BIT"
cffb2a26 609 "@
610 cmn%?\\t%0, %1
611 cmp%?\\t%0, #%n1"
0d66636f 612 [(set_attr "conds" "set")]
613)
cffb2a26 614
aed179ae 615(define_insn "*compare_negsi_si"
616 [(set (reg:CC_Z CC_REGNUM)
617 (compare:CC_Z
618 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
619 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 620 "TARGET_32BIT"
aed179ae 621 "cmn%?\\t%1, %0"
0d66636f 622 [(set_attr "conds" "set")]
623)
aea4c774 624
203c488f 625;; This is the canonicalization of addsi3_compare0_for_combiner when the
626;; addend is a constant.
627(define_insn "*cmpsi2_addneg"
628 [(set (reg:CC CC_REGNUM)
629 (compare:CC
630 (match_operand:SI 1 "s_register_operand" "r,r")
631 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
632 (set (match_operand:SI 0 "s_register_operand" "=r,r")
633 (plus:SI (match_dup 1)
634 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
25f905c2 635 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 636 "@
25f905c2 637 sub%.\\t%0, %1, %2
638 add%.\\t%0, %1, #%n2"
203c488f 639 [(set_attr "conds" "set")]
640)
641
642;; Convert the sequence
643;; sub rd, rn, #1
644;; cmn rd, #1 (equivalent to cmp rd, #-1)
645;; bne dest
646;; into
647;; subs rd, rn, #1
648;; bcs dest ((unsigned)rn >= 1)
649;; similarly for the beq variant using bcc.
650;; This is a common looping idiom (while (n--))
651(define_peephole2
372575c7 652 [(set (match_operand:SI 0 "arm_general_register_operand" "")
653 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 654 (const_int -1)))
655 (set (match_operand 2 "cc_register" "")
656 (compare (match_dup 0) (const_int -1)))
657 (set (pc)
658 (if_then_else (match_operator 3 "equality_operator"
659 [(match_dup 2) (const_int 0)])
660 (match_operand 4 "" "")
661 (match_operand 5 "" "")))]
25f905c2 662 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 663 [(parallel[
664 (set (match_dup 2)
665 (compare:CC
666 (match_dup 1) (const_int 1)))
667 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
668 (set (pc)
669 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
670 (match_dup 4)
671 (match_dup 5)))]
672 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
673 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
674 ? GEU : LTU),
675 VOIDmode,
676 operands[2], const0_rtx);"
677)
678
ebcc79bc 679;; The next four insns work because they compare the result with one of
680;; the operands, and we know that the use of the condition code is
681;; either GEU or LTU, so we can use the carry flag from the addition
682;; instead of doing the compare a second time.
683(define_insn "*addsi3_compare_op1"
bd5b4116 684 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 685 (compare:CC_C
686 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
687 (match_operand:SI 2 "arm_add_operand" "rI,L"))
688 (match_dup 1)))
689 (set (match_operand:SI 0 "s_register_operand" "=r,r")
690 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 691 "TARGET_32BIT"
ebcc79bc 692 "@
25f905c2 693 add%.\\t%0, %1, %2
694 sub%.\\t%0, %1, #%n2"
0d66636f 695 [(set_attr "conds" "set")]
696)
ebcc79bc 697
698(define_insn "*addsi3_compare_op2"
bd5b4116 699 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 700 (compare:CC_C
701 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
702 (match_operand:SI 2 "arm_add_operand" "rI,L"))
703 (match_dup 2)))
5565501b 704 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 705 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 706 "TARGET_32BIT"
5565501b 707 "@
25f905c2 708 add%.\\t%0, %1, %2
709 sub%.\\t%0, %1, #%n2"
0d66636f 710 [(set_attr "conds" "set")]
711)
9c08d1fa 712
ebcc79bc 713(define_insn "*compare_addsi2_op0"
bd5b4116 714 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 715 (compare:CC_C
716 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
717 (match_operand:SI 1 "arm_add_operand" "rI,L"))
718 (match_dup 0)))]
25f905c2 719 "TARGET_32BIT"
ebcc79bc 720 "@
721 cmn%?\\t%0, %1
722 cmp%?\\t%0, #%n1"
0d66636f 723 [(set_attr "conds" "set")]
724)
ebcc79bc 725
726(define_insn "*compare_addsi2_op1"
bd5b4116 727 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 728 (compare:CC_C
729 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
730 (match_operand:SI 1 "arm_add_operand" "rI,L"))
731 (match_dup 1)))]
25f905c2 732 "TARGET_32BIT"
ebcc79bc 733 "@
734 cmn%?\\t%0, %1
735 cmp%?\\t%0, #%n1"
0d66636f 736 [(set_attr "conds" "set")]
737)
ebcc79bc 738
739(define_insn "*addsi3_carryin"
740 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 741 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 742 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
743 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
25f905c2 744 "TARGET_32BIT"
ebcc79bc 745 "adc%?\\t%0, %1, %2"
cffb2a26 746 [(set_attr "conds" "use")]
747)
ebcc79bc 748
33782ec7 749(define_insn "*addsi3_carryin_shift"
7b63a8dd 750 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 751 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 752 (plus:SI
753 (match_operator:SI 2 "shift_operator"
7b63a8dd 754 [(match_operand:SI 3 "s_register_operand" "r")
755 (match_operand:SI 4 "reg_or_int_operand" "rM")])
756 (match_operand:SI 1 "s_register_operand" "r"))))]
25f905c2 757 "TARGET_32BIT"
33782ec7 758 "adc%?\\t%0, %1, %3%S2"
a2cd141b 759 [(set_attr "conds" "use")
760 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
761 (const_string "alu_shift")
762 (const_string "alu_shift_reg")))]
33782ec7 763)
764
ebcc79bc 765(define_insn "*addsi3_carryin_alt1"
766 [(set (match_operand:SI 0 "s_register_operand" "=r")
767 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
768 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 769 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
25f905c2 770 "TARGET_32BIT"
ebcc79bc 771 "adc%?\\t%0, %1, %2"
cffb2a26 772 [(set_attr "conds" "use")]
773)
ebcc79bc 774
775(define_insn "*addsi3_carryin_alt2"
776 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 777 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 778 (match_operand:SI 1 "s_register_operand" "r"))
779 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 780 "TARGET_32BIT"
ebcc79bc 781 "adc%?\\t%0, %1, %2"
0d66636f 782 [(set_attr "conds" "use")]
783)
ebcc79bc 784
785(define_insn "*addsi3_carryin_alt3"
786 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 787 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 788 (match_operand:SI 2 "arm_rhs_operand" "rI"))
789 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 790 "TARGET_32BIT"
ebcc79bc 791 "adc%?\\t%0, %1, %2"
cffb2a26 792 [(set_attr "conds" "use")]
793)
ebcc79bc 794
25f905c2 795(define_expand "incscc"
796 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
797 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
798 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
799 (match_operand:SI 1 "s_register_operand" "0,?r")))]
800 "TARGET_32BIT"
801 ""
802)
803
804(define_insn "*arm_incscc"
9c08d1fa 805 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 806 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 807 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 808 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 809 "TARGET_ARM"
5565501b 810 "@
811 add%d2\\t%0, %1, #1
812 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 813 [(set_attr "conds" "use")
215b30b3 814 (set_attr "length" "4,8")]
815)
9c08d1fa 816
d795fb69 817; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
818(define_split
819 [(set (match_operand:SI 0 "s_register_operand" "")
820 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
821 (match_operand:SI 2 "s_register_operand" ""))
822 (const_int -1)))
823 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 824 "TARGET_32BIT"
d795fb69 825 [(set (match_dup 3) (match_dup 1))
826 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
827 "
828 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
829")
830
604f3a0a 831(define_expand "addsf3"
832 [(set (match_operand:SF 0 "s_register_operand" "")
833 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 834 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 835 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 836 "
a2cd141b 837 if (TARGET_MAVERICK
604f3a0a 838 && !cirrus_fp_register (operands[2], SFmode))
839 operands[2] = force_reg (SFmode, operands[2]);
840")
841
604f3a0a 842(define_expand "adddf3"
843 [(set (match_operand:DF 0 "s_register_operand" "")
844 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 845 (match_operand:DF 2 "arm_float_add_operand" "")))]
25f905c2 846 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 847 "
a2cd141b 848 if (TARGET_MAVERICK
604f3a0a 849 && !cirrus_fp_register (operands[2], DFmode))
850 operands[2] = force_reg (DFmode, operands[2]);
851")
852
cffb2a26 853(define_expand "subdi3"
854 [(parallel
855 [(set (match_operand:DI 0 "s_register_operand" "")
856 (minus:DI (match_operand:DI 1 "s_register_operand" "")
857 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 858 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 859 "TARGET_EITHER"
860 "
a2cd141b 861 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 862 && TARGET_32BIT
7d57ec45 863 && cirrus_fp_register (operands[0], DImode)
864 && cirrus_fp_register (operands[1], DImode))
865 {
866 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
867 DONE;
868 }
869
25f905c2 870 if (TARGET_THUMB1)
cffb2a26 871 {
872 if (GET_CODE (operands[1]) != REG)
873 operands[1] = force_reg (SImode, operands[1]);
874 if (GET_CODE (operands[2]) != REG)
875 operands[2] = force_reg (SImode, operands[2]);
876 }
877 "
878)
879
880(define_insn "*arm_subdi3"
881 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 882 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
883 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 884 (clobber (reg:CC CC_REGNUM))]
25f905c2 885 "TARGET_32BIT"
97499065 886 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 887 [(set_attr "conds" "clob")
888 (set_attr "length" "8")]
889)
890
891(define_insn "*thumb_subdi3"
892 [(set (match_operand:DI 0 "register_operand" "=l")
893 (minus:DI (match_operand:DI 1 "register_operand" "0")
894 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 895 (clobber (reg:CC CC_REGNUM))]
25f905c2 896 "TARGET_THUMB1"
cffb2a26 897 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
898 [(set_attr "length" "4")]
899)
9c08d1fa 900
f7fbdd4a 901(define_insn "*subdi_di_zesidi"
cffb2a26 902 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
903 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 904 (zero_extend:DI
cffb2a26 905 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 906 (clobber (reg:CC CC_REGNUM))]
25f905c2 907 "TARGET_32BIT"
97499065 908 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 909 [(set_attr "conds" "clob")
910 (set_attr "length" "8")]
911)
9c08d1fa 912
f7fbdd4a 913(define_insn "*subdi_di_sesidi"
cffb2a26 914 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
915 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 916 (sign_extend:DI
cffb2a26 917 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 918 (clobber (reg:CC CC_REGNUM))]
25f905c2 919 "TARGET_32BIT"
97499065 920 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 921 [(set_attr "conds" "clob")
922 (set_attr "length" "8")]
923)
9c08d1fa 924
f7fbdd4a 925(define_insn "*subdi_zesidi_di"
cffb2a26 926 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 927 (minus:DI (zero_extend:DI
cffb2a26 928 (match_operand:SI 2 "s_register_operand" "r,r"))
929 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 930 (clobber (reg:CC CC_REGNUM))]
cffb2a26 931 "TARGET_ARM"
97499065 932 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 933 [(set_attr "conds" "clob")
934 (set_attr "length" "8")]
935)
9c08d1fa 936
f7fbdd4a 937(define_insn "*subdi_sesidi_di"
cffb2a26 938 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 939 (minus:DI (sign_extend:DI
cffb2a26 940 (match_operand:SI 2 "s_register_operand" "r,r"))
941 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 942 (clobber (reg:CC CC_REGNUM))]
cffb2a26 943 "TARGET_ARM"
97499065 944 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 945 [(set_attr "conds" "clob")
946 (set_attr "length" "8")]
947)
9c08d1fa 948
f7fbdd4a 949(define_insn "*subdi_zesidi_zesidi"
cffb2a26 950 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 951 (minus:DI (zero_extend:DI
cffb2a26 952 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 953 (zero_extend:DI
cffb2a26 954 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 955 (clobber (reg:CC CC_REGNUM))]
25f905c2 956 "TARGET_32BIT"
957 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 958 [(set_attr "conds" "clob")
959 (set_attr "length" "8")]
960)
b11cae9e 961
87b22bf7 962(define_expand "subsi3"
cffb2a26 963 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 964 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
965 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 966 "TARGET_EITHER"
87b22bf7 967 "
968 if (GET_CODE (operands[1]) == CONST_INT)
969 {
25f905c2 970 if (TARGET_32BIT)
cffb2a26 971 {
96f57e36 972 arm_split_constant (MINUS, SImode, NULL_RTX,
973 INTVAL (operands[1]), operands[0],
e1ba4a27 974 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 975 DONE;
976 }
25f905c2 977 else /* TARGET_THUMB1 */
cffb2a26 978 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 979 }
cffb2a26 980 "
981)
87b22bf7 982
25f905c2 983(define_insn "*thumb1_subsi3_insn"
cffb2a26 984 [(set (match_operand:SI 0 "register_operand" "=l")
985 (minus:SI (match_operand:SI 1 "register_operand" "l")
986 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 987 "TARGET_THUMB1"
cffb2a26 988 "sub\\t%0, %1, %2"
989 [(set_attr "length" "2")]
990)
991
25f905c2 992; ??? Check Thumb-2 split length
a0f94409 993(define_insn_and_split "*arm_subsi3_insn"
cffb2a26 994 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 995 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
996 (match_operand:SI 2 "s_register_operand" "r,r")))]
25f905c2 997 "TARGET_32BIT"
e2348bcb 998 "@
87b22bf7 999 rsb%?\\t%0, %2, %1
1000 #"
25f905c2 1001 "TARGET_32BIT
a0f94409 1002 && GET_CODE (operands[1]) == CONST_INT
1003 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 1004 [(clobber (const_int 0))]
1005 "
96f57e36 1006 arm_split_constant (MINUS, SImode, curr_insn,
1007 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1008 DONE;
cffb2a26 1009 "
a0f94409 1010 [(set_attr "length" "4,16")
1011 (set_attr "predicable" "yes")]
1012)
1013
1014(define_peephole2
1015 [(match_scratch:SI 3 "r")
372575c7 1016 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1017 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1018 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1019 "TARGET_32BIT
a0f94409 1020 && !const_ok_for_arm (INTVAL (operands[1]))
1021 && const_ok_for_arm (~INTVAL (operands[1]))"
1022 [(set (match_dup 3) (match_dup 1))
1023 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1024 ""
cffb2a26 1025)
b11cae9e 1026
f7fbdd4a 1027(define_insn "*subsi3_compare0"
bd5b4116 1028 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1029 (compare:CC_NOOV
1030 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1031 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1032 (const_int 0)))
9c08d1fa 1033 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1034 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1035 "TARGET_32BIT"
e2348bcb 1036 "@
25f905c2 1037 sub%.\\t%0, %1, %2
1038 rsb%.\\t%0, %2, %1"
cffb2a26 1039 [(set_attr "conds" "set")]
1040)
9c08d1fa 1041
25f905c2 1042(define_expand "decscc"
1043 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1044 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1045 (match_operator:SI 2 "arm_comparison_operator"
1046 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1047 "TARGET_32BIT"
1048 ""
1049)
1050
1051(define_insn "*arm_decscc"
cffb2a26 1052 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1053 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1054 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1055 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1056 "TARGET_ARM"
e2348bcb 1057 "@
215b30b3 1058 sub%d2\\t%0, %1, #1
1059 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1060 [(set_attr "conds" "use")
1061 (set_attr "length" "*,8")]
1062)
9c08d1fa 1063
604f3a0a 1064(define_expand "subsf3"
1065 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1066 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1067 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1068 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1069 "
a2cd141b 1070 if (TARGET_MAVERICK)
604f3a0a 1071 {
1072 if (!cirrus_fp_register (operands[1], SFmode))
1073 operands[1] = force_reg (SFmode, operands[1]);
1074 if (!cirrus_fp_register (operands[2], SFmode))
1075 operands[2] = force_reg (SFmode, operands[2]);
1076 }
1077")
1078
604f3a0a 1079(define_expand "subdf3"
1080 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1081 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1082 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1083 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1084 "
a2cd141b 1085 if (TARGET_MAVERICK)
604f3a0a 1086 {
1087 if (!cirrus_fp_register (operands[1], DFmode))
1088 operands[1] = force_reg (DFmode, operands[1]);
1089 if (!cirrus_fp_register (operands[2], DFmode))
1090 operands[2] = force_reg (DFmode, operands[2]);
1091 }
1092")
1093
b11cae9e 1094\f
1095;; Multiplication insns
1096
cffb2a26 1097(define_expand "mulsi3"
1098 [(set (match_operand:SI 0 "s_register_operand" "")
1099 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1100 (match_operand:SI 1 "s_register_operand" "")))]
1101 "TARGET_EITHER"
1102 ""
1103)
1104
9c08d1fa 1105;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1106(define_insn "*arm_mulsi3"
1107 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1108 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1109 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
58d7d654 1110 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1111 "mul%?\\t%0, %2, %1"
a2cd141b 1112 [(set_attr "insn" "mul")
0d66636f 1113 (set_attr "predicable" "yes")]
cffb2a26 1114)
1115
58d7d654 1116(define_insn "*arm_mulsi3_v6"
1117 [(set (match_operand:SI 0 "s_register_operand" "=r")
1118 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1119 (match_operand:SI 2 "s_register_operand" "r")))]
1120 "TARGET_32BIT && arm_arch6"
1121 "mul%?\\t%0, %1, %2"
1122 [(set_attr "insn" "mul")
1123 (set_attr "predicable" "yes")]
1124)
1125
215b30b3 1126; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1127; 1 and 2; are the same, because reload will make operand 0 match
1128; operand 1 without realizing that this conflicts with operand 2. We fix
1129; this by adding another alternative to match this case, and then `reload'
1130; it ourselves. This alternative must come first.
cffb2a26 1131(define_insn "*thumb_mulsi3"
1132 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1133 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1134 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1135 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1136 "*
1137 if (which_alternative < 2)
20c4e896 1138 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1139 else
20c4e896 1140 return \"mul\\t%0, %2\";
cffb2a26 1141 "
1142 [(set_attr "length" "4,4,2")
a2cd141b 1143 (set_attr "insn" "mul")]
cffb2a26 1144)
b11cae9e 1145
58d7d654 1146(define_insn "*thumb_mulsi3_v6"
1147 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1148 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1149 (match_operand:SI 2 "register_operand" "l,0,0")))]
1150 "TARGET_THUMB1 && arm_arch6"
1151 "@
1152 mul\\t%0, %2
1153 mul\\t%0, %1
1154 mul\\t%0, %1"
1155 [(set_attr "length" "2")
1156 (set_attr "insn" "mul")]
1157)
1158
f7fbdd4a 1159(define_insn "*mulsi3_compare0"
bd5b4116 1160 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1161 (compare:CC_NOOV (mult:SI
1162 (match_operand:SI 2 "s_register_operand" "r,r")
1163 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1164 (const_int 0)))
1165 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1166 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1167 "TARGET_ARM && !arm_arch6"
1168 "mul%.\\t%0, %2, %1"
1169 [(set_attr "conds" "set")
1170 (set_attr "insn" "muls")]
1171)
1172
1173(define_insn "*mulsi3_compare0_v6"
1174 [(set (reg:CC_NOOV CC_REGNUM)
1175 (compare:CC_NOOV (mult:SI
1176 (match_operand:SI 2 "s_register_operand" "r")
1177 (match_operand:SI 1 "s_register_operand" "r"))
1178 (const_int 0)))
1179 (set (match_operand:SI 0 "s_register_operand" "=r")
1180 (mult:SI (match_dup 2) (match_dup 1)))]
1181 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1182 "mul%.\\t%0, %2, %1"
cffb2a26 1183 [(set_attr "conds" "set")
a2cd141b 1184 (set_attr "insn" "muls")]
cffb2a26 1185)
9c08d1fa 1186
f7fbdd4a 1187(define_insn "*mulsi_compare0_scratch"
bd5b4116 1188 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1189 (compare:CC_NOOV (mult:SI
1190 (match_operand:SI 2 "s_register_operand" "r,r")
1191 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1192 (const_int 0)))
1193 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1194 "TARGET_ARM && !arm_arch6"
1195 "mul%.\\t%0, %2, %1"
1196 [(set_attr "conds" "set")
1197 (set_attr "insn" "muls")]
1198)
1199
1200(define_insn "*mulsi_compare0_scratch_v6"
1201 [(set (reg:CC_NOOV CC_REGNUM)
1202 (compare:CC_NOOV (mult:SI
1203 (match_operand:SI 2 "s_register_operand" "r")
1204 (match_operand:SI 1 "s_register_operand" "r"))
1205 (const_int 0)))
1206 (clobber (match_scratch:SI 0 "=r"))]
1207 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1208 "mul%.\\t%0, %2, %1"
cffb2a26 1209 [(set_attr "conds" "set")
a2cd141b 1210 (set_attr "insn" "muls")]
cffb2a26 1211)
9c08d1fa 1212
b11cae9e 1213;; Unnamed templates to match MLA instruction.
1214
f7fbdd4a 1215(define_insn "*mulsi3addsi"
9c08d1fa 1216 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1217 (plus:SI
9c08d1fa 1218 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1219 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1220 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
58d7d654 1221 "TARGET_32BIT && !arm_arch6"
1222 "mla%?\\t%0, %2, %1, %3"
1223 [(set_attr "insn" "mla")
1224 (set_attr "predicable" "yes")]
1225)
1226
1227(define_insn "*mulsi3addsi_v6"
1228 [(set (match_operand:SI 0 "s_register_operand" "=r")
1229 (plus:SI
1230 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1231 (match_operand:SI 1 "s_register_operand" "r"))
1232 (match_operand:SI 3 "s_register_operand" "r")))]
1233 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1234 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1235 [(set_attr "insn" "mla")
0d66636f 1236 (set_attr "predicable" "yes")]
1237)
b11cae9e 1238
f7fbdd4a 1239(define_insn "*mulsi3addsi_compare0"
bd5b4116 1240 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1241 (compare:CC_NOOV
1242 (plus:SI (mult:SI
1243 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1244 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1245 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1246 (const_int 0)))
9c08d1fa 1247 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1248 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1249 (match_dup 3)))]
58d7d654 1250 "TARGET_ARM && arm_arch6"
1251 "mla%.\\t%0, %2, %1, %3"
1252 [(set_attr "conds" "set")
1253 (set_attr "insn" "mlas")]
1254)
1255
1256(define_insn "*mulsi3addsi_compare0_v6"
1257 [(set (reg:CC_NOOV CC_REGNUM)
1258 (compare:CC_NOOV
1259 (plus:SI (mult:SI
1260 (match_operand:SI 2 "s_register_operand" "r")
1261 (match_operand:SI 1 "s_register_operand" "r"))
1262 (match_operand:SI 3 "s_register_operand" "r"))
1263 (const_int 0)))
1264 (set (match_operand:SI 0 "s_register_operand" "=r")
1265 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1266 (match_dup 3)))]
1267 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1268 "mla%.\\t%0, %2, %1, %3"
0d66636f 1269 [(set_attr "conds" "set")
a2cd141b 1270 (set_attr "insn" "mlas")]
0d66636f 1271)
9c08d1fa 1272
f7fbdd4a 1273(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1274 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1275 (compare:CC_NOOV
1276 (plus:SI (mult:SI
1277 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1278 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1279 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1280 (const_int 0)))
9c08d1fa 1281 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1282 "TARGET_ARM && !arm_arch6"
1283 "mla%.\\t%0, %2, %1, %3"
1284 [(set_attr "conds" "set")
1285 (set_attr "insn" "mlas")]
1286)
1287
1288(define_insn "*mulsi3addsi_compare0_scratch_v6"
1289 [(set (reg:CC_NOOV CC_REGNUM)
1290 (compare:CC_NOOV
1291 (plus:SI (mult:SI
1292 (match_operand:SI 2 "s_register_operand" "r")
1293 (match_operand:SI 1 "s_register_operand" "r"))
1294 (match_operand:SI 3 "s_register_operand" "r"))
1295 (const_int 0)))
1296 (clobber (match_scratch:SI 0 "=r"))]
1297 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1298 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1299 [(set_attr "conds" "set")
a2cd141b 1300 (set_attr "insn" "mlas")]
cffb2a26 1301)
f7fbdd4a 1302
89545238 1303(define_insn "*mulsi3subsi"
1304 [(set (match_operand:SI 0 "s_register_operand" "=r")
1305 (minus:SI
1306 (match_operand:SI 3 "s_register_operand" "r")
1307 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1308 (match_operand:SI 1 "s_register_operand" "r"))))]
1309 "TARGET_32BIT && arm_arch_thumb2"
1310 "mls%?\\t%0, %2, %1, %3"
1311 [(set_attr "insn" "mla")
1312 (set_attr "predicable" "yes")]
1313)
1314
efee20da 1315;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1316
1317(define_insn "*mulsidi3adddi"
fe8dbf85 1318 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1319 (plus:DI
215b30b3 1320 (mult:DI
fe8dbf85 1321 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1322 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1323 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1324 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1325 "smlal%?\\t%Q0, %R0, %3, %2"
1326 [(set_attr "insn" "smlal")
1327 (set_attr "predicable" "yes")]
1328)
1329
1330(define_insn "*mulsidi3adddi_v6"
1331 [(set (match_operand:DI 0 "s_register_operand" "=r")
1332 (plus:DI
1333 (mult:DI
1334 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1335 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1336 (match_operand:DI 1 "s_register_operand" "0")))]
1337 "TARGET_32BIT && arm_arch6"
fe8dbf85 1338 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1339 [(set_attr "insn" "smlal")
0d66636f 1340 (set_attr "predicable" "yes")]
1341)
82b85d08 1342
957788b0 1343;; 32x32->64 widening multiply.
1344;; As with mulsi3, the only difference between the v3-5 and v6+
1345;; versions of these patterns is the requirement that the output not
1346;; overlap the inputs, but that still means we have to have a named
1347;; expander and two different starred insns.
1348
1349(define_expand "mulsidi3"
1350 [(set (match_operand:DI 0 "s_register_operand" "")
1351 (mult:DI
1352 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1353 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1354 "TARGET_32BIT && arm_arch3m"
1355 ""
1356)
1357
1358(define_insn "*mulsidi3_nov6"
f7fbdd4a 1359 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1360 (mult:DI
1361 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1362 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1363 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1364 "smull%?\\t%Q0, %R0, %1, %2"
1365 [(set_attr "insn" "smull")
1366 (set_attr "predicable" "yes")]
1367)
1368
957788b0 1369(define_insn "*mulsidi3_v6"
58d7d654 1370 [(set (match_operand:DI 0 "s_register_operand" "=r")
1371 (mult:DI
1372 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1373 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1374 "TARGET_32BIT && arm_arch6"
97499065 1375 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1376 [(set_attr "insn" "smull")
0d66636f 1377 (set_attr "predicable" "yes")]
1378)
f7fbdd4a 1379
957788b0 1380(define_expand "umulsidi3"
1381 [(set (match_operand:DI 0 "s_register_operand" "")
1382 (mult:DI
1383 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1384 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1385 "TARGET_32BIT && arm_arch3m"
1386 ""
1387)
1388
1389(define_insn "*umulsidi3_nov6"
f7fbdd4a 1390 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1391 (mult:DI
1392 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1393 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1394 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1395 "umull%?\\t%Q0, %R0, %1, %2"
1396 [(set_attr "insn" "umull")
1397 (set_attr "predicable" "yes")]
1398)
1399
957788b0 1400(define_insn "*umulsidi3_v6"
58d7d654 1401 [(set (match_operand:DI 0 "s_register_operand" "=r")
1402 (mult:DI
1403 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1404 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1405 "TARGET_32BIT && arm_arch6"
97499065 1406 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1407 [(set_attr "insn" "umull")
0d66636f 1408 (set_attr "predicable" "yes")]
1409)
b11cae9e 1410
efee20da 1411;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1412
1413(define_insn "*umulsidi3adddi"
8ead09f9 1414 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1415 (plus:DI
215b30b3 1416 (mult:DI
fe8dbf85 1417 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1418 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1419 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1420 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1421 "umlal%?\\t%Q0, %R0, %3, %2"
1422 [(set_attr "insn" "umlal")
1423 (set_attr "predicable" "yes")]
1424)
1425
1426(define_insn "*umulsidi3adddi_v6"
1427 [(set (match_operand:DI 0 "s_register_operand" "=r")
1428 (plus:DI
1429 (mult:DI
1430 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1431 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1432 (match_operand:DI 1 "s_register_operand" "0")))]
1433 "TARGET_32BIT && arm_arch6"
fe8dbf85 1434 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1435 [(set_attr "insn" "umlal")
0d66636f 1436 (set_attr "predicable" "yes")]
1437)
82b85d08 1438
957788b0 1439(define_expand "smulsi3_highpart"
1440 [(parallel
1441 [(set (match_operand:SI 0 "s_register_operand" "")
1442 (truncate:SI
1443 (lshiftrt:DI
1444 (mult:DI
1445 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1446 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1447 (const_int 32))))
1448 (clobber (match_scratch:SI 3 ""))])]
1449 "TARGET_32BIT && arm_arch3m"
1450 ""
1451)
1452
1453(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1454 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1455 (truncate:SI
1456 (lshiftrt:DI
215b30b3 1457 (mult:DI
1458 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1459 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1460 (const_int 32))))
1461 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1462 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1463 "smull%?\\t%3, %0, %2, %1"
1464 [(set_attr "insn" "smull")
1465 (set_attr "predicable" "yes")]
1466)
1467
957788b0 1468(define_insn "*smulsi3_highpart_v6"
58d7d654 1469 [(set (match_operand:SI 0 "s_register_operand" "=r")
1470 (truncate:SI
1471 (lshiftrt:DI
1472 (mult:DI
1473 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1474 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1475 (const_int 32))))
1476 (clobber (match_scratch:SI 3 "=r"))]
1477 "TARGET_32BIT && arm_arch6"
f082f1c4 1478 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1479 [(set_attr "insn" "smull")
0d66636f 1480 (set_attr "predicable" "yes")]
cffb2a26 1481)
f082f1c4 1482
957788b0 1483(define_expand "umulsi3_highpart"
1484 [(parallel
1485 [(set (match_operand:SI 0 "s_register_operand" "")
1486 (truncate:SI
1487 (lshiftrt:DI
1488 (mult:DI
1489 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1490 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1491 (const_int 32))))
1492 (clobber (match_scratch:SI 3 ""))])]
1493 "TARGET_32BIT && arm_arch3m"
1494 ""
1495)
1496
1497(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1498 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1499 (truncate:SI
1500 (lshiftrt:DI
215b30b3 1501 (mult:DI
1502 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1503 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1504 (const_int 32))))
1505 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1506 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1507 "umull%?\\t%3, %0, %2, %1"
1508 [(set_attr "insn" "umull")
1509 (set_attr "predicable" "yes")]
1510)
1511
957788b0 1512(define_insn "*umulsi3_highpart_v6"
58d7d654 1513 [(set (match_operand:SI 0 "s_register_operand" "=r")
1514 (truncate:SI
1515 (lshiftrt:DI
1516 (mult:DI
1517 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1518 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1519 (const_int 32))))
1520 (clobber (match_scratch:SI 3 "=r"))]
1521 "TARGET_32BIT && arm_arch6"
f082f1c4 1522 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1523 [(set_attr "insn" "umull")
0d66636f 1524 (set_attr "predicable" "yes")]
cffb2a26 1525)
f082f1c4 1526
331beb1a 1527(define_insn "mulhisi3"
1528 [(set (match_operand:SI 0 "s_register_operand" "=r")
1529 (mult:SI (sign_extend:SI
1530 (match_operand:HI 1 "s_register_operand" "%r"))
1531 (sign_extend:SI
1532 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1533 "TARGET_DSP_MULTIPLY"
61a2d04c 1534 "smulbb%?\\t%0, %1, %2"
a2cd141b 1535 [(set_attr "insn" "smulxy")
fec538d9 1536 (set_attr "predicable" "yes")]
1537)
1538
1539(define_insn "*mulhisi3tb"
1540 [(set (match_operand:SI 0 "s_register_operand" "=r")
1541 (mult:SI (ashiftrt:SI
1542 (match_operand:SI 1 "s_register_operand" "r")
1543 (const_int 16))
1544 (sign_extend:SI
1545 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1546 "TARGET_DSP_MULTIPLY"
fec538d9 1547 "smultb%?\\t%0, %1, %2"
a2cd141b 1548 [(set_attr "insn" "smulxy")
fec538d9 1549 (set_attr "predicable" "yes")]
1550)
1551
1552(define_insn "*mulhisi3bt"
1553 [(set (match_operand:SI 0 "s_register_operand" "=r")
1554 (mult:SI (sign_extend:SI
1555 (match_operand:HI 1 "s_register_operand" "r"))
1556 (ashiftrt:SI
1557 (match_operand:SI 2 "s_register_operand" "r")
1558 (const_int 16))))]
25f905c2 1559 "TARGET_DSP_MULTIPLY"
fec538d9 1560 "smulbt%?\\t%0, %1, %2"
a2cd141b 1561 [(set_attr "insn" "smulxy")
fec538d9 1562 (set_attr "predicable" "yes")]
1563)
1564
1565(define_insn "*mulhisi3tt"
1566 [(set (match_operand:SI 0 "s_register_operand" "=r")
1567 (mult:SI (ashiftrt:SI
1568 (match_operand:SI 1 "s_register_operand" "r")
1569 (const_int 16))
1570 (ashiftrt:SI
1571 (match_operand:SI 2 "s_register_operand" "r")
1572 (const_int 16))))]
25f905c2 1573 "TARGET_DSP_MULTIPLY"
fec538d9 1574 "smultt%?\\t%0, %1, %2"
a2cd141b 1575 [(set_attr "insn" "smulxy")
fec538d9 1576 (set_attr "predicable" "yes")]
331beb1a 1577)
1578
1579(define_insn "*mulhisi3addsi"
1580 [(set (match_operand:SI 0 "s_register_operand" "=r")
1581 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1582 (mult:SI (sign_extend:SI
1583 (match_operand:HI 2 "s_register_operand" "%r"))
1584 (sign_extend:SI
1585 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1586 "TARGET_DSP_MULTIPLY"
61a2d04c 1587 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1588 [(set_attr "insn" "smlaxy")
fec538d9 1589 (set_attr "predicable" "yes")]
331beb1a 1590)
1591
1592(define_insn "*mulhidi3adddi"
1593 [(set (match_operand:DI 0 "s_register_operand" "=r")
1594 (plus:DI
1595 (match_operand:DI 1 "s_register_operand" "0")
1596 (mult:DI (sign_extend:DI
1597 (match_operand:HI 2 "s_register_operand" "%r"))
1598 (sign_extend:DI
1599 (match_operand:HI 3 "s_register_operand" "r")))))]
25f905c2 1600 "TARGET_DSP_MULTIPLY"
331beb1a 1601 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1602 [(set_attr "insn" "smlalxy")
fec538d9 1603 (set_attr "predicable" "yes")])
331beb1a 1604
604f3a0a 1605(define_expand "mulsf3"
1606 [(set (match_operand:SF 0 "s_register_operand" "")
1607 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1608 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1609 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1610 "
a2cd141b 1611 if (TARGET_MAVERICK
604f3a0a 1612 && !cirrus_fp_register (operands[2], SFmode))
1613 operands[2] = force_reg (SFmode, operands[2]);
1614")
1615
604f3a0a 1616(define_expand "muldf3"
1617 [(set (match_operand:DF 0 "s_register_operand" "")
1618 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1619 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1620 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1621 "
a2cd141b 1622 if (TARGET_MAVERICK
604f3a0a 1623 && !cirrus_fp_register (operands[2], DFmode))
1624 operands[2] = force_reg (DFmode, operands[2]);
1625")
b11cae9e 1626\f
1627;; Division insns
1628
7db9af5d 1629(define_expand "divsf3"
1630 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1631 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1632 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1633 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1634 "")
9c08d1fa 1635
7db9af5d 1636(define_expand "divdf3"
1637 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1638 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1639 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1640 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1641 "")
b11cae9e 1642\f
1643;; Modulo insns
1644
7db9af5d 1645(define_expand "modsf3"
1646 [(set (match_operand:SF 0 "s_register_operand" "")
1647 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1648 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1649 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1650 "")
9c08d1fa 1651
7db9af5d 1652(define_expand "moddf3"
1653 [(set (match_operand:DF 0 "s_register_operand" "")
1654 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1655 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1656 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1657 "")
b11cae9e 1658\f
1659;; Boolean and,ior,xor insns
1660
f6ebffac 1661;; Split up double word logical operations
1662
1663;; Split up simple DImode logical operations. Simply perform the logical
1664;; operation on the upper and lower halves of the registers.
1665(define_split
1666 [(set (match_operand:DI 0 "s_register_operand" "")
1667 (match_operator:DI 6 "logical_binary_operator"
1668 [(match_operand:DI 1 "s_register_operand" "")
1669 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1670 "TARGET_32BIT && reload_completed
1671 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1672 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1673 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1674 "
215b30b3 1675 {
1676 operands[3] = gen_highpart (SImode, operands[0]);
1677 operands[0] = gen_lowpart (SImode, operands[0]);
1678 operands[4] = gen_highpart (SImode, operands[1]);
1679 operands[1] = gen_lowpart (SImode, operands[1]);
1680 operands[5] = gen_highpart (SImode, operands[2]);
1681 operands[2] = gen_lowpart (SImode, operands[2]);
1682 }"
1683)
f6ebffac 1684
f6ebffac 1685(define_split
1686 [(set (match_operand:DI 0 "s_register_operand" "")
1687 (match_operator:DI 6 "logical_binary_operator"
1688 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1689 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1690 "TARGET_32BIT && reload_completed"
f6ebffac 1691 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1692 (set (match_dup 3) (match_op_dup:SI 6
1693 [(ashiftrt:SI (match_dup 2) (const_int 31))
1694 (match_dup 4)]))]
1695 "
215b30b3 1696 {
1697 operands[3] = gen_highpart (SImode, operands[0]);
1698 operands[0] = gen_lowpart (SImode, operands[0]);
1699 operands[4] = gen_highpart (SImode, operands[1]);
1700 operands[1] = gen_lowpart (SImode, operands[1]);
1701 operands[5] = gen_highpart (SImode, operands[2]);
1702 operands[2] = gen_lowpart (SImode, operands[2]);
1703 }"
1704)
f6ebffac 1705
f6ebffac 1706;; The zero extend of operand 2 means we can just copy the high part of
1707;; operand1 into operand0.
1708(define_split
1709 [(set (match_operand:DI 0 "s_register_operand" "")
1710 (ior:DI
1711 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1712 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1713 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1714 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1715 (set (match_dup 3) (match_dup 4))]
1716 "
215b30b3 1717 {
1718 operands[4] = gen_highpart (SImode, operands[1]);
1719 operands[3] = gen_highpart (SImode, operands[0]);
1720 operands[0] = gen_lowpart (SImode, operands[0]);
1721 operands[1] = gen_lowpart (SImode, operands[1]);
1722 }"
1723)
f6ebffac 1724
1725;; The zero extend of operand 2 means we can just copy the high part of
1726;; operand1 into operand0.
1727(define_split
1728 [(set (match_operand:DI 0 "s_register_operand" "")
1729 (xor:DI
1730 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1731 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1732 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1733 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1734 (set (match_dup 3) (match_dup 4))]
1735 "
215b30b3 1736 {
1737 operands[4] = gen_highpart (SImode, operands[1]);
1738 operands[3] = gen_highpart (SImode, operands[0]);
1739 operands[0] = gen_lowpart (SImode, operands[0]);
1740 operands[1] = gen_lowpart (SImode, operands[1]);
1741 }"
1742)
f6ebffac 1743
b11cae9e 1744(define_insn "anddi3"
cffb2a26 1745 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1746 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1747 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 1748 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 1749 "#"
215b30b3 1750 [(set_attr "length" "8")]
1751)
b11cae9e 1752
a0f94409 1753(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1754 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1755 (and:DI (zero_extend:DI
1756 (match_operand:SI 2 "s_register_operand" "r,r"))
1757 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1758 "TARGET_32BIT"
f6ebffac 1759 "#"
25f905c2 1760 "TARGET_32BIT && reload_completed"
a0f94409 1761 ; The zero extend of operand 2 clears the high word of the output
1762 ; operand.
1763 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1764 (set (match_dup 3) (const_int 0))]
1765 "
1766 {
1767 operands[3] = gen_highpart (SImode, operands[0]);
1768 operands[0] = gen_lowpart (SImode, operands[0]);
1769 operands[1] = gen_lowpart (SImode, operands[1]);
1770 }"
215b30b3 1771 [(set_attr "length" "8")]
1772)
b11cae9e 1773
f7fbdd4a 1774(define_insn "*anddi_sesdi_di"
cffb2a26 1775 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1776 (and:DI (sign_extend:DI
1777 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1778 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 1779 "TARGET_32BIT"
f6ebffac 1780 "#"
cffb2a26 1781 [(set_attr "length" "8")]
1782)
b11cae9e 1783
87b22bf7 1784(define_expand "andsi3"
cffb2a26 1785 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1786 (and:SI (match_operand:SI 1 "s_register_operand" "")
1787 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1788 "TARGET_EITHER"
87b22bf7 1789 "
25f905c2 1790 if (TARGET_32BIT)
87b22bf7 1791 {
cffb2a26 1792 if (GET_CODE (operands[2]) == CONST_INT)
1793 {
96f57e36 1794 arm_split_constant (AND, SImode, NULL_RTX,
1795 INTVAL (operands[2]), operands[0],
e1ba4a27 1796 operands[1], optimize && can_create_pseudo_p ());
615caa51 1797
cffb2a26 1798 DONE;
1799 }
87b22bf7 1800 }
25f905c2 1801 else /* TARGET_THUMB1 */
cffb2a26 1802 {
1803 if (GET_CODE (operands[2]) != CONST_INT)
1804 operands[2] = force_reg (SImode, operands[2]);
1805 else
1806 {
1807 int i;
1808
215b30b3 1809 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1810 {
215b30b3 1811 operands[2] = force_reg (SImode,
1812 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1813
1814 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1815
1816 DONE;
1817 }
87b22bf7 1818
cffb2a26 1819 for (i = 9; i <= 31; i++)
1820 {
1821 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1822 {
1823 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1824 const0_rtx));
1825 DONE;
1826 }
215b30b3 1827 else if ((((HOST_WIDE_INT) 1) << i) - 1
1828 == ~INTVAL (operands[2]))
cffb2a26 1829 {
1830 rtx shift = GEN_INT (i);
1831 rtx reg = gen_reg_rtx (SImode);
1832
1833 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1834 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1835
1836 DONE;
1837 }
1838 }
1839
1840 operands[2] = force_reg (SImode, operands[2]);
1841 }
215b30b3 1842 }
1843 "
cffb2a26 1844)
1845
25f905c2 1846; ??? Check split length for Thumb-2
a0f94409 1847(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1848 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1849 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1850 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 1851 "TARGET_32BIT"
5565501b 1852 "@
1853 and%?\\t%0, %1, %2
87b22bf7 1854 bic%?\\t%0, %1, #%B2
1855 #"
25f905c2 1856 "TARGET_32BIT
a0f94409 1857 && GET_CODE (operands[2]) == CONST_INT
1858 && !(const_ok_for_arm (INTVAL (operands[2]))
1859 || const_ok_for_arm (~INTVAL (operands[2])))"
1860 [(clobber (const_int 0))]
1861 "
96f57e36 1862 arm_split_constant (AND, SImode, curr_insn,
1863 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1864 DONE;
1865 "
0d66636f 1866 [(set_attr "length" "4,4,16")
1867 (set_attr "predicable" "yes")]
cffb2a26 1868)
1869
25f905c2 1870(define_insn "*thumb1_andsi3_insn"
cffb2a26 1871 [(set (match_operand:SI 0 "register_operand" "=l")
1872 (and:SI (match_operand:SI 1 "register_operand" "%0")
1873 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 1874 "TARGET_THUMB1"
cffb2a26 1875 "and\\t%0, %0, %2"
1876 [(set_attr "length" "2")]
1877)
87b22bf7 1878
f7fbdd4a 1879(define_insn "*andsi3_compare0"
bd5b4116 1880 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1881 (compare:CC_NOOV
1882 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1883 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1884 (const_int 0)))
cffb2a26 1885 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 1886 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 1887 "TARGET_32BIT"
5565501b 1888 "@
25f905c2 1889 and%.\\t%0, %1, %2
1890 bic%.\\t%0, %1, #%B2"
cffb2a26 1891 [(set_attr "conds" "set")]
1892)
9c08d1fa 1893
f7fbdd4a 1894(define_insn "*andsi3_compare0_scratch"
bd5b4116 1895 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1896 (compare:CC_NOOV
1897 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1898 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1899 (const_int 0)))
dd193d7c 1900 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 1901 "TARGET_32BIT"
5565501b 1902 "@
1903 tst%?\\t%0, %1
25f905c2 1904 bic%.\\t%2, %0, #%B1"
0d66636f 1905 [(set_attr "conds" "set")]
1906)
9c08d1fa 1907
f7fbdd4a 1908(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 1909 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1910 (compare:CC_NOOV (zero_extract:SI
1911 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 1912 (match_operand 1 "const_int_operand" "n")
1913 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 1914 (const_int 0)))]
25f905c2 1915 "TARGET_32BIT
cffb2a26 1916 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1917 && INTVAL (operands[1]) > 0
1918 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1919 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 1920 "*
5c49a439 1921 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1922 << INTVAL (operands[2]));
40dbec34 1923 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 1924 return \"\";
0d66636f 1925 "
1926 [(set_attr "conds" "set")]
1927)
9c08d1fa 1928
f4462328 1929(define_insn_and_split "*ne_zeroextractsi"
c4034607 1930 [(set (match_operand:SI 0 "s_register_operand" "=r")
1931 (ne:SI (zero_extract:SI
1932 (match_operand:SI 1 "s_register_operand" "r")
1933 (match_operand:SI 2 "const_int_operand" "n")
1934 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 1935 (const_int 0)))
1936 (clobber (reg:CC CC_REGNUM))]
25f905c2 1937 "TARGET_32BIT
cffb2a26 1938 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1939 && INTVAL (operands[2]) > 0
1940 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1941 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 1942 "#"
25f905c2 1943 "TARGET_32BIT
f4462328 1944 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1945 && INTVAL (operands[2]) > 0
1946 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1947 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1948 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1949 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1950 (const_int 0)))
1951 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1952 (set (match_dup 0)
1953 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1954 (match_dup 0) (const_int 1)))]
1955 "
1956 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1957 << INTVAL (operands[3]));
1958 "
1959 [(set_attr "conds" "clob")
25f905c2 1960 (set (attr "length")
1961 (if_then_else (eq_attr "is_thumb" "yes")
1962 (const_int 12)
1963 (const_int 8)))]
f4462328 1964)
1965
1966(define_insn_and_split "*ne_zeroextractsi_shifted"
1967 [(set (match_operand:SI 0 "s_register_operand" "=r")
1968 (ne:SI (zero_extract:SI
1969 (match_operand:SI 1 "s_register_operand" "r")
1970 (match_operand:SI 2 "const_int_operand" "n")
1971 (const_int 0))
1972 (const_int 0)))
1973 (clobber (reg:CC CC_REGNUM))]
1974 "TARGET_ARM"
1975 "#"
1976 "TARGET_ARM"
1977 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1978 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1979 (const_int 0)))
1980 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1981 (set (match_dup 0)
1982 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1983 (match_dup 0) (const_int 1)))]
1984 "
1985 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1986 "
1987 [(set_attr "conds" "clob")
1988 (set_attr "length" "8")]
1989)
1990
1991(define_insn_and_split "*ite_ne_zeroextractsi"
1992 [(set (match_operand:SI 0 "s_register_operand" "=r")
1993 (if_then_else:SI (ne (zero_extract:SI
1994 (match_operand:SI 1 "s_register_operand" "r")
1995 (match_operand:SI 2 "const_int_operand" "n")
1996 (match_operand:SI 3 "const_int_operand" "n"))
1997 (const_int 0))
1998 (match_operand:SI 4 "arm_not_operand" "rIK")
1999 (const_int 0)))
2000 (clobber (reg:CC CC_REGNUM))]
2001 "TARGET_ARM
2002 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2003 && INTVAL (operands[2]) > 0
2004 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2005 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2006 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2007 "#"
2008 "TARGET_ARM
2009 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2010 && INTVAL (operands[2]) > 0
2011 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2012 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2013 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2014 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2015 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2016 (const_int 0)))
2017 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2018 (set (match_dup 0)
2019 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2020 (match_dup 0) (match_dup 4)))]
2021 "
c4034607 2022 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2023 << INTVAL (operands[3]));
2024 "
2025 [(set_attr "conds" "clob")
2026 (set_attr "length" "8")]
2027)
2028
2029(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2030 [(set (match_operand:SI 0 "s_register_operand" "=r")
2031 (if_then_else:SI (ne (zero_extract:SI
2032 (match_operand:SI 1 "s_register_operand" "r")
2033 (match_operand:SI 2 "const_int_operand" "n")
2034 (const_int 0))
2035 (const_int 0))
2036 (match_operand:SI 3 "arm_not_operand" "rIK")
2037 (const_int 0)))
2038 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2039 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2040 "#"
f8d7bf2f 2041 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2042 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2043 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2044 (const_int 0)))
2045 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2046 (set (match_dup 0)
2047 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2048 (match_dup 0) (match_dup 3)))]
2049 "
2050 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2051 "
2052 [(set_attr "conds" "clob")
215b30b3 2053 (set_attr "length" "8")]
2054)
9c08d1fa 2055
58d6528b 2056(define_split
2057 [(set (match_operand:SI 0 "s_register_operand" "")
2058 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2059 (match_operand:SI 2 "const_int_operand" "")
2060 (match_operand:SI 3 "const_int_operand" "")))
2061 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2062 "TARGET_THUMB1"
58d6528b 2063 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2064 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2065 "{
2066 HOST_WIDE_INT temp = INTVAL (operands[2]);
2067
2068 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2069 operands[3] = GEN_INT (32 - temp);
2070 }"
2071)
2072
25f905c2 2073;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2074(define_split
2075 [(set (match_operand:SI 0 "s_register_operand" "")
2076 (match_operator:SI 1 "shiftable_operator"
2077 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2078 (match_operand:SI 3 "const_int_operand" "")
2079 (match_operand:SI 4 "const_int_operand" ""))
2080 (match_operand:SI 5 "s_register_operand" "")]))
2081 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2082 "TARGET_ARM"
2083 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2084 (set (match_dup 0)
2085 (match_op_dup 1
2086 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2087 (match_dup 5)]))]
2088 "{
2089 HOST_WIDE_INT temp = INTVAL (operands[3]);
2090
2091 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2092 operands[4] = GEN_INT (32 - temp);
2093 }"
2094)
2095
58d6528b 2096(define_split
2097 [(set (match_operand:SI 0 "s_register_operand" "")
2098 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2099 (match_operand:SI 2 "const_int_operand" "")
2100 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2101 "TARGET_THUMB1"
58d6528b 2102 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2103 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2104 "{
2105 HOST_WIDE_INT temp = INTVAL (operands[2]);
2106
2107 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2108 operands[3] = GEN_INT (32 - temp);
2109 }"
2110)
2111
d7863cfe 2112(define_split
2113 [(set (match_operand:SI 0 "s_register_operand" "")
2114 (match_operator:SI 1 "shiftable_operator"
2115 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2116 (match_operand:SI 3 "const_int_operand" "")
2117 (match_operand:SI 4 "const_int_operand" ""))
2118 (match_operand:SI 5 "s_register_operand" "")]))
2119 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2120 "TARGET_ARM"
2121 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2122 (set (match_dup 0)
2123 (match_op_dup 1
2124 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2125 (match_dup 5)]))]
2126 "{
2127 HOST_WIDE_INT temp = INTVAL (operands[3]);
2128
2129 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2130 operands[4] = GEN_INT (32 - temp);
2131 }"
2132)
2133
a42059fd 2134;;; ??? This pattern is bogus. If operand3 has bits outside the range
2135;;; represented by the bitfield, then this will produce incorrect results.
2136;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2137;;; which have a real bit-field insert instruction, the truncation happens
2138;;; in the bit-field insert instruction itself. Since arm does not have a
2139;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2140;;; the value before we insert. This loses some of the advantage of having
2141;;; this insv pattern, so this pattern needs to be reevalutated.
2142
25f905c2 2143; ??? Use Thumb-2 bitfield insert/extract instructions
8a18b90c 2144(define_expand "insv"
2145 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2146 (match_operand:SI 1 "general_operand" "")
2147 (match_operand:SI 2 "general_operand" ""))
19335226 2148 (match_operand:SI 3 "reg_or_int_operand" ""))]
cffb2a26 2149 "TARGET_ARM"
8a18b90c 2150 "
215b30b3 2151 {
2152 int start_bit = INTVAL (operands[2]);
2153 int width = INTVAL (operands[1]);
2154 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2155 rtx target, subtarget;
2156
2157 target = operands[0];
2158 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2159 subreg as the final target. */
2160 if (GET_CODE (target) == SUBREG)
2161 {
2162 subtarget = gen_reg_rtx (SImode);
2163 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2164 < GET_MODE_SIZE (SImode))
2165 target = SUBREG_REG (target);
2166 }
2167 else
2168 subtarget = target;
8a18b90c 2169
215b30b3 2170 if (GET_CODE (operands[3]) == CONST_INT)
2171 {
2172 /* Since we are inserting a known constant, we may be able to
2173 reduce the number of bits that we have to clear so that
2174 the mask becomes simple. */
2175 /* ??? This code does not check to see if the new mask is actually
2176 simpler. It may not be. */
2177 rtx op1 = gen_reg_rtx (SImode);
2178 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2179 start of this pattern. */
2180 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2181 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2182
c5b3a71b 2183 emit_insn (gen_andsi3 (op1, operands[0],
2184 gen_int_mode (~mask2, SImode)));
215b30b3 2185 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2186 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2187 }
2188 else if (start_bit == 0
2189 && !(const_ok_for_arm (mask)
2190 || const_ok_for_arm (~mask)))
2191 {
2192 /* A Trick, since we are setting the bottom bits in the word,
2193 we can shift operand[3] up, operand[0] down, OR them together
2194 and rotate the result back again. This takes 3 insns, and
5910bb95 2195 the third might be mergeable into another op. */
215b30b3 2196 /* The shift up copes with the possibility that operand[3] is
2197 wider than the bitfield. */
2198 rtx op0 = gen_reg_rtx (SImode);
2199 rtx op1 = gen_reg_rtx (SImode);
2200
2201 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2202 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2203 emit_insn (gen_iorsi3 (op1, op1, op0));
2204 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2205 }
2206 else if ((width + start_bit == 32)
2207 && !(const_ok_for_arm (mask)
2208 || const_ok_for_arm (~mask)))
2209 {
2210 /* Similar trick, but slightly less efficient. */
8a18b90c 2211
215b30b3 2212 rtx op0 = gen_reg_rtx (SImode);
2213 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2214
215b30b3 2215 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2216 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2217 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2218 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2219 }
2220 else
2221 {
c5b3a71b 2222 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2223 rtx op1 = gen_reg_rtx (SImode);
2224 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2225
215b30b3 2226 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2227 {
2228 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2229
215b30b3 2230 emit_insn (gen_movsi (tmp, op0));
2231 op0 = tmp;
2232 }
8a18b90c 2233
215b30b3 2234 /* Mask out any bits in operand[3] that are not needed. */
2235 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2236
215b30b3 2237 if (GET_CODE (op0) == CONST_INT
2238 && (const_ok_for_arm (mask << start_bit)
2239 || const_ok_for_arm (~(mask << start_bit))))
2240 {
c5b3a71b 2241 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2242 emit_insn (gen_andsi3 (op2, operands[0], op0));
2243 }
2244 else
2245 {
2246 if (GET_CODE (op0) == CONST_INT)
2247 {
2248 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2249
215b30b3 2250 emit_insn (gen_movsi (tmp, op0));
2251 op0 = tmp;
2252 }
2253
2254 if (start_bit != 0)
2255 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2256
215b30b3 2257 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2258 }
8a18b90c 2259
215b30b3 2260 if (start_bit != 0)
2261 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2262
215b30b3 2263 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2264 }
f082f1c4 2265
215b30b3 2266 if (subtarget != target)
2267 {
2268 /* If TARGET is still a SUBREG, then it must be wider than a word,
2269 so we must be careful only to set the subword we were asked to. */
2270 if (GET_CODE (target) == SUBREG)
2271 emit_move_insn (target, subtarget);
2272 else
2273 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2274 }
8a18b90c 2275
215b30b3 2276 DONE;
2277 }"
2278)
8a18b90c 2279
215b30b3 2280; constants for op 2 will never be given to these patterns.
a0f94409 2281(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2282 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 2283 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2284 (match_operand:DI 2 "s_register_operand" "0,r")))]
25f905c2 2285 "TARGET_32BIT"
f6ebffac 2286 "#"
25f905c2 2287 "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2288 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2289 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2290 "
2291 {
2292 operands[3] = gen_highpart (SImode, operands[0]);
2293 operands[0] = gen_lowpart (SImode, operands[0]);
2294 operands[4] = gen_highpart (SImode, operands[1]);
2295 operands[1] = gen_lowpart (SImode, operands[1]);
2296 operands[5] = gen_highpart (SImode, operands[2]);
2297 operands[2] = gen_lowpart (SImode, operands[2]);
2298 }"
0d66636f 2299 [(set_attr "length" "8")
2300 (set_attr "predicable" "yes")]
2301)
9c08d1fa 2302
a0f94409 2303(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2304 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2305 (and:DI (not:DI (zero_extend:DI
2306 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2307 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2308 "TARGET_32BIT"
e2348bcb 2309 "@
97499065 2310 bic%?\\t%Q0, %Q1, %2
f6ebffac 2311 #"
a0f94409 2312 ; (not (zero_extend ...)) allows us to just copy the high word from
2313 ; operand1 to operand0.
25f905c2 2314 "TARGET_32BIT
a0f94409 2315 && reload_completed
2316 && operands[0] != operands[1]"
5a097f7d 2317 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2318 (set (match_dup 3) (match_dup 4))]
2319 "
2320 {
2321 operands[3] = gen_highpart (SImode, operands[0]);
2322 operands[0] = gen_lowpart (SImode, operands[0]);
2323 operands[4] = gen_highpart (SImode, operands[1]);
2324 operands[1] = gen_lowpart (SImode, operands[1]);
2325 }"
0d66636f 2326 [(set_attr "length" "4,8")
2327 (set_attr "predicable" "yes")]
2328)
9c08d1fa 2329
a0f94409 2330(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2331 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2332 (and:DI (not:DI (sign_extend:DI
2333 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2334 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2335 "TARGET_32BIT"
f6ebffac 2336 "#"
25f905c2 2337 "TARGET_32BIT && reload_completed"
5a097f7d 2338 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2339 (set (match_dup 3) (and:SI (not:SI
2340 (ashiftrt:SI (match_dup 2) (const_int 31)))
2341 (match_dup 4)))]
2342 "
2343 {
2344 operands[3] = gen_highpart (SImode, operands[0]);
2345 operands[0] = gen_lowpart (SImode, operands[0]);
2346 operands[4] = gen_highpart (SImode, operands[1]);
2347 operands[1] = gen_lowpart (SImode, operands[1]);
2348 }"
0d66636f 2349 [(set_attr "length" "8")
2350 (set_attr "predicable" "yes")]
2351)
9c08d1fa 2352
8a18b90c 2353(define_insn "andsi_notsi_si"
9c08d1fa 2354 [(set (match_operand:SI 0 "s_register_operand" "=r")
2355 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2356 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2357 "TARGET_32BIT"
0d66636f 2358 "bic%?\\t%0, %1, %2"
2359 [(set_attr "predicable" "yes")]
2360)
b11cae9e 2361
cffb2a26 2362(define_insn "bicsi3"
2363 [(set (match_operand:SI 0 "register_operand" "=l")
2364 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2365 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2366 "TARGET_THUMB1"
cffb2a26 2367 "bic\\t%0, %0, %1"
2368 [(set_attr "length" "2")]
2369)
2370
8a18b90c 2371(define_insn "andsi_not_shiftsi_si"
a2cd141b 2372 [(set (match_operand:SI 0 "s_register_operand" "=r")
2373 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2374 [(match_operand:SI 2 "s_register_operand" "r")
2375 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2376 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2377 "TARGET_ARM"
6c4c2133 2378 "bic%?\\t%0, %1, %2%S4"
344495ea 2379 [(set_attr "predicable" "yes")
331beb1a 2380 (set_attr "shift" "2")
a2cd141b 2381 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2382 (const_string "alu_shift")
2383 (const_string "alu_shift_reg")))]
6c4c2133 2384)
8a18b90c 2385
f7fbdd4a 2386(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2387 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2388 (compare:CC_NOOV
2389 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2390 (match_operand:SI 1 "s_register_operand" "r"))
2391 (const_int 0)))
9c08d1fa 2392 (set (match_operand:SI 0 "s_register_operand" "=r")
2393 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2394 "TARGET_32BIT"
2395 "bic%.\\t%0, %1, %2"
0d66636f 2396 [(set_attr "conds" "set")]
2397)
9c08d1fa 2398
f7fbdd4a 2399(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2400 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2401 (compare:CC_NOOV
2402 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2403 (match_operand:SI 1 "s_register_operand" "r"))
2404 (const_int 0)))
9c08d1fa 2405 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2406 "TARGET_32BIT"
2407 "bic%.\\t%0, %1, %2"
0d66636f 2408 [(set_attr "conds" "set")]
2409)
9c08d1fa 2410
2411(define_insn "iordi3"
cffb2a26 2412 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2413 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2414 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2415 "TARGET_32BIT && ! TARGET_IWMMXT"
f6ebffac 2416 "#"
0d66636f 2417 [(set_attr "length" "8")
2418 (set_attr "predicable" "yes")]
cffb2a26 2419)
9c08d1fa 2420
f7fbdd4a 2421(define_insn "*iordi_zesidi_di"
9c08d1fa 2422 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2423 (ior:DI (zero_extend:DI
2424 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2425 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2426 "TARGET_32BIT"
e2348bcb 2427 "@
97499065 2428 orr%?\\t%Q0, %Q1, %2
f6ebffac 2429 #"
0d66636f 2430 [(set_attr "length" "4,8")
2431 (set_attr "predicable" "yes")]
cffb2a26 2432)
9c08d1fa 2433
f7fbdd4a 2434(define_insn "*iordi_sesidi_di"
9c08d1fa 2435 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2436 (ior:DI (sign_extend:DI
2437 (match_operand:SI 2 "s_register_operand" "r,r"))
2438 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2439 "TARGET_32BIT"
f6ebffac 2440 "#"
0d66636f 2441 [(set_attr "length" "8")
2442 (set_attr "predicable" "yes")]
cffb2a26 2443)
9c08d1fa 2444
87b22bf7 2445(define_expand "iorsi3"
cffb2a26 2446 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2447 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2448 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2449 "TARGET_EITHER"
87b22bf7 2450 "
2451 if (GET_CODE (operands[2]) == CONST_INT)
2452 {
25f905c2 2453 if (TARGET_32BIT)
cffb2a26 2454 {
96f57e36 2455 arm_split_constant (IOR, SImode, NULL_RTX,
2456 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2457 optimize && can_create_pseudo_p ());
cffb2a26 2458 DONE;
2459 }
25f905c2 2460 else /* TARGET_THUMB1 */
cffb2a26 2461 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2462 }
cffb2a26 2463 "
2464)
87b22bf7 2465
a0f94409 2466(define_insn_and_split "*arm_iorsi3"
cffb2a26 2467 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2468 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2469 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
25f905c2 2470 "TARGET_32BIT"
87b22bf7 2471 "@
2472 orr%?\\t%0, %1, %2
2473 #"
25f905c2 2474 "TARGET_32BIT
a0f94409 2475 && GET_CODE (operands[2]) == CONST_INT
2476 && !const_ok_for_arm (INTVAL (operands[2]))"
2477 [(clobber (const_int 0))]
2478 "
96f57e36 2479 arm_split_constant (IOR, SImode, curr_insn,
2480 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2481 DONE;
2482 "
0d66636f 2483 [(set_attr "length" "4,16")
2484 (set_attr "predicable" "yes")]
cffb2a26 2485)
2486
25f905c2 2487(define_insn "*thumb1_iorsi3"
cffb2a26 2488 [(set (match_operand:SI 0 "register_operand" "=l")
2489 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2490 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2491 "TARGET_THUMB1"
cffb2a26 2492 "orr\\t%0, %0, %2"
2493 [(set_attr "length" "2")]
2494)
9c08d1fa 2495
a0f94409 2496(define_peephole2
2497 [(match_scratch:SI 3 "r")
372575c7 2498 (set (match_operand:SI 0 "arm_general_register_operand" "")
2499 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2500 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 2501 "TARGET_32BIT
a0f94409 2502 && !const_ok_for_arm (INTVAL (operands[2]))
2503 && const_ok_for_arm (~INTVAL (operands[2]))"
2504 [(set (match_dup 3) (match_dup 2))
2505 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2506 ""
215b30b3 2507)
a0f94409 2508
f7fbdd4a 2509(define_insn "*iorsi3_compare0"
bd5b4116 2510 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2511 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2512 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2513 (const_int 0)))
2514 (set (match_operand:SI 0 "s_register_operand" "=r")
2515 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2516 "TARGET_32BIT"
2517 "orr%.\\t%0, %1, %2"
cffb2a26 2518 [(set_attr "conds" "set")]
2519)
9c08d1fa 2520
f7fbdd4a 2521(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2522 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2523 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2524 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2525 (const_int 0)))
2526 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2527 "TARGET_32BIT"
2528 "orr%.\\t%0, %1, %2"
0d66636f 2529 [(set_attr "conds" "set")]
2530)
9c08d1fa 2531
2532(define_insn "xordi3"
cffb2a26 2533 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2534 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2535 (match_operand:DI 2 "s_register_operand" "r,r")))]
25f905c2 2536 "TARGET_32BIT && !TARGET_IWMMXT"
f6ebffac 2537 "#"
0d66636f 2538 [(set_attr "length" "8")
2539 (set_attr "predicable" "yes")]
cffb2a26 2540)
9c08d1fa 2541
f7fbdd4a 2542(define_insn "*xordi_zesidi_di"
9c08d1fa 2543 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2544 (xor:DI (zero_extend:DI
2545 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2546 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2547 "TARGET_32BIT"
e2348bcb 2548 "@
97499065 2549 eor%?\\t%Q0, %Q1, %2
f6ebffac 2550 #"
0d66636f 2551 [(set_attr "length" "4,8")
2552 (set_attr "predicable" "yes")]
cffb2a26 2553)
9c08d1fa 2554
f7fbdd4a 2555(define_insn "*xordi_sesidi_di"
9c08d1fa 2556 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2557 (xor:DI (sign_extend:DI
2558 (match_operand:SI 2 "s_register_operand" "r,r"))
2559 (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 2560 "TARGET_32BIT"
f6ebffac 2561 "#"
0d66636f 2562 [(set_attr "length" "8")
2563 (set_attr "predicable" "yes")]
cffb2a26 2564)
9c08d1fa 2565
cffb2a26 2566(define_expand "xorsi3"
2567 [(set (match_operand:SI 0 "s_register_operand" "")
2568 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2569 (match_operand:SI 2 "arm_rhs_operand" "")))]
2570 "TARGET_EITHER"
25f905c2 2571 "if (TARGET_THUMB1)
cffb2a26 2572 if (GET_CODE (operands[2]) == CONST_INT)
2573 operands[2] = force_reg (SImode, operands[2]);
2574 "
2575)
2576
2577(define_insn "*arm_xorsi3"
2578 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2579 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2580 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 2581 "TARGET_32BIT"
cffb2a26 2582 "eor%?\\t%0, %1, %2"
0d66636f 2583 [(set_attr "predicable" "yes")]
cffb2a26 2584)
2585
25f905c2 2586(define_insn "*thumb1_xorsi3"
cffb2a26 2587 [(set (match_operand:SI 0 "register_operand" "=l")
2588 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2589 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2590 "TARGET_THUMB1"
cffb2a26 2591 "eor\\t%0, %0, %2"
2592 [(set_attr "length" "2")]
2593)
9c08d1fa 2594
f7fbdd4a 2595(define_insn "*xorsi3_compare0"
bd5b4116 2596 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2597 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2598 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2599 (const_int 0)))
2600 (set (match_operand:SI 0 "s_register_operand" "=r")
2601 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2602 "TARGET_32BIT"
2603 "eor%.\\t%0, %1, %2"
0d66636f 2604 [(set_attr "conds" "set")]
2605)
9c08d1fa 2606
f7fbdd4a 2607(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2608 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2609 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2610 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2611 (const_int 0)))]
25f905c2 2612 "TARGET_32BIT"
40dbec34 2613 "teq%?\\t%0, %1"
cffb2a26 2614 [(set_attr "conds" "set")]
2615)
9c08d1fa 2616
215b30b3 2617; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2618; (NOT D) we can sometimes merge the final NOT into one of the following
2619; insns.
9c08d1fa 2620
2621(define_split
a058e94a 2622 [(set (match_operand:SI 0 "s_register_operand" "")
2623 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2624 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2625 (match_operand:SI 3 "arm_rhs_operand" "")))
2626 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2627 "TARGET_32BIT"
9c08d1fa 2628 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2629 (not:SI (match_dup 3))))
2630 (set (match_dup 0) (not:SI (match_dup 4)))]
2631 ""
2632)
2633
f7fbdd4a 2634(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2635 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2636 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2637 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2638 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2639 "TARGET_32BIT"
40dbec34 2640 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2641 [(set_attr "length" "8")
25f905c2 2642 (set_attr "ce_count" "2")
0d66636f 2643 (set_attr "predicable" "yes")]
cffb2a26 2644)
9c08d1fa 2645
25f905c2 2646; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2647; insns are available?
d7863cfe 2648(define_split
2649 [(set (match_operand:SI 0 "s_register_operand" "")
2650 (match_operator:SI 1 "logical_binary_operator"
2651 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2652 (match_operand:SI 3 "const_int_operand" "")
2653 (match_operand:SI 4 "const_int_operand" ""))
2654 (match_operator:SI 9 "logical_binary_operator"
2655 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2656 (match_operand:SI 6 "const_int_operand" ""))
2657 (match_operand:SI 7 "s_register_operand" "")])]))
2658 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2659 "TARGET_32BIT
d7863cfe 2660 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2661 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2662 [(set (match_dup 8)
2663 (match_op_dup 1
2664 [(ashift:SI (match_dup 2) (match_dup 4))
2665 (match_dup 5)]))
2666 (set (match_dup 0)
2667 (match_op_dup 1
2668 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2669 (match_dup 7)]))]
2670 "
2671 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2672")
2673
2674(define_split
2675 [(set (match_operand:SI 0 "s_register_operand" "")
2676 (match_operator:SI 1 "logical_binary_operator"
2677 [(match_operator:SI 9 "logical_binary_operator"
2678 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2679 (match_operand:SI 6 "const_int_operand" ""))
2680 (match_operand:SI 7 "s_register_operand" "")])
2681 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2682 (match_operand:SI 3 "const_int_operand" "")
2683 (match_operand:SI 4 "const_int_operand" ""))]))
2684 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2685 "TARGET_32BIT
d7863cfe 2686 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2687 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2688 [(set (match_dup 8)
2689 (match_op_dup 1
2690 [(ashift:SI (match_dup 2) (match_dup 4))
2691 (match_dup 5)]))
2692 (set (match_dup 0)
2693 (match_op_dup 1
2694 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2695 (match_dup 7)]))]
2696 "
2697 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2698")
2699
2700(define_split
2701 [(set (match_operand:SI 0 "s_register_operand" "")
2702 (match_operator:SI 1 "logical_binary_operator"
2703 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2704 (match_operand:SI 3 "const_int_operand" "")
2705 (match_operand:SI 4 "const_int_operand" ""))
2706 (match_operator:SI 9 "logical_binary_operator"
2707 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2708 (match_operand:SI 6 "const_int_operand" ""))
2709 (match_operand:SI 7 "s_register_operand" "")])]))
2710 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2711 "TARGET_32BIT
d7863cfe 2712 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2713 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2714 [(set (match_dup 8)
2715 (match_op_dup 1
2716 [(ashift:SI (match_dup 2) (match_dup 4))
2717 (match_dup 5)]))
2718 (set (match_dup 0)
2719 (match_op_dup 1
2720 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2721 (match_dup 7)]))]
2722 "
2723 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2724")
2725
2726(define_split
2727 [(set (match_operand:SI 0 "s_register_operand" "")
2728 (match_operator:SI 1 "logical_binary_operator"
2729 [(match_operator:SI 9 "logical_binary_operator"
2730 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2731 (match_operand:SI 6 "const_int_operand" ""))
2732 (match_operand:SI 7 "s_register_operand" "")])
2733 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2734 (match_operand:SI 3 "const_int_operand" "")
2735 (match_operand:SI 4 "const_int_operand" ""))]))
2736 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2737 "TARGET_32BIT
d7863cfe 2738 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2739 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2740 [(set (match_dup 8)
2741 (match_op_dup 1
2742 [(ashift:SI (match_dup 2) (match_dup 4))
2743 (match_dup 5)]))
2744 (set (match_dup 0)
2745 (match_op_dup 1
2746 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2747 (match_dup 7)]))]
2748 "
2749 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2750")
9c08d1fa 2751\f
2752
2753;; Minimum and maximum insns
2754
8b9dc177 2755(define_expand "smaxsi3"
2756 [(parallel [
2757 (set (match_operand:SI 0 "s_register_operand" "")
2758 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2759 (match_operand:SI 2 "arm_rhs_operand" "")))
2760 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2761 "TARGET_32BIT"
8b9dc177 2762 "
8774928b 2763 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 2764 {
2765 /* No need for a clobber of the condition code register here. */
2766 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2767 gen_rtx_SMAX (SImode, operands[1],
2768 operands[2])));
2769 DONE;
2770 }
2771")
2772
2773(define_insn "*smax_0"
2774 [(set (match_operand:SI 0 "s_register_operand" "=r")
2775 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2776 (const_int 0)))]
25f905c2 2777 "TARGET_32BIT"
8b9dc177 2778 "bic%?\\t%0, %1, %1, asr #31"
2779 [(set_attr "predicable" "yes")]
2780)
2781
8774928b 2782(define_insn "*smax_m1"
2783 [(set (match_operand:SI 0 "s_register_operand" "=r")
2784 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2785 (const_int -1)))]
25f905c2 2786 "TARGET_32BIT"
8774928b 2787 "orr%?\\t%0, %1, %1, asr #31"
2788 [(set_attr "predicable" "yes")]
2789)
2790
25f905c2 2791(define_insn "*arm_smax_insn"
8b9dc177 2792 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2793 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2794 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 2795 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2796 "TARGET_ARM"
e2348bcb 2797 "@
2798 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 2799 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2800 [(set_attr "conds" "clob")
8b9dc177 2801 (set_attr "length" "8,12")]
cffb2a26 2802)
9c08d1fa 2803
8b9dc177 2804(define_expand "sminsi3"
2805 [(parallel [
2806 (set (match_operand:SI 0 "s_register_operand" "")
2807 (smin:SI (match_operand:SI 1 "s_register_operand" "")
2808 (match_operand:SI 2 "arm_rhs_operand" "")))
2809 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2810 "TARGET_32BIT"
8b9dc177 2811 "
2812 if (operands[2] == const0_rtx)
2813 {
2814 /* No need for a clobber of the condition code register here. */
2815 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2816 gen_rtx_SMIN (SImode, operands[1],
2817 operands[2])));
2818 DONE;
2819 }
2820")
2821
2822(define_insn "*smin_0"
2823 [(set (match_operand:SI 0 "s_register_operand" "=r")
2824 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2825 (const_int 0)))]
25f905c2 2826 "TARGET_32BIT"
8b9dc177 2827 "and%?\\t%0, %1, %1, asr #31"
2828 [(set_attr "predicable" "yes")]
2829)
2830
25f905c2 2831(define_insn "*arm_smin_insn"
8b9dc177 2832 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2833 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2834 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 2835 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2836 "TARGET_ARM"
e2348bcb 2837 "@
2838 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 2839 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 2840 [(set_attr "conds" "clob")
8b9dc177 2841 (set_attr "length" "8,12")]
0d66636f 2842)
9c08d1fa 2843
25f905c2 2844(define_expand "umaxsi3"
2845 [(parallel [
2846 (set (match_operand:SI 0 "s_register_operand" "")
2847 (umax:SI (match_operand:SI 1 "s_register_operand" "")
2848 (match_operand:SI 2 "arm_rhs_operand" "")))
2849 (clobber (reg:CC CC_REGNUM))])]
2850 "TARGET_32BIT"
2851 ""
2852)
2853
2854(define_insn "*arm_umaxsi3"
9c08d1fa 2855 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2856 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2857 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2858 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2859 "TARGET_ARM"
e2348bcb 2860 "@
2861 cmp\\t%1, %2\;movcc\\t%0, %2
2862 cmp\\t%1, %2\;movcs\\t%0, %1
2863 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 2864 [(set_attr "conds" "clob")
2865 (set_attr "length" "8,8,12")]
2866)
9c08d1fa 2867
25f905c2 2868(define_expand "uminsi3"
2869 [(parallel [
2870 (set (match_operand:SI 0 "s_register_operand" "")
2871 (umin:SI (match_operand:SI 1 "s_register_operand" "")
2872 (match_operand:SI 2 "arm_rhs_operand" "")))
2873 (clobber (reg:CC CC_REGNUM))])]
2874 "TARGET_32BIT"
2875 ""
2876)
2877
2878(define_insn "*arm_uminsi3"
9c08d1fa 2879 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2880 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2881 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2882 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2883 "TARGET_ARM"
e2348bcb 2884 "@
2885 cmp\\t%1, %2\;movcs\\t%0, %2
2886 cmp\\t%1, %2\;movcc\\t%0, %1
2887 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 2888 [(set_attr "conds" "clob")
2889 (set_attr "length" "8,8,12")]
2890)
9c08d1fa 2891
8a18b90c 2892(define_insn "*store_minmaxsi"
9c08d1fa 2893 [(set (match_operand:SI 0 "memory_operand" "=m")
2894 (match_operator:SI 3 "minmax_operator"
2895 [(match_operand:SI 1 "s_register_operand" "r")
2896 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 2897 (clobber (reg:CC CC_REGNUM))]
25f905c2 2898 "TARGET_32BIT"
9c08d1fa 2899 "*
dc55b8a9 2900 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2901 operands[1], operands[2]);
e2348bcb 2902 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 2903 if (TARGET_THUMB2)
2904 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 2905 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2906 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2907 return \"\";
0d66636f 2908 "
2909 [(set_attr "conds" "clob")
25f905c2 2910 (set (attr "length")
2911 (if_then_else (eq_attr "is_thumb" "yes")
2912 (const_int 14)
2913 (const_int 12)))
0d66636f 2914 (set_attr "type" "store1")]
2915)
9c08d1fa 2916
8a18b90c 2917; Reject the frame pointer in operand[1], since reloading this after
2918; it has been eliminated can cause carnage.
f7fbdd4a 2919(define_insn "*minmax_arithsi"
9c08d1fa 2920 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2921 (match_operator:SI 4 "shiftable_operator"
2922 [(match_operator:SI 5 "minmax_operator"
2923 [(match_operand:SI 2 "s_register_operand" "r,r")
2924 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2925 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 2926 (clobber (reg:CC CC_REGNUM))]
25f905c2 2927 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 2928 "*
0d66636f 2929 {
2930 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 2931 bool need_else;
2932
2933 if (which_alternative != 0 || operands[3] != const0_rtx
2934 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2935 need_else = true;
2936 else
2937 need_else = false;
0d66636f 2938
dc55b8a9 2939 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2940 operands[2], operands[3]);
0d66636f 2941 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 2942 if (TARGET_THUMB2)
2943 {
2944 if (need_else)
2945 output_asm_insn (\"ite\\t%d5\", operands);
2946 else
2947 output_asm_insn (\"it\\t%d5\", operands);
2948 }
0d66636f 2949 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 2950 if (need_else)
0d66636f 2951 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2952 return \"\";
215b30b3 2953 }"
0d66636f 2954 [(set_attr "conds" "clob")
25f905c2 2955 (set (attr "length")
2956 (if_then_else (eq_attr "is_thumb" "yes")
2957 (const_int 14)
2958 (const_int 12)))]
0d66636f 2959)
9c08d1fa 2960
b11cae9e 2961\f
2962;; Shift and rotation insns
2963
a2cd141b 2964(define_expand "ashldi3"
2965 [(set (match_operand:DI 0 "s_register_operand" "")
2966 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2967 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 2968 "TARGET_32BIT"
a2cd141b 2969 "
2970 if (GET_CODE (operands[2]) == CONST_INT)
2971 {
2972 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2973 {
2974 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2975 DONE;
2976 }
2977 /* Ideally we shouldn't fail here if we could know that operands[1]
2978 ends up already living in an iwmmxt register. Otherwise it's
2979 cheaper to have the alternate code being generated than moving
1d60d981 2980 values to iwmmxt regs and back. */
a2cd141b 2981 FAIL;
2982 }
2983 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2984 FAIL;
2985 "
2986)
2987
2988(define_insn "arm_ashldi3_1bit"
2989 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2990 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2991 (const_int 1)))
2992 (clobber (reg:CC CC_REGNUM))]
25f905c2 2993 "TARGET_32BIT"
a2cd141b 2994 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2995 [(set_attr "conds" "clob")
2996 (set_attr "length" "8")]
2997)
2998
87b22bf7 2999(define_expand "ashlsi3"
cffb2a26 3000 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3001 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3002 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3003 "TARGET_EITHER"
87b22bf7 3004 "
3005 if (GET_CODE (operands[2]) == CONST_INT
3006 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3007 {
3008 emit_insn (gen_movsi (operands[0], const0_rtx));
3009 DONE;
3010 }
cffb2a26 3011 "
3012)
3013
25f905c2 3014(define_insn "*thumb1_ashlsi3"
cffb2a26 3015 [(set (match_operand:SI 0 "register_operand" "=l,l")
3016 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3017 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3018 "TARGET_THUMB1"
cffb2a26 3019 "lsl\\t%0, %1, %2"
3020 [(set_attr "length" "2")]
3021)
b11cae9e 3022
a2cd141b 3023(define_expand "ashrdi3"
3024 [(set (match_operand:DI 0 "s_register_operand" "")
3025 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3026 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3027 "TARGET_32BIT"
a2cd141b 3028 "
3029 if (GET_CODE (operands[2]) == CONST_INT)
3030 {
3031 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3032 {
3033 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3034 DONE;
3035 }
3036 /* Ideally we shouldn't fail here if we could know that operands[1]
3037 ends up already living in an iwmmxt register. Otherwise it's
3038 cheaper to have the alternate code being generated than moving
1d60d981 3039 values to iwmmxt regs and back. */
a2cd141b 3040 FAIL;
3041 }
3042 else if (!TARGET_REALLY_IWMMXT)
3043 FAIL;
3044 "
3045)
3046
3047(define_insn "arm_ashrdi3_1bit"
3048 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3049 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3050 (const_int 1)))
3051 (clobber (reg:CC CC_REGNUM))]
25f905c2 3052 "TARGET_32BIT"
a2cd141b 3053 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3054 [(set_attr "conds" "clob")
3055 (set_attr "length" "8")]
3056)
3057
87b22bf7 3058(define_expand "ashrsi3"
cffb2a26 3059 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3060 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3061 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3062 "TARGET_EITHER"
87b22bf7 3063 "
3064 if (GET_CODE (operands[2]) == CONST_INT
3065 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3066 operands[2] = GEN_INT (31);
cffb2a26 3067 "
3068)
3069
25f905c2 3070(define_insn "*thumb1_ashrsi3"
cffb2a26 3071 [(set (match_operand:SI 0 "register_operand" "=l,l")
3072 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3073 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3074 "TARGET_THUMB1"
cffb2a26 3075 "asr\\t%0, %1, %2"
3076 [(set_attr "length" "2")]
3077)
b11cae9e 3078
a2cd141b 3079(define_expand "lshrdi3"
3080 [(set (match_operand:DI 0 "s_register_operand" "")
3081 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3082 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3083 "TARGET_32BIT"
a2cd141b 3084 "
3085 if (GET_CODE (operands[2]) == CONST_INT)
3086 {
3087 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3088 {
3089 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3090 DONE;
3091 }
3092 /* Ideally we shouldn't fail here if we could know that operands[1]
3093 ends up already living in an iwmmxt register. Otherwise it's
3094 cheaper to have the alternate code being generated than moving
1d60d981 3095 values to iwmmxt regs and back. */
a2cd141b 3096 FAIL;
3097 }
3098 else if (!TARGET_REALLY_IWMMXT)
3099 FAIL;
3100 "
3101)
3102
3103(define_insn "arm_lshrdi3_1bit"
3104 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3105 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3106 (const_int 1)))
3107 (clobber (reg:CC CC_REGNUM))]
25f905c2 3108 "TARGET_32BIT"
a2cd141b 3109 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3110 [(set_attr "conds" "clob")
3111 (set_attr "length" "8")]
3112)
3113
87b22bf7 3114(define_expand "lshrsi3"
cffb2a26 3115 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3116 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3117 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3118 "TARGET_EITHER"
87b22bf7 3119 "
3120 if (GET_CODE (operands[2]) == CONST_INT
3121 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3122 {
3123 emit_insn (gen_movsi (operands[0], const0_rtx));
3124 DONE;
3125 }
cffb2a26 3126 "
3127)
3128
25f905c2 3129(define_insn "*thumb1_lshrsi3"
cffb2a26 3130 [(set (match_operand:SI 0 "register_operand" "=l,l")
3131 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3132 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3133 "TARGET_THUMB1"
cffb2a26 3134 "lsr\\t%0, %1, %2"
3135 [(set_attr "length" "2")]
3136)
b11cae9e 3137
87b22bf7 3138(define_expand "rotlsi3"
cffb2a26 3139 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3140 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3141 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3142 "TARGET_32BIT"
87b22bf7 3143 "
3144 if (GET_CODE (operands[2]) == CONST_INT)
3145 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3146 else
b11cae9e 3147 {
87b22bf7 3148 rtx reg = gen_reg_rtx (SImode);
3149 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3150 operands[2] = reg;
b11cae9e 3151 }
cffb2a26 3152 "
3153)
9c08d1fa 3154
87b22bf7 3155(define_expand "rotrsi3"
cffb2a26 3156 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3157 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3158 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3159 "TARGET_EITHER"
87b22bf7 3160 "
25f905c2 3161 if (TARGET_32BIT)
cffb2a26 3162 {
3163 if (GET_CODE (operands[2]) == CONST_INT
3164 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3165 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3166 }
25f905c2 3167 else /* TARGET_THUMB1 */
cffb2a26 3168 {
3169 if (GET_CODE (operands [2]) == CONST_INT)
3170 operands [2] = force_reg (SImode, operands[2]);
3171 }
3172 "
3173)
87b22bf7 3174
25f905c2 3175(define_insn "*thumb1_rotrsi3"
cffb2a26 3176 [(set (match_operand:SI 0 "register_operand" "=l")
3177 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3178 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3179 "TARGET_THUMB1"
cffb2a26 3180 "ror\\t%0, %0, %2"
3181 [(set_attr "length" "2")]
3182)
3183
3184(define_insn "*arm_shiftsi3"
3185 [(set (match_operand:SI 0 "s_register_operand" "=r")
3186 (match_operator:SI 3 "shift_operator"
3187 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3188 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3189 "TARGET_32BIT"
3190 "* return arm_output_shift(operands, 0);"
344495ea 3191 [(set_attr "predicable" "yes")
331beb1a 3192 (set_attr "shift" "1")
a2cd141b 3193 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3194 (const_string "alu_shift")
3195 (const_string "alu_shift_reg")))]
6c4c2133 3196)
87b22bf7 3197
f7fbdd4a 3198(define_insn "*shiftsi3_compare0"
bd5b4116 3199 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3200 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3201 [(match_operand:SI 1 "s_register_operand" "r")
3202 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3203 (const_int 0)))
3204 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3205 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3206 "TARGET_32BIT"
3207 "* return arm_output_shift(operands, 1);"
344495ea 3208 [(set_attr "conds" "set")
331beb1a 3209 (set_attr "shift" "1")
a2cd141b 3210 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3211 (const_string "alu_shift")
3212 (const_string "alu_shift_reg")))]
0d66636f 3213)
9c08d1fa 3214
f7fbdd4a 3215(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3216 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3217 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3218 [(match_operand:SI 1 "s_register_operand" "r")
3219 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3220 (const_int 0)))
3221 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3222 "TARGET_32BIT"
3223 "* return arm_output_shift(operands, 1);"
344495ea 3224 [(set_attr "conds" "set")
a2cd141b 3225 (set_attr "shift" "1")]
0d66636f 3226)
9c08d1fa 3227
25f905c2 3228(define_insn "*arm_notsi_shiftsi"
9c08d1fa 3229 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3230 (not:SI (match_operator:SI 3 "shift_operator"
3231 [(match_operand:SI 1 "s_register_operand" "r")
3232 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 3233 "TARGET_ARM"
6c4c2133 3234 "mvn%?\\t%0, %1%S3"
344495ea 3235 [(set_attr "predicable" "yes")
331beb1a 3236 (set_attr "shift" "1")
a2cd141b 3237 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3238 (const_string "alu_shift")
3239 (const_string "alu_shift_reg")))]
0d66636f 3240)
9c08d1fa 3241
25f905c2 3242(define_insn "*arm_notsi_shiftsi_compare0"
bd5b4116 3243 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3244 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3245 [(match_operand:SI 1 "s_register_operand" "r")
3246 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3247 (const_int 0)))
3248 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3249 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 3250 "TARGET_ARM"
25f905c2 3251 "mvn%.\\t%0, %1%S3"
344495ea 3252 [(set_attr "conds" "set")
331beb1a 3253 (set_attr "shift" "1")
a2cd141b 3254 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3255 (const_string "alu_shift")
3256 (const_string "alu_shift_reg")))]
0d66636f 3257)
9c08d1fa 3258
25f905c2 3259(define_insn "*arm_not_shiftsi_compare0_scratch"
bd5b4116 3260 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3261 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3262 [(match_operand:SI 1 "s_register_operand" "r")
3263 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 3264 (const_int 0)))
3265 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3266 "TARGET_ARM"
25f905c2 3267 "mvn%.\\t%0, %1%S3"
344495ea 3268 [(set_attr "conds" "set")
331beb1a 3269 (set_attr "shift" "1")
a2cd141b 3270 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3271 (const_string "alu_shift")
3272 (const_string "alu_shift_reg")))]
0d66636f 3273)
9c08d1fa 3274
cffb2a26 3275;; We don't really have extzv, but defining this using shifts helps
3276;; to reduce register pressure later on.
3277
3278(define_expand "extzv"
3279 [(set (match_dup 4)
3280 (ashift:SI (match_operand:SI 1 "register_operand" "")
3281 (match_operand:SI 2 "const_int_operand" "")))
3282 (set (match_operand:SI 0 "register_operand" "")
3283 (lshiftrt:SI (match_dup 4)
215b30b3 3284 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 3285 "TARGET_THUMB1"
cffb2a26 3286 "
3287 {
3288 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3289 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3290
3291 operands[3] = GEN_INT (rshift);
3292
3293 if (lshift == 0)
3294 {
3295 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3296 DONE;
3297 }
3298
3299 operands[2] = GEN_INT (lshift);
3300 operands[4] = gen_reg_rtx (SImode);
215b30b3 3301 }"
cffb2a26 3302)
3303
b11cae9e 3304\f
3305;; Unary arithmetic insns
3306
cffb2a26 3307(define_expand "negdi2"
3308 [(parallel
3309 [(set (match_operand:DI 0 "s_register_operand" "")
3310 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 3311 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 3312 "TARGET_EITHER"
3313 "
25f905c2 3314 if (TARGET_THUMB1)
cffb2a26 3315 {
3316 if (GET_CODE (operands[1]) != REG)
3317 operands[1] = force_reg (SImode, operands[1]);
3318 }
215b30b3 3319 "
cffb2a26 3320)
3321
3322;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3323;; The second alternative is to allow the common case of a *full* overlap.
3324(define_insn "*arm_negdi2"
3325 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3326 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 3327 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3328 "TARGET_ARM"
97499065 3329 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 3330 [(set_attr "conds" "clob")
3331 (set_attr "length" "8")]
3332)
b11cae9e 3333
25f905c2 3334(define_insn "*thumb1_negdi2"
cffb2a26 3335 [(set (match_operand:DI 0 "register_operand" "=&l")
3336 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 3337 (clobber (reg:CC CC_REGNUM))]
25f905c2 3338 "TARGET_THUMB1"
cffb2a26 3339 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3340 [(set_attr "length" "6")]
3341)
3342
3343(define_expand "negsi2"
3344 [(set (match_operand:SI 0 "s_register_operand" "")
3345 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3346 "TARGET_EITHER"
b11cae9e 3347 ""
cffb2a26 3348)
3349
3350(define_insn "*arm_negsi2"
3351 [(set (match_operand:SI 0 "s_register_operand" "=r")
3352 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3353 "TARGET_32BIT"
cffb2a26 3354 "rsb%?\\t%0, %1, #0"
0d66636f 3355 [(set_attr "predicable" "yes")]
cffb2a26 3356)
3357
25f905c2 3358(define_insn "*thumb1_negsi2"
cffb2a26 3359 [(set (match_operand:SI 0 "register_operand" "=l")
3360 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3361 "TARGET_THUMB1"
cffb2a26 3362 "neg\\t%0, %1"
3363 [(set_attr "length" "2")]
3364)
b11cae9e 3365
604f3a0a 3366(define_expand "negsf2"
3367 [(set (match_operand:SF 0 "s_register_operand" "")
3368 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3369 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3370 ""
3371)
3372
3373(define_expand "negdf2"
3374 [(set (match_operand:DF 0 "s_register_operand" "")
3375 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3376 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 3377 "")
3378
9c08d1fa 3379;; abssi2 doesn't really clobber the condition codes if a different register
3380;; is being set. To keep things simple, assume during rtl manipulations that
3381;; it does, but tell the final scan operator the truth. Similarly for
3382;; (neg (abs...))
3383
604f3a0a 3384(define_expand "abssi2"
3385 [(parallel
3386 [(set (match_operand:SI 0 "s_register_operand" "")
3387 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 3388 (clobber (match_dup 2))])]
3389 "TARGET_EITHER"
3390 "
25f905c2 3391 if (TARGET_THUMB1)
ba156559 3392 operands[2] = gen_rtx_SCRATCH (SImode);
3393 else
3394 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3395")
604f3a0a 3396
7d57ec45 3397(define_insn "*arm_abssi2"
ba156559 3398 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3399 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3400 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3401 "TARGET_ARM"
e2348bcb 3402 "@
3403 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3404 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3405 [(set_attr "conds" "clob,*")
331beb1a 3406 (set_attr "shift" "1")
0d66636f 3407 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3408 (set_attr "length" "8")]
3409)
9c08d1fa 3410
25f905c2 3411(define_insn_and_split "*thumb1_abssi2"
ba156559 3412 [(set (match_operand:SI 0 "s_register_operand" "=l")
3413 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3414 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3415 "TARGET_THUMB1"
ba156559 3416 "#"
25f905c2 3417 "TARGET_THUMB1 && reload_completed"
ba156559 3418 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3419 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3420 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3421 ""
3422 [(set_attr "length" "6")]
3423)
3424
3425(define_insn "*arm_neg_abssi2"
9c08d1fa 3426 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3427 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3428 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3429 "TARGET_ARM"
e2348bcb 3430 "@
3431 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3432 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3433 [(set_attr "conds" "clob,*")
331beb1a 3434 (set_attr "shift" "1")
0d66636f 3435 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3436 (set_attr "length" "8")]
3437)
b11cae9e 3438
25f905c2 3439(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 3440 [(set (match_operand:SI 0 "s_register_operand" "=l")
3441 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3442 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 3443 "TARGET_THUMB1"
ba156559 3444 "#"
25f905c2 3445 "TARGET_THUMB1 && reload_completed"
ba156559 3446 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3447 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3448 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3449 ""
3450 [(set_attr "length" "6")]
3451)
3452
604f3a0a 3453(define_expand "abssf2"
3454 [(set (match_operand:SF 0 "s_register_operand" "")
3455 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3456 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3457 "")
3458
604f3a0a 3459(define_expand "absdf2"
3460 [(set (match_operand:DF 0 "s_register_operand" "")
3461 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3462 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3463 "")
3464
7db9af5d 3465(define_expand "sqrtsf2"
3466 [(set (match_operand:SF 0 "s_register_operand" "")
3467 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 3468 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3469 "")
9c08d1fa 3470
7db9af5d 3471(define_expand "sqrtdf2"
3472 [(set (match_operand:DF 0 "s_register_operand" "")
3473 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3474 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3475 "")
9c08d1fa 3476
a0f94409 3477(define_insn_and_split "one_cmpldi2"
9c08d1fa 3478 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3479 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
25f905c2 3480 "TARGET_32BIT"
f6ebffac 3481 "#"
25f905c2 3482 "TARGET_32BIT && reload_completed"
a0f94409 3483 [(set (match_dup 0) (not:SI (match_dup 1)))
3484 (set (match_dup 2) (not:SI (match_dup 3)))]
3485 "
3486 {
3487 operands[2] = gen_highpart (SImode, operands[0]);
3488 operands[0] = gen_lowpart (SImode, operands[0]);
3489 operands[3] = gen_highpart (SImode, operands[1]);
3490 operands[1] = gen_lowpart (SImode, operands[1]);
3491 }"
0d66636f 3492 [(set_attr "length" "8")
3493 (set_attr "predicable" "yes")]
cffb2a26 3494)
b11cae9e 3495
cffb2a26 3496(define_expand "one_cmplsi2"
3497 [(set (match_operand:SI 0 "s_register_operand" "")
3498 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3499 "TARGET_EITHER"
b11cae9e 3500 ""
cffb2a26 3501)
3502
3503(define_insn "*arm_one_cmplsi2"
3504 [(set (match_operand:SI 0 "s_register_operand" "=r")
3505 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3506 "TARGET_32BIT"
cffb2a26 3507 "mvn%?\\t%0, %1"
0d66636f 3508 [(set_attr "predicable" "yes")]
cffb2a26 3509)
3510
25f905c2 3511(define_insn "*thumb1_one_cmplsi2"
cffb2a26 3512 [(set (match_operand:SI 0 "register_operand" "=l")
3513 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 3514 "TARGET_THUMB1"
cffb2a26 3515 "mvn\\t%0, %1"
3516 [(set_attr "length" "2")]
3517)
9c08d1fa 3518
f7fbdd4a 3519(define_insn "*notsi_compare0"
bd5b4116 3520 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3521 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3522 (const_int 0)))
3523 (set (match_operand:SI 0 "s_register_operand" "=r")
3524 (not:SI (match_dup 1)))]
25f905c2 3525 "TARGET_32BIT"
3526 "mvn%.\\t%0, %1"
cffb2a26 3527 [(set_attr "conds" "set")]
3528)
9c08d1fa 3529
f7fbdd4a 3530(define_insn "*notsi_compare0_scratch"
bd5b4116 3531 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3532 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3533 (const_int 0)))
3534 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3535 "TARGET_32BIT"
3536 "mvn%.\\t%0, %1"
cffb2a26 3537 [(set_attr "conds" "set")]
3538)
b11cae9e 3539\f
3540;; Fixed <--> Floating conversion insns
3541
604f3a0a 3542(define_expand "floatsisf2"
3543 [(set (match_operand:SF 0 "s_register_operand" "")
3544 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3545 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3546 "
a2cd141b 3547 if (TARGET_MAVERICK)
604f3a0a 3548 {
3549 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3550 DONE;
3551 }
3552")
3553
604f3a0a 3554(define_expand "floatsidf2"
3555 [(set (match_operand:DF 0 "s_register_operand" "")
3556 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 3557 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3558 "
a2cd141b 3559 if (TARGET_MAVERICK)
604f3a0a 3560 {
3561 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3562 DONE;
3563 }
3564")
3565
604f3a0a 3566(define_expand "fix_truncsfsi2"
3567 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3568 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 3569 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3570 "
a2cd141b 3571 if (TARGET_MAVERICK)
604f3a0a 3572 {
3573 if (!cirrus_fp_register (operands[0], SImode))
3574 operands[0] = force_reg (SImode, operands[0]);
3575 if (!cirrus_fp_register (operands[1], SFmode))
3576 operands[1] = force_reg (SFmode, operands[0]);
3577 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3578 DONE;
3579 }
3580")
3581
604f3a0a 3582(define_expand "fix_truncdfsi2"
3583 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3584 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
25f905c2 3585 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3586 "
a2cd141b 3587 if (TARGET_MAVERICK)
604f3a0a 3588 {
3589 if (!cirrus_fp_register (operands[1], DFmode))
3590 operands[1] = force_reg (DFmode, operands[0]);
3591 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3592 DONE;
3593 }
3594")
3595
f544c6d2 3596;; Truncation insns
b11cae9e 3597
604f3a0a 3598(define_expand "truncdfsf2"
3599 [(set (match_operand:SF 0 "s_register_operand" "")
3600 (float_truncate:SF
3601 (match_operand:DF 1 "s_register_operand" "")))]
25f905c2 3602 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3603 ""
3604)
b11cae9e 3605\f
9c08d1fa 3606;; Zero and sign extension instructions.
b11cae9e 3607
25f905c2 3608(define_expand "zero_extendsidi2"
3609 [(set (match_operand:DI 0 "s_register_operand" "")
3610 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3611 "TARGET_32BIT"
3612 ""
3613)
3614
3615(define_insn "*arm_zero_extendsidi2"
9c08d1fa 3616 [(set (match_operand:DI 0 "s_register_operand" "=r")
3617 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3618 "TARGET_ARM"
9c08d1fa 3619 "*
0d66636f 3620 if (REGNO (operands[1])
3621 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3622 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3623 return \"mov%?\\t%R0, #0\";
3624 "
3625 [(set_attr "length" "8")
3626 (set_attr "predicable" "yes")]
3627)
9c08d1fa 3628
25f905c2 3629(define_expand "zero_extendqidi2"
3630 [(set (match_operand:DI 0 "s_register_operand" "")
3631 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3632 "TARGET_32BIT"
3633 ""
3634)
3635
3636(define_insn "*arm_zero_extendqidi2"
cffb2a26 3637 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3638 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3639 "TARGET_ARM"
e2348bcb 3640 "@
97499065 3641 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
25f905c2 3642 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3643 [(set_attr "length" "8")
0d66636f 3644 (set_attr "predicable" "yes")
a2cd141b 3645 (set_attr "type" "*,load_byte")
cffb2a26 3646 (set_attr "pool_range" "*,4092")
3647 (set_attr "neg_pool_range" "*,4084")]
3648)
9c08d1fa 3649
25f905c2 3650(define_expand "extendsidi2"
3651 [(set (match_operand:DI 0 "s_register_operand" "")
3652 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3653 "TARGET_32BIT"
3654 ""
3655)
3656
3657(define_insn "*arm_extendsidi2"
9c08d1fa 3658 [(set (match_operand:DI 0 "s_register_operand" "=r")
3659 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3660 "TARGET_ARM"
9c08d1fa 3661 "*
0d66636f 3662 if (REGNO (operands[1])
3663 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3664 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3665 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3666 "
3667 [(set_attr "length" "8")
331beb1a 3668 (set_attr "shift" "1")
0d66636f 3669 (set_attr "predicable" "yes")]
3670)
9c08d1fa 3671
3672(define_expand "zero_extendhisi2"
cffb2a26 3673 [(set (match_dup 2)
0d66636f 3674 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3675 (const_int 16)))
9c08d1fa 3676 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3677 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3678 "TARGET_EITHER"
9c08d1fa 3679 "
cffb2a26 3680 {
25f905c2 3681 if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3682 {
a2cd141b 3683 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3684 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3685 DONE;
cffb2a26 3686 }
cffb2a26 3687
c1a66faf 3688 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3689 {
3690 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3691 DONE;
3692 }
cffb2a26 3693
a2cd141b 3694 if (!s_register_operand (operands[1], HImode))
3695 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3696
a2cd141b 3697 if (arm_arch6)
3698 {
3699 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3700 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3701 DONE;
cffb2a26 3702 }
a2cd141b 3703
3704 operands[1] = gen_lowpart (SImode, operands[1]);
3705 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3706 }"
3707)
3708
25f905c2 3709(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 3710 [(set (match_operand:SI 0 "register_operand" "=l")
3711 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
25f905c2 3712 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 3713 "*
3714 rtx mem = XEXP (operands[1], 0);
3715
3716 if (GET_CODE (mem) == CONST)
3717 mem = XEXP (mem, 0);
3718
3719 if (GET_CODE (mem) == LABEL_REF)
3720 return \"ldr\\t%0, %1\";
3721
3722 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3723 {
cffb2a26 3724 rtx a = XEXP (mem, 0);
3725 rtx b = XEXP (mem, 1);
3726
3727 /* This can happen due to bugs in reload. */
3728 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3729 {
3730 rtx ops[2];
3731 ops[0] = operands[0];
3732 ops[1] = a;
3733
3734 output_asm_insn (\"mov %0, %1\", ops);
3735
3736 XEXP (mem, 0) = operands[0];
3737 }
3738
3739 else if ( GET_CODE (a) == LABEL_REF
3740 && GET_CODE (b) == CONST_INT)
3741 return \"ldr\\t%0, %1\";
25f7a26e 3742 }
cffb2a26 3743
3744 return \"ldrh\\t%0, %1\";
3745 "
3746 [(set_attr "length" "4")
a2cd141b 3747 (set_attr "type" "load_byte")
cffb2a26 3748 (set_attr "pool_range" "60")]
3749)
9c08d1fa 3750
25f905c2 3751(define_insn "*thumb1_zero_extendhisi2_v6"
a2cd141b 3752 [(set (match_operand:SI 0 "register_operand" "=l,l")
3753 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
25f905c2 3754 "TARGET_THUMB1 && arm_arch6"
a2cd141b 3755 "*
3756 rtx mem;
3757
3758 if (which_alternative == 0)
3759 return \"uxth\\t%0, %1\";
3760
3761 mem = XEXP (operands[1], 0);
3762
3763 if (GET_CODE (mem) == CONST)
3764 mem = XEXP (mem, 0);
3765
3766 if (GET_CODE (mem) == LABEL_REF)
3767 return \"ldr\\t%0, %1\";
3768
3769 if (GET_CODE (mem) == PLUS)
3770 {
3771 rtx a = XEXP (mem, 0);
3772 rtx b = XEXP (mem, 1);
3773
3774 /* This can happen due to bugs in reload. */
3775 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3776 {
3777 rtx ops[2];
3778 ops[0] = operands[0];
3779 ops[1] = a;
3780
3781 output_asm_insn (\"mov %0, %1\", ops);
3782
3783 XEXP (mem, 0) = operands[0];
3784 }
3785
3786 else if ( GET_CODE (a) == LABEL_REF
3787 && GET_CODE (b) == CONST_INT)
3788 return \"ldr\\t%0, %1\";
3789 }
3790
3791 return \"ldrh\\t%0, %1\";
3792 "
3793 [(set_attr "length" "2,4")
3794 (set_attr "type" "alu_shift,load_byte")
3795 (set_attr "pool_range" "*,60")]
3796)
3797
cffb2a26 3798(define_insn "*arm_zero_extendhisi2"
a2cd141b 3799 [(set (match_operand:SI 0 "s_register_operand" "=r")
3800 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3801 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 3802 "ldr%(h%)\\t%0, %1"
a2cd141b 3803 [(set_attr "type" "load_byte")
0d66636f 3804 (set_attr "predicable" "yes")
cffb2a26 3805 (set_attr "pool_range" "256")
3806 (set_attr "neg_pool_range" "244")]
3807)
f7fbdd4a 3808
a2cd141b 3809(define_insn "*arm_zero_extendhisi2_v6"
3810 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3811 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3812 "TARGET_ARM && arm_arch6"
3813 "@
3814 uxth%?\\t%0, %1
25f905c2 3815 ldr%(h%)\\t%0, %1"
a2cd141b 3816 [(set_attr "type" "alu_shift,load_byte")
3817 (set_attr "predicable" "yes")
3818 (set_attr "pool_range" "*,256")
3819 (set_attr "neg_pool_range" "*,244")]
3820)
3821
3822(define_insn "*arm_zero_extendhisi2addsi"
3823 [(set (match_operand:SI 0 "s_register_operand" "=r")
3824 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3825 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 3826 "TARGET_INT_SIMD"
a2cd141b 3827 "uxtah%?\\t%0, %2, %1"
3828 [(set_attr "type" "alu_shift")
3829 (set_attr "predicable" "yes")]
3830)
3831
87b22bf7 3832(define_expand "zero_extendqisi2"
cffb2a26 3833 [(set (match_operand:SI 0 "s_register_operand" "")
3834 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3835 "TARGET_EITHER"
87b22bf7 3836 "
a2cd141b 3837 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 3838 {
cffb2a26 3839 if (TARGET_ARM)
3840 {
215b30b3 3841 emit_insn (gen_andsi3 (operands[0],
3842 gen_lowpart (SImode, operands[1]),
cffb2a26 3843 GEN_INT (255)));
3844 }
3845 else /* TARGET_THUMB */
3846 {
3847 rtx temp = gen_reg_rtx (SImode);
3848 rtx ops[3];
3849
3850 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3851 operands[1] = gen_lowpart (SImode, operands[1]);
3852
3853 ops[0] = temp;
3854 ops[1] = operands[1];
3855 ops[2] = GEN_INT (24);
3856
215b30b3 3857 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3858 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3859
3860 ops[0] = operands[0];
3861 ops[1] = temp;
3862 ops[2] = GEN_INT (24);
3863
215b30b3 3864 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3865 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3866 }
87b22bf7 3867 DONE;
3868 }
215b30b3 3869 "
3870)
9c08d1fa 3871
25f905c2 3872(define_insn "*thumb1_zero_extendqisi2"
a2cd141b 3873 [(set (match_operand:SI 0 "register_operand" "=l")
3874 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
25f905c2 3875 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 3876 "ldrb\\t%0, %1"
3877 [(set_attr "length" "2")
a2cd141b 3878 (set_attr "type" "load_byte")
cffb2a26 3879 (set_attr "pool_range" "32")]
3880)
3881
25f905c2 3882(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 3883 [(set (match_operand:SI 0 "register_operand" "=l,l")
3884 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 3885 "TARGET_THUMB1 && arm_arch6"
a2cd141b 3886 "@
3887 uxtb\\t%0, %1
3888 ldrb\\t%0, %1"
3889 [(set_attr "length" "2,2")
3890 (set_attr "type" "alu_shift,load_byte")
3891 (set_attr "pool_range" "*,32")]
3892)
3893
cffb2a26 3894(define_insn "*arm_zero_extendqisi2"
a2cd141b 3895 [(set (match_operand:SI 0 "s_register_operand" "=r")
3896 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3897 "TARGET_ARM && !arm_arch6"
25f905c2 3898 "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 3899 [(set_attr "type" "load_byte")
0d66636f 3900 (set_attr "predicable" "yes")
cffb2a26 3901 (set_attr "pool_range" "4096")
3902 (set_attr "neg_pool_range" "4084")]
3903)
87b22bf7 3904
a2cd141b 3905(define_insn "*arm_zero_extendqisi2_v6"
3906 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3907 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3908 "TARGET_ARM && arm_arch6"
3909 "@
25f905c2 3910 uxtb%(%)\\t%0, %1
3911 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 3912 [(set_attr "type" "alu_shift,load_byte")
3913 (set_attr "predicable" "yes")
3914 (set_attr "pool_range" "*,4096")
3915 (set_attr "neg_pool_range" "*,4084")]
3916)
3917
3918(define_insn "*arm_zero_extendqisi2addsi"
3919 [(set (match_operand:SI 0 "s_register_operand" "=r")
3920 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3921 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 3922 "TARGET_INT_SIMD"
a2cd141b 3923 "uxtab%?\\t%0, %2, %1"
3924 [(set_attr "predicable" "yes")
bcaec148 3925 (set_attr "insn" "xtab")
a2cd141b 3926 (set_attr "type" "alu_shift")]
3927)
3928
87b22bf7 3929(define_split
3930 [(set (match_operand:SI 0 "s_register_operand" "")
3931 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3932 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 3933 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 3934 [(set (match_dup 2) (match_dup 1))
3935 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 3936 ""
3937)
9c08d1fa 3938
8a4d25d6 3939(define_split
3940 [(set (match_operand:SI 0 "s_register_operand" "")
3941 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3942 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 3943 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 3944 [(set (match_dup 2) (match_dup 1))
3945 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3946 ""
3947)
3948
f7fbdd4a 3949(define_insn "*compareqi_eq0"
bd5b4116 3950 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 3951 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 3952 (const_int 0)))]
25f905c2 3953 "TARGET_32BIT"
87b22bf7 3954 "tst\\t%0, #255"
cffb2a26 3955 [(set_attr "conds" "set")]
3956)
b11cae9e 3957
b11cae9e 3958(define_expand "extendhisi2"
c8f69309 3959 [(set (match_dup 2)
25f7a26e 3960 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 3961 (const_int 16)))
9c08d1fa 3962 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3963 (ashiftrt:SI (match_dup 2)
3964 (const_int 16)))]
cffb2a26 3965 "TARGET_EITHER"
b11cae9e 3966 "
cffb2a26 3967 {
a2cd141b 3968 if (GET_CODE (operands[1]) == MEM)
cffb2a26 3969 {
25f905c2 3970 if (TARGET_THUMB1)
a2cd141b 3971 {
25f905c2 3972 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 3973 DONE;
3974 }
3975 else if (arm_arch4)
3976 {
a2cd141b 3977 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3978 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3979 DONE;
3980 }
cffb2a26 3981 }
7bd8ccc9 3982
c1a66faf 3983 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 3984 {
3985 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3986 DONE;
3987 }
a2cd141b 3988
215b30b3 3989 if (!s_register_operand (operands[1], HImode))
cffb2a26 3990 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3991
a2cd141b 3992 if (arm_arch6)
cffb2a26 3993 {
25f905c2 3994 if (TARGET_THUMB1)
3995 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
a2cd141b 3996 else
3997 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3998 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3999
cffb2a26 4000 DONE;
4001 }
a2cd141b 4002
4003 operands[1] = gen_lowpart (SImode, operands[1]);
4004 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4005 }"
4006)
4007
25f905c2 4008(define_insn "thumb1_extendhisi2"
a2cd141b 4009 [(set (match_operand:SI 0 "register_operand" "=l")
4010 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4011 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4012 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4013 "*
4014 {
4015 rtx ops[4];
4016 rtx mem = XEXP (operands[1], 0);
4017
4018 /* This code used to try to use 'V', and fix the address only if it was
4019 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4020 range of QImode offsets, and offsettable_address_p does a QImode
4021 address check. */
4022
4023 if (GET_CODE (mem) == CONST)
4024 mem = XEXP (mem, 0);
4025
4026 if (GET_CODE (mem) == LABEL_REF)
4027 return \"ldr\\t%0, %1\";
4028
4029 if (GET_CODE (mem) == PLUS)
4030 {
4031 rtx a = XEXP (mem, 0);
4032 rtx b = XEXP (mem, 1);
4033
4034 if (GET_CODE (a) == LABEL_REF
4035 && GET_CODE (b) == CONST_INT)
4036 return \"ldr\\t%0, %1\";
4037
4038 if (GET_CODE (b) == REG)
4039 return \"ldrsh\\t%0, %1\";
4040
4041 ops[1] = a;
4042 ops[2] = b;
4043 }
4044 else
4045 {
4046 ops[1] = mem;
4047 ops[2] = const0_rtx;
4048 }
ed29c566 4049
4050 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 4051
4052 ops[0] = operands[0];
4053 ops[3] = operands[2];
4054 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4055 return \"\";
4056 }"
4057 [(set_attr "length" "4")
a2cd141b 4058 (set_attr "type" "load_byte")
cffb2a26 4059 (set_attr "pool_range" "1020")]
4060)
25f7a26e 4061
a2cd141b 4062;; We used to have an early-clobber on the scratch register here.
4063;; However, there's a bug somewhere in reload which means that this
4064;; can be partially ignored during spill allocation if the memory
ed29c566 4065;; address also needs reloading; this causes us to die later on when
a2cd141b 4066;; we try to verify the operands. Fortunately, we don't really need
4067;; the early-clobber: we can always use operand 0 if operand 2
4068;; overlaps the address.
25f905c2 4069(define_insn "*thumb1_extendhisi2_insn_v6"
a2cd141b 4070 [(set (match_operand:SI 0 "register_operand" "=l,l")
4071 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4072 (clobber (match_scratch:SI 2 "=X,l"))]
25f905c2 4073 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4074 "*
4075 {
4076 rtx ops[4];
4077 rtx mem;
4078
4079 if (which_alternative == 0)
4080 return \"sxth\\t%0, %1\";
4081
4082 mem = XEXP (operands[1], 0);
4083
4084 /* This code used to try to use 'V', and fix the address only if it was
4085 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4086 range of QImode offsets, and offsettable_address_p does a QImode
4087 address check. */
4088
4089 if (GET_CODE (mem) == CONST)
4090 mem = XEXP (mem, 0);
4091
4092 if (GET_CODE (mem) == LABEL_REF)
4093 return \"ldr\\t%0, %1\";
4094
4095 if (GET_CODE (mem) == PLUS)
4096 {
4097 rtx a = XEXP (mem, 0);
4098 rtx b = XEXP (mem, 1);
4099
4100 if (GET_CODE (a) == LABEL_REF
4101 && GET_CODE (b) == CONST_INT)
4102 return \"ldr\\t%0, %1\";
4103
4104 if (GET_CODE (b) == REG)
4105 return \"ldrsh\\t%0, %1\";
4106
4107 ops[1] = a;
4108 ops[2] = b;
4109 }
4110 else
4111 {
4112 ops[1] = mem;
4113 ops[2] = const0_rtx;
4114 }
4115
ed29c566 4116 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4117
4118 ops[0] = operands[0];
4119 if (reg_mentioned_p (operands[2], ops[1]))
4120 ops[3] = ops[0];
4121 else
4122 ops[3] = operands[2];
4123 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4124 return \"\";
4125 }"
4126 [(set_attr "length" "2,4")
4127 (set_attr "type" "alu_shift,load_byte")
4128 (set_attr "pool_range" "*,1020")]
4129)
4130
25f905c2 4131;; This pattern will only be used when ldsh is not available
25f7a26e 4132(define_expand "extendhisi2_mem"
eab14235 4133 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4134 (set (match_dup 3)
eab14235 4135 (zero_extend:SI (match_dup 7)))
25f7a26e 4136 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4137 (set (match_operand:SI 0 "" "")
4138 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4139 "TARGET_ARM"
25f7a26e 4140 "
215b30b3 4141 {
4142 rtx mem1, mem2;
4143 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4144
788fcce0 4145 mem1 = change_address (operands[1], QImode, addr);
4146 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4147 operands[0] = gen_lowpart (SImode, operands[0]);
4148 operands[1] = mem1;
4149 operands[2] = gen_reg_rtx (SImode);
4150 operands[3] = gen_reg_rtx (SImode);
4151 operands[6] = gen_reg_rtx (SImode);
4152 operands[7] = mem2;
25f7a26e 4153
215b30b3 4154 if (BYTES_BIG_ENDIAN)
4155 {
4156 operands[4] = operands[2];
4157 operands[5] = operands[3];
4158 }
4159 else
4160 {
4161 operands[4] = operands[3];
4162 operands[5] = operands[2];
4163 }
4164 }"
4165)
b11cae9e 4166
a2cd141b 4167(define_insn "*arm_extendhisi2"
4168 [(set (match_operand:SI 0 "s_register_operand" "=r")
4169 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4170 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4171 "ldr%(sh%)\\t%0, %1"
a2cd141b 4172 [(set_attr "type" "load_byte")
0d66636f 4173 (set_attr "predicable" "yes")
cffb2a26 4174 (set_attr "pool_range" "256")
4175 (set_attr "neg_pool_range" "244")]
4176)
f7fbdd4a 4177
25f905c2 4178;; ??? Check Thumb-2 pool range
a2cd141b 4179(define_insn "*arm_extendhisi2_v6"
4180 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4181 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4182 "TARGET_32BIT && arm_arch6"
a2cd141b 4183 "@
4184 sxth%?\\t%0, %1
25f905c2 4185 ldr%(sh%)\\t%0, %1"
a2cd141b 4186 [(set_attr "type" "alu_shift,load_byte")
4187 (set_attr "predicable" "yes")
4188 (set_attr "pool_range" "*,256")
4189 (set_attr "neg_pool_range" "*,244")]
4190)
4191
4192(define_insn "*arm_extendhisi2addsi"
4193 [(set (match_operand:SI 0 "s_register_operand" "=r")
4194 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4195 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4196 "TARGET_INT_SIMD"
a2cd141b 4197 "sxtah%?\\t%0, %2, %1"
4198)
4199
c8f69309 4200(define_expand "extendqihi2"
4201 [(set (match_dup 2)
f7fbdd4a 4202 (ashift:SI (match_operand:QI 1 "general_operand" "")
c8f69309 4203 (const_int 24)))
9c08d1fa 4204 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4205 (ashiftrt:SI (match_dup 2)
4206 (const_int 24)))]
cffb2a26 4207 "TARGET_ARM"
c8f69309 4208 "
215b30b3 4209 {
4210 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4211 {
4212 emit_insn (gen_rtx_SET (VOIDmode,
4213 operands[0],
4214 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4215 DONE;
4216 }
4217 if (!s_register_operand (operands[1], QImode))
4218 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4219 operands[0] = gen_lowpart (SImode, operands[0]);
4220 operands[1] = gen_lowpart (SImode, operands[1]);
4221 operands[2] = gen_reg_rtx (SImode);
4222 }"
4223)
f7fbdd4a 4224
25f905c2 4225(define_insn "*arm_extendqihi_insn"
b4e8a300 4226 [(set (match_operand:HI 0 "s_register_operand" "=r")
4227 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
cffb2a26 4228 "TARGET_ARM && arm_arch4"
25f905c2 4229 "ldr%(sb%)\\t%0, %1"
a2cd141b 4230 [(set_attr "type" "load_byte")
0d66636f 4231 (set_attr "predicable" "yes")
cffb2a26 4232 (set_attr "pool_range" "256")
4233 (set_attr "neg_pool_range" "244")]
4234)
3fc2009e 4235
b11cae9e 4236(define_expand "extendqisi2"
c8f69309 4237 [(set (match_dup 2)
3fc2009e 4238 (ashift:SI (match_operand:QI 1 "general_operand" "")
b11cae9e 4239 (const_int 24)))
9c08d1fa 4240 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 4241 (ashiftrt:SI (match_dup 2)
4242 (const_int 24)))]
cffb2a26 4243 "TARGET_EITHER"
b11cae9e 4244 "
cffb2a26 4245 {
a2cd141b 4246 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 4247 {
a2cd141b 4248 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 4249 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4250 DONE;
4251 }
a2cd141b 4252
215b30b3 4253 if (!s_register_operand (operands[1], QImode))
cffb2a26 4254 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 4255
a2cd141b 4256 if (arm_arch6)
4257 {
4258 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4259 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4260 DONE;
cffb2a26 4261 }
a2cd141b 4262
4263 operands[1] = gen_lowpart (SImode, operands[1]);
4264 operands[2] = gen_reg_rtx (SImode);
cffb2a26 4265 }"
4266)
f7fbdd4a 4267
a2cd141b 4268(define_insn "*arm_extendqisi"
4269 [(set (match_operand:SI 0 "s_register_operand" "=r")
b4e8a300 4270 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
a2cd141b 4271 "TARGET_ARM && arm_arch4 && !arm_arch6"
25f905c2 4272 "ldr%(sb%)\\t%0, %1"
a2cd141b 4273 [(set_attr "type" "load_byte")
0d66636f 4274 (set_attr "predicable" "yes")
cffb2a26 4275 (set_attr "pool_range" "256")
4276 (set_attr "neg_pool_range" "244")]
4277)
3fc2009e 4278
a2cd141b 4279(define_insn "*arm_extendqisi_v6"
4280 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
b4e8a300 4281 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
a2cd141b 4282 "TARGET_ARM && arm_arch6"
b4e8a300 4283 "@
4284 sxtb%?\\t%0, %1
25f905c2 4285 ldr%(sb%)\\t%0, %1"
a2cd141b 4286 [(set_attr "type" "alu_shift,load_byte")
4287 (set_attr "predicable" "yes")
a2cd141b 4288 (set_attr "pool_range" "*,256")
4289 (set_attr "neg_pool_range" "*,244")]
4290)
4291
4292(define_insn "*arm_extendqisi2addsi"
4293 [(set (match_operand:SI 0 "s_register_operand" "=r")
4294 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4295 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4296 "TARGET_INT_SIMD"
a2cd141b 4297 "sxtab%?\\t%0, %2, %1"
4298 [(set_attr "type" "alu_shift")
bcaec148 4299 (set_attr "insn" "xtab")
a2cd141b 4300 (set_attr "predicable" "yes")]
4301)
4302
25f905c2 4303(define_insn "*thumb1_extendqisi2"
a2cd141b 4304 [(set (match_operand:SI 0 "register_operand" "=l,l")
4305 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
25f905c2 4306 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 4307 "*
4308 {
4309 rtx ops[3];
4310 rtx mem = XEXP (operands[1], 0);
4311
4312 if (GET_CODE (mem) == CONST)
4313 mem = XEXP (mem, 0);
4314
4315 if (GET_CODE (mem) == LABEL_REF)
4316 return \"ldr\\t%0, %1\";
4317
4318 if (GET_CODE (mem) == PLUS
4319 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4320 return \"ldr\\t%0, %1\";
4321
4322 if (which_alternative == 0)
4323 return \"ldrsb\\t%0, %1\";
4324
4325 ops[0] = operands[0];
4326
4327 if (GET_CODE (mem) == PLUS)
4328 {
4329 rtx a = XEXP (mem, 0);
4330 rtx b = XEXP (mem, 1);
4331
4332 ops[1] = a;
4333 ops[2] = b;
4334
4335 if (GET_CODE (a) == REG)
4336 {
4337 if (GET_CODE (b) == REG)
4338 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4339 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 4340 {
4341 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4342 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4343 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4344 }
cffb2a26 4345 else
4346 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4347 }
cffb2a26 4348 else
4349 {
ed29c566 4350 gcc_assert (GET_CODE (b) == REG);
cffb2a26 4351 if (REGNO (b) == REGNO (ops[0]))
215b30b3 4352 {
4353 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4354 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4355 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4356 }
cffb2a26 4357 else
4358 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4359 }
4360 }
4361 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4362 {
215b30b3 4363 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4364 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4365 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 4366 }
4367 else
4368 {
4369 ops[1] = mem;
4370 ops[2] = const0_rtx;
4371
4372 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4373 }
4374 return \"\";
4375 }"
4376 [(set_attr "length" "2,6")
a2cd141b 4377 (set_attr "type" "load_byte,load_byte")
cffb2a26 4378 (set_attr "pool_range" "32,32")]
4379)
4380
25f905c2 4381(define_insn "*thumb1_extendqisi2_v6"
a2cd141b 4382 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4383 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
25f905c2 4384 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4385 "*
4386 {
4387 rtx ops[3];
4388 rtx mem;
4389
4390 if (which_alternative == 0)
4391 return \"sxtb\\t%0, %1\";
4392
4393 mem = XEXP (operands[1], 0);
4394
4395 if (GET_CODE (mem) == CONST)
4396 mem = XEXP (mem, 0);
4397
4398 if (GET_CODE (mem) == LABEL_REF)
4399 return \"ldr\\t%0, %1\";
4400
4401 if (GET_CODE (mem) == PLUS
4402 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4403 return \"ldr\\t%0, %1\";
4404
4405 if (which_alternative == 0)
4406 return \"ldrsb\\t%0, %1\";
4407
4408 ops[0] = operands[0];
4409
4410 if (GET_CODE (mem) == PLUS)
4411 {
4412 rtx a = XEXP (mem, 0);
4413 rtx b = XEXP (mem, 1);
4414
4415 ops[1] = a;
4416 ops[2] = b;
4417
4418 if (GET_CODE (a) == REG)
4419 {
4420 if (GET_CODE (b) == REG)
4421 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4422 else if (REGNO (a) == REGNO (ops[0]))
4423 {
4424 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4425 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4426 }
4427 else
4428 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4429 }
a2cd141b 4430 else
4431 {
ed29c566 4432 gcc_assert (GET_CODE (b) == REG);
a2cd141b 4433 if (REGNO (b) == REGNO (ops[0]))
4434 {
4435 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4436 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4437 }
4438 else
4439 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4440 }
4441 }
4442 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4443 {
4444 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4445 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4446 }
4447 else
4448 {
4449 ops[1] = mem;
4450 ops[2] = const0_rtx;
4451
4452 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4453 }
4454 return \"\";
4455 }"
4456 [(set_attr "length" "2,2,4")
4457 (set_attr "type" "alu_shift,load_byte,load_byte")
4458 (set_attr "pool_range" "*,32,32")]
4459)
4460
caedf871 4461(define_expand "extendsfdf2"
4462 [(set (match_operand:DF 0 "s_register_operand" "")
4463 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4464 "TARGET_32BIT && TARGET_HARD_FLOAT"
caedf871 4465 ""
4466)
b11cae9e 4467\f
4468;; Move insns (including loads and stores)
4469
4470;; XXX Just some ideas about movti.
9c08d1fa 4471;; I don't think these are a good idea on the arm, there just aren't enough
4472;; registers
b11cae9e 4473;;(define_expand "loadti"
9c08d1fa 4474;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4475;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4476;; "" "")
4477
4478;;(define_expand "storeti"
4479;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4480;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4481;; "" "")
4482
4483;;(define_expand "movti"
4484;; [(set (match_operand:TI 0 "general_operand" "")
4485;; (match_operand:TI 1 "general_operand" ""))]
4486;; ""
4487;; "
4488;;{
4489;; rtx insn;
4490;;
4491;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4492;; operands[1] = copy_to_reg (operands[1]);
4493;; if (GET_CODE (operands[0]) == MEM)
4494;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4495;; else if (GET_CODE (operands[1]) == MEM)
4496;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4497;; else
4498;; FAIL;
4499;;
4500;; emit_insn (insn);
4501;; DONE;
4502;;}")
4503
a2f10574 4504;; Recognize garbage generated above.
b11cae9e 4505
4506;;(define_insn ""
4507;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4508;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4509;; ""
4510;; "*
4511;; {
4512;; register mem = (which_alternative < 3);
0d66636f 4513;; register const char *template;
b11cae9e 4514;;
4515;; operands[mem] = XEXP (operands[mem], 0);
4516;; switch (which_alternative)
4517;; {
4518;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4519;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4520;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4521;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4522;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4523;; case 5: template = \"stmia\\t%0, %M1\"; break;
4524;; }
e2348bcb 4525;; output_asm_insn (template, operands);
4526;; return \"\";
b11cae9e 4527;; }")
4528
cffb2a26 4529(define_expand "movdi"
4530 [(set (match_operand:DI 0 "general_operand" "")
4531 (match_operand:DI 1 "general_operand" ""))]
4532 "TARGET_EITHER"
4533 "
e1ba4a27 4534 if (can_create_pseudo_p ())
cffb2a26 4535 {
b2778788 4536 if (GET_CODE (operands[0]) != REG)
4537 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4538 }
4539 "
4540)
b11cae9e 4541
cffb2a26 4542(define_insn "*arm_movdi"
d51f92df 4543 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4544 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4545 "TARGET_ARM
b2778788 4546 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4547 && !TARGET_IWMMXT
4548 && ( register_operand (operands[0], DImode)
4549 || register_operand (operands[1], DImode))"
b11cae9e 4550 "*
d51f92df 4551 switch (which_alternative)
4552 {
4553 case 0:
4554 case 1:
4555 case 2:
4556 return \"#\";
4557 default:
4558 return output_move_double (operands);
4559 }
cffb2a26 4560 "
359a6e9f 4561 [(set_attr "length" "8,12,16,8,8")
4562 (set_attr "type" "*,*,*,load2,store2")
4563 (set_attr "pool_range" "*,*,*,1020,*")
4564 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4565)
4566
d51f92df 4567(define_split
4568 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4569 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 4570 "TARGET_32BIT
d51f92df 4571 && reload_completed
4572 && (arm_const_double_inline_cost (operands[1])
4573 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4574 [(const_int 0)]
4575 "
4576 arm_split_constant (SET, SImode, curr_insn,
4577 INTVAL (gen_lowpart (SImode, operands[1])),
4578 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4579 arm_split_constant (SET, SImode, curr_insn,
4580 INTVAL (gen_highpart_mode (SImode,
4581 GET_MODE (operands[0]),
4582 operands[1])),
4583 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4584 DONE;
4585 "
4586)
4587
e5ba9289 4588; If optimizing for size, or if we have load delay slots, then
4589; we want to split the constant into two separate operations.
4590; In both cases this may split a trivial part into a single data op
4591; leaving a single complex constant to load. We can also get longer
4592; offsets in a LDR which means we get better chances of sharing the pool
4593; entries. Finally, we can normally do a better job of scheduling
4594; LDR instructions than we can with LDM.
4595; This pattern will only match if the one above did not.
4596(define_split
4597 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4598 (match_operand:ANY64 1 "const_double_operand" ""))]
4599 "TARGET_ARM && reload_completed
4600 && arm_const_double_by_parts (operands[1])"
4601 [(set (match_dup 0) (match_dup 1))
4602 (set (match_dup 2) (match_dup 3))]
4603 "
4604 operands[2] = gen_highpart (SImode, operands[0]);
4605 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4606 operands[1]);
4607 operands[0] = gen_lowpart (SImode, operands[0]);
4608 operands[1] = gen_lowpart (SImode, operands[1]);
4609 "
4610)
4611
d51f92df 4612(define_split
4613 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4614 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4615 "TARGET_EITHER && reload_completed"
4616 [(set (match_dup 0) (match_dup 1))
4617 (set (match_dup 2) (match_dup 3))]
4618 "
4619 operands[2] = gen_highpart (SImode, operands[0]);
4620 operands[3] = gen_highpart (SImode, operands[1]);
4621 operands[0] = gen_lowpart (SImode, operands[0]);
4622 operands[1] = gen_lowpart (SImode, operands[1]);
4623
4624 /* Handle a partial overlap. */
4625 if (rtx_equal_p (operands[0], operands[3]))
4626 {
4627 rtx tmp0 = operands[0];
4628 rtx tmp1 = operands[1];
4629
4630 operands[0] = operands[2];
4631 operands[1] = operands[3];
4632 operands[2] = tmp0;
4633 operands[3] = tmp1;
4634 }
4635 "
4636)
4637
a8a3b539 4638;; We can't actually do base+index doubleword loads if the index and
4639;; destination overlap. Split here so that we at least have chance to
4640;; schedule.
4641(define_split
4642 [(set (match_operand:DI 0 "s_register_operand" "")
4643 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4644 (match_operand:SI 2 "s_register_operand" ""))))]
4645 "TARGET_LDRD
4646 && reg_overlap_mentioned_p (operands[0], operands[1])
4647 && reg_overlap_mentioned_p (operands[0], operands[2])"
4648 [(set (match_dup 4)
4649 (plus:SI (match_dup 1)
4650 (match_dup 2)))
4651 (set (match_dup 0)
4652 (mem:DI (match_dup 4)))]
4653 "
4654 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4655 "
4656)
4657
cffb2a26 4658;;; ??? This should have alternatives for constants.
4659;;; ??? This was originally identical to the movdf_insn pattern.
4660;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4661;;; thumb_reorg with a memory reference.
25f905c2 4662(define_insn "*thumb1_movdi_insn"
215b30b3 4663 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4664 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 4665 "TARGET_THUMB1
a2cd141b 4666 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4667 && ( register_operand (operands[0], DImode)
4668 || register_operand (operands[1], DImode))"
4669 "*
4670 {
4671 switch (which_alternative)
4672 {
4673 default:
4674 case 0:
4675 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4676 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4677 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4678 case 1:
4679 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4680 case 2:
4681 operands[1] = GEN_INT (- INTVAL (operands[1]));
4682 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4683 case 3:
4684 return \"ldmia\\t%1, {%0, %H0}\";
4685 case 4:
4686 return \"stmia\\t%0, {%1, %H1}\";
4687 case 5:
4688 return thumb_load_double_from_address (operands);
4689 case 6:
1a83b3ff 4690 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4691 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4692 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4693 return \"\";
4694 case 7:
4695 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4696 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4697 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4698 }
4699 }"
4700 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4701 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4702 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4703)
b11cae9e 4704
9c08d1fa 4705(define_expand "movsi"
4706 [(set (match_operand:SI 0 "general_operand" "")
4707 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4708 "TARGET_EITHER"
9c08d1fa 4709 "
befb0bac 4710 {
e348ff3e 4711 rtx base, offset, tmp;
4712
25f905c2 4713 if (TARGET_32BIT)
9c08d1fa 4714 {
674a8f0b 4715 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4716 if (GET_CODE (operands[0]) == MEM)
4717 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4718 if (arm_general_register_operand (operands[0], SImode)
4719 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4720 && !(const_ok_for_arm (INTVAL (operands[1]))
4721 || const_ok_for_arm (~INTVAL (operands[1]))))
4722 {
96f57e36 4723 arm_split_constant (SET, SImode, NULL_RTX,
4724 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 4725 optimize && can_create_pseudo_p ());
cffb2a26 4726 DONE;
4727 }
4728 }
25f905c2 4729 else /* TARGET_THUMB1... */
cffb2a26 4730 {
e1ba4a27 4731 if (can_create_pseudo_p ())
cffb2a26 4732 {
4733 if (GET_CODE (operands[0]) != REG)
4734 operands[1] = force_reg (SImode, operands[1]);
4735 }
9c08d1fa 4736 }
f655717d 4737
e348ff3e 4738 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
4739 {
4740 split_const (operands[1], &base, &offset);
4741 if (GET_CODE (base) == SYMBOL_REF
4742 && !offset_within_block_p (base, INTVAL (offset)))
4743 {
b308ddcf 4744 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 4745 emit_move_insn (tmp, base);
4746 emit_insn (gen_addsi3 (operands[0], tmp, offset));
4747 DONE;
4748 }
4749 }
4750
f655717d 4751 /* Recognize the case where operand[1] is a reference to thread-local
4752 data and load its address to a register. */
4753 if (arm_tls_referenced_p (operands[1]))
4754 {
4755 rtx tmp = operands[1];
4756 rtx addend = NULL;
4757
4758 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4759 {
4760 addend = XEXP (XEXP (tmp, 0), 1);
4761 tmp = XEXP (XEXP (tmp, 0), 0);
4762 }
4763
4764 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4765 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4766
e1ba4a27 4767 tmp = legitimize_tls_address (tmp,
4768 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 4769 if (addend)
4770 {
4771 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4772 tmp = force_operand (tmp, operands[0]);
4773 }
4774 operands[1] = tmp;
4775 }
4776 else if (flag_pic
4777 && (CONSTANT_P (operands[1])
4778 || symbol_mentioned_p (operands[1])
4779 || label_mentioned_p (operands[1])))
4780 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 4781 (!can_create_pseudo_p ()
4782 ? operands[0]
4783 : 0));
befb0bac 4784 }
215b30b3 4785 "
4786)
9c08d1fa 4787
cffb2a26 4788(define_insn "*arm_movsi_insn"
25f905c2 4789 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r, m")
4790 (match_operand:SI 1 "general_operand" "rI,K,N,mi,r"))]
755eb2b4 4791 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 4792 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 4793 && ( register_operand (operands[0], SImode)
4794 || register_operand (operands[1], SImode))"
f7fbdd4a 4795 "@
4796 mov%?\\t%0, %1
4797 mvn%?\\t%0, #%B1
25f905c2 4798 movw%?\\t%0, %1
f7fbdd4a 4799 ldr%?\\t%0, %1
4800 str%?\\t%1, %0"
25f905c2 4801 [(set_attr "type" "*,*,*,load1,store1")
0d66636f 4802 (set_attr "predicable" "yes")
25f905c2 4803 (set_attr "pool_range" "*,*,*,4096,*")
4804 (set_attr "neg_pool_range" "*,*,*,4084,*")]
cffb2a26 4805)
87b22bf7 4806
4807(define_split
a2cd141b 4808 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 4809 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 4810 "TARGET_32BIT
215b30b3 4811 && (!(const_ok_for_arm (INTVAL (operands[1]))
4812 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 4813 [(clobber (const_int 0))]
4814 "
96f57e36 4815 arm_split_constant (SET, SImode, NULL_RTX,
4816 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 4817 DONE;
215b30b3 4818 "
4819)
9c08d1fa 4820
25f905c2 4821(define_insn "*thumb1_movsi_insn"
215b30b3 4822 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4823 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
25f905c2 4824 "TARGET_THUMB1
cffb2a26 4825 && ( register_operand (operands[0], SImode)
4826 || register_operand (operands[1], SImode))"
4827 "@
4828 mov %0, %1
4829 mov %0, %1
4830 #
4831 #
4832 ldmia\\t%1, {%0}
4833 stmia\\t%0, {%1}
4834 ldr\\t%0, %1
4835 str\\t%1, %0
4836 mov\\t%0, %1"
4837 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 4838 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 4839 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4840)
4841
4842(define_split
4843 [(set (match_operand:SI 0 "register_operand" "")
4844 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 4845 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
cffb2a26 4846 [(set (match_dup 0) (match_dup 1))
4847 (set (match_dup 0) (neg:SI (match_dup 0)))]
4848 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4849)
4850
4851(define_split
4852 [(set (match_operand:SI 0 "register_operand" "")
4853 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 4854 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
cffb2a26 4855 [(set (match_dup 0) (match_dup 1))
4856 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4857 "
4858 {
4859 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4860 unsigned HOST_WIDE_INT mask = 0xff;
4861 int i;
4862
4863 for (i = 0; i < 25; i++)
4864 if ((val & (mask << i)) == val)
4865 break;
4866
f5b3169c 4867 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 4868 if (i == 0)
4869 FAIL;
4870
4871 operands[1] = GEN_INT (val >> i);
4872 operands[2] = GEN_INT (i);
4873 }"
4874)
4875
67336bcf 4876;; When generating pic, we need to load the symbol offset into a register.
4877;; So that the optimizer does not confuse this with a normal symbol load
4878;; we use an unspec. The offset will be loaded from a constant pool entry,
4879;; since that is the only type of relocation we can use.
4880
4881;; The rather odd constraints on the following are to force reload to leave
4882;; the insn alone, and to force the minipool generation pass to then move
4883;; the GOT symbol to memory.
849170fd 4884
8c4d8060 4885(define_insn "pic_load_addr_arm"
849170fd 4886 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4887 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4888 "TARGET_ARM && flag_pic"
67336bcf 4889 "ldr%?\\t%0, %1"
a2cd141b 4890 [(set_attr "type" "load1")
8c4d8060 4891 (set (attr "pool_range") (const_int 4096))
4892 (set (attr "neg_pool_range") (const_int 4084))]
4893)
4894
25f905c2 4895(define_insn "pic_load_addr_thumb1"
8c4d8060 4896 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 4897 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 4898 "TARGET_THUMB1 && flag_pic"
8c4d8060 4899 "ldr\\t%0, %1"
a2cd141b 4900 [(set_attr "type" "load1")
8c4d8060 4901 (set (attr "pool_range") (const_int 1024))]
cffb2a26 4902)
849170fd 4903
cffb2a26 4904(define_insn "pic_add_dot_plus_four"
15d5d060 4905 [(set (match_operand:SI 0 "register_operand" "=r")
4906 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
beef0fb5 4907 (const (plus:SI (pc) (const_int 4))))
4908 (match_operand 2 "" "")]
4909 UNSPEC_PIC_BASE))]
25f905c2 4910 "TARGET_THUMB1"
cffb2a26 4911 "*
6cdcb15c 4912 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4913 INTVAL (operands[2]));
cffb2a26 4914 return \"add\\t%0, %|pc\";
4915 "
4916 [(set_attr "length" "2")]
4917)
849170fd 4918
4919(define_insn "pic_add_dot_plus_eight"
15d5d060 4920 [(set (match_operand:SI 0 "register_operand" "=r")
4921 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
beef0fb5 4922 (const (plus:SI (pc) (const_int 8))))
4923 (match_operand 2 "" "")]
4924 UNSPEC_PIC_BASE))]
f655717d 4925 "TARGET_ARM"
c4034607 4926 "*
6cdcb15c 4927 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4928 INTVAL (operands[2]));
15d5d060 4929 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 4930 "
0d66636f 4931 [(set_attr "predicable" "yes")]
cffb2a26 4932)
849170fd 4933
f655717d 4934(define_insn "tls_load_dot_plus_eight"
4935 [(set (match_operand:SI 0 "register_operand" "+r")
4936 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
beef0fb5 4937 (const (plus:SI (pc) (const_int 8))))
4938 (match_operand 2 "" "")]
4939 UNSPEC_PIC_BASE)))]
f655717d 4940 "TARGET_ARM"
4941 "*
6cdcb15c 4942 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4943 INTVAL (operands[2]));
f655717d 4944 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4945 "
4946 [(set_attr "predicable" "yes")]
4947)
4948
4949;; PIC references to local variables can generate pic_add_dot_plus_eight
4950;; followed by a load. These sequences can be crunched down to
4951;; tls_load_dot_plus_eight by a peephole.
4952
4953(define_peephole2
4954 [(parallel [(set (match_operand:SI 0 "register_operand" "")
15d5d060 4955 (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
f655717d 4956 (const (plus:SI (pc) (const_int 8))))]
4957 UNSPEC_PIC_BASE))
4958 (use (label_ref (match_operand 1 "" "")))])
4959 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4960 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
15d5d060 4961 [(parallel [(set (match_dup 2)
4962 (mem:SI (unspec:SI [(plus:SI (match_dup 3)
f655717d 4963 (const (plus:SI (pc) (const_int 8))))]
4964 UNSPEC_PIC_BASE)))
15d5d060 4965 (use (label_ref (match_dup 1)))])]
f655717d 4966 ""
4967)
4968
bac7fc85 4969(define_insn "pic_offset_arm"
4970 [(set (match_operand:SI 0 "register_operand" "=r")
4971 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
4972 (unspec:SI [(match_operand:SI 2 "" "X")]
4973 UNSPEC_PIC_OFFSET))))]
4974 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
4975 "ldr%?\\t%0, [%1,%2]"
4976 [(set_attr "type" "load1")]
4977)
4978
95373f08 4979(define_expand "builtin_setjmp_receiver"
4980 [(label_ref (match_operand 0 "" ""))]
4981 "flag_pic"
4982 "
4983{
b935b306 4984 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4985 register. */
2cb7d577 4986 if (arm_pic_register != INVALID_REGNUM)
4987 arm_load_pic_register (1UL << 3);
95373f08 4988 DONE;
4989}")
4990
9c08d1fa 4991;; If copying one reg to another we can set the condition codes according to
4992;; its value. Such a move is common after a return from subroutine and the
4993;; result is being tested against zero.
4994
f7fbdd4a 4995(define_insn "*movsi_compare0"
bd5b4116 4996 [(set (reg:CC CC_REGNUM)
cffb2a26 4997 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4998 (const_int 0)))
4999 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5000 (match_dup 1))]
25f905c2 5001 "TARGET_32BIT"
e2348bcb 5002 "@
40dbec34 5003 cmp%?\\t%0, #0
25f905c2 5004 sub%.\\t%0, %1, #0"
cffb2a26 5005 [(set_attr "conds" "set")]
5006)
b11cae9e 5007
b11cae9e 5008;; Subroutine to store a half word from a register into memory.
5009;; Operand 0 is the source register (HImode)
c8f69309 5010;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5011
9c08d1fa 5012;; In both this routine and the next, we must be careful not to spill
01cc3b75 5013;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5014;; can generate unrecognizable rtl.
5015
b11cae9e 5016(define_expand "storehi"
c8f69309 5017 [;; store the low byte
f082f1c4 5018 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5019 ;; extract the high byte
c8f69309 5020 (set (match_dup 2)
5021 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5022 ;; store the high byte
787f8210 5023 (set (match_dup 4) (match_dup 5))]
cffb2a26 5024 "TARGET_ARM"
b11cae9e 5025 "
215b30b3 5026 {
537ffcfc 5027 rtx op1 = operands[1];
5028 rtx addr = XEXP (op1, 0);
215b30b3 5029 enum rtx_code code = GET_CODE (addr);
5030
5031 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5032 || code == MINUS)
537ffcfc 5033 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5034
537ffcfc 5035 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5036 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5037 operands[3] = gen_lowpart (QImode, operands[0]);
5038 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5039 operands[2] = gen_reg_rtx (SImode);
5040 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5041 }"
5042)
b11cae9e 5043
c7597b5d 5044(define_expand "storehi_bigend"
f082f1c4 5045 [(set (match_dup 4) (match_dup 3))
c7597b5d 5046 (set (match_dup 2)
5047 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5048 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5049 "TARGET_ARM"
b11cae9e 5050 "
215b30b3 5051 {
537ffcfc 5052 rtx op1 = operands[1];
5053 rtx addr = XEXP (op1, 0);
215b30b3 5054 enum rtx_code code = GET_CODE (addr);
5055
5056 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5057 || code == MINUS)
537ffcfc 5058 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5059
537ffcfc 5060 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5061 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5062 operands[3] = gen_lowpart (QImode, operands[0]);
5063 operands[0] = gen_lowpart (SImode, operands[0]);
5064 operands[2] = gen_reg_rtx (SImode);
787f8210 5065 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5066 }"
5067)
c7597b5d 5068
5069;; Subroutine to store a half word integer constant into memory.
5070(define_expand "storeinthi"
f082f1c4 5071 [(set (match_operand 0 "" "")
787f8210 5072 (match_operand 1 "" ""))
9e8503e6 5073 (set (match_dup 3) (match_dup 2))]
cffb2a26 5074 "TARGET_ARM"
c7597b5d 5075 "
215b30b3 5076 {
5077 HOST_WIDE_INT value = INTVAL (operands[1]);
5078 rtx addr = XEXP (operands[0], 0);
537ffcfc 5079 rtx op0 = operands[0];
215b30b3 5080 enum rtx_code code = GET_CODE (addr);
c7597b5d 5081
215b30b3 5082 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5083 || code == MINUS)
537ffcfc 5084 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5085
215b30b3 5086 operands[1] = gen_reg_rtx (SImode);
5087 if (BYTES_BIG_ENDIAN)
5088 {
5089 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5090 if ((value & 255) == ((value >> 8) & 255))
5091 operands[2] = operands[1];
5092 else
5093 {
5094 operands[2] = gen_reg_rtx (SImode);
5095 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5096 }
5097 }
5098 else
5099 {
5100 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5101 if ((value & 255) == ((value >> 8) & 255))
5102 operands[2] = operands[1];
5103 else
5104 {
5105 operands[2] = gen_reg_rtx (SImode);
5106 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5107 }
5108 }
c7597b5d 5109
537ffcfc 5110 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5111 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5112 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5113 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5114 }"
5115)
b11cae9e 5116
f7fbdd4a 5117(define_expand "storehi_single_op"
5118 [(set (match_operand:HI 0 "memory_operand" "")
5119 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5120 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5121 "
215b30b3 5122 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5123 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5124 "
5125)
f7fbdd4a 5126
b11cae9e 5127(define_expand "movhi"
5128 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5129 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5130 "TARGET_EITHER"
b11cae9e 5131 "
cffb2a26 5132 if (TARGET_ARM)
b11cae9e 5133 {
e1ba4a27 5134 if (can_create_pseudo_p ())
cffb2a26 5135 {
5136 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5137 {
cffb2a26 5138 if (arm_arch4)
5139 {
5140 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5141 DONE;
5142 }
5143 if (GET_CODE (operands[1]) == CONST_INT)
5144 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5145 else
cffb2a26 5146 {
5147 if (GET_CODE (operands[1]) == MEM)
5148 operands[1] = force_reg (HImode, operands[1]);
5149 if (BYTES_BIG_ENDIAN)
5150 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5151 else
5152 emit_insn (gen_storehi (operands[1], operands[0]));
5153 }
5154 DONE;
b11cae9e 5155 }
cffb2a26 5156 /* Sign extend a constant, and keep it in an SImode reg. */
5157 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5158 {
cffb2a26 5159 rtx reg = gen_reg_rtx (SImode);
5160 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5161
5162 /* If the constant is already valid, leave it alone. */
215b30b3 5163 if (!const_ok_for_arm (val))
cffb2a26 5164 {
5165 /* If setting all the top bits will make the constant
5166 loadable in a single instruction, then set them.
5167 Otherwise, sign extend the number. */
5168
215b30b3 5169 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5170 val |= ~0xffff;
5171 else if (val & 0x8000)
5172 val |= ~0xffff;
5173 }
5174
5175 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5176 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5177 }
e1ba4a27 5178 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5179 && GET_CODE (operands[1]) == MEM)
5180 {
5181 rtx reg = gen_reg_rtx (SImode);
5182
5183 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5184 operands[1] = gen_lowpart (HImode, reg);
5185 }
215b30b3 5186 else if (!arm_arch4)
f7fbdd4a 5187 {
cffb2a26 5188 if (GET_CODE (operands[1]) == MEM)
5189 {
c1a66faf 5190 rtx base;
5191 rtx offset = const0_rtx;
5192 rtx reg = gen_reg_rtx (SImode);
5193
5194 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5195 || (GET_CODE (base) == PLUS
5196 && (GET_CODE (offset = XEXP (base, 1))
5197 == CONST_INT)
5198 && ((INTVAL(offset) & 1) != 1)
5199 && GET_CODE (base = XEXP (base, 0)) == REG))
5200 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5201 {
c1a66faf 5202 rtx new;
5203
788fcce0 5204 new = widen_memory_access (operands[1], SImode,
5205 ((INTVAL (offset) & ~3)
5206 - INTVAL (offset)));
c1a66faf 5207 emit_insn (gen_movsi (reg, new));
5208 if (((INTVAL (offset) & 2) != 0)
5209 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5210 {
5211 rtx reg2 = gen_reg_rtx (SImode);
5212
5213 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5214 reg = reg2;
5215 }
206ee9a2 5216 }
c1a66faf 5217 else
5218 emit_insn (gen_movhi_bytes (reg, operands[1]));
5219
5220 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5221 }
5222 }
5223 }
674a8f0b 5224 /* Handle loading a large integer during reload. */
cffb2a26 5225 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5226 && !const_ok_for_arm (INTVAL (operands[1]))
5227 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5228 {
5229 /* Writing a constant to memory needs a scratch, which should
5230 be handled with SECONDARY_RELOADs. */
ed29c566 5231 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5232
5233 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5234 emit_insn (gen_movsi (operands[0], operands[1]));
5235 DONE;
5236 }
5237 }
25f905c2 5238 else if (TARGET_THUMB2)
5239 {
5240 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5241 if (can_create_pseudo_p ())
25f905c2 5242 {
5243 if (GET_CODE (operands[0]) != REG)
5244 operands[1] = force_reg (HImode, operands[1]);
5245 /* Zero extend a constant, and keep it in an SImode reg. */
5246 else if (GET_CODE (operands[1]) == CONST_INT)
5247 {
5248 rtx reg = gen_reg_rtx (SImode);
5249 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5250
5251 emit_insn (gen_movsi (reg, GEN_INT (val)));
5252 operands[1] = gen_lowpart (HImode, reg);
5253 }
5254 }
5255 }
5256 else /* TARGET_THUMB1 */
cffb2a26 5257 {
e1ba4a27 5258 if (can_create_pseudo_p ())
cffb2a26 5259 {
6cffc037 5260 if (GET_CODE (operands[1]) == CONST_INT)
5261 {
5262 rtx reg = gen_reg_rtx (SImode);
5263
5264 emit_insn (gen_movsi (reg, operands[1]));
5265 operands[1] = gen_lowpart (HImode, reg);
5266 }
cffb2a26 5267
5268 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5269 happen if we are passed a SP (never OK for HImode/QImode) or
5270 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5271 HImode/QImode) relative address. */
cffb2a26 5272 /* ??? This should perhaps be fixed elsewhere, for instance, in
5273 fixup_stack_1, by checking for other kinds of invalid addresses,
5274 e.g. a bare reference to a virtual register. This may confuse the
5275 alpha though, which must handle this case differently. */
5276 if (GET_CODE (operands[0]) == MEM
215b30b3 5277 && !memory_address_p (GET_MODE (operands[0]),
5278 XEXP (operands[0], 0)))
537ffcfc 5279 operands[0]
5280 = replace_equiv_address (operands[0],
5281 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5282
5283 if (GET_CODE (operands[1]) == MEM
215b30b3 5284 && !memory_address_p (GET_MODE (operands[1]),
5285 XEXP (operands[1], 0)))
537ffcfc 5286 operands[1]
5287 = replace_equiv_address (operands[1],
5288 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5289
5290 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5291 {
5292 rtx reg = gen_reg_rtx (SImode);
5293
5294 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5295 operands[1] = gen_lowpart (HImode, reg);
5296 }
5297
5298 if (GET_CODE (operands[0]) == MEM)
5299 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5300 }
cffb2a26 5301 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 5302 && !satisfies_constraint_I (operands[1]))
cffb2a26 5303 {
6cffc037 5304 /* Handle loading a large integer during reload. */
5305
cffb2a26 5306 /* Writing a constant to memory needs a scratch, which should
5307 be handled with SECONDARY_RELOADs. */
ed29c566 5308 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5309
1a83b3ff 5310 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5311 emit_insn (gen_movsi (operands[0], operands[1]));
5312 DONE;
5313 }
b11cae9e 5314 }
cffb2a26 5315 "
5316)
5317
25f905c2 5318(define_insn "*thumb1_movhi_insn"
a941568e 5319 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5320 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 5321 "TARGET_THUMB1
cffb2a26 5322 && ( register_operand (operands[0], HImode)
5323 || register_operand (operands[1], HImode))"
5324 "*
5325 switch (which_alternative)
d79300ac 5326 {
cffb2a26 5327 case 0: return \"add %0, %1, #0\";
5328 case 2: return \"strh %1, %0\";
5329 case 3: return \"mov %0, %1\";
5330 case 4: return \"mov %0, %1\";
5331 case 5: return \"mov %0, %1\";
ed29c566 5332 default: gcc_unreachable ();
cffb2a26 5333 case 1:
5334 /* The stack pointer can end up being taken as an index register.
5335 Catch this case here and deal with it. */
5336 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5337 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5338 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5339 {
5340 rtx ops[2];
5341 ops[0] = operands[0];
5342 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5343
5344 output_asm_insn (\"mov %0, %1\", ops);
5345
5346 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5347
5348 }
5349 return \"ldrh %0, %1\";
5350 }"
5351 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 5352 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 5353)
d79300ac 5354
b11cae9e 5355
25f7a26e 5356(define_expand "movhi_bytes"
eab14235 5357 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5358 (set (match_dup 3)
eab14235 5359 (zero_extend:SI (match_dup 6)))
25f7a26e 5360 (set (match_operand:SI 0 "" "")
5361 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5362 "TARGET_ARM"
25f7a26e 5363 "
215b30b3 5364 {
5365 rtx mem1, mem2;
5366 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5367
788fcce0 5368 mem1 = change_address (operands[1], QImode, addr);
5369 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 5370 operands[0] = gen_lowpart (SImode, operands[0]);
5371 operands[1] = mem1;
5372 operands[2] = gen_reg_rtx (SImode);
5373 operands[3] = gen_reg_rtx (SImode);
5374 operands[6] = mem2;
25f7a26e 5375
215b30b3 5376 if (BYTES_BIG_ENDIAN)
5377 {
5378 operands[4] = operands[2];
5379 operands[5] = operands[3];
5380 }
5381 else
5382 {
5383 operands[4] = operands[3];
5384 operands[5] = operands[2];
5385 }
5386 }"
5387)
25f7a26e 5388
c7597b5d 5389(define_expand "movhi_bigend"
5390 [(set (match_dup 2)
5391 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5392 (const_int 16)))
5393 (set (match_dup 3)
5394 (ashiftrt:SI (match_dup 2) (const_int 16)))
5395 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 5396 (match_dup 4))]
cffb2a26 5397 "TARGET_ARM"
c7597b5d 5398 "
5399 operands[2] = gen_reg_rtx (SImode);
5400 operands[3] = gen_reg_rtx (SImode);
787f8210 5401 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5402 "
5403)
b11cae9e 5404
a2f10574 5405;; Pattern to recognize insn generated default case above
f7fbdd4a 5406(define_insn "*movhi_insn_arch4"
cffb2a26 5407 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 5408 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 5409 "TARGET_ARM
5410 && arm_arch4
f7fbdd4a 5411 && (GET_CODE (operands[1]) != CONST_INT
5412 || const_ok_for_arm (INTVAL (operands[1]))
5413 || const_ok_for_arm (~INTVAL (operands[1])))"
5414 "@
5415 mov%?\\t%0, %1\\t%@ movhi
5416 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 5417 str%(h%)\\t%1, %0\\t%@ movhi
5418 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 5419 [(set_attr "type" "*,*,store1,load1")
0d66636f 5420 (set_attr "predicable" "yes")
cffb2a26 5421 (set_attr "pool_range" "*,*,*,256")
5422 (set_attr "neg_pool_range" "*,*,*,244")]
5423)
f7fbdd4a 5424
f7fbdd4a 5425(define_insn "*movhi_bytes"
25f7a26e 5426 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5427 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 5428 "TARGET_ARM"
25f7a26e 5429 "@
5430 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5431 mvn%?\\t%0, #%B1\\t%@ movhi"
5432 [(set_attr "predicable" "yes")]
5433)
25f7a26e 5434
f90b51f1 5435(define_expand "thumb_movhi_clobber"
5436 [(set (match_operand:HI 0 "memory_operand" "")
5437 (match_operand:HI 1 "register_operand" ""))
5438 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 5439 "TARGET_THUMB1"
f90b51f1 5440 "
5441 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5442 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5443 {
5444 emit_insn (gen_movhi (operands[0], operands[1]));
5445 DONE;
5446 }
5447 /* XXX Fixme, need to handle other cases here as well. */
5448 gcc_unreachable ();
5449 "
cffb2a26 5450)
5451
bc5c7e08 5452;; We use a DImode scratch because we may occasionally need an additional
5453;; temporary if the address isn't offsettable -- push_reload doesn't seem
5454;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5455(define_expand "reload_outhi"
cffb2a26 5456 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5457 (match_operand:HI 1 "s_register_operand" "r")
5458 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5459 "TARGET_EITHER"
5460 "if (TARGET_ARM)
5461 arm_reload_out_hi (operands);
5462 else
5463 thumb_reload_out_hi (operands);
d3373b54 5464 DONE;
cffb2a26 5465 "
5466)
d3373b54 5467
25f7a26e 5468(define_expand "reload_inhi"
5469 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5470 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5471 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5472 "TARGET_EITHER"
25f7a26e 5473 "
cffb2a26 5474 if (TARGET_ARM)
5475 arm_reload_in_hi (operands);
5476 else
5477 thumb_reload_out_hi (operands);
25f7a26e 5478 DONE;
5479")
5480
9c08d1fa 5481(define_expand "movqi"
5482 [(set (match_operand:QI 0 "general_operand" "")
5483 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5484 "TARGET_EITHER"
9c08d1fa 5485 "
6cffc037 5486 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5487
e1ba4a27 5488 if (can_create_pseudo_p ())
cffb2a26 5489 {
6cffc037 5490 if (GET_CODE (operands[1]) == CONST_INT)
5491 {
5492 rtx reg = gen_reg_rtx (SImode);
5493
5494 emit_insn (gen_movsi (reg, operands[1]));
5495 operands[1] = gen_lowpart (QImode, reg);
5496 }
cffb2a26 5497
6cffc037 5498 if (TARGET_THUMB)
5499 {
cffb2a26 5500 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5501 happen if we are passed a SP (never OK for HImode/QImode) or
5502 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5503 HImode/QImode) relative address. */
cffb2a26 5504 /* ??? This should perhaps be fixed elsewhere, for instance, in
5505 fixup_stack_1, by checking for other kinds of invalid addresses,
5506 e.g. a bare reference to a virtual register. This may confuse the
5507 alpha though, which must handle this case differently. */
5508 if (GET_CODE (operands[0]) == MEM
215b30b3 5509 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5510 XEXP (operands[0], 0)))
537ffcfc 5511 operands[0]
5512 = replace_equiv_address (operands[0],
5513 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5514 if (GET_CODE (operands[1]) == MEM
5515 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5516 XEXP (operands[1], 0)))
537ffcfc 5517 operands[1]
5518 = replace_equiv_address (operands[1],
5519 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5520 }
5521
5522 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5523 {
5524 rtx reg = gen_reg_rtx (SImode);
5525
5526 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5527 operands[1] = gen_lowpart (QImode, reg);
5528 }
5529
5530 if (GET_CODE (operands[0]) == MEM)
5531 operands[1] = force_reg (QImode, operands[1]);
5532 }
5533 else if (TARGET_THUMB
5534 && GET_CODE (operands[1]) == CONST_INT
234f6557 5535 && !satisfies_constraint_I (operands[1]))
6cffc037 5536 {
674a8f0b 5537 /* Handle loading a large integer during reload. */
cffb2a26 5538
6cffc037 5539 /* Writing a constant to memory needs a scratch, which should
5540 be handled with SECONDARY_RELOADs. */
5541 gcc_assert (GET_CODE (operands[0]) == REG);
5542
5543 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5544 emit_insn (gen_movsi (operands[0], operands[1]));
5545 DONE;
cffb2a26 5546 }
5547 "
5548)
b11cae9e 5549
9c08d1fa 5550
cffb2a26 5551(define_insn "*arm_movqi_insn"
5552 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5553 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
25f905c2 5554 "TARGET_32BIT
cffb2a26 5555 && ( register_operand (operands[0], QImode)
5556 || register_operand (operands[1], QImode))"
5565501b 5557 "@
5558 mov%?\\t%0, %1
5559 mvn%?\\t%0, #%B1
25f905c2 5560 ldr%(b%)\\t%0, %1
5561 str%(b%)\\t%1, %0"
a2cd141b 5562 [(set_attr "type" "*,*,load1,store1")
0d66636f 5563 (set_attr "predicable" "yes")]
cffb2a26 5564)
5565
25f905c2 5566(define_insn "*thumb1_movqi_insn"
cffb2a26 5567 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5568 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 5569 "TARGET_THUMB1
cffb2a26 5570 && ( register_operand (operands[0], QImode)
5571 || register_operand (operands[1], QImode))"
5572 "@
5573 add\\t%0, %1, #0
5574 ldrb\\t%0, %1
5575 strb\\t%1, %0
5576 mov\\t%0, %1
5577 mov\\t%0, %1
5578 mov\\t%0, %1"
5579 [(set_attr "length" "2")
a2cd141b 5580 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5581 (set_attr "pool_range" "*,32,*,*,*,*")]
5582)
b11cae9e 5583
87b22bf7 5584(define_expand "movsf"
5585 [(set (match_operand:SF 0 "general_operand" "")
5586 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5587 "TARGET_EITHER"
87b22bf7 5588 "
25f905c2 5589 if (TARGET_32BIT)
cffb2a26 5590 {
5591 if (GET_CODE (operands[0]) == MEM)
5592 operands[1] = force_reg (SFmode, operands[1]);
5593 }
25f905c2 5594 else /* TARGET_THUMB1 */
cffb2a26 5595 {
e1ba4a27 5596 if (can_create_pseudo_p ())
cffb2a26 5597 {
5598 if (GET_CODE (operands[0]) != REG)
5599 operands[1] = force_reg (SFmode, operands[1]);
5600 }
5601 }
5602 "
5603)
5604
03d440a6 5605;; Transform a floating-point move of a constant into a core register into
5606;; an SImode operation.
cffb2a26 5607(define_split
03d440a6 5608 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 5609 (match_operand:SF 1 "immediate_operand" ""))]
25f905c2 5610 "TARGET_32BIT
cffb2a26 5611 && reload_completed
5612 && GET_CODE (operands[1]) == CONST_DOUBLE"
5613 [(set (match_dup 2) (match_dup 3))]
5614 "
5615 operands[2] = gen_lowpart (SImode, operands[0]);
5616 operands[3] = gen_lowpart (SImode, operands[1]);
5617 if (operands[2] == 0 || operands[3] == 0)
5618 FAIL;
215b30b3 5619 "
5620)
87b22bf7 5621
cffb2a26 5622(define_insn "*arm_movsf_soft_insn"
5623 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5624 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5625 "TARGET_ARM
5626 && TARGET_SOFT_FLOAT
215b30b3 5627 && (GET_CODE (operands[0]) != MEM
5628 || register_operand (operands[1], SFmode))"
9a1112d7 5629 "@
5630 mov%?\\t%0, %1
5631 ldr%?\\t%0, %1\\t%@ float
5632 str%?\\t%1, %0\\t%@ float"
cffb2a26 5633 [(set_attr "length" "4,4,4")
0d66636f 5634 (set_attr "predicable" "yes")
a2cd141b 5635 (set_attr "type" "*,load1,store1")
cffb2a26 5636 (set_attr "pool_range" "*,4096,*")
5637 (set_attr "neg_pool_range" "*,4084,*")]
5638)
5639
5640;;; ??? This should have alternatives for constants.
25f905c2 5641(define_insn "*thumb1_movsf_insn"
215b30b3 5642 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5643 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 5644 "TARGET_THUMB1
cffb2a26 5645 && ( register_operand (operands[0], SFmode)
5646 || register_operand (operands[1], SFmode))"
5647 "@
5648 add\\t%0, %1, #0
5649 ldmia\\t%1, {%0}
5650 stmia\\t%0, {%1}
5651 ldr\\t%0, %1
5652 str\\t%1, %0
5653 mov\\t%0, %1
5654 mov\\t%0, %1"
5655 [(set_attr "length" "2")
a2cd141b 5656 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 5657 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5658)
9a1112d7 5659
9c08d1fa 5660(define_expand "movdf"
87b22bf7 5661 [(set (match_operand:DF 0 "general_operand" "")
5662 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5663 "TARGET_EITHER"
9c08d1fa 5664 "
25f905c2 5665 if (TARGET_32BIT)
cffb2a26 5666 {
5667 if (GET_CODE (operands[0]) == MEM)
5668 operands[1] = force_reg (DFmode, operands[1]);
5669 }
5670 else /* TARGET_THUMB */
5671 {
e1ba4a27 5672 if (can_create_pseudo_p ())
cffb2a26 5673 {
5674 if (GET_CODE (operands[0]) != REG)
5675 operands[1] = force_reg (DFmode, operands[1]);
5676 }
5677 }
5678 "
5679)
b11cae9e 5680
9c08d1fa 5681;; Reloading a df mode value stored in integer regs to memory can require a
5682;; scratch reg.
5683(define_expand "reload_outdf"
cffb2a26 5684 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5685 (match_operand:DF 1 "s_register_operand" "r")
5686 (match_operand:SI 2 "s_register_operand" "=&r")]
25f905c2 5687 "TARGET_32BIT"
87b22bf7 5688 "
215b30b3 5689 {
5690 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5691
215b30b3 5692 if (code == REG)
5693 operands[2] = XEXP (operands[0], 0);
5694 else if (code == POST_INC || code == PRE_DEC)
5695 {
5696 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5697 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5698 emit_insn (gen_movdi (operands[0], operands[1]));
5699 DONE;
5700 }
5701 else if (code == PRE_INC)
5702 {
5703 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5704
215b30b3 5705 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5706 operands[2] = reg;
5707 }
5708 else if (code == POST_DEC)
5709 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5710 else
5711 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5712 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5713
788fcce0 5714 emit_insn (gen_rtx_SET (VOIDmode,
5715 replace_equiv_address (operands[0], operands[2]),
215b30b3 5716 operands[1]));
f7fbdd4a 5717
215b30b3 5718 if (code == POST_DEC)
5719 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5720
5721 DONE;
5722 }"
5723)
9c08d1fa 5724
9a1112d7 5725(define_insn "*movdf_soft_insn"
359a6e9f 5726 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5727 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 5728 "TARGET_ARM && TARGET_SOFT_FLOAT
b2778788 5729 && ( register_operand (operands[0], DFmode)
5730 || register_operand (operands[1], DFmode))"
d51f92df 5731 "*
5732 switch (which_alternative)
5733 {
5734 case 0:
5735 case 1:
5736 case 2:
5737 return \"#\";
5738 default:
5739 return output_move_double (operands);
5740 }
5741 "
359a6e9f 5742 [(set_attr "length" "8,12,16,8,8")
5743 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 5744 (set_attr "pool_range" "1020")
5745 (set_attr "neg_pool_range" "1008")]
cffb2a26 5746)
5747
5748;;; ??? This should have alternatives for constants.
5749;;; ??? This was originally identical to the movdi_insn pattern.
5750;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5751;;; thumb_reorg with a memory reference.
5752(define_insn "*thumb_movdf_insn"
215b30b3 5753 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5754 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 5755 "TARGET_THUMB1
cffb2a26 5756 && ( register_operand (operands[0], DFmode)
5757 || register_operand (operands[1], DFmode))"
5758 "*
5759 switch (which_alternative)
5760 {
5761 default:
5762 case 0:
5763 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5764 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5765 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5766 case 1:
5767 return \"ldmia\\t%1, {%0, %H0}\";
5768 case 2:
5769 return \"stmia\\t%0, {%1, %H1}\";
5770 case 3:
5771 return thumb_load_double_from_address (operands);
5772 case 4:
1a83b3ff 5773 operands[2] = gen_rtx_MEM (SImode,
5774 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5775 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5776 return \"\";
5777 case 5:
5778 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5779 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5780 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5781 }
5782 "
5783 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 5784 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 5785 (set_attr "pool_range" "*,*,*,1020,*,*")]
5786)
755eb2b4 5787
ccd90aaa 5788(define_expand "movxf"
5789 [(set (match_operand:XF 0 "general_operand" "")
5790 (match_operand:XF 1 "general_operand" ""))]
25f905c2 5791 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 5792 "
5793 if (GET_CODE (operands[0]) == MEM)
5794 operands[1] = force_reg (XFmode, operands[1]);
5795 "
5796)
5797
b11cae9e 5798\f
b11cae9e 5799
9c08d1fa 5800;; load- and store-multiple insns
5801;; The arm can load/store any set of registers, provided that they are in
5802;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 5803
9c08d1fa 5804(define_expand "load_multiple"
5805 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5806 (match_operand:SI 1 "" ""))
5807 (use (match_operand:SI 2 "" ""))])]
25f905c2 5808 "TARGET_32BIT"
9580c25f 5809{
5810 HOST_WIDE_INT offset = 0;
5811
bd5b4116 5812 /* Support only fixed point registers. */
9c08d1fa 5813 if (GET_CODE (operands[2]) != CONST_INT
5814 || INTVAL (operands[2]) > 14
5815 || INTVAL (operands[2]) < 2
5816 || GET_CODE (operands[1]) != MEM
5817 || GET_CODE (operands[0]) != REG
bd5b4116 5818 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5819 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5820 FAIL;
5821
5822 operands[3]
f082f1c4 5823 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5824 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 5825 TRUE, FALSE, operands[1], &offset);
5826})
b11cae9e 5827
9c08d1fa 5828;; Load multiple with write-back
5829
2162064c 5830(define_insn "*ldmsi_postinc4"
9c08d1fa 5831 [(match_parallel 0 "load_multiple_operation"
13e9316a 5832 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5833 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5834 (const_int 16)))
5835 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5836 (mem:SI (match_dup 2)))
a0a72ac3 5837 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 5838 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5839 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5840 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5841 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5842 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 5843 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5844 "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
a2cd141b 5845 [(set_attr "type" "load4")
2162064c 5846 (set_attr "predicable" "yes")]
5847)
b11cae9e 5848
25f905c2 5849(define_insn "*ldmsi_postinc4_thumb1"
ccd90aaa 5850 [(match_parallel 0 "load_multiple_operation"
5851 [(set (match_operand:SI 1 "s_register_operand" "=l")
5852 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5853 (const_int 16)))
5854 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5855 (mem:SI (match_dup 2)))
5856 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5857 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5858 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5859 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5860 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5861 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
25f905c2 5862 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 5863 "ldmia\\t%1!, {%3, %4, %5, %6}"
5864 [(set_attr "type" "load4")]
5865)
5866
2162064c 5867(define_insn "*ldmsi_postinc3"
5868 [(match_parallel 0 "load_multiple_operation"
13e9316a 5869 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5870 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5871 (const_int 12)))
5872 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5873 (mem:SI (match_dup 2)))
5874 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5875 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5876 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5877 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
25f905c2 5878 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5879 "ldm%(ia%)\\t%1!, {%3, %4, %5}"
a2cd141b 5880 [(set_attr "type" "load3")
2162064c 5881 (set_attr "predicable" "yes")]
5882)
b11cae9e 5883
2162064c 5884(define_insn "*ldmsi_postinc2"
5885 [(match_parallel 0 "load_multiple_operation"
13e9316a 5886 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5887 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5888 (const_int 8)))
5889 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5890 (mem:SI (match_dup 2)))
5891 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5892 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
25f905c2 5893 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5894 "ldm%(ia%)\\t%1!, {%3, %4}"
a2cd141b 5895 [(set_attr "type" "load2")
0d66636f 5896 (set_attr "predicable" "yes")]
5897)
b11cae9e 5898
9c08d1fa 5899;; Ordinary load multiple
b11cae9e 5900
2162064c 5901(define_insn "*ldmsi4"
9c08d1fa 5902 [(match_parallel 0 "load_multiple_operation"
2162064c 5903 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5904 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5905 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5906 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5907 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5908 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5909 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5910 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
25f905c2 5911 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5912 "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
a2cd141b 5913 [(set_attr "type" "load4")
2162064c 5914 (set_attr "predicable" "yes")]
5915)
9c08d1fa 5916
2162064c 5917(define_insn "*ldmsi3"
5918 [(match_parallel 0 "load_multiple_operation"
5919 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5920 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5921 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5922 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5923 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5924 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
25f905c2 5925 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5926 "ldm%(ia%)\\t%1, {%2, %3, %4}"
a2cd141b 5927 [(set_attr "type" "load3")
2162064c 5928 (set_attr "predicable" "yes")]
5929)
9c08d1fa 5930
2162064c 5931(define_insn "*ldmsi2"
5932 [(match_parallel 0 "load_multiple_operation"
5933 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5934 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5935 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5936 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
25f905c2 5937 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
5938 "ldm%(ia%)\\t%1, {%2, %3}"
a2cd141b 5939 [(set_attr "type" "load2")
0d66636f 5940 (set_attr "predicable" "yes")]
5941)
9c08d1fa 5942
5943(define_expand "store_multiple"
5944 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5945 (match_operand:SI 1 "" ""))
5946 (use (match_operand:SI 2 "" ""))])]
25f905c2 5947 "TARGET_32BIT"
9580c25f 5948{
5949 HOST_WIDE_INT offset = 0;
5950
674a8f0b 5951 /* Support only fixed point registers. */
9c08d1fa 5952 if (GET_CODE (operands[2]) != CONST_INT
5953 || INTVAL (operands[2]) > 14
5954 || INTVAL (operands[2]) < 2
5955 || GET_CODE (operands[1]) != REG
5956 || GET_CODE (operands[0]) != MEM
bd5b4116 5957 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5958 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5959 FAIL;
5960
5961 operands[3]
f082f1c4 5962 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5963 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 5964 TRUE, FALSE, operands[0], &offset);
5965})
b11cae9e 5966
9c08d1fa 5967;; Store multiple with write-back
5968
2162064c 5969(define_insn "*stmsi_postinc4"
9c08d1fa 5970 [(match_parallel 0 "store_multiple_operation"
13e9316a 5971 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5972 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5973 (const_int 16)))
a0a72ac3 5974 (set (mem:SI (match_dup 2))
2162064c 5975 (match_operand:SI 3 "arm_hard_register_operand" ""))
5976 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5977 (match_operand:SI 4 "arm_hard_register_operand" ""))
5978 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5979 (match_operand:SI 5 "arm_hard_register_operand" ""))
5980 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5981 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 5982 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5983 "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
2162064c 5984 [(set_attr "predicable" "yes")
5985 (set_attr "type" "store4")]
5986)
b11cae9e 5987
25f905c2 5988(define_insn "*stmsi_postinc4_thumb1"
ccd90aaa 5989 [(match_parallel 0 "store_multiple_operation"
5990 [(set (match_operand:SI 1 "s_register_operand" "=l")
5991 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5992 (const_int 16)))
5993 (set (mem:SI (match_dup 2))
5994 (match_operand:SI 3 "arm_hard_register_operand" ""))
5995 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5996 (match_operand:SI 4 "arm_hard_register_operand" ""))
5997 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5998 (match_operand:SI 5 "arm_hard_register_operand" ""))
5999 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6000 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
25f905c2 6001 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
ccd90aaa 6002 "stmia\\t%1!, {%3, %4, %5, %6}"
6003 [(set_attr "type" "store4")]
6004)
6005
2162064c 6006(define_insn "*stmsi_postinc3"
6007 [(match_parallel 0 "store_multiple_operation"
13e9316a 6008 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6009 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6010 (const_int 12)))
6011 (set (mem:SI (match_dup 2))
6012 (match_operand:SI 3 "arm_hard_register_operand" ""))
6013 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6014 (match_operand:SI 4 "arm_hard_register_operand" ""))
6015 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6016 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6017 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6018 "stm%(ia%)\\t%1!, {%3, %4, %5}"
2162064c 6019 [(set_attr "predicable" "yes")
6020 (set_attr "type" "store3")]
6021)
9c08d1fa 6022
2162064c 6023(define_insn "*stmsi_postinc2"
6024 [(match_parallel 0 "store_multiple_operation"
13e9316a 6025 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 6026 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6027 (const_int 8)))
6028 (set (mem:SI (match_dup 2))
6029 (match_operand:SI 3 "arm_hard_register_operand" ""))
6030 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6031 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6032 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6033 "stm%(ia%)\\t%1!, {%3, %4}"
0d66636f 6034 [(set_attr "predicable" "yes")
2162064c 6035 (set_attr "type" "store2")]
cffb2a26 6036)
9c08d1fa 6037
6038;; Ordinary store multiple
6039
2162064c 6040(define_insn "*stmsi4"
9c08d1fa 6041 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 6042 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 6043 (match_operand:SI 2 "arm_hard_register_operand" ""))
6044 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6045 (match_operand:SI 3 "arm_hard_register_operand" ""))
6046 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6047 (match_operand:SI 4 "arm_hard_register_operand" ""))
6048 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6049 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
25f905c2 6050 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6051 "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
2162064c 6052 [(set_attr "predicable" "yes")
6053 (set_attr "type" "store4")]
6054)
9c08d1fa 6055
2162064c 6056(define_insn "*stmsi3"
6057 [(match_parallel 0 "store_multiple_operation"
6058 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6059 (match_operand:SI 2 "arm_hard_register_operand" ""))
6060 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6061 (match_operand:SI 3 "arm_hard_register_operand" ""))
6062 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6063 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
25f905c2 6064 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6065 "stm%(ia%)\\t%1, {%2, %3, %4}"
2162064c 6066 [(set_attr "predicable" "yes")
6067 (set_attr "type" "store3")]
6068)
9c08d1fa 6069
2162064c 6070(define_insn "*stmsi2"
6071 [(match_parallel 0 "store_multiple_operation"
6072 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6073 (match_operand:SI 2 "arm_hard_register_operand" ""))
6074 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6075 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
25f905c2 6076 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6077 "stm%(ia%)\\t%1, {%2, %3}"
0d66636f 6078 [(set_attr "predicable" "yes")
2162064c 6079 (set_attr "type" "store2")]
cffb2a26 6080)
9c08d1fa 6081
6082;; Move a block of memory if it is word aligned and MORE than 2 words long.
6083;; We could let this apply for blocks of less than this, but it clobbers so
6084;; many registers that there is then probably a better way.
6085
008c057d 6086(define_expand "movmemqi"
34191dd1 6087 [(match_operand:BLK 0 "general_operand" "")
6088 (match_operand:BLK 1 "general_operand" "")
6089 (match_operand:SI 2 "const_int_operand" "")
6090 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6091 "TARGET_EITHER"
9c08d1fa 6092 "
25f905c2 6093 if (TARGET_32BIT)
cffb2a26 6094 {
008c057d 6095 if (arm_gen_movmemqi (operands))
cffb2a26 6096 DONE;
6097 FAIL;
6098 }
25f905c2 6099 else /* TARGET_THUMB1 */
cffb2a26 6100 {
6101 if ( INTVAL (operands[3]) != 4
6102 || INTVAL (operands[2]) > 48)
6103 FAIL;
6104
008c057d 6105 thumb_expand_movmemqi (operands);
cffb2a26 6106 DONE;
6107 }
6108 "
6109)
6110
2162064c 6111;; Thumb block-move insns
cffb2a26 6112
6113(define_insn "movmem12b"
960f3acf 6114 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6115 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6116 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6117 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6118 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6119 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6120 (set (match_operand:SI 0 "register_operand" "=l")
6121 (plus:SI (match_dup 2) (const_int 12)))
6122 (set (match_operand:SI 1 "register_operand" "=l")
6123 (plus:SI (match_dup 3) (const_int 12)))
6124 (clobber (match_scratch:SI 4 "=&l"))
6125 (clobber (match_scratch:SI 5 "=&l"))
6126 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6127 "TARGET_THUMB1"
cffb2a26 6128 "* return thumb_output_move_mem_multiple (3, operands);"
6129 [(set_attr "length" "4")
215b30b3 6130 ; This isn't entirely accurate... It loads as well, but in terms of
6131 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6132 (set_attr "type" "store3")]
6133)
6134
6135(define_insn "movmem8b"
960f3acf 6136 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6137 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6138 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6139 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6140 (set (match_operand:SI 0 "register_operand" "=l")
6141 (plus:SI (match_dup 2) (const_int 8)))
6142 (set (match_operand:SI 1 "register_operand" "=l")
6143 (plus:SI (match_dup 3) (const_int 8)))
6144 (clobber (match_scratch:SI 4 "=&l"))
6145 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6146 "TARGET_THUMB1"
cffb2a26 6147 "* return thumb_output_move_mem_multiple (2, operands);"
6148 [(set_attr "length" "4")
215b30b3 6149 ; This isn't entirely accurate... It loads as well, but in terms of
6150 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6151 (set_attr "type" "store2")]
6152)
6153
9c08d1fa 6154\f
b11cae9e 6155
341940e8 6156;; Compare & branch insns
8d232dc7 6157;; The range calculations are based as follows:
341940e8 6158;; For forward branches, the address calculation returns the address of
6159;; the next instruction. This is 2 beyond the branch instruction.
6160;; For backward branches, the address calculation returns the address of
6161;; the first instruction in this pattern (cmp). This is 2 before the branch
6162;; instruction for the shortest sequence, and 4 before the branch instruction
6163;; if we have to jump around an unconditional branch.
6164;; To the basic branch range the PC offset must be added (this is +4).
6165;; So for forward branches we have
6166;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6167;; And for backward branches we have
6168;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6169;;
6170;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6171;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6172
aeac46d4 6173(define_expand "cbranchsi4"
6174 [(set (pc) (if_then_else
6175 (match_operator 0 "arm_comparison_operator"
6176 [(match_operand:SI 1 "s_register_operand" "")
6177 (match_operand:SI 2 "nonmemory_operand" "")])
6178 (label_ref (match_operand 3 "" ""))
6179 (pc)))]
25f905c2 6180 "TARGET_THUMB1"
aeac46d4 6181 "
25f905c2 6182 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6183 {
6184 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6185 operands[3], operands[0]));
6186 DONE;
6187 }
25f905c2 6188 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6189 operands[2] = force_reg (SImode, operands[2]);
6190 ")
6191
6192(define_insn "*cbranchsi4_insn"
6193 [(set (pc) (if_then_else
6194 (match_operator 0 "arm_comparison_operator"
6195 [(match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 6196 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6197 (label_ref (match_operand 3 "" ""))
6198 (pc)))]
25f905c2 6199 "TARGET_THUMB1"
cffb2a26 6200 "*
6201 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 6202
cffb2a26 6203 switch (get_attr_length (insn))
6204 {
6205 case 4: return \"b%d0\\t%l3\";
6206 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6207 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6208 }
6209 "
6210 [(set (attr "far_jump")
6211 (if_then_else
6212 (eq_attr "length" "8")
6213 (const_string "yes")
6214 (const_string "no")))
6215 (set (attr "length")
6216 (if_then_else
6217 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6218 (le (minus (match_dup 3) (pc)) (const_int 256)))
6219 (const_int 4)
6220 (if_then_else
6221 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6222 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6223 (const_int 6)
6224 (const_int 8))))]
6225)
6226
aeac46d4 6227(define_insn "cbranchsi4_scratch"
6228 [(set (pc) (if_then_else
6229 (match_operator 4 "arm_comparison_operator"
6230 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6231 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6232 (label_ref (match_operand 3 "" ""))
6233 (pc)))
6234 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6235 "TARGET_THUMB1"
aeac46d4 6236 "*
6237 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6238
6239 switch (get_attr_length (insn))
6240 {
6241 case 4: return \"b%d4\\t%l3\";
6242 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6243 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6244 }
6245 "
6246 [(set (attr "far_jump")
6247 (if_then_else
6248 (eq_attr "length" "8")
6249 (const_string "yes")
6250 (const_string "no")))
6251 (set (attr "length")
6252 (if_then_else
6253 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6254 (le (minus (match_dup 3) (pc)) (const_int 256)))
6255 (const_int 4)
6256 (if_then_else
6257 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6258 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6259 (const_int 6)
6260 (const_int 8))))]
6261)
6262(define_insn "*movsi_cbranchsi4"
6263 [(set (pc)
6264 (if_then_else
6265 (match_operator 3 "arm_comparison_operator"
6266 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6267 (const_int 0)])
6268 (label_ref (match_operand 2 "" ""))
6269 (pc)))
6270 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6271 (match_dup 1))]
25f905c2 6272 "TARGET_THUMB1"
aeac46d4 6273 "*{
6274 if (which_alternative == 0)
6275 output_asm_insn (\"cmp\t%0, #0\", operands);
6276 else if (which_alternative == 1)
6277 output_asm_insn (\"sub\t%0, %1, #0\", operands);
6278 else
6279 {
6280 output_asm_insn (\"cmp\t%1, #0\", operands);
6281 if (which_alternative == 2)
6282 output_asm_insn (\"mov\t%0, %1\", operands);
6283 else
6284 output_asm_insn (\"str\t%1, %0\", operands);
6285 }
6286 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6287 {
6288 case 4: return \"b%d3\\t%l2\";
6289 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6290 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6291 }
6292 }"
6293 [(set (attr "far_jump")
6294 (if_then_else
6295 (ior (and (gt (symbol_ref ("which_alternative"))
6296 (const_int 1))
6297 (eq_attr "length" "8"))
6298 (eq_attr "length" "10"))
6299 (const_string "yes")
6300 (const_string "no")))
6301 (set (attr "length")
6302 (if_then_else
6303 (le (symbol_ref ("which_alternative"))
6304 (const_int 1))
6305 (if_then_else
6306 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6307 (le (minus (match_dup 2) (pc)) (const_int 256)))
6308 (const_int 4)
6309 (if_then_else
6310 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6311 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6312 (const_int 6)
6313 (const_int 8)))
6314 (if_then_else
6315 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6316 (le (minus (match_dup 2) (pc)) (const_int 256)))
6317 (const_int 6)
6318 (if_then_else
6319 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6320 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6321 (const_int 8)
6322 (const_int 10)))))]
6323)
6324
cffb2a26 6325(define_insn "*negated_cbranchsi4"
6326 [(set (pc)
6327 (if_then_else
aed179ae 6328 (match_operator 0 "equality_operator"
aeac46d4 6329 [(match_operand:SI 1 "s_register_operand" "l")
6330 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6331 (label_ref (match_operand 3 "" ""))
215b30b3 6332 (pc)))]
25f905c2 6333 "TARGET_THUMB1"
cffb2a26 6334 "*
6335 output_asm_insn (\"cmn\\t%1, %2\", operands);
6336 switch (get_attr_length (insn))
6337 {
6338 case 4: return \"b%d0\\t%l3\";
6339 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6340 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6341 }
6342 "
6343 [(set (attr "far_jump")
6344 (if_then_else
6345 (eq_attr "length" "8")
6346 (const_string "yes")
6347 (const_string "no")))
6348 (set (attr "length")
6349 (if_then_else
6350 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 6351 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 6352 (const_int 4)
6353 (if_then_else
341940e8 6354 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6355 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6356 (const_int 6)
6357 (const_int 8))))]
6358)
6359
58d6528b 6360(define_insn "*tbit_cbranch"
6361 [(set (pc)
6362 (if_then_else
6363 (match_operator 0 "equality_operator"
6364 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6365 (const_int 1)
6366 (match_operand:SI 2 "const_int_operand" "i"))
6367 (const_int 0)])
6368 (label_ref (match_operand 3 "" ""))
6369 (pc)))
6370 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6371 "TARGET_THUMB1"
58d6528b 6372 "*
6373 {
6374 rtx op[3];
6375 op[0] = operands[4];
6376 op[1] = operands[1];
6377 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6378
86efa74d 6379 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6380 switch (get_attr_length (insn))
6381 {
6382 case 4: return \"b%d0\\t%l3\";
6383 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6384 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6385 }
6386 }"
6387 [(set (attr "far_jump")
6388 (if_then_else
6389 (eq_attr "length" "8")
6390 (const_string "yes")
6391 (const_string "no")))
6392 (set (attr "length")
6393 (if_then_else
6394 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6395 (le (minus (match_dup 3) (pc)) (const_int 256)))
6396 (const_int 4)
6397 (if_then_else
6398 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6399 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6400 (const_int 6)
6401 (const_int 8))))]
6402)
6403
6404(define_insn "*tlobits_cbranch"
6405 [(set (pc)
6406 (if_then_else
6407 (match_operator 0 "equality_operator"
6408 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6409 (match_operand:SI 2 "const_int_operand" "i")
6410 (const_int 0))
6411 (const_int 0)])
6412 (label_ref (match_operand 3 "" ""))
6413 (pc)))
6414 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 6415 "TARGET_THUMB1"
86efa74d 6416 "*
6417 {
6418 rtx op[3];
6419 op[0] = operands[4];
6420 op[1] = operands[1];
6421 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6422
58d6528b 6423 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6424 switch (get_attr_length (insn))
6425 {
6426 case 4: return \"b%d0\\t%l3\";
6427 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6428 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6429 }
6430 }"
6431 [(set (attr "far_jump")
6432 (if_then_else
6433 (eq_attr "length" "8")
6434 (const_string "yes")
6435 (const_string "no")))
6436 (set (attr "length")
6437 (if_then_else
6438 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6439 (le (minus (match_dup 3) (pc)) (const_int 256)))
6440 (const_int 4)
6441 (if_then_else
6442 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6443 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6444 (const_int 6)
6445 (const_int 8))))]
6446)
6447
aeac46d4 6448(define_insn "*tstsi3_cbranch"
58d6528b 6449 [(set (pc)
6450 (if_then_else
aeac46d4 6451 (match_operator 3 "equality_operator"
6452 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6453 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 6454 (const_int 0)])
aeac46d4 6455 (label_ref (match_operand 2 "" ""))
6456 (pc)))]
25f905c2 6457 "TARGET_THUMB1"
58d6528b 6458 "*
6459 {
aeac46d4 6460 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 6461 switch (get_attr_length (insn))
6462 {
aeac46d4 6463 case 4: return \"b%d3\\t%l2\";
6464 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6465 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 6466 }
6467 }"
6468 [(set (attr "far_jump")
6469 (if_then_else
6470 (eq_attr "length" "8")
6471 (const_string "yes")
6472 (const_string "no")))
6473 (set (attr "length")
6474 (if_then_else
aeac46d4 6475 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6476 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 6477 (const_int 4)
6478 (if_then_else
aeac46d4 6479 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6480 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6481 (const_int 6)
6482 (const_int 8))))]
6483)
6484
6485(define_insn "*andsi3_cbranch"
6486 [(set (pc)
6487 (if_then_else
6488 (match_operator 5 "equality_operator"
6489 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6490 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6491 (const_int 0)])
6492 (label_ref (match_operand 4 "" ""))
6493 (pc)))
aeac46d4 6494 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6495 (and:SI (match_dup 2) (match_dup 3)))
6496 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6497 "TARGET_THUMB1"
58d6528b 6498 "*
6499 {
6500 if (which_alternative == 0)
6501 output_asm_insn (\"and\\t%0, %3\", operands);
6502 else if (which_alternative == 1)
6503 {
6504 output_asm_insn (\"and\\t%1, %3\", operands);
6505 output_asm_insn (\"mov\\t%0, %1\", operands);
6506 }
6507 else
6508 {
6509 output_asm_insn (\"and\\t%1, %3\", operands);
6510 output_asm_insn (\"str\\t%1, %0\", operands);
6511 }
6512
6513 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6514 {
6515 case 4: return \"b%d5\\t%l4\";
6516 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6517 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6518 }
6519 }"
6520 [(set (attr "far_jump")
6521 (if_then_else
6522 (ior (and (eq (symbol_ref ("which_alternative"))
6523 (const_int 0))
6524 (eq_attr "length" "8"))
6525 (eq_attr "length" "10"))
6526 (const_string "yes")
6527 (const_string "no")))
6528 (set (attr "length")
6529 (if_then_else
6530 (eq (symbol_ref ("which_alternative"))
6531 (const_int 0))
6532 (if_then_else
6533 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6534 (le (minus (match_dup 4) (pc)) (const_int 256)))
6535 (const_int 4)
6536 (if_then_else
6537 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6538 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6539 (const_int 6)
6540 (const_int 8)))
6541 (if_then_else
6542 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6543 (le (minus (match_dup 4) (pc)) (const_int 256)))
6544 (const_int 6)
6545 (if_then_else
6546 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6547 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6548 (const_int 8)
6549 (const_int 10)))))]
6550)
6551
6552(define_insn "*orrsi3_cbranch_scratch"
6553 [(set (pc)
6554 (if_then_else
6555 (match_operator 4 "equality_operator"
6556 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6557 (match_operand:SI 2 "s_register_operand" "l"))
6558 (const_int 0)])
6559 (label_ref (match_operand 3 "" ""))
6560 (pc)))
6561 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 6562 "TARGET_THUMB1"
58d6528b 6563 "*
6564 {
6565 output_asm_insn (\"orr\\t%0, %2\", operands);
6566 switch (get_attr_length (insn))
6567 {
6568 case 4: return \"b%d4\\t%l3\";
6569 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6570 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6571 }
6572 }"
6573 [(set (attr "far_jump")
6574 (if_then_else
6575 (eq_attr "length" "8")
6576 (const_string "yes")
6577 (const_string "no")))
6578 (set (attr "length")
6579 (if_then_else
6580 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6581 (le (minus (match_dup 3) (pc)) (const_int 256)))
6582 (const_int 4)
6583 (if_then_else
6584 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6585 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6586 (const_int 6)
6587 (const_int 8))))]
6588)
6589
6590(define_insn "*orrsi3_cbranch"
6591 [(set (pc)
6592 (if_then_else
6593 (match_operator 5 "equality_operator"
6594 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6595 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6596 (const_int 0)])
6597 (label_ref (match_operand 4 "" ""))
6598 (pc)))
aeac46d4 6599 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6600 (ior:SI (match_dup 2) (match_dup 3)))
6601 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6602 "TARGET_THUMB1"
58d6528b 6603 "*
6604 {
6605 if (which_alternative == 0)
6606 output_asm_insn (\"orr\\t%0, %3\", operands);
6607 else if (which_alternative == 1)
6608 {
6609 output_asm_insn (\"orr\\t%1, %3\", operands);
6610 output_asm_insn (\"mov\\t%0, %1\", operands);
6611 }
6612 else
6613 {
6614 output_asm_insn (\"orr\\t%1, %3\", operands);
6615 output_asm_insn (\"str\\t%1, %0\", operands);
6616 }
6617
6618 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6619 {
6620 case 4: return \"b%d5\\t%l4\";
6621 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6622 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6623 }
6624 }"
6625 [(set (attr "far_jump")
6626 (if_then_else
6627 (ior (and (eq (symbol_ref ("which_alternative"))
6628 (const_int 0))
6629 (eq_attr "length" "8"))
6630 (eq_attr "length" "10"))
6631 (const_string "yes")
6632 (const_string "no")))
6633 (set (attr "length")
6634 (if_then_else
6635 (eq (symbol_ref ("which_alternative"))
6636 (const_int 0))
6637 (if_then_else
6638 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6639 (le (minus (match_dup 4) (pc)) (const_int 256)))
6640 (const_int 4)
6641 (if_then_else
6642 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6643 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6644 (const_int 6)
6645 (const_int 8)))
6646 (if_then_else
6647 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6648 (le (minus (match_dup 4) (pc)) (const_int 256)))
6649 (const_int 6)
6650 (if_then_else
6651 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6652 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6653 (const_int 8)
6654 (const_int 10)))))]
6655)
6656
6657(define_insn "*xorsi3_cbranch_scratch"
6658 [(set (pc)
6659 (if_then_else
6660 (match_operator 4 "equality_operator"
6661 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6662 (match_operand:SI 2 "s_register_operand" "l"))
6663 (const_int 0)])
6664 (label_ref (match_operand 3 "" ""))
6665 (pc)))
6666 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 6667 "TARGET_THUMB1"
58d6528b 6668 "*
6669 {
6670 output_asm_insn (\"eor\\t%0, %2\", operands);
6671 switch (get_attr_length (insn))
6672 {
6673 case 4: return \"b%d4\\t%l3\";
6674 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6675 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6676 }
6677 }"
6678 [(set (attr "far_jump")
6679 (if_then_else
6680 (eq_attr "length" "8")
6681 (const_string "yes")
6682 (const_string "no")))
6683 (set (attr "length")
6684 (if_then_else
6685 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6686 (le (minus (match_dup 3) (pc)) (const_int 256)))
6687 (const_int 4)
6688 (if_then_else
6689 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6690 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6691 (const_int 6)
6692 (const_int 8))))]
6693)
6694
6695(define_insn "*xorsi3_cbranch"
6696 [(set (pc)
6697 (if_then_else
6698 (match_operator 5 "equality_operator"
6699 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6700 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6701 (const_int 0)])
6702 (label_ref (match_operand 4 "" ""))
6703 (pc)))
aeac46d4 6704 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6705 (xor:SI (match_dup 2) (match_dup 3)))
6706 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6707 "TARGET_THUMB1"
58d6528b 6708 "*
6709 {
6710 if (which_alternative == 0)
6711 output_asm_insn (\"eor\\t%0, %3\", operands);
6712 else if (which_alternative == 1)
6713 {
6714 output_asm_insn (\"eor\\t%1, %3\", operands);
6715 output_asm_insn (\"mov\\t%0, %1\", operands);
6716 }
6717 else
6718 {
6719 output_asm_insn (\"eor\\t%1, %3\", operands);
6720 output_asm_insn (\"str\\t%1, %0\", operands);
6721 }
6722
6723 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6724 {
6725 case 4: return \"b%d5\\t%l4\";
6726 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6727 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6728 }
6729 }"
6730 [(set (attr "far_jump")
6731 (if_then_else
6732 (ior (and (eq (symbol_ref ("which_alternative"))
6733 (const_int 0))
6734 (eq_attr "length" "8"))
6735 (eq_attr "length" "10"))
6736 (const_string "yes")
6737 (const_string "no")))
6738 (set (attr "length")
6739 (if_then_else
6740 (eq (symbol_ref ("which_alternative"))
6741 (const_int 0))
6742 (if_then_else
6743 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6744 (le (minus (match_dup 4) (pc)) (const_int 256)))
6745 (const_int 4)
6746 (if_then_else
6747 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6748 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6749 (const_int 6)
6750 (const_int 8)))
6751 (if_then_else
6752 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6753 (le (minus (match_dup 4) (pc)) (const_int 256)))
6754 (const_int 6)
6755 (if_then_else
6756 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6757 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6758 (const_int 8)
6759 (const_int 10)))))]
6760)
6761
aeac46d4 6762(define_insn "*bicsi3_cbranch_scratch"
6763 [(set (pc)
6764 (if_then_else
6765 (match_operator 4 "equality_operator"
6766 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6767 (match_operand:SI 1 "s_register_operand" "0"))
6768 (const_int 0)])
6769 (label_ref (match_operand 3 "" ""))
6770 (pc)))
6771 (clobber (match_scratch:SI 0 "=l"))]
25f905c2 6772 "TARGET_THUMB1"
aeac46d4 6773 "*
6774 {
6775 output_asm_insn (\"bic\\t%0, %2\", operands);
6776 switch (get_attr_length (insn))
6777 {
6778 case 4: return \"b%d4\\t%l3\";
6779 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6780 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6781 }
6782 }"
6783 [(set (attr "far_jump")
6784 (if_then_else
6785 (eq_attr "length" "8")
6786 (const_string "yes")
6787 (const_string "no")))
6788 (set (attr "length")
6789 (if_then_else
6790 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6791 (le (minus (match_dup 3) (pc)) (const_int 256)))
6792 (const_int 4)
6793 (if_then_else
6794 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6795 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6796 (const_int 6)
6797 (const_int 8))))]
6798)
6799
6800(define_insn "*bicsi3_cbranch"
6801 [(set (pc)
6802 (if_then_else
6803 (match_operator 5 "equality_operator"
01145ae6 6804 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6805 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 6806 (const_int 0)])
6807 (label_ref (match_operand 4 "" ""))
6808 (pc)))
01145ae6 6809 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 6810 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 6811 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
25f905c2 6812 "TARGET_THUMB1"
aeac46d4 6813 "*
6814 {
6815 if (which_alternative == 0)
6816 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 6817 else if (which_alternative <= 2)
aeac46d4 6818 {
6819 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 6820 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6821 conditions again, since we're only testing for equality. */
aeac46d4 6822 output_asm_insn (\"mov\\t%0, %1\", operands);
6823 }
6824 else
6825 {
6826 output_asm_insn (\"bic\\t%1, %3\", operands);
6827 output_asm_insn (\"str\\t%1, %0\", operands);
6828 }
6829
6830 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6831 {
6832 case 4: return \"b%d5\\t%l4\";
6833 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6834 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6835 }
6836 }"
6837 [(set (attr "far_jump")
6838 (if_then_else
6839 (ior (and (eq (symbol_ref ("which_alternative"))
6840 (const_int 0))
6841 (eq_attr "length" "8"))
6842 (eq_attr "length" "10"))
6843 (const_string "yes")
6844 (const_string "no")))
6845 (set (attr "length")
6846 (if_then_else
6847 (eq (symbol_ref ("which_alternative"))
6848 (const_int 0))
6849 (if_then_else
6850 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6851 (le (minus (match_dup 4) (pc)) (const_int 256)))
6852 (const_int 4)
6853 (if_then_else
6854 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6855 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6856 (const_int 6)
6857 (const_int 8)))
6858 (if_then_else
6859 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6860 (le (minus (match_dup 4) (pc)) (const_int 256)))
6861 (const_int 6)
6862 (if_then_else
6863 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6864 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6865 (const_int 8)
6866 (const_int 10)))))]
6867)
6868
203c488f 6869(define_insn "*cbranchne_decr1"
6870 [(set (pc)
6871 (if_then_else (match_operator 3 "equality_operator"
6872 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6873 (const_int 0)])
6874 (label_ref (match_operand 4 "" ""))
6875 (pc)))
aeac46d4 6876 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6877 (plus:SI (match_dup 2) (const_int -1)))
6878 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 6879 "TARGET_THUMB1"
203c488f 6880 "*
6881 {
6882 rtx cond[2];
6883 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6884 ? GEU : LTU),
58d6528b 6885 VOIDmode, operands[2], const1_rtx);
203c488f 6886 cond[1] = operands[4];
6887
6888 if (which_alternative == 0)
6889 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6890 else if (which_alternative == 1)
6891 {
6892 /* We must provide an alternative for a hi reg because reload
6893 cannot handle output reloads on a jump instruction, but we
6894 can't subtract into that. Fortunately a mov from lo to hi
6895 does not clobber the condition codes. */
6896 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6897 output_asm_insn (\"mov\\t%0, %1\", operands);
6898 }
6899 else
6900 {
6901 /* Similarly, but the target is memory. */
6902 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6903 output_asm_insn (\"str\\t%1, %0\", operands);
6904 }
6905
6906 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6907 {
6908 case 4:
8aea555f 6909 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6910 return \"\";
6911 case 6:
8aea555f 6912 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6913 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6914 default:
8aea555f 6915 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6916 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6917 }
6918 }
6919 "
6920 [(set (attr "far_jump")
6921 (if_then_else
6922 (ior (and (eq (symbol_ref ("which_alternative"))
6923 (const_int 0))
6924 (eq_attr "length" "8"))
6925 (eq_attr "length" "10"))
6926 (const_string "yes")
6927 (const_string "no")))
6928 (set_attr_alternative "length"
6929 [
6930 ;; Alternative 0
6931 (if_then_else
6932 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6933 (le (minus (match_dup 4) (pc)) (const_int 256)))
6934 (const_int 4)
6935 (if_then_else
6936 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6937 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6938 (const_int 6)
6939 (const_int 8)))
6940 ;; Alternative 1
6941 (if_then_else
6942 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6943 (le (minus (match_dup 4) (pc)) (const_int 256)))
6944 (const_int 6)
6945 (if_then_else
6946 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6947 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6948 (const_int 8)
6949 (const_int 10)))
6950 ;; Alternative 2
6951 (if_then_else
6952 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6953 (le (minus (match_dup 4) (pc)) (const_int 256)))
6954 (const_int 6)
6955 (if_then_else
6956 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6957 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6958 (const_int 8)
6959 (const_int 10)))
6960 ;; Alternative 3
6961 (if_then_else
6962 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6963 (le (minus (match_dup 4) (pc)) (const_int 256)))
6964 (const_int 6)
6965 (if_then_else
6966 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6967 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6968 (const_int 8)
6969 (const_int 10)))])]
6970)
cffb2a26 6971
58d6528b 6972(define_insn "*addsi3_cbranch"
6973 [(set (pc)
6974 (if_then_else
6975 (match_operator 4 "comparison_operator"
6976 [(plus:SI
6977 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6978 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6979 (const_int 0)])
6980 (label_ref (match_operand 5 "" ""))
6981 (pc)))
aeac46d4 6982 (set
6983 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6984 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 6985 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
25f905c2 6986 "TARGET_THUMB1
58d6528b 6987 && (GET_CODE (operands[4]) == EQ
6988 || GET_CODE (operands[4]) == NE
6989 || GET_CODE (operands[4]) == GE
6990 || GET_CODE (operands[4]) == LT)"
6991 "*
6992 {
6993 rtx cond[3];
6994
6995
6996 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6997 cond[1] = operands[2];
6998 cond[2] = operands[3];
6999
7000 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7001 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7002 else
7003 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7004
7005 if (which_alternative >= 3
7006 && which_alternative < 4)
7007 output_asm_insn (\"mov\\t%0, %1\", operands);
7008 else if (which_alternative >= 4)
7009 output_asm_insn (\"str\\t%1, %0\", operands);
7010
7011 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7012 {
7013 case 4:
7014 return \"b%d4\\t%l5\";
7015 case 6:
7016 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7017 default:
7018 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7019 }
7020 }
7021 "
7022 [(set (attr "far_jump")
7023 (if_then_else
7024 (ior (and (lt (symbol_ref ("which_alternative"))
7025 (const_int 3))
7026 (eq_attr "length" "8"))
7027 (eq_attr "length" "10"))
7028 (const_string "yes")
7029 (const_string "no")))
7030 (set (attr "length")
7031 (if_then_else
7032 (lt (symbol_ref ("which_alternative"))
7033 (const_int 3))
7034 (if_then_else
7035 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7036 (le (minus (match_dup 5) (pc)) (const_int 256)))
7037 (const_int 4)
7038 (if_then_else
7039 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7040 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7041 (const_int 6)
7042 (const_int 8)))
7043 (if_then_else
7044 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7045 (le (minus (match_dup 5) (pc)) (const_int 256)))
7046 (const_int 6)
7047 (if_then_else
7048 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7049 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7050 (const_int 8)
7051 (const_int 10)))))]
7052)
7053
7054(define_insn "*addsi3_cbranch_scratch"
7055 [(set (pc)
7056 (if_then_else
7057 (match_operator 3 "comparison_operator"
7058 [(plus:SI
7059 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7060 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7061 (const_int 0)])
7062 (label_ref (match_operand 4 "" ""))
7063 (pc)))
7064 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7065 "TARGET_THUMB1
58d6528b 7066 && (GET_CODE (operands[3]) == EQ
7067 || GET_CODE (operands[3]) == NE
7068 || GET_CODE (operands[3]) == GE
7069 || GET_CODE (operands[3]) == LT)"
7070 "*
7071 {
7072 switch (which_alternative)
7073 {
7074 case 0:
7075 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7076 break;
7077 case 1:
7078 output_asm_insn (\"cmn\t%1, %2\", operands);
7079 break;
0f5e9701 7080 case 2:
3a445a04 7081 if (INTVAL (operands[2]) < 0)
7082 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7083 else
7084 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7085 break;
0f5e9701 7086 case 3:
3a445a04 7087 if (INTVAL (operands[2]) < 0)
7088 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7089 else
7090 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7091 break;
7092 }
7093
7094 switch (get_attr_length (insn))
7095 {
7096 case 4:
7097 return \"b%d3\\t%l4\";
7098 case 6:
7099 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7100 default:
7101 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7102 }
7103 }
7104 "
7105 [(set (attr "far_jump")
7106 (if_then_else
7107 (eq_attr "length" "8")
7108 (const_string "yes")
7109 (const_string "no")))
7110 (set (attr "length")
7111 (if_then_else
7112 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7113 (le (minus (match_dup 4) (pc)) (const_int 256)))
7114 (const_int 4)
7115 (if_then_else
7116 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7117 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7118 (const_int 6)
7119 (const_int 8))))]
7120)
7121
7122(define_insn "*subsi3_cbranch"
7123 [(set (pc)
7124 (if_then_else
7125 (match_operator 4 "comparison_operator"
7126 [(minus:SI
7127 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7128 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7129 (const_int 0)])
7130 (label_ref (match_operand 5 "" ""))
7131 (pc)))
aeac46d4 7132 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 7133 (minus:SI (match_dup 2) (match_dup 3)))
7134 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7135 "TARGET_THUMB1
58d6528b 7136 && (GET_CODE (operands[4]) == EQ
7137 || GET_CODE (operands[4]) == NE
7138 || GET_CODE (operands[4]) == GE
7139 || GET_CODE (operands[4]) == LT)"
7140 "*
7141 {
7142 if (which_alternative == 0)
7143 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7144 else if (which_alternative == 1)
7145 {
7146 /* We must provide an alternative for a hi reg because reload
7147 cannot handle output reloads on a jump instruction, but we
7148 can't subtract into that. Fortunately a mov from lo to hi
7149 does not clobber the condition codes. */
7150 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7151 output_asm_insn (\"mov\\t%0, %1\", operands);
7152 }
7153 else
7154 {
7155 /* Similarly, but the target is memory. */
7156 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7157 output_asm_insn (\"str\\t%1, %0\", operands);
7158 }
7159
7160 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7161 {
7162 case 4:
7163 return \"b%d4\\t%l5\";
7164 case 6:
7165 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7166 default:
7167 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7168 }
7169 }
7170 "
7171 [(set (attr "far_jump")
7172 (if_then_else
7173 (ior (and (eq (symbol_ref ("which_alternative"))
7174 (const_int 0))
7175 (eq_attr "length" "8"))
7176 (eq_attr "length" "10"))
7177 (const_string "yes")
7178 (const_string "no")))
7179 (set (attr "length")
7180 (if_then_else
7181 (eq (symbol_ref ("which_alternative"))
7182 (const_int 0))
7183 (if_then_else
7184 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7185 (le (minus (match_dup 5) (pc)) (const_int 256)))
7186 (const_int 4)
7187 (if_then_else
7188 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7189 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7190 (const_int 6)
7191 (const_int 8)))
7192 (if_then_else
7193 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7194 (le (minus (match_dup 5) (pc)) (const_int 256)))
7195 (const_int 6)
7196 (if_then_else
7197 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7198 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7199 (const_int 8)
7200 (const_int 10)))))]
7201)
7202
7203(define_insn "*subsi3_cbranch_scratch"
7204 [(set (pc)
7205 (if_then_else
7206 (match_operator 0 "arm_comparison_operator"
7207 [(minus:SI (match_operand:SI 1 "register_operand" "l")
7208 (match_operand:SI 2 "nonmemory_operand" "l"))
7209 (const_int 0)])
7210 (label_ref (match_operand 3 "" ""))
7211 (pc)))]
25f905c2 7212 "TARGET_THUMB1
58d6528b 7213 && (GET_CODE (operands[0]) == EQ
7214 || GET_CODE (operands[0]) == NE
7215 || GET_CODE (operands[0]) == GE
7216 || GET_CODE (operands[0]) == LT)"
7217 "*
7218 output_asm_insn (\"cmp\\t%1, %2\", operands);
7219 switch (get_attr_length (insn))
7220 {
7221 case 4: return \"b%d0\\t%l3\";
7222 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7223 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7224 }
7225 "
7226 [(set (attr "far_jump")
7227 (if_then_else
7228 (eq_attr "length" "8")
7229 (const_string "yes")
7230 (const_string "no")))
7231 (set (attr "length")
7232 (if_then_else
7233 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7234 (le (minus (match_dup 3) (pc)) (const_int 256)))
7235 (const_int 4)
7236 (if_then_else
7237 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7238 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7239 (const_int 6)
7240 (const_int 8))))]
7241)
7242
9c08d1fa 7243;; Comparison and test insns
7244
7245(define_expand "cmpsi"
aea4c774 7246 [(match_operand:SI 0 "s_register_operand" "")
7247 (match_operand:SI 1 "arm_add_operand" "")]
25f905c2 7248 "TARGET_32BIT"
cffb2a26 7249 "{
7250 arm_compare_op0 = operands[0];
7251 arm_compare_op1 = operands[1];
7252 DONE;
7253 }"
7254)
b11cae9e 7255
9c08d1fa 7256(define_expand "cmpsf"
aea4c774 7257 [(match_operand:SF 0 "s_register_operand" "")
a2cd141b 7258 (match_operand:SF 1 "arm_float_compare_operand" "")]
25f905c2 7259 "TARGET_32BIT && TARGET_HARD_FLOAT"
9c08d1fa 7260 "
9c08d1fa 7261 arm_compare_op0 = operands[0];
7262 arm_compare_op1 = operands[1];
9c08d1fa 7263 DONE;
215b30b3 7264 "
7265)
b11cae9e 7266
9c08d1fa 7267(define_expand "cmpdf"
aea4c774 7268 [(match_operand:DF 0 "s_register_operand" "")
a2cd141b 7269 (match_operand:DF 1 "arm_float_compare_operand" "")]
25f905c2 7270 "TARGET_32BIT && TARGET_HARD_FLOAT"
9c08d1fa 7271 "
9c08d1fa 7272 arm_compare_op0 = operands[0];
7273 arm_compare_op1 = operands[1];
9c08d1fa 7274 DONE;
215b30b3 7275 "
7276)
b11cae9e 7277
cffb2a26 7278(define_insn "*arm_cmpsi_insn"
bd5b4116 7279 [(set (reg:CC CC_REGNUM)
aea4c774 7280 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7281 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
25f905c2 7282 "TARGET_32BIT"
5565501b 7283 "@
aea4c774 7284 cmp%?\\t%0, %1
7285 cmn%?\\t%0, #%n1"
cffb2a26 7286 [(set_attr "conds" "set")]
7287)
b11cae9e 7288
25f905c2 7289(define_insn "*arm_cmpsi_shiftsi"
bd5b4116 7290 [(set (reg:CC CC_REGNUM)
cffb2a26 7291 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
7292 (match_operator:SI 3 "shift_operator"
aea4c774 7293 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 7294 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
7295 "TARGET_ARM"
aea4c774 7296 "cmp%?\\t%0, %1%S3"
344495ea 7297 [(set_attr "conds" "set")
331beb1a 7298 (set_attr "shift" "1")
a2cd141b 7299 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7300 (const_string "alu_shift")
7301 (const_string "alu_shift_reg")))]
0d66636f 7302)
b11cae9e 7303
25f905c2 7304(define_insn "*arm_cmpsi_shiftsi_swp"
bd5b4116 7305 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7306 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7307 [(match_operand:SI 1 "s_register_operand" "r")
7308 (match_operand:SI 2 "reg_or_int_operand" "rM")])
7309 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7310 "TARGET_ARM"
aea4c774 7311 "cmp%?\\t%0, %1%S3"
344495ea 7312 [(set_attr "conds" "set")
331beb1a 7313 (set_attr "shift" "1")
a2cd141b 7314 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7315 (const_string "alu_shift")
7316 (const_string "alu_shift_reg")))]
0d66636f 7317)
b11cae9e 7318
25f905c2 7319(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7320 [(set (reg:CC_Z CC_REGNUM)
7321 (compare:CC_Z
7322 (neg:SI (match_operator:SI 1 "shift_operator"
7323 [(match_operand:SI 2 "s_register_operand" "r")
7324 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7325 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7326 "TARGET_ARM"
aed179ae 7327 "cmn%?\\t%0, %2%S1"
344495ea 7328 [(set_attr "conds" "set")
aed179ae 7329 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7330 (const_string "alu_shift")
7331 (const_string "alu_shift_reg")))]
0d66636f 7332)
b11cae9e 7333
7d57ec45 7334;; Cirrus SF compare instruction
7335(define_insn "*cirrus_cmpsf"
7336 [(set (reg:CCFP CC_REGNUM)
7337 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7338 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7339 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7340 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7341 [(set_attr "type" "mav_farith")
7d57ec45 7342 (set_attr "cirrus" "compare")]
7343)
7344
7345;; Cirrus DF compare instruction
7346(define_insn "*cirrus_cmpdf"
7347 [(set (reg:CCFP CC_REGNUM)
7348 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7349 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7350 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7351 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7352 [(set_attr "type" "mav_farith")
7d57ec45 7353 (set_attr "cirrus" "compare")]
7354)
7355
7356;; Cirrus DI compare instruction
7357(define_expand "cmpdi"
7358 [(match_operand:DI 0 "cirrus_fp_register" "")
7359 (match_operand:DI 1 "cirrus_fp_register" "")]
a2cd141b 7360 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7361 "{
7362 arm_compare_op0 = operands[0];
7363 arm_compare_op1 = operands[1];
7364 DONE;
7365 }")
7366
7367(define_insn "*cirrus_cmpdi"
7368 [(set (reg:CC CC_REGNUM)
7369 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7370 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7371 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7372 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7373 [(set_attr "type" "mav_farith")
7d57ec45 7374 (set_attr "cirrus" "compare")]
7375)
7376
9c08d1fa 7377; This insn allows redundant compares to be removed by cse, nothing should
7378; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7379; is deleted later on. The match_dup will match the mode here, so that
7380; mode changes of the condition codes aren't lost by this even though we don't
7381; specify what they are.
7382
8a18b90c 7383(define_insn "*deleted_compare"
9c08d1fa 7384 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7385 "TARGET_32BIT"
40dbec34 7386 "\\t%@ deleted compare"
cffb2a26 7387 [(set_attr "conds" "set")
7388 (set_attr "length" "0")]
7389)
9c08d1fa 7390
7391\f
7392;; Conditional branch insns
7393
7394(define_expand "beq"
7395 [(set (pc)
7396 (if_then_else (eq (match_dup 1) (const_int 0))
7397 (label_ref (match_operand 0 "" ""))
7398 (pc)))]
25f905c2 7399 "TARGET_32BIT"
cffb2a26 7400 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7401)
5c951228 7402
9c08d1fa 7403(define_expand "bne"
7404 [(set (pc)
7405 (if_then_else (ne (match_dup 1) (const_int 0))
7406 (label_ref (match_operand 0 "" ""))
7407 (pc)))]
25f905c2 7408 "TARGET_32BIT"
cffb2a26 7409 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7410)
5c951228 7411
9c08d1fa 7412(define_expand "bgt"
7413 [(set (pc)
7414 (if_then_else (gt (match_dup 1) (const_int 0))
7415 (label_ref (match_operand 0 "" ""))
7416 (pc)))]
25f905c2 7417 "TARGET_32BIT"
cffb2a26 7418 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7419)
5c951228 7420
9c08d1fa 7421(define_expand "ble"
7422 [(set (pc)
7423 (if_then_else (le (match_dup 1) (const_int 0))
7424 (label_ref (match_operand 0 "" ""))
7425 (pc)))]
25f905c2 7426 "TARGET_32BIT"
cffb2a26 7427 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7428)
5c951228 7429
9c08d1fa 7430(define_expand "bge"
7431 [(set (pc)
7432 (if_then_else (ge (match_dup 1) (const_int 0))
7433 (label_ref (match_operand 0 "" ""))
7434 (pc)))]
25f905c2 7435 "TARGET_32BIT"
cffb2a26 7436 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7437)
5c951228 7438
9c08d1fa 7439(define_expand "blt"
7440 [(set (pc)
7441 (if_then_else (lt (match_dup 1) (const_int 0))
7442 (label_ref (match_operand 0 "" ""))
7443 (pc)))]
25f905c2 7444 "TARGET_32BIT"
cffb2a26 7445 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7446)
5c951228 7447
9c08d1fa 7448(define_expand "bgtu"
7449 [(set (pc)
7450 (if_then_else (gtu (match_dup 1) (const_int 0))
7451 (label_ref (match_operand 0 "" ""))
7452 (pc)))]
25f905c2 7453 "TARGET_32BIT"
cffb2a26 7454 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7455)
5c951228 7456
9c08d1fa 7457(define_expand "bleu"
b11cae9e 7458 [(set (pc)
9c08d1fa 7459 (if_then_else (leu (match_dup 1) (const_int 0))
7460 (label_ref (match_operand 0 "" ""))
7461 (pc)))]
25f905c2 7462 "TARGET_32BIT"
cffb2a26 7463 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7464)
b11cae9e 7465
9c08d1fa 7466(define_expand "bgeu"
b11cae9e 7467 [(set (pc)
9c08d1fa 7468 (if_then_else (geu (match_dup 1) (const_int 0))
7469 (label_ref (match_operand 0 "" ""))
7470 (pc)))]
25f905c2 7471 "TARGET_32BIT"
cffb2a26 7472 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7473)
b11cae9e 7474
9c08d1fa 7475(define_expand "bltu"
7476 [(set (pc)
7477 (if_then_else (ltu (match_dup 1) (const_int 0))
7478 (label_ref (match_operand 0 "" ""))
7479 (pc)))]
25f905c2 7480 "TARGET_32BIT"
cffb2a26 7481 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7482)
b11cae9e 7483
8fa3ba89 7484(define_expand "bunordered"
7485 [(set (pc)
7486 (if_then_else (unordered (match_dup 1) (const_int 0))
7487 (label_ref (match_operand 0 "" ""))
7488 (pc)))]
25f905c2 7489 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7490 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7491 arm_compare_op1);"
7492)
7493
7494(define_expand "bordered"
7495 [(set (pc)
7496 (if_then_else (ordered (match_dup 1) (const_int 0))
7497 (label_ref (match_operand 0 "" ""))
7498 (pc)))]
25f905c2 7499 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7500 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7501 arm_compare_op1);"
7502)
7503
7504(define_expand "bungt"
7505 [(set (pc)
7506 (if_then_else (ungt (match_dup 1) (const_int 0))
7507 (label_ref (match_operand 0 "" ""))
7508 (pc)))]
25f905c2 7509 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7510 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7511)
7512
7513(define_expand "bunlt"
7514 [(set (pc)
7515 (if_then_else (unlt (match_dup 1) (const_int 0))
7516 (label_ref (match_operand 0 "" ""))
7517 (pc)))]
25f905c2 7518 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7519 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7520)
7521
7522(define_expand "bunge"
7523 [(set (pc)
7524 (if_then_else (unge (match_dup 1) (const_int 0))
7525 (label_ref (match_operand 0 "" ""))
7526 (pc)))]
25f905c2 7527 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7528 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7529)
7530
7531(define_expand "bunle"
7532 [(set (pc)
7533 (if_then_else (unle (match_dup 1) (const_int 0))
7534 (label_ref (match_operand 0 "" ""))
7535 (pc)))]
25f905c2 7536 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7537 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7538)
7539
7540;; The following two patterns need two branch instructions, since there is
7541;; no single instruction that will handle all cases.
7542(define_expand "buneq"
7543 [(set (pc)
7544 (if_then_else (uneq (match_dup 1) (const_int 0))
7545 (label_ref (match_operand 0 "" ""))
7546 (pc)))]
25f905c2 7547 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7548 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7549)
7550
7551(define_expand "bltgt"
7552 [(set (pc)
7553 (if_then_else (ltgt (match_dup 1) (const_int 0))
7554 (label_ref (match_operand 0 "" ""))
7555 (pc)))]
25f905c2 7556 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7557 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7558)
7559
7560;;
7561;; Patterns to match conditional branch insns.
7562;;
7563
7564; Special pattern to match UNEQ.
7565(define_insn "*arm_buneq"
7566 [(set (pc)
7567 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7568 (label_ref (match_operand 0 "" ""))
7569 (pc)))]
25f905c2 7570 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7571 "*
ed29c566 7572 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7573
278b301d 7574 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7575 "
7576 [(set_attr "conds" "jump_clob")
7577 (set_attr "length" "8")]
7578)
7579
7580; Special pattern to match LTGT.
7581(define_insn "*arm_bltgt"
7582 [(set (pc)
7583 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7584 (label_ref (match_operand 0 "" ""))
7585 (pc)))]
25f905c2 7586 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7587 "*
ed29c566 7588 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7589
278b301d 7590 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7591 "
7592 [(set_attr "conds" "jump_clob")
7593 (set_attr "length" "8")]
7594)
9c08d1fa 7595
cffb2a26 7596(define_insn "*arm_cond_branch"
9c08d1fa 7597 [(set (pc)
8fa3ba89 7598 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7599 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7600 (label_ref (match_operand 0 "" ""))
7601 (pc)))]
25f905c2 7602 "TARGET_32BIT"
d75350ce 7603 "*
9c08d1fa 7604 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7605 {
7606 arm_ccfsm_state += 2;
7607 return \"\";
7608 }
e2348bcb 7609 return \"b%d1\\t%l0\";
cffb2a26 7610 "
a2cd141b 7611 [(set_attr "conds" "use")
7612 (set_attr "type" "branch")]
cffb2a26 7613)
d75350ce 7614
8fa3ba89 7615; Special pattern to match reversed UNEQ.
7616(define_insn "*arm_buneq_reversed"
7617 [(set (pc)
7618 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7619 (pc)
7620 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7621 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7622 "*
ed29c566 7623 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7624
278b301d 7625 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7626 "
7627 [(set_attr "conds" "jump_clob")
7628 (set_attr "length" "8")]
7629)
7630
7631; Special pattern to match reversed LTGT.
7632(define_insn "*arm_bltgt_reversed"
7633 [(set (pc)
7634 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7635 (pc)
7636 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7637 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7638 "*
ed29c566 7639 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7640
278b301d 7641 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7642 "
7643 [(set_attr "conds" "jump_clob")
7644 (set_attr "length" "8")]
7645)
7646
cffb2a26 7647(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7648 [(set (pc)
8fa3ba89 7649 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7650 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7651 (pc)
7652 (label_ref (match_operand 0 "" ""))))]
25f905c2 7653 "TARGET_32BIT"
d75350ce 7654 "*
9c08d1fa 7655 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7656 {
7657 arm_ccfsm_state += 2;
7658 return \"\";
7659 }
e2348bcb 7660 return \"b%D1\\t%l0\";
cffb2a26 7661 "
a2cd141b 7662 [(set_attr "conds" "use")
7663 (set_attr "type" "branch")]
cffb2a26 7664)
7665
b11cae9e 7666\f
9c08d1fa 7667
7668; scc insns
7669
7670(define_expand "seq"
7db9af5d 7671 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7672 (eq:SI (match_dup 1) (const_int 0)))]
25f905c2 7673 "TARGET_32BIT"
cffb2a26 7674 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7675)
9c08d1fa 7676
7677(define_expand "sne"
7db9af5d 7678 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7679 (ne:SI (match_dup 1) (const_int 0)))]
25f905c2 7680 "TARGET_32BIT"
cffb2a26 7681 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7682)
9c08d1fa 7683
7684(define_expand "sgt"
7db9af5d 7685 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7686 (gt:SI (match_dup 1) (const_int 0)))]
25f905c2 7687 "TARGET_32BIT"
cffb2a26 7688 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7689)
9c08d1fa 7690
7691(define_expand "sle"
7db9af5d 7692 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7693 (le:SI (match_dup 1) (const_int 0)))]
25f905c2 7694 "TARGET_32BIT"
cffb2a26 7695 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7696)
9c08d1fa 7697
7698(define_expand "sge"
7db9af5d 7699 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7700 (ge:SI (match_dup 1) (const_int 0)))]
25f905c2 7701 "TARGET_32BIT"
cffb2a26 7702 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7703)
9c08d1fa 7704
7705(define_expand "slt"
7db9af5d 7706 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7707 (lt:SI (match_dup 1) (const_int 0)))]
25f905c2 7708 "TARGET_32BIT"
cffb2a26 7709 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7710)
9c08d1fa 7711
7712(define_expand "sgtu"
7db9af5d 7713 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7714 (gtu:SI (match_dup 1) (const_int 0)))]
25f905c2 7715 "TARGET_32BIT"
cffb2a26 7716 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7717)
9c08d1fa 7718
7719(define_expand "sleu"
7db9af5d 7720 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7721 (leu:SI (match_dup 1) (const_int 0)))]
25f905c2 7722 "TARGET_32BIT"
cffb2a26 7723 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7724)
9c08d1fa 7725
7726(define_expand "sgeu"
7db9af5d 7727 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7728 (geu:SI (match_dup 1) (const_int 0)))]
25f905c2 7729 "TARGET_32BIT"
cffb2a26 7730 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7731)
9c08d1fa 7732
7733(define_expand "sltu"
7db9af5d 7734 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7735 (ltu:SI (match_dup 1) (const_int 0)))]
25f905c2 7736 "TARGET_32BIT"
cffb2a26 7737 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7738)
9c08d1fa 7739
8fa3ba89 7740(define_expand "sunordered"
7db9af5d 7741 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7742 (unordered:SI (match_dup 1) (const_int 0)))]
25f905c2 7743 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7744 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7745 arm_compare_op1);"
7746)
7747
7748(define_expand "sordered"
7db9af5d 7749 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7750 (ordered:SI (match_dup 1) (const_int 0)))]
25f905c2 7751 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7752 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7753 arm_compare_op1);"
7754)
7755
7756(define_expand "sungt"
7db9af5d 7757 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7758 (ungt:SI (match_dup 1) (const_int 0)))]
25f905c2 7759 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7760 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7761 arm_compare_op1);"
7762)
7763
7764(define_expand "sunge"
7db9af5d 7765 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7766 (unge:SI (match_dup 1) (const_int 0)))]
25f905c2 7767 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7768 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7769 arm_compare_op1);"
7770)
7771
7772(define_expand "sunlt"
7db9af5d 7773 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7774 (unlt:SI (match_dup 1) (const_int 0)))]
25f905c2 7775 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7776 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7777 arm_compare_op1);"
7778)
7779
7780(define_expand "sunle"
7db9af5d 7781 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7782 (unle:SI (match_dup 1) (const_int 0)))]
25f905c2 7783 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7784 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7785 arm_compare_op1);"
7786)
7787
7788;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7789;;; simple ARM instructions.
7790;
7791; (define_expand "suneq"
7db9af5d 7792; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7793; (uneq:SI (match_dup 1) (const_int 0)))]
25f905c2 7794; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7795; "gcc_unreachable ();"
8fa3ba89 7796; )
7797;
7798; (define_expand "sltgt"
7db9af5d 7799; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7800; (ltgt:SI (match_dup 1) (const_int 0)))]
25f905c2 7801; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7802; "gcc_unreachable ();"
8fa3ba89 7803; )
7804
f7fbdd4a 7805(define_insn "*mov_scc"
9c08d1fa 7806 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7807 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7808 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7809 "TARGET_ARM"
4d61e570 7810 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7811 [(set_attr "conds" "use")
7812 (set_attr "length" "8")]
7813)
9c08d1fa 7814
f7fbdd4a 7815(define_insn "*mov_negscc"
9c08d1fa 7816 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7817 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7818 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7819 "TARGET_ARM"
4d61e570 7820 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7821 [(set_attr "conds" "use")
7822 (set_attr "length" "8")]
7823)
9c08d1fa 7824
f7fbdd4a 7825(define_insn "*mov_notscc"
9c08d1fa 7826 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7827 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7828 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7829 "TARGET_ARM"
4d61e570 7830 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7831 [(set_attr "conds" "use")
7832 (set_attr "length" "8")]
7833)
9c08d1fa 7834
595d88b5 7835(define_expand "cstoresi4"
7836 [(set (match_operand:SI 0 "s_register_operand" "")
7837 (match_operator:SI 1 "arm_comparison_operator"
7838 [(match_operand:SI 2 "s_register_operand" "")
7839 (match_operand:SI 3 "reg_or_int_operand" "")]))]
25f905c2 7840 "TARGET_THUMB1"
595d88b5 7841 "{
7842 rtx op3, scratch, scratch2;
7843
7844 if (operands[3] == const0_rtx)
7845 {
7846 switch (GET_CODE (operands[1]))
7847 {
7848 case EQ:
25f905c2 7849 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7850 break;
7851
7852 case NE:
25f905c2 7853 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7854 break;
7855
7856 case LE:
7857 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7858 NULL_RTX, 0, OPTAB_WIDEN);
7859 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7860 NULL_RTX, 0, OPTAB_WIDEN);
7861 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7862 operands[0], 1, OPTAB_WIDEN);
7863 break;
7864
7865 case GE:
7866 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7867 NULL_RTX, 1);
7868 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7869 NULL_RTX, 1, OPTAB_WIDEN);
7870 break;
7871
7872 case GT:
7873 scratch = expand_binop (SImode, ashr_optab, operands[2],
7874 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7875 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7876 NULL_RTX, 0, OPTAB_WIDEN);
7877 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7878 0, OPTAB_WIDEN);
7879 break;
7880
7881 /* LT is handled by generic code. No need for unsigned with 0. */
7882 default:
7883 FAIL;
7884 }
7885 DONE;
7886 }
7887
7888 switch (GET_CODE (operands[1]))
7889 {
7890 case EQ:
7891 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7892 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7893 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7894 break;
7895
7896 case NE:
7897 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7898 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7899 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7900 break;
7901
7902 case LE:
7903 op3 = force_reg (SImode, operands[3]);
7904
7905 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7906 NULL_RTX, 1, OPTAB_WIDEN);
7907 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7908 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7909 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7910 op3, operands[2]));
7911 break;
7912
7913 case GE:
7914 op3 = operands[3];
25f905c2 7915 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7916 op3 = force_reg (SImode, op3);
7917 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7918 NULL_RTX, 0, OPTAB_WIDEN);
7919 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7920 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7921 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7922 operands[2], op3));
7923 break;
7924
7925 case LEU:
7926 op3 = force_reg (SImode, operands[3]);
7927 scratch = force_reg (SImode, const0_rtx);
25f905c2 7928 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7929 op3, operands[2]));
7930 break;
7931
7932 case GEU:
7933 op3 = operands[3];
25f905c2 7934 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7935 op3 = force_reg (SImode, op3);
7936 scratch = force_reg (SImode, const0_rtx);
25f905c2 7937 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7938 operands[2], op3));
7939 break;
7940
7941 case LTU:
7942 op3 = operands[3];
25f905c2 7943 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7944 op3 = force_reg (SImode, op3);
7945 scratch = gen_reg_rtx (SImode);
25f905c2 7946 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
595d88b5 7947 emit_insn (gen_negsi2 (operands[0], scratch));
7948 break;
7949
7950 case GTU:
7951 op3 = force_reg (SImode, operands[3]);
7952 scratch = gen_reg_rtx (SImode);
25f905c2 7953 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
595d88b5 7954 emit_insn (gen_negsi2 (operands[0], scratch));
7955 break;
7956
7957 /* No good sequences for GT, LT. */
7958 default:
7959 FAIL;
7960 }
7961 DONE;
7962}")
7963
25f905c2 7964(define_expand "cstoresi_eq0_thumb1"
595d88b5 7965 [(parallel
7966 [(set (match_operand:SI 0 "s_register_operand" "")
7967 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7968 (const_int 0)))
7969 (clobber (match_dup:SI 2))])]
25f905c2 7970 "TARGET_THUMB1"
595d88b5 7971 "operands[2] = gen_reg_rtx (SImode);"
7972)
7973
25f905c2 7974(define_expand "cstoresi_ne0_thumb1"
595d88b5 7975 [(parallel
7976 [(set (match_operand:SI 0 "s_register_operand" "")
7977 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7978 (const_int 0)))
7979 (clobber (match_dup:SI 2))])]
25f905c2 7980 "TARGET_THUMB1"
595d88b5 7981 "operands[2] = gen_reg_rtx (SImode);"
7982)
7983
25f905c2 7984(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7985 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7986 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7987 (const_int 0)))
7988 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7989 "TARGET_THUMB1"
595d88b5 7990 "@
7991 neg\\t%0, %1\;adc\\t%0, %0, %1
7992 neg\\t%2, %1\;adc\\t%0, %1, %2"
7993 [(set_attr "length" "4")]
7994)
7995
25f905c2 7996(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7997 [(set (match_operand:SI 0 "s_register_operand" "=l")
7998 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7999 (const_int 0)))
8000 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8001 "TARGET_THUMB1"
595d88b5 8002 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8003 [(set_attr "length" "4")]
8004)
8005
25f905c2 8006(define_insn "cstoresi_nltu_thumb1"
595d88b5 8007 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8008 (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8009 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8010 "TARGET_THUMB1"
595d88b5 8011 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8012 [(set_attr "length" "4")]
8013)
8014
8015;; Used as part of the expansion of thumb les sequence.
25f905c2 8016(define_insn "thumb1_addsi3_addgeu"
595d88b5 8017 [(set (match_operand:SI 0 "s_register_operand" "=l")
8018 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8019 (match_operand:SI 2 "s_register_operand" "l"))
8020 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8021 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8022 "TARGET_THUMB1"
595d88b5 8023 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8024 [(set_attr "length" "4")]
8025)
8026
9c08d1fa 8027\f
39b5e676 8028;; Conditional move insns
8029
8030(define_expand "movsicc"
8a18b90c 8031 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 8032 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 8033 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8034 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8035 "TARGET_32BIT"
39b5e676 8036 "
215b30b3 8037 {
8038 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8039 rtx ccreg;
8040
8041 if (code == UNEQ || code == LTGT)
8042 FAIL;
39b5e676 8043
278b301d 8044 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 8045 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8046 }"
8047)
39b5e676 8048
8049(define_expand "movsfcc"
8a18b90c 8050 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 8051 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8052 (match_operand:SF 2 "s_register_operand" "")
8053 (match_operand:SF 3 "nonmemory_operand" "")))]
25f905c2 8054 "TARGET_32BIT"
39b5e676 8055 "
215b30b3 8056 {
8057 enum rtx_code code = GET_CODE (operands[1]);
8058 rtx ccreg;
f082f1c4 8059
278b301d 8060 if (code == UNEQ || code == LTGT)
8061 FAIL;
8062
215b30b3 8063 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 8064 Otherwise, ensure it is a valid FP add operand */
8065 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8066 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 8067 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8068
215b30b3 8069 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 8070 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8071 }"
8072)
39b5e676 8073
8074(define_expand "movdfcc"
8a18b90c 8075 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 8076 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 8077 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8078 (match_operand:DF 3 "arm_float_add_operand" "")))]
25f905c2 8079 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 8080 "
215b30b3 8081 {
8082 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8083 rtx ccreg;
39b5e676 8084
278b301d 8085 if (code == UNEQ || code == LTGT)
8086 FAIL;
8087
8088 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 8089 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8090 }"
8091)
39b5e676 8092
8093(define_insn "*movsicc_insn"
f082f1c4 8094 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8095 (if_then_else:SI
8fa3ba89 8096 (match_operator 3 "arm_comparison_operator"
8a18b90c 8097 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8098 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8099 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8100 "TARGET_ARM"
39b5e676 8101 "@
8a18b90c 8102 mov%D3\\t%0, %2
8103 mvn%D3\\t%0, #%B2
f082f1c4 8104 mov%d3\\t%0, %1
8105 mvn%d3\\t%0, #%B1
8a18b90c 8106 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8107 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8108 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8109 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8110 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 8111 (set_attr "conds" "use")]
8112)
39b5e676 8113
39b5e676 8114(define_insn "*movsfcc_soft_insn"
f082f1c4 8115 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8116 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8117 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8118 (match_operand:SF 1 "s_register_operand" "0,r")
8119 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8120 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8121 "@
8122 mov%D3\\t%0, %2
8123 mov%d3\\t%0, %1"
8fa3ba89 8124 [(set_attr "conds" "use")]
8125)
39b5e676 8126
39b5e676 8127\f
9c08d1fa 8128;; Jump and linkage insns
8129
cffb2a26 8130(define_expand "jump"
9c08d1fa 8131 [(set (pc)
8132 (label_ref (match_operand 0 "" "")))]
cffb2a26 8133 "TARGET_EITHER"
9c08d1fa 8134 ""
cffb2a26 8135)
8136
8137(define_insn "*arm_jump"
8138 [(set (pc)
8139 (label_ref (match_operand 0 "" "")))]
25f905c2 8140 "TARGET_32BIT"
9c08d1fa 8141 "*
0d66636f 8142 {
8143 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8144 {
8145 arm_ccfsm_state += 2;
8146 return \"\";
8147 }
8148 return \"b%?\\t%l0\";
8149 }
8150 "
8151 [(set_attr "predicable" "yes")]
8152)
9c08d1fa 8153
cffb2a26 8154(define_insn "*thumb_jump"
8155 [(set (pc)
8156 (label_ref (match_operand 0 "" "")))]
25f905c2 8157 "TARGET_THUMB1"
cffb2a26 8158 "*
8159 if (get_attr_length (insn) == 2)
8160 return \"b\\t%l0\";
8161 return \"bl\\t%l0\\t%@ far jump\";
8162 "
8163 [(set (attr "far_jump")
8164 (if_then_else
8165 (eq_attr "length" "4")
8166 (const_string "yes")
8167 (const_string "no")))
8168 (set (attr "length")
8169 (if_then_else
911ed8af 8170 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8171 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8172 (const_int 2)
8173 (const_int 4)))]
8174)
8175
d3373b54 8176(define_expand "call"
8177 [(parallel [(call (match_operand 0 "memory_operand" "")
8178 (match_operand 1 "general_operand" ""))
cffb2a26 8179 (use (match_operand 2 "" ""))
bd5b4116 8180 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8181 "TARGET_EITHER"
6c4c2133 8182 "
8183 {
bac7fc85 8184 rtx callee, pat;
bbe777ea 8185
bbe777ea 8186 /* In an untyped call, we can get NULL for operand 2. */
8187 if (operands[2] == NULL_RTX)
8188 operands[2] = const0_rtx;
8189
de55252a 8190 /* Decide if we should generate indirect calls by loading the
85c36fd1 8191 32-bit address of the callee into a register before performing the
de55252a 8192 branch and link. */
8193 callee = XEXP (operands[0], 0);
8194 if (GET_CODE (callee) == SYMBOL_REF
8195 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8196 : !REG_P (callee))
bbe777ea 8197 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8198
8199 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8200 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8201 DONE;
6c4c2133 8202 }"
8203)
d3373b54 8204
bac7fc85 8205(define_expand "call_internal"
8206 [(parallel [(call (match_operand 0 "memory_operand" "")
8207 (match_operand 1 "general_operand" ""))
8208 (use (match_operand 2 "" ""))
8209 (clobber (reg:SI LR_REGNUM))])])
8210
f1039640 8211(define_insn "*call_reg_armv5"
d3373b54 8212 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8213 (match_operand 1 "" ""))
8214 (use (match_operand 2 "" ""))
bd5b4116 8215 (clobber (reg:SI LR_REGNUM))]
f1039640 8216 "TARGET_ARM && arm_arch5"
8217 "blx%?\\t%0"
8218 [(set_attr "type" "call")]
8219)
8220
8221(define_insn "*call_reg_arm"
8222 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8223 (match_operand 1 "" ""))
8224 (use (match_operand 2 "" ""))
8225 (clobber (reg:SI LR_REGNUM))]
8226 "TARGET_ARM && !arm_arch5"
9c08d1fa 8227 "*
5565501b 8228 return output_call (operands);
cffb2a26 8229 "
8230 ;; length is worst case, normally it is only two
8231 [(set_attr "length" "12")
8232 (set_attr "type" "call")]
8233)
9c08d1fa 8234
f7fbdd4a 8235(define_insn "*call_mem"
a3c63a9d 8236 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8237 (match_operand 1 "" ""))
8238 (use (match_operand 2 "" ""))
bd5b4116 8239 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8240 "TARGET_ARM"
9c08d1fa 8241 "*
5565501b 8242 return output_call_mem (operands);
cffb2a26 8243 "
8244 [(set_attr "length" "12")
8245 (set_attr "type" "call")]
8246)
8247
25f905c2 8248(define_insn "*call_reg_thumb1_v5"
cffb2a26 8249 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8250 (match_operand 1 "" ""))
8251 (use (match_operand 2 "" ""))
bd5b4116 8252 (clobber (reg:SI LR_REGNUM))]
25f905c2 8253 "TARGET_THUMB1 && arm_arch5"
f1039640 8254 "blx\\t%0"
8255 [(set_attr "length" "2")
8256 (set_attr "type" "call")]
cffb2a26 8257)
8258
25f905c2 8259(define_insn "*call_reg_thumb1"
f1039640 8260 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8261 (match_operand 1 "" ""))
8262 (use (match_operand 2 "" ""))
bd5b4116 8263 (clobber (reg:SI LR_REGNUM))]
25f905c2 8264 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8265 "*
8266 {
150502c9 8267 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8268 return thumb_call_via_reg (operands[0]);
150502c9 8269 else if (operands[1] == const0_rtx)
f1039640 8270 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8271 else if (frame_pointer_needed)
8272 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8273 else
150502c9 8274 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8275 }"
8276 [(set_attr "type" "call")]
8277)
9c08d1fa 8278
d3373b54 8279(define_expand "call_value"
e0698af7 8280 [(parallel [(set (match_operand 0 "" "")
8281 (call (match_operand 1 "memory_operand" "")
8282 (match_operand 2 "general_operand" "")))
cffb2a26 8283 (use (match_operand 3 "" ""))
bd5b4116 8284 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8285 "TARGET_EITHER"
6c4c2133 8286 "
8287 {
bac7fc85 8288 rtx pat, callee;
bbe777ea 8289
8290 /* In an untyped call, we can get NULL for operand 2. */
8291 if (operands[3] == 0)
8292 operands[3] = const0_rtx;
8293
de55252a 8294 /* Decide if we should generate indirect calls by loading the
8295 32-bit address of the callee into a register before performing the
8296 branch and link. */
8297 callee = XEXP (operands[1], 0);
8298 if (GET_CODE (callee) == SYMBOL_REF
8299 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8300 : !REG_P (callee))
78fe751b 8301 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8302
8303 pat = gen_call_value_internal (operands[0], operands[1],
8304 operands[2], operands[3]);
8305 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8306 DONE;
6c4c2133 8307 }"
8308)
d3373b54 8309
bac7fc85 8310(define_expand "call_value_internal"
8311 [(parallel [(set (match_operand 0 "" "")
8312 (call (match_operand 1 "memory_operand" "")
8313 (match_operand 2 "general_operand" "")))
8314 (use (match_operand 3 "" ""))
8315 (clobber (reg:SI LR_REGNUM))])])
8316
f1039640 8317(define_insn "*call_value_reg_armv5"
27ed6835 8318 [(set (match_operand 0 "" "")
755eb2b4 8319 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8320 (match_operand 2 "" "")))
bbe777ea 8321 (use (match_operand 3 "" ""))
bd5b4116 8322 (clobber (reg:SI LR_REGNUM))]
f1039640 8323 "TARGET_ARM && arm_arch5"
8324 "blx%?\\t%1"
8325 [(set_attr "type" "call")]
8326)
8327
8328(define_insn "*call_value_reg_arm"
8329 [(set (match_operand 0 "" "")
8330 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8331 (match_operand 2 "" "")))
8332 (use (match_operand 3 "" ""))
8333 (clobber (reg:SI LR_REGNUM))]
8334 "TARGET_ARM && !arm_arch5"
9c08d1fa 8335 "*
215b30b3 8336 return output_call (&operands[1]);
cffb2a26 8337 "
8338 [(set_attr "length" "12")
8339 (set_attr "type" "call")]
8340)
9c08d1fa 8341
f7fbdd4a 8342(define_insn "*call_value_mem"
27ed6835 8343 [(set (match_operand 0 "" "")
a3c63a9d 8344 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8345 (match_operand 2 "" "")))
bbe777ea 8346 (use (match_operand 3 "" ""))
bd5b4116 8347 (clobber (reg:SI LR_REGNUM))]
215b30b3 8348 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8349 "*
215b30b3 8350 return output_call_mem (&operands[1]);
cffb2a26 8351 "
8352 [(set_attr "length" "12")
8353 (set_attr "type" "call")]
8354)
9c08d1fa 8355
25f905c2 8356(define_insn "*call_value_reg_thumb1_v5"
f1039640 8357 [(set (match_operand 0 "" "")
8358 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8359 (match_operand 2 "" "")))
8360 (use (match_operand 3 "" ""))
8361 (clobber (reg:SI LR_REGNUM))]
25f905c2 8362 "TARGET_THUMB1 && arm_arch5"
f1039640 8363 "blx\\t%1"
8364 [(set_attr "length" "2")
8365 (set_attr "type" "call")]
8366)
8367
25f905c2 8368(define_insn "*call_value_reg_thumb1"
f1039640 8369 [(set (match_operand 0 "" "")
8370 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8371 (match_operand 2 "" "")))
8372 (use (match_operand 3 "" ""))
8373 (clobber (reg:SI LR_REGNUM))]
25f905c2 8374 "TARGET_THUMB1 && !arm_arch5"
f1039640 8375 "*
8376 {
150502c9 8377 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8378 return thumb_call_via_reg (operands[1]);
150502c9 8379 else if (operands[2] == const0_rtx)
f1039640 8380 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8381 else if (frame_pointer_needed)
8382 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8383 else
150502c9 8384 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8385 }"
8386 [(set_attr "type" "call")]
8387)
8388
9c08d1fa 8389;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8390;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8391
f7fbdd4a 8392(define_insn "*call_symbol"
27ed6835 8393 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8394 (match_operand 1 "" ""))
bbe777ea 8395 (use (match_operand 2 "" ""))
bd5b4116 8396 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8397 "TARGET_ARM
8398 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8399 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8400 "*
8401 {
55c1e470 8402 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8403 }"
cffb2a26 8404 [(set_attr "type" "call")]
8405)
9c08d1fa 8406
f7fbdd4a 8407(define_insn "*call_value_symbol"
ccd90aaa 8408 [(set (match_operand 0 "" "")
27ed6835 8409 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8410 (match_operand:SI 2 "" "")))
bbe777ea 8411 (use (match_operand 3 "" ""))
bd5b4116 8412 (clobber (reg:SI LR_REGNUM))]
cffb2a26 8413 "TARGET_ARM
8414 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8415 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8416 "*
8417 {
55c1e470 8418 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8419 }"
cffb2a26 8420 [(set_attr "type" "call")]
8421)
8422
8423(define_insn "*call_insn"
27ed6835 8424 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8425 (match_operand:SI 1 "" ""))
8426 (use (match_operand 2 "" ""))
bd5b4116 8427 (clobber (reg:SI LR_REGNUM))]
1c494086 8428 "TARGET_THUMB
1675c6e9 8429 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8430 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8431 "bl\\t%a0"
8432 [(set_attr "length" "4")
8433 (set_attr "type" "call")]
8434)
8435
8436(define_insn "*call_value_insn"
ccd90aaa 8437 [(set (match_operand 0 "" "")
27ed6835 8438 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8439 (match_operand 2 "" "")))
8440 (use (match_operand 3 "" ""))
bd5b4116 8441 (clobber (reg:SI LR_REGNUM))]
1c494086 8442 "TARGET_THUMB
1675c6e9 8443 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8444 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8445 "bl\\t%a1"
8446 [(set_attr "length" "4")
8447 (set_attr "type" "call")]
8448)
9c08d1fa 8449
1c494086 8450;; We may also be able to do sibcalls for Thumb, but it's much harder...
8451(define_expand "sibcall"
8452 [(parallel [(call (match_operand 0 "memory_operand" "")
8453 (match_operand 1 "general_operand" ""))
2ba80634 8454 (return)
8455 (use (match_operand 2 "" ""))])]
1c494086 8456 "TARGET_ARM"
8457 "
8458 {
8459 if (operands[2] == NULL_RTX)
8460 operands[2] = const0_rtx;
1c494086 8461 }"
8462)
8463
8464(define_expand "sibcall_value"
ccd90aaa 8465 [(parallel [(set (match_operand 0 "" "")
1c494086 8466 (call (match_operand 1 "memory_operand" "")
8467 (match_operand 2 "general_operand" "")))
2ba80634 8468 (return)
8469 (use (match_operand 3 "" ""))])]
1c494086 8470 "TARGET_ARM"
8471 "
8472 {
8473 if (operands[3] == NULL_RTX)
8474 operands[3] = const0_rtx;
1c494086 8475 }"
8476)
8477
8478(define_insn "*sibcall_insn"
8479 [(call (mem:SI (match_operand:SI 0 "" "X"))
8480 (match_operand 1 "" ""))
2ba80634 8481 (return)
8482 (use (match_operand 2 "" ""))]
1c494086 8483 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8484 "*
8485 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8486 "
8487 [(set_attr "type" "call")]
8488)
8489
8490(define_insn "*sibcall_value_insn"
ccd90aaa 8491 [(set (match_operand 0 "" "")
755eb2b4 8492 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8493 (match_operand 2 "" "")))
2ba80634 8494 (return)
8495 (use (match_operand 3 "" ""))]
1c494086 8496 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8497 "*
8498 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8499 "
8500 [(set_attr "type" "call")]
8501)
8502
9c08d1fa 8503;; Often the return insn will be the same as loading from memory, so set attr
8504(define_insn "return"
8505 [(return)]
cffb2a26 8506 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8507 "*
9c08d1fa 8508 {
cffb2a26 8509 if (arm_ccfsm_state == 2)
8510 {
8511 arm_ccfsm_state += 2;
8512 return \"\";
8513 }
5db468b7 8514 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8515 }"
a2cd141b 8516 [(set_attr "type" "load1")
755eb2b4 8517 (set_attr "length" "12")
0d66636f 8518 (set_attr "predicable" "yes")]
cffb2a26 8519)
9c08d1fa 8520
f7fbdd4a 8521(define_insn "*cond_return"
9c08d1fa 8522 [(set (pc)
8fa3ba89 8523 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8524 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8525 (return)
8526 (pc)))]
cffb2a26 8527 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8528 "*
8fa3ba89 8529 {
8530 if (arm_ccfsm_state == 2)
8531 {
8532 arm_ccfsm_state += 2;
8533 return \"\";
8534 }
8535 return output_return_instruction (operands[0], TRUE, FALSE);
8536 }"
8537 [(set_attr "conds" "use")
755eb2b4 8538 (set_attr "length" "12")
a2cd141b 8539 (set_attr "type" "load1")]
8fa3ba89 8540)
9c08d1fa 8541
f7fbdd4a 8542(define_insn "*cond_return_inverted"
9c08d1fa 8543 [(set (pc)
8fa3ba89 8544 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8545 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8546 (pc)
8547 (return)))]
cffb2a26 8548 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8549 "*
8fa3ba89 8550 {
8551 if (arm_ccfsm_state == 2)
8552 {
8553 arm_ccfsm_state += 2;
8554 return \"\";
8555 }
8556 return output_return_instruction (operands[0], TRUE, TRUE);
8557 }"
8558 [(set_attr "conds" "use")
37a1317b 8559 (set_attr "length" "12")
a2cd141b 8560 (set_attr "type" "load1")]
8fa3ba89 8561)
9c08d1fa 8562
68121397 8563;; Generate a sequence of instructions to determine if the processor is
8564;; in 26-bit or 32-bit mode, and return the appropriate return address
8565;; mask.
8566
8567(define_expand "return_addr_mask"
8568 [(set (match_dup 1)
8569 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8570 (const_int 0)))
8571 (set (match_operand:SI 0 "s_register_operand" "")
8572 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8573 (const_int -1)
8574 (const_int 67108860)))] ; 0x03fffffc
8575 "TARGET_ARM"
8576 "
62eddbd4 8577 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8578 ")
8579
8580(define_insn "*check_arch2"
8581 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8582 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8583 (const_int 0)))]
8584 "TARGET_ARM"
8585 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8586 [(set_attr "length" "8")
8587 (set_attr "conds" "set")]
8588)
8589
9c08d1fa 8590;; Call subroutine returning any type.
8591
8592(define_expand "untyped_call"
8593 [(parallel [(call (match_operand 0 "" "")
8594 (const_int 0))
8595 (match_operand 1 "" "")
8596 (match_operand 2 "" "")])]
ccd90aaa 8597 "TARGET_EITHER"
9c08d1fa 8598 "
215b30b3 8599 {
8600 int i;
ccd90aaa 8601 rtx par = gen_rtx_PARALLEL (VOIDmode,
8602 rtvec_alloc (XVECLEN (operands[2], 0)));
8603 rtx addr = gen_reg_rtx (Pmode);
8604 rtx mem;
8605 int size = 0;
9c08d1fa 8606
ccd90aaa 8607 emit_move_insn (addr, XEXP (operands[1], 0));
8608 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8609
215b30b3 8610 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8611 {
ccd90aaa 8612 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8613
ccd90aaa 8614 /* Default code only uses r0 as a return value, but we could
8615 be using anything up to 4 registers. */
8616 if (REGNO (src) == R0_REGNUM)
8617 src = gen_rtx_REG (TImode, R0_REGNUM);
8618
8619 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8620 GEN_INT (size));
8621 size += GET_MODE_SIZE (GET_MODE (src));
8622 }
8623
8624 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8625 const0_rtx));
8626
8627 size = 0;
8628
8629 for (i = 0; i < XVECLEN (par, 0); i++)
8630 {
8631 HOST_WIDE_INT offset = 0;
8632 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8633
8634 if (size != 0)
8635 emit_move_insn (addr, plus_constant (addr, size));
8636
8637 mem = change_address (mem, GET_MODE (reg), NULL);
8638 if (REGNO (reg) == R0_REGNUM)
8639 {
8640 /* On thumb we have to use a write-back instruction. */
8641 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8642 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8643 size = TARGET_ARM ? 16 : 0;
8644 }
8645 else
8646 {
8647 emit_move_insn (mem, reg);
8648 size = GET_MODE_SIZE (GET_MODE (reg));
8649 }
215b30b3 8650 }
9c08d1fa 8651
215b30b3 8652 /* The optimizer does not know that the call sets the function value
8653 registers we stored in the result block. We avoid problems by
8654 claiming that all hard registers are used and clobbered at this
8655 point. */
8656 emit_insn (gen_blockage ());
8657
8658 DONE;
8659 }"
8660)
9c08d1fa 8661
ccd90aaa 8662(define_expand "untyped_return"
8663 [(match_operand:BLK 0 "memory_operand" "")
8664 (match_operand 1 "" "")]
8665 "TARGET_EITHER"
8666 "
8667 {
8668 int i;
8669 rtx addr = gen_reg_rtx (Pmode);
8670 rtx mem;
8671 int size = 0;
8672
8673 emit_move_insn (addr, XEXP (operands[0], 0));
8674 mem = change_address (operands[0], BLKmode, addr);
8675
8676 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8677 {
8678 HOST_WIDE_INT offset = 0;
8679 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8680
8681 if (size != 0)
8682 emit_move_insn (addr, plus_constant (addr, size));
8683
8684 mem = change_address (mem, GET_MODE (reg), NULL);
8685 if (REGNO (reg) == R0_REGNUM)
8686 {
8687 /* On thumb we have to use a write-back instruction. */
8688 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8689 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8690 size = TARGET_ARM ? 16 : 0;
8691 }
8692 else
8693 {
8694 emit_move_insn (reg, mem);
8695 size = GET_MODE_SIZE (GET_MODE (reg));
8696 }
8697 }
8698
8699 /* Emit USE insns before the return. */
8700 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8701 emit_insn (gen_rtx_USE (VOIDmode,
8702 SET_DEST (XVECEXP (operands[1], 0, i))));
8703
8704 /* Construct the return. */
8705 expand_naked_return ();
8706
8707 DONE;
8708 }"
8709)
8710
9c08d1fa 8711;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8712;; all of memory. This blocks insns from being moved across this point.
8713
8714(define_insn "blockage"
e1159bbe 8715 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8716 "TARGET_EITHER"
9c08d1fa 8717 ""
cffb2a26 8718 [(set_attr "length" "0")
8719 (set_attr "type" "block")]
8720)
9c08d1fa 8721
f7fbdd4a 8722(define_expand "casesi"
8723 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8724 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8725 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8726 (match_operand:SI 3 "" "") ; table label
8727 (match_operand:SI 4 "" "")] ; Out of range label
25f905c2 8728 "TARGET_32BIT"
f7fbdd4a 8729 "
215b30b3 8730 {
8731 rtx reg;
8732 if (operands[1] != const0_rtx)
8733 {
8734 reg = gen_reg_rtx (SImode);
f7fbdd4a 8735
215b30b3 8736 emit_insn (gen_addsi3 (reg, operands[0],
8737 GEN_INT (-INTVAL (operands[1]))));
8738 operands[0] = reg;
8739 }
9c08d1fa 8740
215b30b3 8741 if (!const_ok_for_arm (INTVAL (operands[2])))
8742 operands[2] = force_reg (SImode, operands[2]);
8743
25f905c2 8744 if (TARGET_ARM)
8745 {
8746 emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
8747 operands[3], operands[4]));
8748 }
8749 else if (flag_pic)
8750 {
8751 emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
8752 operands[2], operands[3], operands[4]));
8753 }
8754 else
8755 {
8756 emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
8757 operands[3], operands[4]));
8758 }
215b30b3 8759 DONE;
8760 }"
8761)
f7fbdd4a 8762
f082f1c4 8763;; The USE in this pattern is needed to tell flow analysis that this is
8764;; a CASESI insn. It has no other purpose.
25f905c2 8765(define_insn "arm_casesi_internal"
f082f1c4 8766 [(parallel [(set (pc)
8767 (if_then_else
8768 (leu (match_operand:SI 0 "s_register_operand" "r")
8769 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8770 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8771 (label_ref (match_operand 2 "" ""))))
8772 (label_ref (match_operand 3 "" ""))))
bd5b4116 8773 (clobber (reg:CC CC_REGNUM))
f082f1c4 8774 (use (label_ref (match_dup 2)))])]
cffb2a26 8775 "TARGET_ARM"
f7fbdd4a 8776 "*
0d66636f 8777 if (flag_pic)
8778 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8779 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8780 "
8781 [(set_attr "conds" "clob")
8782 (set_attr "length" "12")]
8783)
9c08d1fa 8784
cffb2a26 8785(define_expand "indirect_jump"
9c08d1fa 8786 [(set (pc)
cffb2a26 8787 (match_operand:SI 0 "s_register_operand" ""))]
8788 "TARGET_EITHER"
25f905c2 8789 "
8790 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8791 address and use bx. */
8792 if (TARGET_THUMB2)
8793 {
8794 rtx tmp;
8795 tmp = gen_reg_rtx (SImode);
8796 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8797 operands[0] = tmp;
8798 }
8799 "
cffb2a26 8800)
8801
f1039640 8802;; NB Never uses BX.
cffb2a26 8803(define_insn "*arm_indirect_jump"
8804 [(set (pc)
8805 (match_operand:SI 0 "s_register_operand" "r"))]
8806 "TARGET_ARM"
8807 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8808 [(set_attr "predicable" "yes")]
cffb2a26 8809)
9c08d1fa 8810
f7fbdd4a 8811(define_insn "*load_indirect_jump"
9c08d1fa 8812 [(set (pc)
8813 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8814 "TARGET_ARM"
8815 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8816 [(set_attr "type" "load1")
61a2d04c 8817 (set_attr "pool_range" "4096")
8818 (set_attr "neg_pool_range" "4084")
0d66636f 8819 (set_attr "predicable" "yes")]
cffb2a26 8820)
8821
f1039640 8822;; NB Never uses BX.
25f905c2 8823(define_insn "*thumb1_indirect_jump"
cffb2a26 8824 [(set (pc)
8825 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8826 "TARGET_THUMB1"
cffb2a26 8827 "mov\\tpc, %0"
8828 [(set_attr "conds" "clob")
8829 (set_attr "length" "2")]
8830)
8831
9c08d1fa 8832\f
8833;; Misc insns
8834
8835(define_insn "nop"
8836 [(const_int 0)]
cffb2a26 8837 "TARGET_EITHER"
8838 "*
25f905c2 8839 if (TARGET_UNIFIED_ASM)
8840 return \"nop\";
cffb2a26 8841 if (TARGET_ARM)
8842 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8843 return \"mov\\tr8, r8\";
8844 "
8845 [(set (attr "length")
8846 (if_then_else (eq_attr "is_thumb" "yes")
8847 (const_int 2)
8848 (const_int 4)))]
8849)
8850
9c08d1fa 8851\f
8852;; Patterns to allow combination of arithmetic, cond code and shifts
8853
f7fbdd4a 8854(define_insn "*arith_shiftsi"
9c08d1fa 8855 [(set (match_operand:SI 0 "s_register_operand" "=r")
8856 (match_operator:SI 1 "shiftable_operator"
8857 [(match_operator:SI 3 "shift_operator"
8858 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8859 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8860 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 8861 "TARGET_ARM"
6c4c2133 8862 "%i1%?\\t%0, %2, %4%S3"
344495ea 8863 [(set_attr "predicable" "yes")
331beb1a 8864 (set_attr "shift" "4")
a2cd141b 8865 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8866 (const_string "alu_shift")
8867 (const_string "alu_shift_reg")))]
6c4c2133 8868)
9c08d1fa 8869
d7863cfe 8870(define_split
8871 [(set (match_operand:SI 0 "s_register_operand" "")
8872 (match_operator:SI 1 "shiftable_operator"
8873 [(match_operator:SI 2 "shiftable_operator"
8874 [(match_operator:SI 3 "shift_operator"
8875 [(match_operand:SI 4 "s_register_operand" "")
8876 (match_operand:SI 5 "reg_or_int_operand" "")])
8877 (match_operand:SI 6 "s_register_operand" "")])
8878 (match_operand:SI 7 "arm_rhs_operand" "")]))
8879 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8880 "TARGET_ARM"
8881 [(set (match_dup 8)
8882 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8883 (match_dup 6)]))
8884 (set (match_dup 0)
8885 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8886 "")
8887
f7fbdd4a 8888(define_insn "*arith_shiftsi_compare0"
bd5b4116 8889 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8890 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8891 [(match_operator:SI 3 "shift_operator"
8892 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8893 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8894 (match_operand:SI 2 "s_register_operand" "r")])
8895 (const_int 0)))
8896 (set (match_operand:SI 0 "s_register_operand" "=r")
8897 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8898 (match_dup 2)]))]
cffb2a26 8899 "TARGET_ARM"
25f905c2 8900 "%i1%.\\t%0, %2, %4%S3"
344495ea 8901 [(set_attr "conds" "set")
331beb1a 8902 (set_attr "shift" "4")
a2cd141b 8903 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8904 (const_string "alu_shift")
8905 (const_string "alu_shift_reg")))]
0d66636f 8906)
9c08d1fa 8907
f7fbdd4a 8908(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8909 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8910 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8911 [(match_operator:SI 3 "shift_operator"
8912 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8913 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8914 (match_operand:SI 2 "s_register_operand" "r")])
8915 (const_int 0)))
8916 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8917 "TARGET_ARM"
25f905c2 8918 "%i1%.\\t%0, %2, %4%S3"
344495ea 8919 [(set_attr "conds" "set")
331beb1a 8920 (set_attr "shift" "4")
a2cd141b 8921 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8922 (const_string "alu_shift")
8923 (const_string "alu_shift_reg")))]
0d66636f 8924)
9c08d1fa 8925
f7fbdd4a 8926(define_insn "*sub_shiftsi"
9c08d1fa 8927 [(set (match_operand:SI 0 "s_register_operand" "=r")
8928 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8929 (match_operator:SI 2 "shift_operator"
8930 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8931 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 8932 "TARGET_ARM"
6c4c2133 8933 "sub%?\\t%0, %1, %3%S2"
344495ea 8934 [(set_attr "predicable" "yes")
331beb1a 8935 (set_attr "shift" "3")
a2cd141b 8936 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8937 (const_string "alu_shift")
8938 (const_string "alu_shift_reg")))]
6c4c2133 8939)
9c08d1fa 8940
f7fbdd4a 8941(define_insn "*sub_shiftsi_compare0"
bd5b4116 8942 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8943 (compare:CC_NOOV
8944 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8945 (match_operator:SI 2 "shift_operator"
8946 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8947 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8948 (const_int 0)))
9c08d1fa 8949 (set (match_operand:SI 0 "s_register_operand" "=r")
8950 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8951 (match_dup 4)])))]
cffb2a26 8952 "TARGET_ARM"
25f905c2 8953 "sub%.\\t%0, %1, %3%S2"
344495ea 8954 [(set_attr "conds" "set")
a2cd141b 8955 (set_attr "shift" "3")
8956 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8957 (const_string "alu_shift")
8958 (const_string "alu_shift_reg")))]
0d66636f 8959)
9c08d1fa 8960
f7fbdd4a 8961(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8962 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8963 (compare:CC_NOOV
8964 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8965 (match_operator:SI 2 "shift_operator"
8966 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8967 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8968 (const_int 0)))
9c08d1fa 8969 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8970 "TARGET_ARM"
25f905c2 8971 "sub%.\\t%0, %1, %3%S2"
344495ea 8972 [(set_attr "conds" "set")
a2cd141b 8973 (set_attr "shift" "3")
8974 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8975 (const_string "alu_shift")
8976 (const_string "alu_shift_reg")))]
0d66636f 8977)
9c08d1fa 8978
9c08d1fa 8979\f
8980
f7fbdd4a 8981(define_insn "*and_scc"
9c08d1fa 8982 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8983 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8984 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8985 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8986 "TARGET_ARM"
e2348bcb 8987 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8988 [(set_attr "conds" "use")
8989 (set_attr "length" "8")]
8990)
9c08d1fa 8991
f7fbdd4a 8992(define_insn "*ior_scc"
9c08d1fa 8993 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8994 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8995 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8996 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8997 "TARGET_ARM"
e2348bcb 8998 "@
899850b0 8999 orr%d2\\t%0, %1, #1
9000 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9001 [(set_attr "conds" "use")
9002 (set_attr "length" "4,8")]
9003)
9c08d1fa 9004
f7fbdd4a 9005(define_insn "*compare_scc"
5565501b 9006 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9007 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9008 [(match_operand:SI 2 "s_register_operand" "r,r")
9009 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9010 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9011 "TARGET_ARM"
9c08d1fa 9012 "*
601f584c 9013 if (operands[3] == const0_rtx)
9014 {
9015 if (GET_CODE (operands[1]) == LT)
9016 return \"mov\\t%0, %2, lsr #31\";
9017
9018 if (GET_CODE (operands[1]) == GE)
9019 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 9020
601f584c 9021 if (GET_CODE (operands[1]) == EQ)
9022 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9023 }
e2348bcb 9024
8fa3ba89 9025 if (GET_CODE (operands[1]) == NE)
9026 {
9027 if (which_alternative == 1)
9028 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9029 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9030 }
9031 if (which_alternative == 1)
9032 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9033 else
9034 output_asm_insn (\"cmp\\t%2, %3\", operands);
9035 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9036 "
9037 [(set_attr "conds" "clob")
9038 (set_attr "length" "12")]
9039)
9c08d1fa 9040
f7fbdd4a 9041(define_insn "*cond_move"
9c08d1fa 9042 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9043 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9044 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9045 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9046 (const_int 0)])
9047 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9048 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9049 "TARGET_ARM"
9c08d1fa 9050 "*
8fa3ba89 9051 if (GET_CODE (operands[3]) == NE)
9052 {
9053 if (which_alternative != 1)
9054 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9055 if (which_alternative != 0)
9056 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9057 return \"\";
9058 }
9059 if (which_alternative != 0)
9060 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9061 if (which_alternative != 1)
9062 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9063 return \"\";
9064 "
9065 [(set_attr "conds" "use")
9066 (set_attr "length" "4,4,8")]
9067)
9c08d1fa 9068
f7fbdd4a 9069(define_insn "*cond_arith"
9c08d1fa 9070 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9071 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9072 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9073 [(match_operand:SI 2 "s_register_operand" "r,r")
9074 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9075 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9076 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9077 "TARGET_ARM"
9c08d1fa 9078 "*
8fa3ba89 9079 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9080 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9081
8fa3ba89 9082 output_asm_insn (\"cmp\\t%2, %3\", operands);
9083 if (GET_CODE (operands[5]) == AND)
9084 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9085 else if (GET_CODE (operands[5]) == MINUS)
9086 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9087 else if (which_alternative != 0)
9088 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9089 return \"%i5%d4\\t%0, %1, #1\";
9090 "
9091 [(set_attr "conds" "clob")
9092 (set_attr "length" "12")]
9093)
9c08d1fa 9094
f7fbdd4a 9095(define_insn "*cond_sub"
9c08d1fa 9096 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9097 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9098 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9099 [(match_operand:SI 2 "s_register_operand" "r,r")
9100 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9101 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9102 "TARGET_ARM"
9c08d1fa 9103 "*
8fa3ba89 9104 output_asm_insn (\"cmp\\t%2, %3\", operands);
9105 if (which_alternative != 0)
9106 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9107 return \"sub%d4\\t%0, %1, #1\";
9108 "
9109 [(set_attr "conds" "clob")
9110 (set_attr "length" "8,12")]
9111)
9c08d1fa 9112
25f905c2 9113;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
aea4c774 9114(define_insn "*cmp_ite0"
cffb2a26 9115 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9116 (compare
9117 (if_then_else:SI
8fa3ba89 9118 (match_operator 4 "arm_comparison_operator"
aea4c774 9119 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9120 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9121 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9122 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9123 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9124 (const_int 0))
9125 (const_int 0)))]
cffb2a26 9126 "TARGET_ARM"
9c08d1fa 9127 "*
aea4c774 9128 {
8fa3ba89 9129 static const char * const opcodes[4][2] =
9130 {
9131 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9132 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9133 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9134 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9135 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9136 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9137 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9138 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9139 };
9140 int swap =
9141 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9142
9143 return opcodes[which_alternative][swap];
9144 }"
9145 [(set_attr "conds" "set")
9146 (set_attr "length" "8")]
9147)
9c08d1fa 9148
aea4c774 9149(define_insn "*cmp_ite1"
cffb2a26 9150 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9151 (compare
9152 (if_then_else:SI
8fa3ba89 9153 (match_operator 4 "arm_comparison_operator"
aea4c774 9154 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 9155 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 9156 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 9157 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 9158 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 9159 (const_int 1))
9160 (const_int 0)))]
cffb2a26 9161 "TARGET_ARM"
9c08d1fa 9162 "*
9c08d1fa 9163 {
215b30b3 9164 static const char * const opcodes[4][2] =
9165 {
9166 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9167 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9168 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9169 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9170 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9171 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9172 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9173 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9174 };
9175 int swap =
9176 comparison_dominates_p (GET_CODE (operands[5]),
9177 reverse_condition (GET_CODE (operands[4])));
9178
9179 return opcodes[which_alternative][swap];
9180 }"
8fa3ba89 9181 [(set_attr "conds" "set")
9182 (set_attr "length" "8")]
9183)
9c08d1fa 9184
f6c53574 9185(define_insn "*cmp_and"
9186 [(set (match_operand 6 "dominant_cc_register" "")
9187 (compare
9188 (and:SI
9189 (match_operator 4 "arm_comparison_operator"
9190 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9191 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9192 (match_operator:SI 5 "arm_comparison_operator"
9193 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9194 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9195 (const_int 0)))]
9196 "TARGET_ARM"
9197 "*
9198 {
35823b64 9199 static const char *const opcodes[4][2] =
f6c53574 9200 {
9201 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9202 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9203 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9204 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9205 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9206 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9207 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9208 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9209 };
9210 int swap =
9211 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9212
9213 return opcodes[which_alternative][swap];
9214 }"
9215 [(set_attr "conds" "set")
9216 (set_attr "predicable" "no")
9217 (set_attr "length" "8")]
9218)
9219
9220(define_insn "*cmp_ior"
9221 [(set (match_operand 6 "dominant_cc_register" "")
9222 (compare
9223 (ior:SI
9224 (match_operator 4 "arm_comparison_operator"
9225 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9226 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9227 (match_operator:SI 5 "arm_comparison_operator"
9228 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9229 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9230 (const_int 0)))]
9231 "TARGET_ARM"
9232 "*
9233{
35823b64 9234 static const char *const opcodes[4][2] =
f6c53574 9235 {
9236 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9237 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9238 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9239 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9240 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9241 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9242 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9243 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9244 };
9245 int swap =
9246 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9247
9248 return opcodes[which_alternative][swap];
9249}
9250"
9251 [(set_attr "conds" "set")
9252 (set_attr "length" "8")]
9253)
9254
3c5afce6 9255(define_insn_and_split "*ior_scc_scc"
9256 [(set (match_operand:SI 0 "s_register_operand" "=r")
9257 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9258 [(match_operand:SI 1 "s_register_operand" "r")
9259 (match_operand:SI 2 "arm_add_operand" "rIL")])
9260 (match_operator:SI 6 "arm_comparison_operator"
9261 [(match_operand:SI 4 "s_register_operand" "r")
9262 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9263 (clobber (reg:CC CC_REGNUM))]
9264 "TARGET_ARM
9265 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9266 != CCmode)"
9267 "#"
9268 "TARGET_ARM && reload_completed"
9269 [(set (match_dup 7)
9270 (compare
9271 (ior:SI
9272 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9273 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9274 (const_int 0)))
9275 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9276 "operands[7]
9277 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9278 DOM_CC_X_OR_Y),
601f584c 9279 CC_REGNUM);"
9280 [(set_attr "conds" "clob")
9281 (set_attr "length" "16")])
9282
9283; If the above pattern is followed by a CMP insn, then the compare is
9284; redundant, since we can rework the conditional instruction that follows.
9285(define_insn_and_split "*ior_scc_scc_cmp"
9286 [(set (match_operand 0 "dominant_cc_register" "")
9287 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9288 [(match_operand:SI 1 "s_register_operand" "r")
9289 (match_operand:SI 2 "arm_add_operand" "rIL")])
9290 (match_operator:SI 6 "arm_comparison_operator"
9291 [(match_operand:SI 4 "s_register_operand" "r")
9292 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9293 (const_int 0)))
9294 (set (match_operand:SI 7 "s_register_operand" "=r")
9295 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9296 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9297 "TARGET_ARM"
9298 "#"
9299 "TARGET_ARM && reload_completed"
9300 [(set (match_dup 0)
9301 (compare
9302 (ior:SI
9303 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9304 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9305 (const_int 0)))
9306 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9307 ""
9308 [(set_attr "conds" "set")
9309 (set_attr "length" "16")])
3c5afce6 9310
9311(define_insn_and_split "*and_scc_scc"
9312 [(set (match_operand:SI 0 "s_register_operand" "=r")
9313 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9314 [(match_operand:SI 1 "s_register_operand" "r")
9315 (match_operand:SI 2 "arm_add_operand" "rIL")])
9316 (match_operator:SI 6 "arm_comparison_operator"
9317 [(match_operand:SI 4 "s_register_operand" "r")
9318 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9319 (clobber (reg:CC CC_REGNUM))]
9320 "TARGET_ARM
9321 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9322 != CCmode)"
9323 "#"
601f584c 9324 "TARGET_ARM && reload_completed
9325 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9326 != CCmode)"
3c5afce6 9327 [(set (match_dup 7)
9328 (compare
9329 (and:SI
9330 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9331 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9332 (const_int 0)))
9333 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9334 "operands[7]
9335 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9336 DOM_CC_X_AND_Y),
601f584c 9337 CC_REGNUM);"
9338 [(set_attr "conds" "clob")
9339 (set_attr "length" "16")])
9340
9341; If the above pattern is followed by a CMP insn, then the compare is
9342; redundant, since we can rework the conditional instruction that follows.
9343(define_insn_and_split "*and_scc_scc_cmp"
9344 [(set (match_operand 0 "dominant_cc_register" "")
9345 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9346 [(match_operand:SI 1 "s_register_operand" "r")
9347 (match_operand:SI 2 "arm_add_operand" "rIL")])
9348 (match_operator:SI 6 "arm_comparison_operator"
9349 [(match_operand:SI 4 "s_register_operand" "r")
9350 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9351 (const_int 0)))
9352 (set (match_operand:SI 7 "s_register_operand" "=r")
9353 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9354 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9355 "TARGET_ARM"
9356 "#"
9357 "TARGET_ARM && reload_completed"
9358 [(set (match_dup 0)
9359 (compare
9360 (and:SI
9361 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9362 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9363 (const_int 0)))
9364 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9365 ""
9366 [(set_attr "conds" "set")
9367 (set_attr "length" "16")])
9368
9369;; If there is no dominance in the comparison, then we can still save an
9370;; instruction in the AND case, since we can know that the second compare
9371;; need only zero the value if false (if true, then the value is already
9372;; correct).
9373(define_insn_and_split "*and_scc_scc_nodom"
9374 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9375 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9376 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9377 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9378 (match_operator:SI 6 "arm_comparison_operator"
9379 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9380 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9381 (clobber (reg:CC CC_REGNUM))]
9382 "TARGET_ARM
9383 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9384 == CCmode)"
9385 "#"
9386 "TARGET_ARM && reload_completed"
9387 [(parallel [(set (match_dup 0)
9388 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9389 (clobber (reg:CC CC_REGNUM))])
9390 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9391 (set (match_dup 0)
9392 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9393 (match_dup 0)
9394 (const_int 0)))]
9395 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9396 operands[4], operands[5]),
9397 CC_REGNUM);
9398 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9399 operands[5]);"
9400 [(set_attr "conds" "clob")
9401 (set_attr "length" "20")])
3c5afce6 9402
3a0bdee0 9403(define_split
9404 [(set (reg:CC_NOOV CC_REGNUM)
9405 (compare:CC_NOOV (ior:SI
9406 (and:SI (match_operand:SI 0 "s_register_operand" "")
9407 (const_int 1))
9408 (match_operator:SI 1 "comparison_operator"
9409 [(match_operand:SI 2 "s_register_operand" "")
9410 (match_operand:SI 3 "arm_add_operand" "")]))
9411 (const_int 0)))
9412 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9413 "TARGET_ARM"
9414 [(set (match_dup 4)
9415 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9416 (match_dup 0)))
9417 (set (reg:CC_NOOV CC_REGNUM)
9418 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9419 (const_int 0)))]
9420 "")
9421
9422(define_split
9423 [(set (reg:CC_NOOV CC_REGNUM)
9424 (compare:CC_NOOV (ior:SI
9425 (match_operator:SI 1 "comparison_operator"
9426 [(match_operand:SI 2 "s_register_operand" "")
9427 (match_operand:SI 3 "arm_add_operand" "")])
9428 (and:SI (match_operand:SI 0 "s_register_operand" "")
9429 (const_int 1)))
9430 (const_int 0)))
9431 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9432 "TARGET_ARM"
9433 [(set (match_dup 4)
9434 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9435 (match_dup 0)))
9436 (set (reg:CC_NOOV CC_REGNUM)
9437 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9438 (const_int 0)))]
9439 "")
25f905c2 9440;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9441
f7fbdd4a 9442(define_insn "*negscc"
9c08d1fa 9443 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9444 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9445 [(match_operand:SI 1 "s_register_operand" "r")
9446 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9447 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9448 "TARGET_ARM"
9c08d1fa 9449 "*
2ca2ec2e 9450 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9451 return \"mov\\t%0, %1, asr #31\";
9452
9c08d1fa 9453 if (GET_CODE (operands[3]) == NE)
e2348bcb 9454 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9455
e2348bcb 9456 output_asm_insn (\"cmp\\t%1, %2\", operands);
9457 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9458 return \"mvn%d3\\t%0, #0\";
215b30b3 9459 "
8fa3ba89 9460 [(set_attr "conds" "clob")
9461 (set_attr "length" "12")]
9462)
9c08d1fa 9463
9464(define_insn "movcond"
9465 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9466 (if_then_else:SI
8fa3ba89 9467 (match_operator 5 "arm_comparison_operator"
5565501b 9468 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9469 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9470 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9471 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9472 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9473 "TARGET_ARM"
9c08d1fa 9474 "*
9475 if (GET_CODE (operands[5]) == LT
9476 && (operands[4] == const0_rtx))
9477 {
5565501b 9478 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9479 {
9c08d1fa 9480 if (operands[2] == const0_rtx)
e2348bcb 9481 return \"and\\t%0, %1, %3, asr #31\";
9482 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9483 }
9484 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9485 {
9c08d1fa 9486 if (operands[1] == const0_rtx)
e2348bcb 9487 return \"bic\\t%0, %2, %3, asr #31\";
9488 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9489 }
9490 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9491 are constants. */
9c08d1fa 9492 }
e2348bcb 9493
9c08d1fa 9494 if (GET_CODE (operands[5]) == GE
9495 && (operands[4] == const0_rtx))
9496 {
9497 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9498 {
9c08d1fa 9499 if (operands[2] == const0_rtx)
e2348bcb 9500 return \"bic\\t%0, %1, %3, asr #31\";
9501 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9502 }
9503 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9504 {
9c08d1fa 9505 if (operands[1] == const0_rtx)
e2348bcb 9506 return \"and\\t%0, %2, %3, asr #31\";
9507 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9508 }
9509 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9510 are constants. */
9c08d1fa 9511 }
9512 if (GET_CODE (operands[4]) == CONST_INT
9513 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9514 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9515 else
e2348bcb 9516 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9517 if (which_alternative != 0)
e2348bcb 9518 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9519 if (which_alternative != 1)
e2348bcb 9520 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9521 return \"\";
215b30b3 9522 "
8fa3ba89 9523 [(set_attr "conds" "clob")
9524 (set_attr "length" "8,8,12")]
9525)
9c08d1fa 9526
25f905c2 9527;; ??? The patterns below need checking for Thumb-2 usefulness.
9528
8a18b90c 9529(define_insn "*ifcompare_plus_move"
9530 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9531 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9532 [(match_operand:SI 4 "s_register_operand" "r,r")
9533 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9534 (plus:SI
9535 (match_operand:SI 2 "s_register_operand" "r,r")
9536 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9537 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9538 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9539 "TARGET_ARM"
8a18b90c 9540 "#"
8fa3ba89 9541 [(set_attr "conds" "clob")
9542 (set_attr "length" "8,12")]
9543)
8a18b90c 9544
9545(define_insn "*if_plus_move"
129a2fe4 9546 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9547 (if_then_else:SI
8fa3ba89 9548 (match_operator 4 "arm_comparison_operator"
8a18b90c 9549 [(match_operand 5 "cc_register" "") (const_int 0)])
9550 (plus:SI
129a2fe4 9551 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9552 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9553 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9554 "TARGET_ARM"
8a18b90c 9555 "@
9556 add%d4\\t%0, %2, %3
9557 sub%d4\\t%0, %2, #%n3
9558 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9559 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9560 [(set_attr "conds" "use")
9561 (set_attr "length" "4,4,8,8")
9562 (set_attr "type" "*,*,*,*")]
9563)
8a18b90c 9564
9565(define_insn "*ifcompare_move_plus"
5565501b 9566 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9567 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9568 [(match_operand:SI 4 "s_register_operand" "r,r")
9569 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9570 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9571 (plus:SI
9572 (match_operand:SI 2 "s_register_operand" "r,r")
9573 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9574 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9575 "TARGET_ARM"
8a18b90c 9576 "#"
8fa3ba89 9577 [(set_attr "conds" "clob")
9578 (set_attr "length" "8,12")]
9579)
8a18b90c 9580
9581(define_insn "*if_move_plus"
129a2fe4 9582 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9583 (if_then_else:SI
8fa3ba89 9584 (match_operator 4 "arm_comparison_operator"
8a18b90c 9585 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9586 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9587 (plus:SI
129a2fe4 9588 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9589 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9590 "TARGET_ARM"
8a18b90c 9591 "@
9592 add%D4\\t%0, %2, %3
9593 sub%D4\\t%0, %2, #%n3
9594 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9595 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9596 [(set_attr "conds" "use")
9597 (set_attr "length" "4,4,8,8")
9598 (set_attr "type" "*,*,*,*")]
9599)
8a18b90c 9600
9601(define_insn "*ifcompare_arith_arith"
9602 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9603 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9604 [(match_operand:SI 5 "s_register_operand" "r")
9605 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9606 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9607 [(match_operand:SI 1 "s_register_operand" "r")
9608 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9609 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9610 [(match_operand:SI 3 "s_register_operand" "r")
9611 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9612 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9613 "TARGET_ARM"
8a18b90c 9614 "#"
8fa3ba89 9615 [(set_attr "conds" "clob")
9616 (set_attr "length" "12")]
9617)
9c08d1fa 9618
8a18b90c 9619(define_insn "*if_arith_arith"
9620 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9621 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9622 [(match_operand 8 "cc_register" "") (const_int 0)])
9623 (match_operator:SI 6 "shiftable_operator"
9624 [(match_operand:SI 1 "s_register_operand" "r")
9625 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9626 (match_operator:SI 7 "shiftable_operator"
9627 [(match_operand:SI 3 "s_register_operand" "r")
9628 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9629 "TARGET_ARM"
8a18b90c 9630 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9631 [(set_attr "conds" "use")
9632 (set_attr "length" "8")]
9633)
8a18b90c 9634
f7fbdd4a 9635(define_insn "*ifcompare_arith_move"
9c08d1fa 9636 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9637 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9638 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9639 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9640 (match_operator:SI 7 "shiftable_operator"
9641 [(match_operand:SI 4 "s_register_operand" "r,r")
9642 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9643 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9644 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9645 "TARGET_ARM"
9c08d1fa 9646 "*
9c08d1fa 9647 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9648 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9649 everything is in registers then we can do this in two instructions. */
9c08d1fa 9650 if (operands[3] == const0_rtx
9651 && GET_CODE (operands[7]) != AND
9652 && GET_CODE (operands[5]) == REG
9653 && GET_CODE (operands[1]) == REG
9654 && REGNO (operands[1]) == REGNO (operands[4])
9655 && REGNO (operands[4]) != REGNO (operands[0]))
9656 {
9657 if (GET_CODE (operands[6]) == LT)
40dbec34 9658 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9659 else if (GET_CODE (operands[6]) == GE)
40dbec34 9660 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9661 }
9662 if (GET_CODE (operands[3]) == CONST_INT
9663 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9664 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9665 else
e2348bcb 9666 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9667 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9668 if (which_alternative != 0)
129a2fe4 9669 return \"mov%D6\\t%0, %1\";
9c08d1fa 9670 return \"\";
215b30b3 9671 "
8fa3ba89 9672 [(set_attr "conds" "clob")
9673 (set_attr "length" "8,12")]
9674)
9c08d1fa 9675
8a18b90c 9676(define_insn "*if_arith_move"
129a2fe4 9677 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9678 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9679 [(match_operand 6 "cc_register" "") (const_int 0)])
9680 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9681 [(match_operand:SI 2 "s_register_operand" "r,r")
9682 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9683 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9684 "TARGET_ARM"
8a18b90c 9685 "@
9686 %I5%d4\\t%0, %2, %3
129a2fe4 9687 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9688 [(set_attr "conds" "use")
9689 (set_attr "length" "4,8")
9690 (set_attr "type" "*,*")]
9691)
8a18b90c 9692
f7fbdd4a 9693(define_insn "*ifcompare_move_arith"
9c08d1fa 9694 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9695 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9696 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9697 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9698 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9699 (match_operator:SI 7 "shiftable_operator"
9700 [(match_operand:SI 2 "s_register_operand" "r,r")
9701 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9702 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9703 "TARGET_ARM"
9c08d1fa 9704 "*
9c08d1fa 9705 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9706 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9707 everything is in registers then we can do this in two instructions */
9708 if (operands[5] == const0_rtx
9709 && GET_CODE (operands[7]) != AND
9710 && GET_CODE (operands[3]) == REG
9711 && GET_CODE (operands[1]) == REG
9712 && REGNO (operands[1]) == REGNO (operands[2])
9713 && REGNO (operands[2]) != REGNO (operands[0]))
9714 {
9715 if (GET_CODE (operands[6]) == GE)
40dbec34 9716 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9717 else if (GET_CODE (operands[6]) == LT)
40dbec34 9718 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9719 }
40dbec34 9720
9c08d1fa 9721 if (GET_CODE (operands[5]) == CONST_INT
9722 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9723 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9724 else
e2348bcb 9725 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9726
9c08d1fa 9727 if (which_alternative != 0)
129a2fe4 9728 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9729 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9730 "
8fa3ba89 9731 [(set_attr "conds" "clob")
9732 (set_attr "length" "8,12")]
9733)
9c08d1fa 9734
8a18b90c 9735(define_insn "*if_move_arith"
129a2fe4 9736 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9737 (if_then_else:SI
8fa3ba89 9738 (match_operator 4 "arm_comparison_operator"
8a18b90c 9739 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9740 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9741 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9742 [(match_operand:SI 2 "s_register_operand" "r,r")
9743 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9744 "TARGET_ARM"
8a18b90c 9745 "@
9746 %I5%D4\\t%0, %2, %3
129a2fe4 9747 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9748 [(set_attr "conds" "use")
9749 (set_attr "length" "4,8")
9750 (set_attr "type" "*,*")]
9751)
8a18b90c 9752
9753(define_insn "*ifcompare_move_not"
9c08d1fa 9754 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9755 (if_then_else:SI
8fa3ba89 9756 (match_operator 5 "arm_comparison_operator"
8a18b90c 9757 [(match_operand:SI 3 "s_register_operand" "r,r")
9758 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9759 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9760 (not:SI
9761 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9762 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9763 "TARGET_ARM"
8a18b90c 9764 "#"
8fa3ba89 9765 [(set_attr "conds" "clob")
9766 (set_attr "length" "8,12")]
9767)
9c08d1fa 9768
8a18b90c 9769(define_insn "*if_move_not"
9770 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9771 (if_then_else:SI
8fa3ba89 9772 (match_operator 4 "arm_comparison_operator"
8a18b90c 9773 [(match_operand 3 "cc_register" "") (const_int 0)])
9774 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9775 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9776 "TARGET_ARM"
8a18b90c 9777 "@
9778 mvn%D4\\t%0, %2
9779 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9780 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9781 [(set_attr "conds" "use")
9782 (set_attr "length" "4,8,8")]
9783)
8a18b90c 9784
9785(define_insn "*ifcompare_not_move"
9c08d1fa 9786 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9787 (if_then_else:SI
8fa3ba89 9788 (match_operator 5 "arm_comparison_operator"
8a18b90c 9789 [(match_operand:SI 3 "s_register_operand" "r,r")
9790 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9791 (not:SI
9792 (match_operand:SI 2 "s_register_operand" "r,r"))
9793 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9794 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9795 "TARGET_ARM"
8a18b90c 9796 "#"
8fa3ba89 9797 [(set_attr "conds" "clob")
9798 (set_attr "length" "8,12")]
9799)
9c08d1fa 9800
8a18b90c 9801(define_insn "*if_not_move"
9802 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9803 (if_then_else:SI
8fa3ba89 9804 (match_operator 4 "arm_comparison_operator"
8a18b90c 9805 [(match_operand 3 "cc_register" "") (const_int 0)])
9806 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9807 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9808 "TARGET_ARM"
8a18b90c 9809 "@
9810 mvn%d4\\t%0, %2
9811 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9812 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9813 [(set_attr "conds" "use")
9814 (set_attr "length" "4,8,8")]
9815)
8a18b90c 9816
9817(define_insn "*ifcompare_shift_move"
9c08d1fa 9818 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9819 (if_then_else:SI
8fa3ba89 9820 (match_operator 6 "arm_comparison_operator"
8a18b90c 9821 [(match_operand:SI 4 "s_register_operand" "r,r")
9822 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9823 (match_operator:SI 7 "shift_operator"
9824 [(match_operand:SI 2 "s_register_operand" "r,r")
9825 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9826 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9827 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9828 "TARGET_ARM"
9c08d1fa 9829 "#"
8fa3ba89 9830 [(set_attr "conds" "clob")
9831 (set_attr "length" "8,12")]
9832)
9c08d1fa 9833
8a18b90c 9834(define_insn "*if_shift_move"
9835 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9836 (if_then_else:SI
8fa3ba89 9837 (match_operator 5 "arm_comparison_operator"
8a18b90c 9838 [(match_operand 6 "cc_register" "") (const_int 0)])
9839 (match_operator:SI 4 "shift_operator"
9840 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9841 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9842 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9843 "TARGET_ARM"
5565501b 9844 "@
8a18b90c 9845 mov%d5\\t%0, %2%S4
9846 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9847 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9848 [(set_attr "conds" "use")
331beb1a 9849 (set_attr "shift" "2")
a2cd141b 9850 (set_attr "length" "4,8,8")
9851 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9852 (const_string "alu_shift")
9853 (const_string "alu_shift_reg")))]
8fa3ba89 9854)
5565501b 9855
8a18b90c 9856(define_insn "*ifcompare_move_shift"
9857 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9858 (if_then_else:SI
8fa3ba89 9859 (match_operator 6 "arm_comparison_operator"
8a18b90c 9860 [(match_operand:SI 4 "s_register_operand" "r,r")
9861 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9862 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9863 (match_operator:SI 7 "shift_operator"
8a18b90c 9864 [(match_operand:SI 2 "s_register_operand" "r,r")
9865 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9866 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9867 "TARGET_ARM"
8a18b90c 9868 "#"
8fa3ba89 9869 [(set_attr "conds" "clob")
9870 (set_attr "length" "8,12")]
9871)
5565501b 9872
8a18b90c 9873(define_insn "*if_move_shift"
9874 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9875 (if_then_else:SI
8fa3ba89 9876 (match_operator 5 "arm_comparison_operator"
8a18b90c 9877 [(match_operand 6 "cc_register" "") (const_int 0)])
9878 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9879 (match_operator:SI 4 "shift_operator"
9880 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9881 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9882 "TARGET_ARM"
5565501b 9883 "@
8a18b90c 9884 mov%D5\\t%0, %2%S4
9885 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9886 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9887 [(set_attr "conds" "use")
331beb1a 9888 (set_attr "shift" "2")
a2cd141b 9889 (set_attr "length" "4,8,8")
9890 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9891 (const_string "alu_shift")
9892 (const_string "alu_shift_reg")))]
8fa3ba89 9893)
9c08d1fa 9894
f7fbdd4a 9895(define_insn "*ifcompare_shift_shift"
8a18b90c 9896 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9897 (if_then_else:SI
8fa3ba89 9898 (match_operator 7 "arm_comparison_operator"
8a18b90c 9899 [(match_operand:SI 5 "s_register_operand" "r")
9900 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9901 (match_operator:SI 8 "shift_operator"
8a18b90c 9902 [(match_operand:SI 1 "s_register_operand" "r")
9903 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9904 (match_operator:SI 9 "shift_operator"
8a18b90c 9905 [(match_operand:SI 3 "s_register_operand" "r")
9906 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9907 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9908 "TARGET_ARM"
8a18b90c 9909 "#"
8fa3ba89 9910 [(set_attr "conds" "clob")
9911 (set_attr "length" "12")]
9912)
9c08d1fa 9913
8a18b90c 9914(define_insn "*if_shift_shift"
9915 [(set (match_operand:SI 0 "s_register_operand" "=r")
9916 (if_then_else:SI
8fa3ba89 9917 (match_operator 5 "arm_comparison_operator"
8a18b90c 9918 [(match_operand 8 "cc_register" "") (const_int 0)])
9919 (match_operator:SI 6 "shift_operator"
9920 [(match_operand:SI 1 "s_register_operand" "r")
9921 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9922 (match_operator:SI 7 "shift_operator"
9923 [(match_operand:SI 3 "s_register_operand" "r")
9924 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9925 "TARGET_ARM"
8a18b90c 9926 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9927 [(set_attr "conds" "use")
331beb1a 9928 (set_attr "shift" "1")
a2cd141b 9929 (set_attr "length" "8")
9930 (set (attr "type") (if_then_else
9931 (and (match_operand 2 "const_int_operand" "")
9932 (match_operand 4 "const_int_operand" ""))
9933 (const_string "alu_shift")
9934 (const_string "alu_shift_reg")))]
8fa3ba89 9935)
8a18b90c 9936
f7fbdd4a 9937(define_insn "*ifcompare_not_arith"
8a18b90c 9938 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9939 (if_then_else:SI
8fa3ba89 9940 (match_operator 6 "arm_comparison_operator"
8a18b90c 9941 [(match_operand:SI 4 "s_register_operand" "r")
9942 (match_operand:SI 5 "arm_add_operand" "rIL")])
9943 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9944 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9945 [(match_operand:SI 2 "s_register_operand" "r")
9946 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9947 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9948 "TARGET_ARM"
8a18b90c 9949 "#"
8fa3ba89 9950 [(set_attr "conds" "clob")
9951 (set_attr "length" "12")]
9952)
9c08d1fa 9953
8a18b90c 9954(define_insn "*if_not_arith"
9955 [(set (match_operand:SI 0 "s_register_operand" "=r")
9956 (if_then_else:SI
8fa3ba89 9957 (match_operator 5 "arm_comparison_operator"
8a18b90c 9958 [(match_operand 4 "cc_register" "") (const_int 0)])
9959 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9960 (match_operator:SI 6 "shiftable_operator"
9961 [(match_operand:SI 2 "s_register_operand" "r")
9962 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9963 "TARGET_ARM"
8a18b90c 9964 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9965 [(set_attr "conds" "use")
9966 (set_attr "length" "8")]
9967)
8a18b90c 9968
9969(define_insn "*ifcompare_arith_not"
9970 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9971 (if_then_else:SI
8fa3ba89 9972 (match_operator 6 "arm_comparison_operator"
8a18b90c 9973 [(match_operand:SI 4 "s_register_operand" "r")
9974 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9975 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9976 [(match_operand:SI 2 "s_register_operand" "r")
9977 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9978 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9979 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9980 "TARGET_ARM"
8a18b90c 9981 "#"
8fa3ba89 9982 [(set_attr "conds" "clob")
9983 (set_attr "length" "12")]
9984)
9c08d1fa 9985
8a18b90c 9986(define_insn "*if_arith_not"
9987 [(set (match_operand:SI 0 "s_register_operand" "=r")
9988 (if_then_else:SI
8fa3ba89 9989 (match_operator 5 "arm_comparison_operator"
8a18b90c 9990 [(match_operand 4 "cc_register" "") (const_int 0)])
9991 (match_operator:SI 6 "shiftable_operator"
9992 [(match_operand:SI 2 "s_register_operand" "r")
9993 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9994 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9995 "TARGET_ARM"
8a18b90c 9996 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9997 [(set_attr "conds" "use")
9998 (set_attr "length" "8")]
9999)
8a18b90c 10000
f7fbdd4a 10001(define_insn "*ifcompare_neg_move"
8a18b90c 10002 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10003 (if_then_else:SI
8fa3ba89 10004 (match_operator 5 "arm_comparison_operator"
8a18b90c 10005 [(match_operand:SI 3 "s_register_operand" "r,r")
10006 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10007 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10008 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10009 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10010 "TARGET_ARM"
8a18b90c 10011 "#"
8fa3ba89 10012 [(set_attr "conds" "clob")
10013 (set_attr "length" "8,12")]
10014)
8a18b90c 10015
10016(define_insn "*if_neg_move"
10017 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10018 (if_then_else:SI
8fa3ba89 10019 (match_operator 4 "arm_comparison_operator"
8a18b90c 10020 [(match_operand 3 "cc_register" "") (const_int 0)])
10021 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10022 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10023 "TARGET_ARM"
8a18b90c 10024 "@
10025 rsb%d4\\t%0, %2, #0
10026 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10027 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10028 [(set_attr "conds" "use")
10029 (set_attr "length" "4,8,8")]
10030)
9c08d1fa 10031
f7fbdd4a 10032(define_insn "*ifcompare_move_neg"
8a18b90c 10033 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10034 (if_then_else:SI
8fa3ba89 10035 (match_operator 5 "arm_comparison_operator"
8a18b90c 10036 [(match_operand:SI 3 "s_register_operand" "r,r")
10037 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10038 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10039 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10040 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10041 "TARGET_ARM"
8a18b90c 10042 "#"
8fa3ba89 10043 [(set_attr "conds" "clob")
10044 (set_attr "length" "8,12")]
10045)
8a18b90c 10046
10047(define_insn "*if_move_neg"
10048 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10049 (if_then_else:SI
8fa3ba89 10050 (match_operator 4 "arm_comparison_operator"
8a18b90c 10051 [(match_operand 3 "cc_register" "") (const_int 0)])
10052 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10053 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10054 "TARGET_ARM"
8a18b90c 10055 "@
10056 rsb%D4\\t%0, %2, #0
10057 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10058 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10059 [(set_attr "conds" "use")
10060 (set_attr "length" "4,8,8")]
10061)
9c08d1fa 10062
f7fbdd4a 10063(define_insn "*arith_adjacentmem"
9c08d1fa 10064 [(set (match_operand:SI 0 "s_register_operand" "=r")
10065 (match_operator:SI 1 "shiftable_operator"
10066 [(match_operand:SI 2 "memory_operand" "m")
10067 (match_operand:SI 3 "memory_operand" "m")]))
10068 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10069 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10070 "*
215b30b3 10071 {
10072 rtx ldm[3];
10073 rtx arith[4];
94dee231 10074 rtx base_reg;
10075 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10076
215b30b3 10077 if (REGNO (operands[0]) > REGNO (operands[4]))
10078 {
10079 ldm[1] = operands[4];
10080 ldm[2] = operands[0];
10081 }
10082 else
10083 {
10084 ldm[1] = operands[0];
10085 ldm[2] = operands[4];
10086 }
94dee231 10087
10088 base_reg = XEXP (operands[2], 0);
10089
10090 if (!REG_P (base_reg))
10091 {
10092 val1 = INTVAL (XEXP (base_reg, 1));
10093 base_reg = XEXP (base_reg, 0);
10094 }
10095
10096 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10097 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10098
215b30b3 10099 arith[0] = operands[0];
10100 arith[3] = operands[1];
94dee231 10101
215b30b3 10102 if (val1 < val2)
10103 {
10104 arith[1] = ldm[1];
10105 arith[2] = ldm[2];
10106 }
10107 else
10108 {
10109 arith[1] = ldm[2];
10110 arith[2] = ldm[1];
10111 }
94dee231 10112
10113 ldm[0] = base_reg;
10114 if (val1 !=0 && val2 != 0)
215b30b3 10115 {
cdb1295a 10116 rtx ops[3];
10117
94dee231 10118 if (val1 == 4 || val2 == 4)
10119 /* Other val must be 8, since we know they are adjacent and neither
10120 is zero. */
25f905c2 10121 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10122 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10123 {
94dee231 10124 ldm[0] = ops[0] = operands[4];
10125 ops[1] = base_reg;
10126 ops[2] = GEN_INT (val1);
10127 output_add_immediate (ops);
10128 if (val1 < val2)
25f905c2 10129 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10130 else
25f905c2 10131 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10132 }
cdb1295a 10133 else
10134 {
10135 /* Offset is out of range for a single add, so use two ldr. */
10136 ops[0] = ldm[1];
10137 ops[1] = base_reg;
10138 ops[2] = GEN_INT (val1);
10139 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10140 ops[0] = ldm[2];
10141 ops[2] = GEN_INT (val2);
10142 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10143 }
215b30b3 10144 }
94dee231 10145 else if (val1 != 0)
215b30b3 10146 {
215b30b3 10147 if (val1 < val2)
25f905c2 10148 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10149 else
25f905c2 10150 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10151 }
10152 else
10153 {
215b30b3 10154 if (val1 < val2)
25f905c2 10155 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10156 else
25f905c2 10157 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10158 }
10159 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10160 return \"\";
10161 }"
10162 [(set_attr "length" "12")
10163 (set_attr "predicable" "yes")
a2cd141b 10164 (set_attr "type" "load1")]
215b30b3 10165)
9c08d1fa 10166
9c08d1fa 10167; This pattern is never tried by combine, so do it as a peephole
10168
a0f94409 10169(define_peephole2
372575c7 10170 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10171 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10172 (set (reg:CC CC_REGNUM)
aea4c774 10173 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10174 "TARGET_ARM"
a0f94409 10175 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10176 (set (match_dup 0) (match_dup 1))])]
10177 ""
0d66636f 10178)
9c08d1fa 10179
675d848d 10180; Peepholes to spot possible load- and store-multiples, if the ordering is
10181; reversed, check that the memory references aren't volatile.
9c08d1fa 10182
10183(define_peephole
10184 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 10185 (match_operand:SI 4 "memory_operand" "m"))
10186 (set (match_operand:SI 1 "s_register_operand" "=r")
10187 (match_operand:SI 5 "memory_operand" "m"))
9c08d1fa 10188 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 10189 (match_operand:SI 6 "memory_operand" "m"))
9c08d1fa 10190 (set (match_operand:SI 3 "s_register_operand" "=r")
aea4c774 10191 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 10192 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10193 "*
10194 return emit_ldm_seq (operands, 4);
215b30b3 10195 "
10196)
9c08d1fa 10197
10198(define_peephole
10199 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 10200 (match_operand:SI 3 "memory_operand" "m"))
10201 (set (match_operand:SI 1 "s_register_operand" "=r")
10202 (match_operand:SI 4 "memory_operand" "m"))
9c08d1fa 10203 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 10204 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 10205 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10206 "*
10207 return emit_ldm_seq (operands, 3);
215b30b3 10208 "
10209)
9c08d1fa 10210
10211(define_peephole
10212 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 10213 (match_operand:SI 2 "memory_operand" "m"))
10214 (set (match_operand:SI 1 "s_register_operand" "=r")
10215 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 10216 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10217 "*
10218 return emit_ldm_seq (operands, 2);
215b30b3 10219 "
10220)
9c08d1fa 10221
10222(define_peephole
aea4c774 10223 [(set (match_operand:SI 4 "memory_operand" "=m")
9c08d1fa 10224 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 10225 (set (match_operand:SI 5 "memory_operand" "=m")
10226 (match_operand:SI 1 "s_register_operand" "r"))
10227 (set (match_operand:SI 6 "memory_operand" "=m")
9c08d1fa 10228 (match_operand:SI 2 "s_register_operand" "r"))
aea4c774 10229 (set (match_operand:SI 7 "memory_operand" "=m")
10230 (match_operand:SI 3 "s_register_operand" "r"))]
cffb2a26 10231 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 10232 "*
10233 return emit_stm_seq (operands, 4);
215b30b3 10234 "
10235)
9c08d1fa 10236
10237(define_peephole
aea4c774 10238 [(set (match_operand:SI 3 "memory_operand" "=m")
9c08d1fa 10239 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 10240 (set (match_operand:SI 4 "memory_operand" "=m")
10241 (match_operand:SI 1 "s_register_operand" "r"))
10242 (set (match_operand:SI 5 "memory_operand" "=m")
10243 (match_operand:SI 2 "s_register_operand" "r"))]
cffb2a26 10244 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 10245 "*
10246 return emit_stm_seq (operands, 3);
215b30b3 10247 "
10248)
9c08d1fa 10249
10250(define_peephole
aea4c774 10251 [(set (match_operand:SI 2 "memory_operand" "=m")
9c08d1fa 10252 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 10253 (set (match_operand:SI 3 "memory_operand" "=m")
10254 (match_operand:SI 1 "s_register_operand" "r"))]
cffb2a26 10255 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 10256 "*
10257 return emit_stm_seq (operands, 2);
215b30b3 10258 "
10259)
9c08d1fa 10260
9c08d1fa 10261(define_split
10262 [(set (match_operand:SI 0 "s_register_operand" "")
10263 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10264 (const_int 0))
8fa3ba89 10265 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10266 [(match_operand:SI 3 "s_register_operand" "")
10267 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10268 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10269 "TARGET_ARM"
9c08d1fa 10270 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10271 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10272 (match_dup 5)))]
215b30b3 10273 ""
10274)
9c08d1fa 10275
aea4c774 10276;; This split can be used because CC_Z mode implies that the following
10277;; branch will be an equality, or an unsigned inequality, so the sign
10278;; extension is not needed.
9c08d1fa 10279
aea4c774 10280(define_split
bd5b4116 10281 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10282 (compare:CC_Z
10283 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10284 (const_int 24))
aea4c774 10285 (match_operand 1 "const_int_operand" "")))
10286 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10287 "TARGET_ARM
10288 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10289 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10290 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10291 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10292 "
9c08d1fa 10293 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10294 "
10295)
25f905c2 10296;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10297
87b22bf7 10298(define_expand "prologue"
10299 [(clobber (const_int 0))]
cffb2a26 10300 "TARGET_EITHER"
25f905c2 10301 "if (TARGET_32BIT)
cffb2a26 10302 arm_expand_prologue ();
10303 else
25f905c2 10304 thumb1_expand_prologue ();
87b22bf7 10305 DONE;
cffb2a26 10306 "
10307)
87b22bf7 10308
56d27660 10309(define_expand "epilogue"
4c44712e 10310 [(clobber (const_int 0))]
cffb2a26 10311 "TARGET_EITHER"
56d27660 10312 "
4c44712e 10313 if (current_function_calls_eh_return)
10314 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10315 if (TARGET_THUMB1)
10316 thumb1_expand_epilogue ();
cffb2a26 10317 else if (USE_RETURN_INSN (FALSE))
56d27660 10318 {
10319 emit_jump_insn (gen_return ());
10320 DONE;
10321 }
cffb2a26 10322 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10323 gen_rtvec (1,
10324 gen_rtx_RETURN (VOIDmode)),
e1159bbe 10325 VUNSPEC_EPILOGUE));
cffb2a26 10326 DONE;
10327 "
10328)
56d27660 10329
ef5651d0 10330;; Note - although unspec_volatile's USE all hard registers,
10331;; USEs are ignored after relaod has completed. Thus we need
10332;; to add an unspec of the link register to ensure that flow
10333;; does not think that it is unused by the sibcall branch that
10334;; will replace the standard function epilogue.
1c494086 10335(define_insn "sibcall_epilogue"
ef5651d0 10336 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10337 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10338 "TARGET_32BIT"
1c494086 10339 "*
ffc9d00c 10340 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10341 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10342 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10343 "
10344;; Length is absolute worst case
10345 [(set_attr "length" "44")
defc47cf 10346 (set_attr "type" "block")
10347 ;; We don't clobber the conditions, but the potential length of this
10348 ;; operation is sufficient to make conditionalizing the sequence
10349 ;; unlikely to be profitable.
10350 (set_attr "conds" "clob")]
1c494086 10351)
10352
cffb2a26 10353(define_insn "*epilogue_insns"
e1159bbe 10354 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10355 "TARGET_EITHER"
56d27660 10356 "*
25f905c2 10357 if (TARGET_32BIT)
ffc9d00c 10358 return arm_output_epilogue (NULL);
25f905c2 10359 else /* TARGET_THUMB1 */
cffb2a26 10360 return thumb_unexpanded_epilogue ();
10361 "
215b30b3 10362 ; Length is absolute worst case
cffb2a26 10363 [(set_attr "length" "44")
defc47cf 10364 (set_attr "type" "block")
10365 ;; We don't clobber the conditions, but the potential length of this
10366 ;; operation is sufficient to make conditionalizing the sequence
10367 ;; unlikely to be profitable.
10368 (set_attr "conds" "clob")]
cffb2a26 10369)
10370
10371(define_expand "eh_epilogue"
7db9af5d 10372 [(use (match_operand:SI 0 "register_operand" ""))
10373 (use (match_operand:SI 1 "register_operand" ""))
10374 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10375 "TARGET_EITHER"
10376 "
215b30b3 10377 {
10378 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10379 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10380 {
10381 rtx ra = gen_rtx_REG (Pmode, 2);
10382
10383 emit_move_insn (ra, operands[2]);
10384 operands[2] = ra;
10385 }
5cf3595a 10386 /* This is a hack -- we may have crystalized the function type too
10387 early. */
10388 cfun->machine->func_type = 0;
215b30b3 10389 }"
10390)
56d27660 10391
9c08d1fa 10392;; This split is only used during output to reduce the number of patterns
10393;; that need assembler instructions adding to them. We allowed the setting
10394;; of the conditions to be implicit during rtl generation so that
10395;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10396;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10397;; up again here.
10398
25f905c2 10399;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10400;; conditional execution sufficient?
10401
9c08d1fa 10402(define_split
10403 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10404 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10405 [(match_operand 2 "" "") (match_operand 3 "" "")])
10406 (match_dup 0)
10407 (match_operand 4 "" "")))
bd5b4116 10408 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10409 "TARGET_ARM && reload_completed"
8fa3ba89 10410 [(set (match_dup 5) (match_dup 6))
10411 (cond_exec (match_dup 7)
10412 (set (match_dup 0) (match_dup 4)))]
10413 "
10414 {
10415 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10416 operands[2], operands[3]);
10417 enum rtx_code rc = GET_CODE (operands[1]);
10418
bd5b4116 10419 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10420 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10421 if (mode == CCFPmode || mode == CCFPEmode)
10422 rc = reverse_condition_maybe_unordered (rc);
10423 else
10424 rc = reverse_condition (rc);
10425
10426 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10427 }"
10428)
10429
10430(define_split
10431 [(set (match_operand:SI 0 "s_register_operand" "")
10432 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10433 [(match_operand 2 "" "") (match_operand 3 "" "")])
10434 (match_operand 4 "" "")
10435 (match_dup 0)))
bd5b4116 10436 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10437 "TARGET_ARM && reload_completed"
8fa3ba89 10438 [(set (match_dup 5) (match_dup 6))
10439 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10440 (set (match_dup 0) (match_dup 4)))]
10441 "
10442 {
10443 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10444 operands[2], operands[3]);
10445
bd5b4116 10446 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10447 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10448 }"
10449)
10450
10451(define_split
10452 [(set (match_operand:SI 0 "s_register_operand" "")
10453 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10454 [(match_operand 2 "" "") (match_operand 3 "" "")])
10455 (match_operand 4 "" "")
10456 (match_operand 5 "" "")))
bd5b4116 10457 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10458 "TARGET_ARM && reload_completed"
8fa3ba89 10459 [(set (match_dup 6) (match_dup 7))
10460 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10461 (set (match_dup 0) (match_dup 4)))
10462 (cond_exec (match_dup 8)
10463 (set (match_dup 0) (match_dup 5)))]
10464 "
10465 {
10466 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10467 operands[2], operands[3]);
10468 enum rtx_code rc = GET_CODE (operands[1]);
10469
bd5b4116 10470 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10471 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10472 if (mode == CCFPmode || mode == CCFPEmode)
10473 rc = reverse_condition_maybe_unordered (rc);
10474 else
10475 rc = reverse_condition (rc);
10476
10477 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10478 }"
10479)
10480
cffb2a26 10481(define_split
10482 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10483 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10484 [(match_operand:SI 2 "s_register_operand" "")
10485 (match_operand:SI 3 "arm_add_operand" "")])
10486 (match_operand:SI 4 "arm_rhs_operand" "")
10487 (not:SI
10488 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10489 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10490 "TARGET_ARM && reload_completed"
cffb2a26 10491 [(set (match_dup 6) (match_dup 7))
f6c53574 10492 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10493 (set (match_dup 0) (match_dup 4)))
10494 (cond_exec (match_dup 8)
10495 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10496 "
215b30b3 10497 {
10498 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10499 operands[2], operands[3]);
f6c53574 10500 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10501
bd5b4116 10502 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10503 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10504 if (mode == CCFPmode || mode == CCFPEmode)
10505 rc = reverse_condition_maybe_unordered (rc);
10506 else
10507 rc = reverse_condition (rc);
10508
10509 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10510 }"
10511)
cffb2a26 10512
10513(define_insn "*cond_move_not"
10514 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10515 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10516 [(match_operand 3 "cc_register" "") (const_int 0)])
10517 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10518 (not:SI
10519 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10520 "TARGET_ARM"
10521 "@
10522 mvn%D4\\t%0, %2
10523 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10524 [(set_attr "conds" "use")
10525 (set_attr "length" "4,8")]
10526)
cffb2a26 10527
9c08d1fa 10528;; The next two patterns occur when an AND operation is followed by a
10529;; scc insn sequence
10530
f7fbdd4a 10531(define_insn "*sign_extract_onebit"
9c08d1fa 10532 [(set (match_operand:SI 0 "s_register_operand" "=r")
10533 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10534 (const_int 1)
ed750274 10535 (match_operand:SI 2 "const_int_operand" "n")))
10536 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10537 "TARGET_ARM"
9c08d1fa 10538 "*
0d66636f 10539 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10540 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10541 return \"mvnne\\t%0, #0\";
10542 "
10543 [(set_attr "conds" "clob")
10544 (set_attr "length" "8")]
10545)
9c08d1fa 10546
f7fbdd4a 10547(define_insn "*not_signextract_onebit"
9c08d1fa 10548 [(set (match_operand:SI 0 "s_register_operand" "=r")
10549 (not:SI
10550 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10551 (const_int 1)
ed750274 10552 (match_operand:SI 2 "const_int_operand" "n"))))
10553 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10554 "TARGET_ARM"
9c08d1fa 10555 "*
0d66636f 10556 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10557 output_asm_insn (\"tst\\t%1, %2\", operands);
10558 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10559 return \"movne\\t%0, #0\";
10560 "
10561 [(set_attr "conds" "clob")
10562 (set_attr "length" "12")]
10563)
25f905c2 10564;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10565
0d66636f 10566;; Push multiple registers to the stack. Registers are in parallel (use ...)
10567;; expressions. For simplicity, the first register is also in the unspec
10568;; part.
f7fbdd4a 10569(define_insn "*push_multi"
87b22bf7 10570 [(match_parallel 2 "multi_register_push"
10571 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10572 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10573 UNSPEC_PUSH_MULT))])]
25f905c2 10574 "TARGET_32BIT"
87b22bf7 10575 "*
215b30b3 10576 {
10577 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10578
215b30b3 10579 /* For the StrongARM at least it is faster to
25f905c2 10580 use STR to store only a single register.
542d5028 10581 In Thumb mode always use push, and the assembler will pick
10582 something appropriate. */
25f905c2 10583 if (num_saves == 1 && TARGET_ARM)
215b30b3 10584 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10585 else
10586 {
10587 int i;
10588 char pattern[100];
ed593f11 10589
25f905c2 10590 if (TARGET_ARM)
10591 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10592 else
10593 strcpy (pattern, \"push\\t{%1\");
215b30b3 10594
6079f055 10595 for (i = 1; i < num_saves; i++)
215b30b3 10596 {
10597 strcat (pattern, \", %|\");
10598 strcat (pattern,
10599 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10600 }
10601
10602 strcat (pattern, \"}\");
10603 output_asm_insn (pattern, operands);
10604 }
10605
10606 return \"\";
10607 }"
10608 [(set_attr "type" "store4")]
10609)
f7fbdd4a 10610
4c58c898 10611(define_insn "stack_tie"
10612 [(set (mem:BLK (scratch))
10613 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10614 (match_operand:SI 1 "s_register_operand" "r")]
10615 UNSPEC_PRLG_STK))]
10616 ""
10617 ""
10618 [(set_attr "length" "0")]
10619)
10620
3398e91d 10621;; Similarly for the floating point registers
7b1d2fc4 10622(define_insn "*push_fp_multi"
10623 [(match_parallel 2 "multi_register_push"
10624 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10625 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10626 UNSPEC_PUSH_MULT))])]
25f905c2 10627 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10628 "*
215b30b3 10629 {
10630 char pattern[100];
7b1d2fc4 10631
215b30b3 10632 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10633 output_asm_insn (pattern, operands);
10634 return \"\";
10635 }"
10636 [(set_attr "type" "f_store")]
10637)
7b1d2fc4 10638
f7fbdd4a 10639;; Special patterns for dealing with the constant pool
10640
cffb2a26 10641(define_insn "align_4"
e1159bbe 10642 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10643 "TARGET_EITHER"
f7fbdd4a 10644 "*
cffb2a26 10645 assemble_align (32);
f7fbdd4a 10646 return \"\";
cffb2a26 10647 "
10648)
f7fbdd4a 10649
755eb2b4 10650(define_insn "align_8"
10651 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10652 "TARGET_EITHER"
755eb2b4 10653 "*
10654 assemble_align (64);
10655 return \"\";
10656 "
10657)
10658
cffb2a26 10659(define_insn "consttable_end"
e1159bbe 10660 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10661 "TARGET_EITHER"
f7fbdd4a 10662 "*
cffb2a26 10663 making_const_table = FALSE;
f7fbdd4a 10664 return \"\";
cffb2a26 10665 "
10666)
f7fbdd4a 10667
cffb2a26 10668(define_insn "consttable_1"
e1159bbe 10669 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10670 "TARGET_THUMB1"
f7fbdd4a 10671 "*
cffb2a26 10672 making_const_table = TRUE;
09d688ff 10673 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10674 assemble_zeros (3);
f7fbdd4a 10675 return \"\";
cffb2a26 10676 "
10677 [(set_attr "length" "4")]
10678)
f7fbdd4a 10679
cffb2a26 10680(define_insn "consttable_2"
e1159bbe 10681 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10682 "TARGET_THUMB1"
f7fbdd4a 10683 "*
cffb2a26 10684 making_const_table = TRUE;
09d688ff 10685 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10686 assemble_zeros (2);
f7fbdd4a 10687 return \"\";
cffb2a26 10688 "
10689 [(set_attr "length" "4")]
10690)
10691
10692(define_insn "consttable_4"
e1159bbe 10693 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10694 "TARGET_EITHER"
10695 "*
10696 {
10697 making_const_table = TRUE;
10698 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10699 {
10700 case MODE_FLOAT:
10701 {
badfe841 10702 REAL_VALUE_TYPE r;
10703 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10704 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10705 break;
10706 }
10707 default:
09d688ff 10708 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
cffb2a26 10709 break;
10710 }
10711 return \"\";
10712 }"
10713 [(set_attr "length" "4")]
10714)
10715
10716(define_insn "consttable_8"
e1159bbe 10717 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10718 "TARGET_EITHER"
10719 "*
10720 {
10721 making_const_table = TRUE;
10722 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10723 {
10724 case MODE_FLOAT:
10725 {
badfe841 10726 REAL_VALUE_TYPE r;
10727 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10728 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10729 break;
10730 }
10731 default:
09d688ff 10732 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10733 break;
10734 }
10735 return \"\";
10736 }"
10737 [(set_attr "length" "8")]
10738)
10739
d98a3884 10740(define_insn "consttable_16"
10741 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10742 "TARGET_EITHER"
10743 "*
10744 {
10745 making_const_table = TRUE;
10746 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10747 {
10748 case MODE_FLOAT:
10749 {
10750 REAL_VALUE_TYPE r;
10751 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10752 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10753 break;
10754 }
10755 default:
10756 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10757 break;
10758 }
10759 return \"\";
10760 }"
10761 [(set_attr "length" "16")]
10762)
10763
cffb2a26 10764;; Miscellaneous Thumb patterns
10765
fd957ef3 10766(define_expand "tablejump"
7db9af5d 10767 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10768 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 10769 "TARGET_THUMB1"
fd957ef3 10770 "
10771 if (flag_pic)
10772 {
10773 /* Hopefully, CSE will eliminate this copy. */
10774 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10775 rtx reg2 = gen_reg_rtx (SImode);
10776
10777 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10778 operands[0] = reg2;
10779 }
10780 "
10781)
10782
f1039640 10783;; NB never uses BX.
25f905c2 10784(define_insn "*thumb1_tablejump"
cffb2a26 10785 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10786 (use (label_ref (match_operand 1 "" "")))]
25f905c2 10787 "TARGET_THUMB1"
fd957ef3 10788 "mov\\t%|pc, %0"
cffb2a26 10789 [(set_attr "length" "2")]
10790)
0d66636f 10791
331beb1a 10792;; V5 Instructions,
10793
8f4be2be 10794(define_insn "clzsi2"
10795 [(set (match_operand:SI 0 "s_register_operand" "=r")
10796 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10797 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10798 "clz%?\\t%0, %1"
bcaec148 10799 [(set_attr "predicable" "yes")
10800 (set_attr "insn" "clz")])
331beb1a 10801
e1159bbe 10802;; V5E instructions.
331beb1a 10803
10804(define_insn "prefetch"
f4e79814 10805 [(prefetch (match_operand:SI 0 "address_operand" "p")
10806 (match_operand:SI 1 "" "")
10807 (match_operand:SI 2 "" ""))]
25f905c2 10808 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 10809 "pld\\t%a0")
331beb1a 10810
0d66636f 10811;; General predication pattern
10812
10813(define_cond_exec
10814 [(match_operator 0 "arm_comparison_operator"
10815 [(match_operand 1 "cc_register" "")
10816 (const_int 0)])]
25f905c2 10817 "TARGET_32BIT"
0d66636f 10818 ""
10819)
10820
063a05c7 10821(define_insn "prologue_use"
10822 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10823 ""
10824 "%@ %0 needed for prologue"
10825)
7db9af5d 10826
4c44712e 10827
10828;; Patterns for exception handling
10829
10830(define_expand "eh_return"
10831 [(use (match_operand 0 "general_operand" ""))]
10832 "TARGET_EITHER"
10833 "
10834 {
25f905c2 10835 if (TARGET_32BIT)
4c44712e 10836 emit_insn (gen_arm_eh_return (operands[0]));
10837 else
10838 emit_insn (gen_thumb_eh_return (operands[0]));
10839 DONE;
10840 }"
10841)
10842
10843;; We can't expand this before we know where the link register is stored.
10844(define_insn_and_split "arm_eh_return"
10845 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10846 VUNSPEC_EH_RETURN)
10847 (clobber (match_scratch:SI 1 "=&r"))]
10848 "TARGET_ARM"
10849 "#"
10850 "&& reload_completed"
10851 [(const_int 0)]
10852 "
10853 {
10854 arm_set_return_address (operands[0], operands[1]);
10855 DONE;
10856 }"
10857)
10858
10859(define_insn_and_split "thumb_eh_return"
10860 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10861 VUNSPEC_EH_RETURN)
10862 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 10863 "TARGET_THUMB1"
4c44712e 10864 "#"
10865 "&& reload_completed"
10866 [(const_int 0)]
10867 "
10868 {
10869 thumb_set_return_address (operands[0], operands[1]);
10870 DONE;
10871 }"
10872)
10873
f655717d 10874\f
10875;; TLS support
10876
10877(define_insn "load_tp_hard"
10878 [(set (match_operand:SI 0 "register_operand" "=r")
10879 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10880 "TARGET_HARD_TP"
10881 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10882 [(set_attr "predicable" "yes")]
10883)
10884
10885;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10886(define_insn "load_tp_soft"
10887 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10888 (clobber (reg:SI LR_REGNUM))
10889 (clobber (reg:SI IP_REGNUM))
10890 (clobber (reg:CC CC_REGNUM))]
10891 "TARGET_SOFT_TP"
10892 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10893 [(set_attr "conds" "clob")]
10894)
10895
7db9af5d 10896;; Load the FPA co-processor patterns
10897(include "fpa.md")
10898;; Load the Maverick co-processor patterns
10899(include "cirrus.md")
d98a3884 10900;; Vector bits common to IWMMXT and Neon
10901(include "vec-common.md")
755eb2b4 10902;; Load the Intel Wireless Multimedia Extension patterns
10903(include "iwmmxt.md")
a2cd141b 10904;; Load the VFP co-processor patterns
10905(include "vfp.md")
25f905c2 10906;; Thumb-2 patterns
10907(include "thumb2.md")
d98a3884 10908;; Neon patterns
10909(include "neon.md")
a2cd141b 10910