]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
host-hpux.c: Change copyright header to refer to version 3 of the GNU General Public...
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
b36ba79f 1;;- Machine description for ARM for GNU compiler
6bacc7b0 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
2f83c7d6 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3a33f76f 4;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
7a0a1f09 5;; and Martin Simmons (@harleqn.co.uk).
b36ba79f 6;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
3a33f76f 7
4f448245 8;; This file is part of GCC.
3a33f76f 9
4f448245
NC
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
2f83c7d6 12;; by the Free Software Foundation; either version 3, or (at your
4f448245 13;; option) any later version.
3a33f76f 14
4f448245
NC
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.
3a33f76f
RK
19
20;; You should have received a copy of the GNU General Public License
2f83c7d6
NC
21;; along with GCC; see the file COPYING3. If not see
22;; <http://www.gnu.org/licenses/>.
3a33f76f
RK
23
24;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25
ff9940b0 26\f
b15bca31
RE
27;;---------------------------------------------------------------------------
28;; Constants
29
30;; Register numbers
31(define_constants
9f7bf991
RE
32 [(R0_REGNUM 0) ; First CORE register
33 (IP_REGNUM 12) ; Scratch register
b15bca31
RE
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
9f7bf991
RE
38 (LAST_ARM_REGNUM 15) ;
39 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
40 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
b15bca31
RE
41 ]
42)
03f1640c
RE
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)
b15bca31 50
ff9940b0 51;; UNSPEC Usage:
f54fd62e 52;; Note: sin and cos are no-longer used.
88f77cba 53;; Unspec constants for Neon are defined in neon.md.
b15bca31
RE
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.
228692e2
RE
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
b15bca31 74 ; being scheduled before the stack adjustment insn.
6bacc7b0
NC
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".
fcd53748 80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
9a9f7594
KH
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.
d3585b76 93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
f16fe45f
DJ
94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95 ; instruction stream.
5b3e6663
PB
96 (UNSPEC_STACK_ALIGN 20) ; Doubleword aligned stack pointer. Used to
97 ; generate correct unwind information.
9403b7f7
RS
98 (UNSPEC_PIC_OFFSET 22) ; A symbolic 12-bit OFFSET that has been treated
99 ; correctly for PIC usage.
b15bca31
RE
100 ]
101)
102
5895f793 103;; UNSPEC_VOLATILE Usage:
b15bca31
RE
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.
88f77cba
JB
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
c112cf2b 132 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
c9ca9b88 133 ; handling.
b15bca31
RE
134 ]
135)
3a33f76f 136\f
b15bca31 137;;---------------------------------------------------------------------------
ff9940b0
RE
138;; Attributes
139
5895f793
RE
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.
0616531f 143(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
d5b7b3ae 144
5895f793
RE
145; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
146; scheduling decisions for the load unit and the multiplier.
abac3b49 147(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
ff9940b0 148
df8e2ad0
BE
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
d19fb8e3
NC
152;; Operand number of an input operand that is shifted. Zero if the
153;; given instruction does not shift one of its input operands.
d19fb8e3
NC
154(define_attr "shift" "" (const_int 0))
155
dfaa6d72
RE
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).
9b66ebb1 159(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
29ad9694 160 (const (symbol_ref "arm_fpu_attr")))
dfaa6d72 161
a1dc0475
RE
162; LENGTH of an instruction (in bytes)
163(define_attr "length" "" (const_int 4))
ff9940b0 164
949d79eb
RE
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.
d5b7b3ae
RE
168; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
169; before its address.
949d79eb 170(define_attr "pool_range" "" (const_int 0))
d5b7b3ae 171(define_attr "neg_pool_range" "" (const_int 0))
949d79eb 172
5895f793 173; An assembler sequence may clobber the condition codes without us knowing.
56fbb855
RE
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.
ff9940b0 176(define_asm_attributes
56fbb855
RE
177 [(set_attr "conds" "clob")
178 (set_attr "length" "4")
179 (set_attr "pool_range" "250")])
ff9940b0 180
9b66ebb1
PB
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"
c956e102 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"
9b66ebb1
PB
187 (const_string "other"))
188
ff9940b0
RE
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
9b66ebb1
PB
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
4cdb3ed4 201; mult a multiply instruction
ff9940b0
RE
202; block blockage insn, this blocks all functional units
203; float a floating point arithmetic operation (subject to expansion)
dfaa6d72
RE
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)
ff9940b0 210; float_em a floating point arithmetic operation that is normally emulated
dfaa6d72 211; even on a machine with an fpa.
ff9940b0
RE
212; f_load a floating point load from memory
213; f_store a floating point store to memory
8ab5f5c9
KH
214; f_load[sd] single/double load from memory
215; f_store[sd] single/double store to memory
75fe7b2f 216; f_flag a transfer of co-processor flags to the CPSR
ff9940b0
RE
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
75fe7b2f 221; f_cvt convert floating<->integral
9b66ebb1 222; branch a branch
ff9940b0 223; call a subroutine call
9b66ebb1
PB
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
ff9940b0
RE
230; store2 store 2 words
231; store3 store 3 words
9b66ebb1 232; store4 store 4 (or more) words
f0375c66
NC
233; Additions for Cirrus Maverick co-processor:
234; mav_farith Floating point arithmetic (4 cycle)
235; mav_dmult Double multiplies (7 cycle)
ff9940b0 236;
c956e102 237
ff9940b0 238(define_attr "type"
c956e102 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"
9b66ebb1
PB
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")))
ff9940b0 244
f5a1b0d2 245; Load scheduling, set from the arm_ld_sched variable
4912a07c 246; initialized by arm_override_options()
f5a1b0d2 247(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
fef37aaf 248
4cdb3ed4
RE
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.
5895f793 252;
4cdb3ed4 253; USE means that the condition codes are used by the insn in the process of
5895f793
RE
254; outputting code, this means (at present) that we can't use the insn in
255; inlined branches
256;
4cdb3ed4 257; SET means that the purpose of the insn is to set the condition codes in a
5895f793
RE
258; well defined manner.
259;
4cdb3ed4 260; CLOB means that the condition codes are altered in an undefined manner, if
5895f793
RE
261; they are altered at all
262;
05ed98a1 263; JUMP_CLOB is used when the condition cannot be represented by a single
5895f793
RE
264; instruction (UNEQ and LTGT). These cannot be predicated.
265;
4cdb3ed4 266; NOCOND means that the condition codes are neither altered nor affect the
5895f793 267; output of this insn
4cdb3ed4
RE
268
269(define_attr "conds" "use,set,clob,jump_clob,nocond"
270 (if_then_else (eq_attr "type" "call")
61f0ccff 271 (const_string "clob")
4cdb3ed4
RE
272 (const_string "nocond")))
273
5895f793
RE
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.
cca0a211
RE
278(define_attr "predicable" "no,yes" (const_string "no"))
279
b36ba79f
RE
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
9a9f7594 282; suffer blockages enough to warrant modelling this (and it can adversely
b36ba79f 283; affect the schedule).
abac3b49 284(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
b36ba79f 285
5895f793
RE
286; WRITE_CONFLICT implies that a read following an unrelated write is likely
287; to stall the processor. Used with model_wbuf above.
ff9940b0
RE
288(define_attr "write_conflict" "no,yes"
289 (if_then_else (eq_attr "type"
9b66ebb1 290 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
ff9940b0
RE
291 (const_string "yes")
292 (const_string "no")))
293
5895f793
RE
294; Classify the insns into those that take one cycle and those that take more
295; than one on the main cpu execution unit.
4cdb3ed4
RE
296(define_attr "core_cycles" "single,multi"
297 (if_then_else (eq_attr "type"
9b66ebb1 298 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
4cdb3ed4
RE
299 (const_string "single")
300 (const_string "multi")))
301
d5b7b3ae 302;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
5895f793 303;; distant label. Only applicable to Thumb code.
d5b7b3ae
RE
304(define_attr "far_jump" "yes,no" (const_string "no"))
305
9b901d50 306
5b3e6663
PB
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
9b901d50
RE
311;;---------------------------------------------------------------------------
312;; Mode macros
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.
317(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
318
319;;---------------------------------------------------------------------------
320;; Predicates
321
a657c98a 322(include "predicates.md")
ce92b223 323(include "constraints.md")
a657c98a 324
9b66ebb1
PB
325;;---------------------------------------------------------------------------
326;; Pipeline descriptions
5895f793 327
2f71a20a
RE
328;; Processor type. This is created automatically from arm-cores.def.
329(include "arm-tune.md")
d19fb8e3 330
9b66ebb1
PB
331;; True if the generic scheduling description should be used.
332
333(define_attr "generic_sched" "yes,no"
e648d85a 334 (const (if_then_else
c956e102 335 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8")
e648d85a
ILT
336 (const_string "no")
337 (const_string "yes"))))
338
75fe7b2f
RE
339(define_attr "generic_vfp" "yes,no"
340 (const (if_then_else
341 (and (eq_attr "fpu" "vfp")
c956e102 342 (eq_attr "tune" "!arm1020e,arm1022e,cortexa8"))
75fe7b2f
RE
343 (const_string "yes")
344 (const_string "no"))))
345
9b66ebb1
PB
346(include "arm-generic.md")
347(include "arm926ejs.md")
75fe7b2f 348(include "arm1020e.md")
9b66ebb1
PB
349(include "arm1026ejs.md")
350(include "arm1136jfs.md")
c956e102 351(include "cortex-a8.md")
103fc15d 352
ff9940b0 353\f
5895f793 354;;---------------------------------------------------------------------------
b15bca31
RE
355;; Insn patterns
356;;
bb6ae783 357;; Addition insns.
5895f793 358
ff9940b0
RE
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.
9b6b54e2
NC
362;; Cirrus 64bit additions should not be split because we have a native
363;; 64bit addition instructions.
ff9940b0 364
d5b7b3ae
RE
365(define_expand "adddi3"
366 [(parallel
5895f793 367 [(set (match_operand:DI 0 "s_register_operand" "")
d5b7b3ae
RE
368 (plus:DI (match_operand:DI 1 "s_register_operand" "")
369 (match_operand:DI 2 "s_register_operand" "")))
48a08b9c 370 (clobber (reg:CC CC_REGNUM))])]
d5b7b3ae
RE
371 "TARGET_EITHER"
372 "
9b66ebb1 373 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
9b6b54e2
NC
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
5b3e6663 383 if (TARGET_THUMB1)
d5b7b3ae
RE
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
5b3e6663 393(define_insn "*thumb1_adddi3"
d5b7b3ae
RE
394 [(set (match_operand:DI 0 "register_operand" "=l")
395 (plus:DI (match_operand:DI 1 "register_operand" "%0")
5895f793 396 (match_operand:DI 2 "register_operand" "l")))
48a08b9c 397 (clobber (reg:CC CC_REGNUM))
d5b7b3ae 398 ]
5b3e6663 399 "TARGET_THUMB1"
d5b7b3ae
RE
400 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
401 [(set_attr "length" "4")]
402)
403
bb6ae783 404(define_insn_and_split "*arm_adddi3"
d5b7b3ae 405 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
5895f793
RE
406 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
407 (match_operand:DI 2 "s_register_operand" "r, 0")))
48a08b9c 408 (clobber (reg:CC CC_REGNUM))]
5b3e6663 409 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
3a8de233 410 "#"
5b3e6663 411 "TARGET_32BIT && reload_completed"
bb6ae783
RE
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 }"
d5b7b3ae
RE
427 [(set_attr "conds" "clob")
428 (set_attr "length" "8")]
429)
ff9940b0 430
bb6ae783 431(define_insn_and_split "*adddi_sesidi_di"
ff9940b0
RE
432 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
433 (plus:DI (sign_extend:DI
3dafc5c3
RE
434 (match_operand:SI 2 "s_register_operand" "r,r"))
435 (match_operand:DI 1 "s_register_operand" "r,0")))
48a08b9c 436 (clobber (reg:CC CC_REGNUM))]
5b3e6663 437 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
3a8de233 438 "#"
5b3e6663 439 "TARGET_32BIT && reload_completed"
bb6ae783
RE
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 }"
5895f793
RE
456 [(set_attr "conds" "clob")
457 (set_attr "length" "8")]
458)
ff9940b0 459
bb6ae783 460(define_insn_and_split "*adddi_zesidi_di"
ff9940b0
RE
461 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
462 (plus:DI (zero_extend:DI
3dafc5c3
RE
463 (match_operand:SI 2 "s_register_operand" "r,r"))
464 (match_operand:DI 1 "s_register_operand" "r,0")))
bb6ae783 465 (clobber (reg:CC CC_REGNUM))]
5b3e6663 466 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
3a8de233 467 "#"
5b3e6663 468 "TARGET_32BIT && reload_completed"
bb6ae783
RE
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 }"
d5b7b3ae
RE
483 [(set_attr "conds" "clob")
484 (set_attr "length" "8")]
485)
3a33f76f 486
091426d3 487(define_expand "addsi3"
d5b7b3ae 488 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
489 (plus:SI (match_operand:SI 1 "s_register_operand" "")
490 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 491 "TARGET_EITHER"
091426d3 492 "
5b3e6663 493 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
091426d3 494 {
a406f566
MM
495 arm_split_constant (PLUS, SImode, NULL_RTX,
496 INTVAL (operands[2]), operands[0], operands[1],
b3a13419 497 optimize && can_create_pseudo_p ());
091426d3
RE
498 DONE;
499 }
d5b7b3ae
RE
500 "
501)
091426d3 502
72ac76be 503; If there is a scratch available, this will be faster than synthesizing the
bb6ae783
RE
504; addition.
505(define_peephole2
506 [(match_scratch:SI 3 "r")
3053b100
RE
507 (set (match_operand:SI 0 "arm_general_register_operand" "")
508 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
d5b7b3ae 509 (match_operand:SI 2 "const_int_operand" "")))]
5b3e6663 510 "TARGET_32BIT &&
bb6ae783
RE
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)
091426d3 518
bb6ae783 519(define_insn_and_split "*arm_addsi3"
d5b7b3ae 520 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
bb6ae783 521 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
091426d3 522 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
5b3e6663 523 "TARGET_32BIT"
68df59d3
RE
524 "@
525 add%?\\t%0, %1, %2
091426d3
RE
526 sub%?\\t%0, %1, #%n2
527 #"
5b3e6663 528 "TARGET_32BIT &&
bb6ae783
RE
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 "
a406f566
MM
534 arm_split_constant (PLUS, SImode, curr_insn,
535 INTVAL (operands[2]), operands[0],
bb6ae783
RE
536 operands[1], 0);
537 DONE;
538 "
cca0a211
RE
539 [(set_attr "length" "4,4,16")
540 (set_attr "predicable" "yes")]
d5b7b3ae
RE
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
5b3e6663 547(define_insn "*thumb1_addsi3"
d5b7b3ae
RE
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")))]
5b3e6663 551 "TARGET_THUMB1"
d5b7b3ae 552 "*
cca0a211 553 static const char * const asms[] =
d5b7b3ae
RE
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.
bb6ae783 574(define_peephole2
3053b100 575 [(set (match_operand:SI 0 "arm_general_register_operand" "")
12249385 576 (match_operand:SI 1 "const_int_operand" ""))
d5b7b3ae 577 (set (match_dup 0)
3053b100 578 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
5b3e6663 579 "TARGET_THUMB1
d5b7b3ae
RE
580 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
581 && (INTVAL (operands[1]) & 3) == 0"
3053b100 582 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
bb6ae783 583 ""
d5b7b3ae 584)
3a33f76f 585
5b3e6663 586;; ??? Make Thumb-2 variants which prefer low regs
4cdb3ed4 587(define_insn "*addsi3_compare0"
48a08b9c 588 [(set (reg:CC_NOOV CC_REGNUM)
68df59d3 589 (compare:CC_NOOV
5895f793
RE
590 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
591 (match_operand:SI 2 "arm_add_operand" "rI,L"))
68df59d3
RE
592 (const_int 0)))
593 (set (match_operand:SI 0 "s_register_operand" "=r,r")
ff9940b0 594 (plus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 595 "TARGET_32BIT"
68df59d3 596 "@
5b3e6663
PB
597 add%.\\t%0, %1, %2
598 sub%.\\t%0, %1, #%n2"
d5b7b3ae
RE
599 [(set_attr "conds" "set")]
600)
ff9940b0 601
589fe0fc 602(define_insn "*addsi3_compare0_scratch"
48a08b9c 603 [(set (reg:CC_NOOV CC_REGNUM)
589fe0fc 604 (compare:CC_NOOV
5895f793
RE
605 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
606 (match_operand:SI 1 "arm_add_operand" "rI,L"))
589fe0fc 607 (const_int 0)))]
5b3e6663 608 "TARGET_32BIT"
d5b7b3ae
RE
609 "@
610 cmn%?\\t%0, %1
611 cmp%?\\t%0, #%n1"
cca0a211
RE
612 [(set_attr "conds" "set")]
613)
d5b7b3ae 614
1ac3e311
RE
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")))]
5b3e6663 620 "TARGET_32BIT"
1ac3e311 621 "cmn%?\\t%1, %0"
cca0a211
RE
622 [(set_attr "conds" "set")]
623)
589fe0fc 624
f9b9980e
RE
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")))]
5b3e6663 635 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
f9b9980e 636 "@
5b3e6663
PB
637 sub%.\\t%0, %1, %2
638 add%.\\t%0, %1, #%n2"
f9b9980e
RE
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
3053b100
RE
652 [(set (match_operand:SI 0 "arm_general_register_operand" "")
653 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
f9b9980e
RE
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 "" "")))]
5b3e6663 662 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
f9b9980e
RE
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
a0b632ec
RE
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"
48a08b9c 684 [(set (reg:CC_C CC_REGNUM)
a0b632ec
RE
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)))]
5b3e6663 691 "TARGET_32BIT"
a0b632ec 692 "@
5b3e6663
PB
693 add%.\\t%0, %1, %2
694 sub%.\\t%0, %1, #%n2"
cca0a211
RE
695 [(set_attr "conds" "set")]
696)
a0b632ec
RE
697
698(define_insn "*addsi3_compare_op2"
48a08b9c 699 [(set (reg:CC_C CC_REGNUM)
a0b632ec
RE
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)))
68df59d3 704 (set (match_operand:SI 0 "s_register_operand" "=r,r")
ff9940b0 705 (plus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 706 "TARGET_32BIT"
68df59d3 707 "@
5b3e6663
PB
708 add%.\\t%0, %1, %2
709 sub%.\\t%0, %1, #%n2"
cca0a211
RE
710 [(set_attr "conds" "set")]
711)
ff9940b0 712
a0b632ec 713(define_insn "*compare_addsi2_op0"
48a08b9c 714 [(set (reg:CC_C CC_REGNUM)
a0b632ec
RE
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)))]
5b3e6663 719 "TARGET_32BIT"
a0b632ec
RE
720 "@
721 cmn%?\\t%0, %1
722 cmp%?\\t%0, #%n1"
cca0a211
RE
723 [(set_attr "conds" "set")]
724)
a0b632ec
RE
725
726(define_insn "*compare_addsi2_op1"
48a08b9c 727 [(set (reg:CC_C CC_REGNUM)
a0b632ec
RE
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)))]
5b3e6663 732 "TARGET_32BIT"
a0b632ec
RE
733 "@
734 cmn%?\\t%0, %1
735 cmp%?\\t%0, #%n1"
cca0a211
RE
736 [(set_attr "conds" "set")]
737)
a0b632ec
RE
738
739(define_insn "*addsi3_carryin"
740 [(set (match_operand:SI 0 "s_register_operand" "=r")
48a08b9c 741 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
a0b632ec
RE
742 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
743 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
5b3e6663 744 "TARGET_32BIT"
a0b632ec 745 "adc%?\\t%0, %1, %2"
d5b7b3ae
RE
746 [(set_attr "conds" "use")]
747)
a0b632ec 748
3a8de233 749(define_insn "*addsi3_carryin_shift"
1cc82d13 750 [(set (match_operand:SI 0 "s_register_operand" "=r")
48a08b9c 751 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
3a8de233
JL
752 (plus:SI
753 (match_operator:SI 2 "shift_operator"
1cc82d13
RE
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"))))]
5b3e6663 757 "TARGET_32BIT"
3a8de233 758 "adc%?\\t%0, %1, %3%S2"
9b66ebb1
PB
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")))]
3a8de233
JL
763)
764
a0b632ec
RE
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"))
48a08b9c 769 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
5b3e6663 770 "TARGET_32BIT"
a0b632ec 771 "adc%?\\t%0, %1, %2"
d5b7b3ae
RE
772 [(set_attr "conds" "use")]
773)
a0b632ec
RE
774
775(define_insn "*addsi3_carryin_alt2"
776 [(set (match_operand:SI 0 "s_register_operand" "=r")
48a08b9c 777 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
a0b632ec
RE
778 (match_operand:SI 1 "s_register_operand" "r"))
779 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
5b3e6663 780 "TARGET_32BIT"
a0b632ec 781 "adc%?\\t%0, %1, %2"
cca0a211
RE
782 [(set_attr "conds" "use")]
783)
a0b632ec
RE
784
785(define_insn "*addsi3_carryin_alt3"
786 [(set (match_operand:SI 0 "s_register_operand" "=r")
48a08b9c 787 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
a0b632ec
RE
788 (match_operand:SI 2 "arm_rhs_operand" "rI"))
789 (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 790 "TARGET_32BIT"
a0b632ec 791 "adc%?\\t%0, %1, %2"
d5b7b3ae
RE
792 [(set_attr "conds" "use")]
793)
a0b632ec 794
5b3e6663
PB
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"
ff9940b0 805 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 806 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
d5b7b3ae 807 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
ff9940b0 808 (match_operand:SI 1 "s_register_operand" "0,?r")))]
d5b7b3ae 809 "TARGET_ARM"
68df59d3
RE
810 "@
811 add%d2\\t%0, %1, #1
812 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
05ed98a1 813 [(set_attr "conds" "use")
5895f793
RE
814 (set_attr "length" "4,8")]
815)
ff9940b0 816
de9315db
RE
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" ""))]
5b3e6663 824 "TARGET_32BIT"
de9315db
RE
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
37f74dcf
RE
831(define_expand "addsf3"
832 [(set (match_operand:SF 0 "s_register_operand" "")
833 (plus:SF (match_operand:SF 1 "s_register_operand" "")
9b66ebb1 834 (match_operand:SF 2 "arm_float_add_operand" "")))]
5b3e6663 835 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 836 "
9b66ebb1 837 if (TARGET_MAVERICK
37f74dcf
RE
838 && !cirrus_fp_register (operands[2], SFmode))
839 operands[2] = force_reg (SFmode, operands[2]);
840")
841
37f74dcf
RE
842(define_expand "adddf3"
843 [(set (match_operand:DF 0 "s_register_operand" "")
844 (plus:DF (match_operand:DF 1 "s_register_operand" "")
9b66ebb1 845 (match_operand:DF 2 "arm_float_add_operand" "")))]
5b3e6663 846 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 847 "
9b66ebb1 848 if (TARGET_MAVERICK
37f74dcf
RE
849 && !cirrus_fp_register (operands[2], DFmode))
850 operands[2] = force_reg (DFmode, operands[2]);
851")
852
d5b7b3ae
RE
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" "")))
48a08b9c 858 (clobber (reg:CC CC_REGNUM))])]
d5b7b3ae
RE
859 "TARGET_EITHER"
860 "
9b66ebb1 861 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
5b3e6663 862 && TARGET_32BIT
9b6b54e2
NC
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
5b3e6663 870 if (TARGET_THUMB1)
d5b7b3ae
RE
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")
ff9940b0
RE
882 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
883 (match_operand:DI 2 "s_register_operand" "r,0,0")))
48a08b9c 884 (clobber (reg:CC CC_REGNUM))]
5b3e6663 885 "TARGET_32BIT"
3dafc5c3 886 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
d5b7b3ae
RE
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")))
48a08b9c 895 (clobber (reg:CC CC_REGNUM))]
5b3e6663 896 "TARGET_THUMB1"
d5b7b3ae
RE
897 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
898 [(set_attr "length" "4")]
899)
ff9940b0 900
4cdb3ed4 901(define_insn "*subdi_di_zesidi"
d5b7b3ae
RE
902 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
903 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
ff9940b0 904 (zero_extend:DI
d5b7b3ae 905 (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 906 (clobber (reg:CC CC_REGNUM))]
5b3e6663 907 "TARGET_32BIT"
3dafc5c3 908 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
d5b7b3ae
RE
909 [(set_attr "conds" "clob")
910 (set_attr "length" "8")]
911)
ff9940b0 912
4cdb3ed4 913(define_insn "*subdi_di_sesidi"
d5b7b3ae
RE
914 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
915 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
ff9940b0 916 (sign_extend:DI
d5b7b3ae 917 (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 918 (clobber (reg:CC CC_REGNUM))]
5b3e6663 919 "TARGET_32BIT"
3dafc5c3 920 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
d5b7b3ae
RE
921 [(set_attr "conds" "clob")
922 (set_attr "length" "8")]
923)
ff9940b0 924
4cdb3ed4 925(define_insn "*subdi_zesidi_di"
d5b7b3ae 926 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
ff9940b0 927 (minus:DI (zero_extend:DI
d5b7b3ae
RE
928 (match_operand:SI 2 "s_register_operand" "r,r"))
929 (match_operand:DI 1 "s_register_operand" "?r,0")))
48a08b9c 930 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 931 "TARGET_ARM"
3dafc5c3 932 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
d5b7b3ae
RE
933 [(set_attr "conds" "clob")
934 (set_attr "length" "8")]
935)
ff9940b0 936
4cdb3ed4 937(define_insn "*subdi_sesidi_di"
d5b7b3ae 938 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
ff9940b0 939 (minus:DI (sign_extend:DI
d5b7b3ae
RE
940 (match_operand:SI 2 "s_register_operand" "r,r"))
941 (match_operand:DI 1 "s_register_operand" "?r,0")))
48a08b9c 942 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 943 "TARGET_ARM"
3dafc5c3 944 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
d5b7b3ae
RE
945 [(set_attr "conds" "clob")
946 (set_attr "length" "8")]
947)
ff9940b0 948
4cdb3ed4 949(define_insn "*subdi_zesidi_zesidi"
d5b7b3ae 950 [(set (match_operand:DI 0 "s_register_operand" "=r")
ff9940b0 951 (minus:DI (zero_extend:DI
d5b7b3ae 952 (match_operand:SI 1 "s_register_operand" "r"))
ff9940b0 953 (zero_extend:DI
d5b7b3ae 954 (match_operand:SI 2 "s_register_operand" "r"))))
48a08b9c 955 (clobber (reg:CC CC_REGNUM))]
5b3e6663
PB
956 "TARGET_32BIT"
957 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
d5b7b3ae
RE
958 [(set_attr "conds" "clob")
959 (set_attr "length" "8")]
960)
3a33f76f 961
091426d3 962(define_expand "subsi3"
d5b7b3ae 963 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
964 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
965 (match_operand:SI 2 "s_register_operand" "")))]
d5b7b3ae 966 "TARGET_EITHER"
091426d3
RE
967 "
968 if (GET_CODE (operands[1]) == CONST_INT)
969 {
5b3e6663 970 if (TARGET_32BIT)
d5b7b3ae 971 {
a406f566
MM
972 arm_split_constant (MINUS, SImode, NULL_RTX,
973 INTVAL (operands[1]), operands[0],
b3a13419 974 operands[2], optimize && can_create_pseudo_p ());
d5b7b3ae
RE
975 DONE;
976 }
5b3e6663 977 else /* TARGET_THUMB1 */
d5b7b3ae 978 operands[1] = force_reg (SImode, operands[1]);
091426d3 979 }
d5b7b3ae
RE
980 "
981)
091426d3 982
5b3e6663 983(define_insn "*thumb1_subsi3_insn"
d5b7b3ae
RE
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")))]
5b3e6663 987 "TARGET_THUMB1"
d5b7b3ae
RE
988 "sub\\t%0, %1, %2"
989 [(set_attr "length" "2")]
990)
991
5b3e6663 992; ??? Check Thumb-2 split length
bb6ae783 993(define_insn_and_split "*arm_subsi3_insn"
d5b7b3ae 994 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
091426d3
RE
995 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
996 (match_operand:SI 2 "s_register_operand" "r,r")))]
5b3e6663 997 "TARGET_32BIT"
0f447ef2 998 "@
091426d3
RE
999 rsb%?\\t%0, %2, %1
1000 #"
5b3e6663 1001 "TARGET_32BIT
bb6ae783
RE
1002 && GET_CODE (operands[1]) == CONST_INT
1003 && !const_ok_for_arm (INTVAL (operands[1]))"
091426d3
RE
1004 [(clobber (const_int 0))]
1005 "
a406f566
MM
1006 arm_split_constant (MINUS, SImode, curr_insn,
1007 INTVAL (operands[1]), operands[0], operands[2], 0);
091426d3 1008 DONE;
d5b7b3ae 1009 "
bb6ae783
RE
1010 [(set_attr "length" "4,16")
1011 (set_attr "predicable" "yes")]
1012)
1013
1014(define_peephole2
1015 [(match_scratch:SI 3 "r")
3053b100 1016 (set (match_operand:SI 0 "arm_general_register_operand" "")
bb6ae783 1017 (minus:SI (match_operand:SI 1 "const_int_operand" "")
3053b100 1018 (match_operand:SI 2 "arm_general_register_operand" "")))]
5b3e6663 1019 "TARGET_32BIT
bb6ae783
RE
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 ""
d5b7b3ae 1025)
3a33f76f 1026
4cdb3ed4 1027(define_insn "*subsi3_compare0"
48a08b9c 1028 [(set (reg:CC_NOOV CC_REGNUM)
5895f793
RE
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)))
ff9940b0
RE
1033 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1034 (minus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 1035 "TARGET_32BIT"
0f447ef2 1036 "@
5b3e6663
PB
1037 sub%.\\t%0, %1, %2
1038 rsb%.\\t%0, %2, %1"
d5b7b3ae
RE
1039 [(set_attr "conds" "set")]
1040)
ff9940b0 1041
5b3e6663
PB
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"
d5b7b3ae
RE
1052 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1053 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
05ed98a1 1054 (match_operator:SI 2 "arm_comparison_operator"
d5b7b3ae
RE
1055 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1056 "TARGET_ARM"
0f447ef2 1057 "@
5895f793
RE
1058 sub%d2\\t%0, %1, #1
1059 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
d5b7b3ae
RE
1060 [(set_attr "conds" "use")
1061 (set_attr "length" "*,8")]
1062)
ff9940b0 1063
37f74dcf
RE
1064(define_expand "subsf3"
1065 [(set (match_operand:SF 0 "s_register_operand" "")
9b66ebb1
PB
1066 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1067 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1068 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1069 "
9b66ebb1 1070 if (TARGET_MAVERICK)
37f74dcf
RE
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
37f74dcf
RE
1079(define_expand "subdf3"
1080 [(set (match_operand:DF 0 "s_register_operand" "")
9b66ebb1
PB
1081 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1082 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1083 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1084 "
9b66ebb1 1085 if (TARGET_MAVERICK)
37f74dcf
RE
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
3a33f76f
RK
1094\f
1095;; Multiplication insns
1096
d5b7b3ae
RE
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
ff9940b0 1105;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
d5b7b3ae
RE
1106(define_insn "*arm_mulsi3"
1107 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
ff9940b0
RE
1108 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1109 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
d6c397b0 1110 "TARGET_32BIT && !arm_arch6"
4cdb3ed4 1111 "mul%?\\t%0, %2, %1"
9b66ebb1 1112 [(set_attr "insn" "mul")
cca0a211 1113 (set_attr "predicable" "yes")]
d5b7b3ae
RE
1114)
1115
d6c397b0
PB
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
5895f793
RE
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.
d5b7b3ae
RE
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")))]
d6c397b0 1135 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
1136 "*
1137 if (which_alternative < 2)
d08e2ccb 1138 return \"mov\\t%0, %1\;mul\\t%0, %2\";
d5b7b3ae 1139 else
d08e2ccb 1140 return \"mul\\t%0, %2\";
d5b7b3ae
RE
1141 "
1142 [(set_attr "length" "4,4,2")
9b66ebb1 1143 (set_attr "insn" "mul")]
d5b7b3ae 1144)
3a33f76f 1145
d6c397b0
PB
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
4cdb3ed4 1159(define_insn "*mulsi3_compare0"
48a08b9c 1160 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
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)))]
d6c397b0
PB
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"
5b3e6663 1182 "mul%.\\t%0, %2, %1"
d5b7b3ae 1183 [(set_attr "conds" "set")
9b66ebb1 1184 (set_attr "insn" "muls")]
d5b7b3ae 1185)
ff9940b0 1186
4cdb3ed4 1187(define_insn "*mulsi_compare0_scratch"
48a08b9c 1188 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
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"))]
d6c397b0
PB
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"
5b3e6663 1208 "mul%.\\t%0, %2, %1"
d5b7b3ae 1209 [(set_attr "conds" "set")
9b66ebb1 1210 (set_attr "insn" "muls")]
d5b7b3ae 1211)
ff9940b0 1212
3a33f76f
RK
1213;; Unnamed templates to match MLA instruction.
1214
4cdb3ed4 1215(define_insn "*mulsi3addsi"
ff9940b0 1216 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
fd3f89a9 1217 (plus:SI
ff9940b0
RE
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")))]
d6c397b0
PB
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"
4cdb3ed4 1234 "mla%?\\t%0, %2, %1, %3"
9b66ebb1 1235 [(set_attr "insn" "mla")
cca0a211
RE
1236 (set_attr "predicable" "yes")]
1237)
3a33f76f 1238
4cdb3ed4 1239(define_insn "*mulsi3addsi_compare0"
48a08b9c 1240 [(set (reg:CC_NOOV CC_REGNUM)
5895f793
RE
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)))
ff9940b0
RE
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)))]
d6c397b0
PB
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"
5b3e6663 1268 "mla%.\\t%0, %2, %1, %3"
cca0a211 1269 [(set_attr "conds" "set")
9b66ebb1 1270 (set_attr "insn" "mlas")]
cca0a211 1271)
ff9940b0 1272
4cdb3ed4 1273(define_insn "*mulsi3addsi_compare0_scratch"
48a08b9c 1274 [(set (reg:CC_NOOV CC_REGNUM)
5895f793
RE
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)))
ff9940b0 1281 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
d6c397b0
PB
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"
5b3e6663 1298 "mla%.\\t%0, %2, %1, %3"
d5b7b3ae 1299 [(set_attr "conds" "set")
9b66ebb1 1300 (set_attr "insn" "mlas")]
d5b7b3ae 1301)
4cdb3ed4 1302
26b53f80
PB
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
839a4992 1315;; Unnamed template to match long long multiply-accumulate (smlal)
9e3fc430
CP
1316
1317(define_insn "*mulsidi3adddi"
b082bfdb 1318 [(set (match_operand:DI 0 "s_register_operand" "=&r")
9e3fc430 1319 (plus:DI
5895f793 1320 (mult:DI
b082bfdb
RE
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")))]
d6c397b0
PB
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"
b082bfdb 1338 "smlal%?\\t%Q0, %R0, %3, %2"
9b66ebb1 1339 [(set_attr "insn" "smlal")
cca0a211
RE
1340 (set_attr "predicable" "yes")]
1341)
9e3fc430 1342
4cdb3ed4
RE
1343(define_insn "mulsidi3"
1344 [(set (match_operand:DI 0 "s_register_operand" "=&r")
5895f793
RE
1345 (mult:DI
1346 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1347 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
d6c397b0
PB
1348 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1349 "smull%?\\t%Q0, %R0, %1, %2"
1350 [(set_attr "insn" "smull")
1351 (set_attr "predicable" "yes")]
1352)
1353
1354(define_insn "mulsidi3_v6"
1355 [(set (match_operand:DI 0 "s_register_operand" "=r")
1356 (mult:DI
1357 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1358 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1359 "TARGET_32BIT && arm_arch6"
3dafc5c3 1360 "smull%?\\t%Q0, %R0, %1, %2"
9b66ebb1 1361 [(set_attr "insn" "smull")
cca0a211
RE
1362 (set_attr "predicable" "yes")]
1363)
4cdb3ed4
RE
1364
1365(define_insn "umulsidi3"
1366 [(set (match_operand:DI 0 "s_register_operand" "=&r")
5895f793
RE
1367 (mult:DI
1368 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1369 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
d6c397b0
PB
1370 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1371 "umull%?\\t%Q0, %R0, %1, %2"
1372 [(set_attr "insn" "umull")
1373 (set_attr "predicable" "yes")]
1374)
1375
1376(define_insn "umulsidi3_v6"
1377 [(set (match_operand:DI 0 "s_register_operand" "=r")
1378 (mult:DI
1379 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1380 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1381 "TARGET_32BIT && arm_arch6"
3dafc5c3 1382 "umull%?\\t%Q0, %R0, %1, %2"
9b66ebb1 1383 [(set_attr "insn" "umull")
cca0a211
RE
1384 (set_attr "predicable" "yes")]
1385)
3a33f76f 1386
839a4992 1387;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
9e3fc430
CP
1388
1389(define_insn "*umulsidi3adddi"
a67ded0f 1390 [(set (match_operand:DI 0 "s_register_operand" "=&r")
9e3fc430 1391 (plus:DI
5895f793 1392 (mult:DI
b082bfdb
RE
1393 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1394 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1395 (match_operand:DI 1 "s_register_operand" "0")))]
d6c397b0
PB
1396 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1397 "umlal%?\\t%Q0, %R0, %3, %2"
1398 [(set_attr "insn" "umlal")
1399 (set_attr "predicable" "yes")]
1400)
1401
1402(define_insn "*umulsidi3adddi_v6"
1403 [(set (match_operand:DI 0 "s_register_operand" "=r")
1404 (plus:DI
1405 (mult:DI
1406 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1407 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1408 (match_operand:DI 1 "s_register_operand" "0")))]
1409 "TARGET_32BIT && arm_arch6"
b082bfdb 1410 "umlal%?\\t%Q0, %R0, %3, %2"
9b66ebb1 1411 [(set_attr "insn" "umlal")
cca0a211
RE
1412 (set_attr "predicable" "yes")]
1413)
9e3fc430 1414
7a0a1f09
RE
1415(define_insn "smulsi3_highpart"
1416 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1417 (truncate:SI
1418 (lshiftrt:DI
5895f793
RE
1419 (mult:DI
1420 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1421 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
7a0a1f09
RE
1422 (const_int 32))))
1423 (clobber (match_scratch:SI 3 "=&r,&r"))]
d6c397b0
PB
1424 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1425 "smull%?\\t%3, %0, %2, %1"
1426 [(set_attr "insn" "smull")
1427 (set_attr "predicable" "yes")]
1428)
1429
1430(define_insn "smulsi3_highpart_v6"
1431 [(set (match_operand:SI 0 "s_register_operand" "=r")
1432 (truncate:SI
1433 (lshiftrt:DI
1434 (mult:DI
1435 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1436 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1437 (const_int 32))))
1438 (clobber (match_scratch:SI 3 "=r"))]
1439 "TARGET_32BIT && arm_arch6"
7a0a1f09 1440 "smull%?\\t%3, %0, %2, %1"
9b66ebb1 1441 [(set_attr "insn" "smull")
cca0a211 1442 (set_attr "predicable" "yes")]
d5b7b3ae 1443)
7a0a1f09
RE
1444
1445(define_insn "umulsi3_highpart"
1446 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1447 (truncate:SI
1448 (lshiftrt:DI
5895f793
RE
1449 (mult:DI
1450 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1451 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
7a0a1f09
RE
1452 (const_int 32))))
1453 (clobber (match_scratch:SI 3 "=&r,&r"))]
d6c397b0
PB
1454 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1455 "umull%?\\t%3, %0, %2, %1"
1456 [(set_attr "insn" "umull")
1457 (set_attr "predicable" "yes")]
1458)
1459
1460(define_insn "umulsi3_highpart_v6"
1461 [(set (match_operand:SI 0 "s_register_operand" "=r")
1462 (truncate:SI
1463 (lshiftrt:DI
1464 (mult:DI
1465 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1466 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1467 (const_int 32))))
1468 (clobber (match_scratch:SI 3 "=r"))]
1469 "TARGET_32BIT && arm_arch6"
7a0a1f09 1470 "umull%?\\t%3, %0, %2, %1"
9b66ebb1 1471 [(set_attr "insn" "umull")
cca0a211 1472 (set_attr "predicable" "yes")]
d5b7b3ae 1473)
7a0a1f09 1474
d19fb8e3
NC
1475(define_insn "mulhisi3"
1476 [(set (match_operand:SI 0 "s_register_operand" "=r")
1477 (mult:SI (sign_extend:SI
1478 (match_operand:HI 1 "s_register_operand" "%r"))
1479 (sign_extend:SI
1480 (match_operand:HI 2 "s_register_operand" "r"))))]
5b3e6663 1481 "TARGET_DSP_MULTIPLY"
859230d4 1482 "smulbb%?\\t%0, %1, %2"
9b66ebb1 1483 [(set_attr "insn" "smulxy")
b8c53e96
RE
1484 (set_attr "predicable" "yes")]
1485)
1486
1487(define_insn "*mulhisi3tb"
1488 [(set (match_operand:SI 0 "s_register_operand" "=r")
1489 (mult:SI (ashiftrt:SI
1490 (match_operand:SI 1 "s_register_operand" "r")
1491 (const_int 16))
1492 (sign_extend:SI
1493 (match_operand:HI 2 "s_register_operand" "r"))))]
5b3e6663 1494 "TARGET_DSP_MULTIPLY"
b8c53e96 1495 "smultb%?\\t%0, %1, %2"
9b66ebb1 1496 [(set_attr "insn" "smulxy")
b8c53e96
RE
1497 (set_attr "predicable" "yes")]
1498)
1499
1500(define_insn "*mulhisi3bt"
1501 [(set (match_operand:SI 0 "s_register_operand" "=r")
1502 (mult:SI (sign_extend:SI
1503 (match_operand:HI 1 "s_register_operand" "r"))
1504 (ashiftrt:SI
1505 (match_operand:SI 2 "s_register_operand" "r")
1506 (const_int 16))))]
5b3e6663 1507 "TARGET_DSP_MULTIPLY"
b8c53e96 1508 "smulbt%?\\t%0, %1, %2"
9b66ebb1 1509 [(set_attr "insn" "smulxy")
b8c53e96
RE
1510 (set_attr "predicable" "yes")]
1511)
1512
1513(define_insn "*mulhisi3tt"
1514 [(set (match_operand:SI 0 "s_register_operand" "=r")
1515 (mult:SI (ashiftrt:SI
1516 (match_operand:SI 1 "s_register_operand" "r")
1517 (const_int 16))
1518 (ashiftrt:SI
1519 (match_operand:SI 2 "s_register_operand" "r")
1520 (const_int 16))))]
5b3e6663 1521 "TARGET_DSP_MULTIPLY"
b8c53e96 1522 "smultt%?\\t%0, %1, %2"
9b66ebb1 1523 [(set_attr "insn" "smulxy")
b8c53e96 1524 (set_attr "predicable" "yes")]
d19fb8e3
NC
1525)
1526
1527(define_insn "*mulhisi3addsi"
1528 [(set (match_operand:SI 0 "s_register_operand" "=r")
1529 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1530 (mult:SI (sign_extend:SI
1531 (match_operand:HI 2 "s_register_operand" "%r"))
1532 (sign_extend:SI
1533 (match_operand:HI 3 "s_register_operand" "r")))))]
5b3e6663 1534 "TARGET_DSP_MULTIPLY"
859230d4 1535 "smlabb%?\\t%0, %2, %3, %1"
9b66ebb1 1536 [(set_attr "insn" "smlaxy")
b8c53e96 1537 (set_attr "predicable" "yes")]
d19fb8e3
NC
1538)
1539
1540(define_insn "*mulhidi3adddi"
1541 [(set (match_operand:DI 0 "s_register_operand" "=r")
1542 (plus:DI
1543 (match_operand:DI 1 "s_register_operand" "0")
1544 (mult:DI (sign_extend:DI
1545 (match_operand:HI 2 "s_register_operand" "%r"))
1546 (sign_extend:DI
1547 (match_operand:HI 3 "s_register_operand" "r")))))]
5b3e6663 1548 "TARGET_DSP_MULTIPLY"
d19fb8e3 1549 "smlalbb%?\\t%Q0, %R0, %2, %3"
9b66ebb1 1550 [(set_attr "insn" "smlalxy")
b8c53e96 1551 (set_attr "predicable" "yes")])
d19fb8e3 1552
37f74dcf
RE
1553(define_expand "mulsf3"
1554 [(set (match_operand:SF 0 "s_register_operand" "")
1555 (mult:SF (match_operand:SF 1 "s_register_operand" "")
9b66ebb1 1556 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1557 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1558 "
9b66ebb1 1559 if (TARGET_MAVERICK
37f74dcf
RE
1560 && !cirrus_fp_register (operands[2], SFmode))
1561 operands[2] = force_reg (SFmode, operands[2]);
1562")
1563
37f74dcf
RE
1564(define_expand "muldf3"
1565 [(set (match_operand:DF 0 "s_register_operand" "")
1566 (mult:DF (match_operand:DF 1 "s_register_operand" "")
9b66ebb1 1567 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1568 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1569 "
9b66ebb1 1570 if (TARGET_MAVERICK
37f74dcf
RE
1571 && !cirrus_fp_register (operands[2], DFmode))
1572 operands[2] = force_reg (DFmode, operands[2]);
1573")
3a33f76f
RK
1574\f
1575;; Division insns
1576
82955615
RE
1577(define_expand "divsf3"
1578 [(set (match_operand:SF 0 "s_register_operand" "")
9b66ebb1
PB
1579 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1580 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1581 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
82955615 1582 "")
ff9940b0 1583
82955615
RE
1584(define_expand "divdf3"
1585 [(set (match_operand:DF 0 "s_register_operand" "")
9b66ebb1
PB
1586 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1587 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1588 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
82955615 1589 "")
3a33f76f
RK
1590\f
1591;; Modulo insns
1592
82955615
RE
1593(define_expand "modsf3"
1594 [(set (match_operand:SF 0 "s_register_operand" "")
1595 (mod:SF (match_operand:SF 1 "s_register_operand" "")
9b66ebb1 1596 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1597 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
82955615 1598 "")
ff9940b0 1599
82955615
RE
1600(define_expand "moddf3"
1601 [(set (match_operand:DF 0 "s_register_operand" "")
1602 (mod:DF (match_operand:DF 1 "s_register_operand" "")
9b66ebb1 1603 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
5b3e6663 1604 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
82955615 1605 "")
3a33f76f
RK
1606\f
1607;; Boolean and,ior,xor insns
1608
6ab589e0
JL
1609;; Split up double word logical operations
1610
1611;; Split up simple DImode logical operations. Simply perform the logical
1612;; operation on the upper and lower halves of the registers.
1613(define_split
1614 [(set (match_operand:DI 0 "s_register_operand" "")
1615 (match_operator:DI 6 "logical_binary_operator"
1616 [(match_operand:DI 1 "s_register_operand" "")
1617 (match_operand:DI 2 "s_register_operand" "")]))]
5b3e6663
PB
1618 "TARGET_32BIT && reload_completed
1619 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
6ab589e0
JL
1620 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1621 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1622 "
5895f793
RE
1623 {
1624 operands[3] = gen_highpart (SImode, operands[0]);
1625 operands[0] = gen_lowpart (SImode, operands[0]);
1626 operands[4] = gen_highpart (SImode, operands[1]);
1627 operands[1] = gen_lowpart (SImode, operands[1]);
1628 operands[5] = gen_highpart (SImode, operands[2]);
1629 operands[2] = gen_lowpart (SImode, operands[2]);
1630 }"
1631)
6ab589e0 1632
6ab589e0
JL
1633(define_split
1634 [(set (match_operand:DI 0 "s_register_operand" "")
1635 (match_operator:DI 6 "logical_binary_operator"
1636 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1637 (match_operand:DI 1 "s_register_operand" "")]))]
5b3e6663 1638 "TARGET_32BIT && reload_completed"
6ab589e0
JL
1639 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1640 (set (match_dup 3) (match_op_dup:SI 6
1641 [(ashiftrt:SI (match_dup 2) (const_int 31))
1642 (match_dup 4)]))]
1643 "
5895f793
RE
1644 {
1645 operands[3] = gen_highpart (SImode, operands[0]);
1646 operands[0] = gen_lowpart (SImode, operands[0]);
1647 operands[4] = gen_highpart (SImode, operands[1]);
1648 operands[1] = gen_lowpart (SImode, operands[1]);
1649 operands[5] = gen_highpart (SImode, operands[2]);
1650 operands[2] = gen_lowpart (SImode, operands[2]);
1651 }"
1652)
6ab589e0 1653
6ab589e0
JL
1654;; The zero extend of operand 2 means we can just copy the high part of
1655;; operand1 into operand0.
1656(define_split
1657 [(set (match_operand:DI 0 "s_register_operand" "")
1658 (ior:DI
1659 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1660 (match_operand:DI 1 "s_register_operand" "")))]
5b3e6663 1661 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
6ab589e0
JL
1662 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1663 (set (match_dup 3) (match_dup 4))]
1664 "
5895f793
RE
1665 {
1666 operands[4] = gen_highpart (SImode, operands[1]);
1667 operands[3] = gen_highpart (SImode, operands[0]);
1668 operands[0] = gen_lowpart (SImode, operands[0]);
1669 operands[1] = gen_lowpart (SImode, operands[1]);
1670 }"
1671)
6ab589e0
JL
1672
1673;; The zero extend of operand 2 means we can just copy the high part of
1674;; operand1 into operand0.
1675(define_split
1676 [(set (match_operand:DI 0 "s_register_operand" "")
1677 (xor:DI
1678 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1679 (match_operand:DI 1 "s_register_operand" "")))]
5b3e6663 1680 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
6ab589e0
JL
1681 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1682 (set (match_dup 3) (match_dup 4))]
1683 "
5895f793
RE
1684 {
1685 operands[4] = gen_highpart (SImode, operands[1]);
1686 operands[3] = gen_highpart (SImode, operands[0]);
1687 operands[0] = gen_lowpart (SImode, operands[0]);
1688 operands[1] = gen_lowpart (SImode, operands[1]);
1689 }"
1690)
6ab589e0 1691
3a33f76f 1692(define_insn "anddi3"
d5b7b3ae
RE
1693 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1694 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1695 (match_operand:DI 2 "s_register_operand" "r,r")))]
5b3e6663 1696 "TARGET_32BIT && ! TARGET_IWMMXT"
6ab589e0 1697 "#"
5895f793
RE
1698 [(set_attr "length" "8")]
1699)
3a33f76f 1700
bb6ae783 1701(define_insn_and_split "*anddi_zesidi_di"
ff9940b0
RE
1702 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1703 (and:DI (zero_extend:DI
1704 (match_operand:SI 2 "s_register_operand" "r,r"))
1705 (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 1706 "TARGET_32BIT"
6ab589e0 1707 "#"
5b3e6663 1708 "TARGET_32BIT && reload_completed"
bb6ae783
RE
1709 ; The zero extend of operand 2 clears the high word of the output
1710 ; operand.
1711 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1712 (set (match_dup 3) (const_int 0))]
1713 "
1714 {
1715 operands[3] = gen_highpart (SImode, operands[0]);
1716 operands[0] = gen_lowpart (SImode, operands[0]);
1717 operands[1] = gen_lowpart (SImode, operands[1]);
1718 }"
5895f793
RE
1719 [(set_attr "length" "8")]
1720)
3a33f76f 1721
4cdb3ed4 1722(define_insn "*anddi_sesdi_di"
d5b7b3ae 1723 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
ff9940b0
RE
1724 (and:DI (sign_extend:DI
1725 (match_operand:SI 2 "s_register_operand" "r,r"))
d5b7b3ae 1726 (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 1727 "TARGET_32BIT"
6ab589e0 1728 "#"
d5b7b3ae
RE
1729 [(set_attr "length" "8")]
1730)
3a33f76f 1731
091426d3 1732(define_expand "andsi3"
d5b7b3ae 1733 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
1734 (and:SI (match_operand:SI 1 "s_register_operand" "")
1735 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 1736 "TARGET_EITHER"
091426d3 1737 "
5b3e6663 1738 if (TARGET_32BIT)
091426d3 1739 {
d5b7b3ae
RE
1740 if (GET_CODE (operands[2]) == CONST_INT)
1741 {
a406f566
MM
1742 arm_split_constant (AND, SImode, NULL_RTX,
1743 INTVAL (operands[2]), operands[0],
b3a13419 1744 operands[1], optimize && can_create_pseudo_p ());
d56993f2 1745
d5b7b3ae
RE
1746 DONE;
1747 }
091426d3 1748 }
5b3e6663 1749 else /* TARGET_THUMB1 */
d5b7b3ae
RE
1750 {
1751 if (GET_CODE (operands[2]) != CONST_INT)
1752 operands[2] = force_reg (SImode, operands[2]);
1753 else
1754 {
1755 int i;
1756
5895f793 1757 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
d5b7b3ae 1758 {
5895f793
RE
1759 operands[2] = force_reg (SImode,
1760 GEN_INT (~INTVAL (operands[2])));
d5b7b3ae
RE
1761
1762 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1763
1764 DONE;
1765 }
091426d3 1766
d5b7b3ae
RE
1767 for (i = 9; i <= 31; i++)
1768 {
1769 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1770 {
1771 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1772 const0_rtx));
1773 DONE;
1774 }
5895f793
RE
1775 else if ((((HOST_WIDE_INT) 1) << i) - 1
1776 == ~INTVAL (operands[2]))
d5b7b3ae
RE
1777 {
1778 rtx shift = GEN_INT (i);
1779 rtx reg = gen_reg_rtx (SImode);
1780
1781 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1782 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1783
1784 DONE;
1785 }
1786 }
1787
1788 operands[2] = force_reg (SImode, operands[2]);
1789 }
5895f793
RE
1790 }
1791 "
d5b7b3ae
RE
1792)
1793
5b3e6663 1794; ??? Check split length for Thumb-2
bb6ae783 1795(define_insn_and_split "*arm_andsi3_insn"
d5b7b3ae 1796 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
091426d3
RE
1797 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1798 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
5b3e6663 1799 "TARGET_32BIT"
68df59d3
RE
1800 "@
1801 and%?\\t%0, %1, %2
091426d3
RE
1802 bic%?\\t%0, %1, #%B2
1803 #"
5b3e6663 1804 "TARGET_32BIT
bb6ae783
RE
1805 && GET_CODE (operands[2]) == CONST_INT
1806 && !(const_ok_for_arm (INTVAL (operands[2]))
1807 || const_ok_for_arm (~INTVAL (operands[2])))"
1808 [(clobber (const_int 0))]
1809 "
a406f566
MM
1810 arm_split_constant (AND, SImode, curr_insn,
1811 INTVAL (operands[2]), operands[0], operands[1], 0);
bb6ae783
RE
1812 DONE;
1813 "
cca0a211
RE
1814 [(set_attr "length" "4,4,16")
1815 (set_attr "predicable" "yes")]
d5b7b3ae
RE
1816)
1817
5b3e6663 1818(define_insn "*thumb1_andsi3_insn"
d5b7b3ae
RE
1819 [(set (match_operand:SI 0 "register_operand" "=l")
1820 (and:SI (match_operand:SI 1 "register_operand" "%0")
1821 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 1822 "TARGET_THUMB1"
d5b7b3ae
RE
1823 "and\\t%0, %0, %2"
1824 [(set_attr "length" "2")]
1825)
091426d3 1826
4cdb3ed4 1827(define_insn "*andsi3_compare0"
48a08b9c 1828 [(set (reg:CC_NOOV CC_REGNUM)
68df59d3
RE
1829 (compare:CC_NOOV
1830 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1831 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1832 (const_int 0)))
d5b7b3ae 1833 (set (match_operand:SI 0 "s_register_operand" "=r,r")
ff9940b0 1834 (and:SI (match_dup 1) (match_dup 2)))]
5b3e6663 1835 "TARGET_32BIT"
68df59d3 1836 "@
5b3e6663
PB
1837 and%.\\t%0, %1, %2
1838 bic%.\\t%0, %1, #%B2"
d5b7b3ae
RE
1839 [(set_attr "conds" "set")]
1840)
ff9940b0 1841
4cdb3ed4 1842(define_insn "*andsi3_compare0_scratch"
48a08b9c 1843 [(set (reg:CC_NOOV CC_REGNUM)
68df59d3
RE
1844 (compare:CC_NOOV
1845 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1846 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1847 (const_int 0)))
c77e04ae 1848 (clobber (match_scratch:SI 2 "=X,r"))]
5b3e6663 1849 "TARGET_32BIT"
68df59d3
RE
1850 "@
1851 tst%?\\t%0, %1
5b3e6663 1852 bic%.\\t%2, %0, #%B1"
cca0a211
RE
1853 [(set_attr "conds" "set")]
1854)
ff9940b0 1855
4cdb3ed4 1856(define_insn "*zeroextractsi_compare0_scratch"
48a08b9c 1857 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
1858 (compare:CC_NOOV (zero_extract:SI
1859 (match_operand:SI 0 "s_register_operand" "r")
0502226c
RE
1860 (match_operand 1 "const_int_operand" "n")
1861 (match_operand 2 "const_int_operand" "n"))
ff9940b0 1862 (const_int 0)))]
5b3e6663 1863 "TARGET_32BIT
d5b7b3ae
RE
1864 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1865 && INTVAL (operands[1]) > 0
1866 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1867 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
ff9940b0 1868 "*
d2ceebd1
RE
1869 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1870 << INTVAL (operands[2]));
c63165be 1871 output_asm_insn (\"tst%?\\t%0, %1\", operands);
0f447ef2 1872 return \"\";
cca0a211
RE
1873 "
1874 [(set_attr "conds" "set")]
1875)
ff9940b0 1876
2a2789d8 1877(define_insn_and_split "*ne_zeroextractsi"
dfa08768
RE
1878 [(set (match_operand:SI 0 "s_register_operand" "=r")
1879 (ne:SI (zero_extract:SI
1880 (match_operand:SI 1 "s_register_operand" "r")
1881 (match_operand:SI 2 "const_int_operand" "n")
1882 (match_operand:SI 3 "const_int_operand" "n"))
872e50d3
RE
1883 (const_int 0)))
1884 (clobber (reg:CC CC_REGNUM))]
5b3e6663 1885 "TARGET_32BIT
d5b7b3ae
RE
1886 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1887 && INTVAL (operands[2]) > 0
1888 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1889 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2a2789d8 1890 "#"
5b3e6663 1891 "TARGET_32BIT
2a2789d8
RE
1892 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1893 && INTVAL (operands[2]) > 0
1894 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1895 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1896 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1897 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1898 (const_int 0)))
1899 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1900 (set (match_dup 0)
1901 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1902 (match_dup 0) (const_int 1)))]
1903 "
1904 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1905 << INTVAL (operands[3]));
1906 "
1907 [(set_attr "conds" "clob")
5b3e6663
PB
1908 (set (attr "length")
1909 (if_then_else (eq_attr "is_thumb" "yes")
1910 (const_int 12)
1911 (const_int 8)))]
2a2789d8
RE
1912)
1913
1914(define_insn_and_split "*ne_zeroextractsi_shifted"
1915 [(set (match_operand:SI 0 "s_register_operand" "=r")
1916 (ne:SI (zero_extract:SI
1917 (match_operand:SI 1 "s_register_operand" "r")
1918 (match_operand:SI 2 "const_int_operand" "n")
1919 (const_int 0))
1920 (const_int 0)))
1921 (clobber (reg:CC CC_REGNUM))]
1922 "TARGET_ARM"
1923 "#"
1924 "TARGET_ARM"
1925 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1926 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1927 (const_int 0)))
1928 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1929 (set (match_dup 0)
1930 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1931 (match_dup 0) (const_int 1)))]
1932 "
1933 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1934 "
1935 [(set_attr "conds" "clob")
1936 (set_attr "length" "8")]
1937)
1938
1939(define_insn_and_split "*ite_ne_zeroextractsi"
1940 [(set (match_operand:SI 0 "s_register_operand" "=r")
1941 (if_then_else:SI (ne (zero_extract:SI
1942 (match_operand:SI 1 "s_register_operand" "r")
1943 (match_operand:SI 2 "const_int_operand" "n")
1944 (match_operand:SI 3 "const_int_operand" "n"))
1945 (const_int 0))
1946 (match_operand:SI 4 "arm_not_operand" "rIK")
1947 (const_int 0)))
1948 (clobber (reg:CC CC_REGNUM))]
1949 "TARGET_ARM
1950 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1951 && INTVAL (operands[2]) > 0
1952 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
69260355
RE
1953 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1954 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2a2789d8
RE
1955 "#"
1956 "TARGET_ARM
1957 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1958 && INTVAL (operands[2]) > 0
1959 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
69260355
RE
1960 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1961 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2a2789d8
RE
1962 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1963 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1964 (const_int 0)))
1965 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1966 (set (match_dup 0)
1967 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1968 (match_dup 0) (match_dup 4)))]
1969 "
dfa08768 1970 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2a2789d8
RE
1971 << INTVAL (operands[3]));
1972 "
1973 [(set_attr "conds" "clob")
1974 (set_attr "length" "8")]
1975)
1976
1977(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1978 [(set (match_operand:SI 0 "s_register_operand" "=r")
1979 (if_then_else:SI (ne (zero_extract:SI
1980 (match_operand:SI 1 "s_register_operand" "r")
1981 (match_operand:SI 2 "const_int_operand" "n")
1982 (const_int 0))
1983 (const_int 0))
1984 (match_operand:SI 3 "arm_not_operand" "rIK")
1985 (const_int 0)))
1986 (clobber (reg:CC CC_REGNUM))]
69260355 1987 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2a2789d8 1988 "#"
69260355 1989 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2a2789d8
RE
1990 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1991 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1992 (const_int 0)))
1993 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1994 (set (match_dup 0)
1995 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1996 (match_dup 0) (match_dup 3)))]
1997 "
1998 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
cca0a211
RE
1999 "
2000 [(set_attr "conds" "clob")
5895f793
RE
2001 (set_attr "length" "8")]
2002)
ff9940b0 2003
defc0463
RE
2004(define_split
2005 [(set (match_operand:SI 0 "s_register_operand" "")
2006 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2007 (match_operand:SI 2 "const_int_operand" "")
2008 (match_operand:SI 3 "const_int_operand" "")))
2009 (clobber (match_operand:SI 4 "s_register_operand" ""))]
5b3e6663 2010 "TARGET_THUMB1"
defc0463
RE
2011 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2012 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2013 "{
2014 HOST_WIDE_INT temp = INTVAL (operands[2]);
2015
2016 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2017 operands[3] = GEN_INT (32 - temp);
2018 }"
2019)
2020
5b3e6663 2021;; ??? Use Thumb-2 has bitfield insert/extract instructions.
da5cafa7
RE
2022(define_split
2023 [(set (match_operand:SI 0 "s_register_operand" "")
2024 (match_operator:SI 1 "shiftable_operator"
2025 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2026 (match_operand:SI 3 "const_int_operand" "")
2027 (match_operand:SI 4 "const_int_operand" ""))
2028 (match_operand:SI 5 "s_register_operand" "")]))
2029 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2030 "TARGET_ARM"
2031 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2032 (set (match_dup 0)
2033 (match_op_dup 1
2034 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2035 (match_dup 5)]))]
2036 "{
2037 HOST_WIDE_INT temp = INTVAL (operands[3]);
2038
2039 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2040 operands[4] = GEN_INT (32 - temp);
2041 }"
2042)
2043
defc0463
RE
2044(define_split
2045 [(set (match_operand:SI 0 "s_register_operand" "")
2046 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2047 (match_operand:SI 2 "const_int_operand" "")
2048 (match_operand:SI 3 "const_int_operand" "")))]
5b3e6663 2049 "TARGET_THUMB1"
defc0463
RE
2050 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2051 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2052 "{
2053 HOST_WIDE_INT temp = INTVAL (operands[2]);
2054
2055 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2056 operands[3] = GEN_INT (32 - temp);
2057 }"
2058)
2059
da5cafa7
RE
2060(define_split
2061 [(set (match_operand:SI 0 "s_register_operand" "")
2062 (match_operator:SI 1 "shiftable_operator"
2063 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2064 (match_operand:SI 3 "const_int_operand" "")
2065 (match_operand:SI 4 "const_int_operand" ""))
2066 (match_operand:SI 5 "s_register_operand" "")]))
2067 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2068 "TARGET_ARM"
2069 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2070 (set (match_dup 0)
2071 (match_op_dup 1
2072 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2073 (match_dup 5)]))]
2074 "{
2075 HOST_WIDE_INT temp = INTVAL (operands[3]);
2076
2077 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2078 operands[4] = GEN_INT (32 - temp);
2079 }"
2080)
2081
da959950
NC
2082;;; ??? This pattern is bogus. If operand3 has bits outside the range
2083;;; represented by the bitfield, then this will produce incorrect results.
2084;;; Somewhere, the value needs to be truncated. On targets like the m68k,
43a88a8c
KH
2085;;; which have a real bit-field insert instruction, the truncation happens
2086;;; in the bit-field insert instruction itself. Since arm does not have a
2087;;; bit-field insert instruction, we would have to emit code here to truncate
da959950
NC
2088;;; the value before we insert. This loses some of the advantage of having
2089;;; this insv pattern, so this pattern needs to be reevalutated.
2090
5b3e6663 2091; ??? Use Thumb-2 bitfield insert/extract instructions
f54fd62e
RE
2092(define_expand "insv"
2093 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2094 (match_operand:SI 1 "general_operand" "")
2095 (match_operand:SI 2 "general_operand" ""))
7730c3ff 2096 (match_operand:SI 3 "reg_or_int_operand" ""))]
d5b7b3ae 2097 "TARGET_ARM"
f54fd62e 2098 "
5895f793
RE
2099 {
2100 int start_bit = INTVAL (operands[2]);
2101 int width = INTVAL (operands[1]);
2102 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2103 rtx target, subtarget;
2104
2105 target = operands[0];
2106 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2107 subreg as the final target. */
2108 if (GET_CODE (target) == SUBREG)
2109 {
2110 subtarget = gen_reg_rtx (SImode);
2111 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2112 < GET_MODE_SIZE (SImode))
2113 target = SUBREG_REG (target);
2114 }
2115 else
2116 subtarget = target;
f54fd62e 2117
5895f793
RE
2118 if (GET_CODE (operands[3]) == CONST_INT)
2119 {
2120 /* Since we are inserting a known constant, we may be able to
2121 reduce the number of bits that we have to clear so that
2122 the mask becomes simple. */
2123 /* ??? This code does not check to see if the new mask is actually
2124 simpler. It may not be. */
2125 rtx op1 = gen_reg_rtx (SImode);
2126 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2127 start of this pattern. */
2128 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2129 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2130
c2540bbb
DJ
2131 emit_insn (gen_andsi3 (op1, operands[0],
2132 gen_int_mode (~mask2, SImode)));
5895f793 2133 emit_insn (gen_iorsi3 (subtarget, op1,
b65e6318 2134 gen_int_mode (op3_value << start_bit, SImode)));
5895f793
RE
2135 }
2136 else if (start_bit == 0
2137 && !(const_ok_for_arm (mask)
2138 || const_ok_for_arm (~mask)))
2139 {
2140 /* A Trick, since we are setting the bottom bits in the word,
2141 we can shift operand[3] up, operand[0] down, OR them together
2142 and rotate the result back again. This takes 3 insns, and
093354e0 2143 the third might be mergeable into another op. */
5895f793
RE
2144 /* The shift up copes with the possibility that operand[3] is
2145 wider than the bitfield. */
2146 rtx op0 = gen_reg_rtx (SImode);
2147 rtx op1 = gen_reg_rtx (SImode);
2148
2149 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2150 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2151 emit_insn (gen_iorsi3 (op1, op1, op0));
2152 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2153 }
2154 else if ((width + start_bit == 32)
2155 && !(const_ok_for_arm (mask)
2156 || const_ok_for_arm (~mask)))
2157 {
2158 /* Similar trick, but slightly less efficient. */
f54fd62e 2159
5895f793
RE
2160 rtx op0 = gen_reg_rtx (SImode);
2161 rtx op1 = gen_reg_rtx (SImode);
f54fd62e 2162
5895f793
RE
2163 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2164 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2165 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2166 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2167 }
2168 else
2169 {
c2540bbb 2170 rtx op0 = gen_int_mode (mask, SImode);
5895f793
RE
2171 rtx op1 = gen_reg_rtx (SImode);
2172 rtx op2 = gen_reg_rtx (SImode);
f54fd62e 2173
5895f793
RE
2174 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2175 {
2176 rtx tmp = gen_reg_rtx (SImode);
f54fd62e 2177
5895f793
RE
2178 emit_insn (gen_movsi (tmp, op0));
2179 op0 = tmp;
2180 }
f54fd62e 2181
5895f793
RE
2182 /* Mask out any bits in operand[3] that are not needed. */
2183 emit_insn (gen_andsi3 (op1, operands[3], op0));
f54fd62e 2184
5895f793
RE
2185 if (GET_CODE (op0) == CONST_INT
2186 && (const_ok_for_arm (mask << start_bit)
2187 || const_ok_for_arm (~(mask << start_bit))))
2188 {
c2540bbb 2189 op0 = gen_int_mode (~(mask << start_bit), SImode);
5895f793
RE
2190 emit_insn (gen_andsi3 (op2, operands[0], op0));
2191 }
2192 else
2193 {
2194 if (GET_CODE (op0) == CONST_INT)
2195 {
2196 rtx tmp = gen_reg_rtx (SImode);
f54fd62e 2197
5895f793
RE
2198 emit_insn (gen_movsi (tmp, op0));
2199 op0 = tmp;
2200 }
2201
2202 if (start_bit != 0)
2203 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
da959950 2204
5895f793
RE
2205 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2206 }
f54fd62e 2207
5895f793
RE
2208 if (start_bit != 0)
2209 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
f54fd62e 2210
5895f793
RE
2211 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2212 }
7a0a1f09 2213
5895f793
RE
2214 if (subtarget != target)
2215 {
2216 /* If TARGET is still a SUBREG, then it must be wider than a word,
2217 so we must be careful only to set the subword we were asked to. */
2218 if (GET_CODE (target) == SUBREG)
2219 emit_move_insn (target, subtarget);
2220 else
2221 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2222 }
f54fd62e 2223
5895f793
RE
2224 DONE;
2225 }"
2226)
f54fd62e 2227
5895f793 2228; constants for op 2 will never be given to these patterns.
bb6ae783 2229(define_insn_and_split "*anddi_notdi_di"
ff9940b0 2230 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
bb6ae783
RE
2231 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2232 (match_operand:DI 2 "s_register_operand" "0,r")))]
5b3e6663 2233 "TARGET_32BIT"
6ab589e0 2234 "#"
5b3e6663 2235 "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
bb6ae783
RE
2236 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2237 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2238 "
2239 {
2240 operands[3] = gen_highpart (SImode, operands[0]);
2241 operands[0] = gen_lowpart (SImode, operands[0]);
2242 operands[4] = gen_highpart (SImode, operands[1]);
2243 operands[1] = gen_lowpart (SImode, operands[1]);
2244 operands[5] = gen_highpart (SImode, operands[2]);
2245 operands[2] = gen_lowpart (SImode, operands[2]);
2246 }"
cca0a211
RE
2247 [(set_attr "length" "8")
2248 (set_attr "predicable" "yes")]
2249)
ff9940b0 2250
bb6ae783 2251(define_insn_and_split "*anddi_notzesidi_di"
ff9940b0
RE
2252 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2253 (and:DI (not:DI (zero_extend:DI
2254 (match_operand:SI 2 "s_register_operand" "r,r")))
0f447ef2 2255 (match_operand:DI 1 "s_register_operand" "0,?r")))]
5b3e6663 2256 "TARGET_32BIT"
0f447ef2 2257 "@
3dafc5c3 2258 bic%?\\t%Q0, %Q1, %2
6ab589e0 2259 #"
bb6ae783
RE
2260 ; (not (zero_extend ...)) allows us to just copy the high word from
2261 ; operand1 to operand0.
5b3e6663 2262 "TARGET_32BIT
bb6ae783
RE
2263 && reload_completed
2264 && operands[0] != operands[1]"
1dda7ee4 2265 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
bb6ae783
RE
2266 (set (match_dup 3) (match_dup 4))]
2267 "
2268 {
2269 operands[3] = gen_highpart (SImode, operands[0]);
2270 operands[0] = gen_lowpart (SImode, operands[0]);
2271 operands[4] = gen_highpart (SImode, operands[1]);
2272 operands[1] = gen_lowpart (SImode, operands[1]);
2273 }"
cca0a211
RE
2274 [(set_attr "length" "4,8")
2275 (set_attr "predicable" "yes")]
2276)
ff9940b0 2277
bb6ae783 2278(define_insn_and_split "*anddi_notsesidi_di"
ff9940b0
RE
2279 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2280 (and:DI (not:DI (sign_extend:DI
2281 (match_operand:SI 2 "s_register_operand" "r,r")))
1dda7ee4 2282 (match_operand:DI 1 "s_register_operand" "0,r")))]
5b3e6663 2283 "TARGET_32BIT"
6ab589e0 2284 "#"
5b3e6663 2285 "TARGET_32BIT && reload_completed"
1dda7ee4 2286 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
bb6ae783
RE
2287 (set (match_dup 3) (and:SI (not:SI
2288 (ashiftrt:SI (match_dup 2) (const_int 31)))
2289 (match_dup 4)))]
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 }"
cca0a211
RE
2297 [(set_attr "length" "8")
2298 (set_attr "predicable" "yes")]
2299)
ff9940b0 2300
f54fd62e 2301(define_insn "andsi_notsi_si"
ff9940b0
RE
2302 [(set (match_operand:SI 0 "s_register_operand" "=r")
2303 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2304 (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 2305 "TARGET_32BIT"
cca0a211
RE
2306 "bic%?\\t%0, %1, %2"
2307 [(set_attr "predicable" "yes")]
2308)
3a33f76f 2309
d5b7b3ae
RE
2310(define_insn "bicsi3"
2311 [(set (match_operand:SI 0 "register_operand" "=l")
2312 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2313 (match_operand:SI 2 "register_operand" "0")))]
5b3e6663 2314 "TARGET_THUMB1"
d5b7b3ae
RE
2315 "bic\\t%0, %0, %1"
2316 [(set_attr "length" "2")]
2317)
2318
f54fd62e 2319(define_insn "andsi_not_shiftsi_si"
9b66ebb1
PB
2320 [(set (match_operand:SI 0 "s_register_operand" "=r")
2321 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2322 [(match_operand:SI 2 "s_register_operand" "r")
2323 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2324 (match_operand:SI 1 "s_register_operand" "r")))]
d5b7b3ae 2325 "TARGET_ARM"
b020fd92 2326 "bic%?\\t%0, %1, %2%S4"
ca68ea18 2327 [(set_attr "predicable" "yes")
d19fb8e3 2328 (set_attr "shift" "2")
9b66ebb1
PB
2329 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2330 (const_string "alu_shift")
2331 (const_string "alu_shift_reg")))]
b020fd92 2332)
f54fd62e 2333
4cdb3ed4 2334(define_insn "*andsi_notsi_si_compare0"
48a08b9c 2335 [(set (reg:CC_NOOV CC_REGNUM)
0f447ef2
RE
2336 (compare:CC_NOOV
2337 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2338 (match_operand:SI 1 "s_register_operand" "r"))
2339 (const_int 0)))
ff9940b0
RE
2340 (set (match_operand:SI 0 "s_register_operand" "=r")
2341 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
5b3e6663
PB
2342 "TARGET_32BIT"
2343 "bic%.\\t%0, %1, %2"
cca0a211
RE
2344 [(set_attr "conds" "set")]
2345)
ff9940b0 2346
4cdb3ed4 2347(define_insn "*andsi_notsi_si_compare0_scratch"
48a08b9c 2348 [(set (reg:CC_NOOV CC_REGNUM)
0f447ef2
RE
2349 (compare:CC_NOOV
2350 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2351 (match_operand:SI 1 "s_register_operand" "r"))
2352 (const_int 0)))
ff9940b0 2353 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
2354 "TARGET_32BIT"
2355 "bic%.\\t%0, %1, %2"
cca0a211
RE
2356 [(set_attr "conds" "set")]
2357)
ff9940b0
RE
2358
2359(define_insn "iordi3"
d5b7b3ae
RE
2360 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2361 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2362 (match_operand:DI 2 "s_register_operand" "r,r")))]
5b3e6663 2363 "TARGET_32BIT && ! TARGET_IWMMXT"
6ab589e0 2364 "#"
cca0a211
RE
2365 [(set_attr "length" "8")
2366 (set_attr "predicable" "yes")]
d5b7b3ae 2367)
ff9940b0 2368
4cdb3ed4 2369(define_insn "*iordi_zesidi_di"
ff9940b0
RE
2370 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2371 (ior:DI (zero_extend:DI
2372 (match_operand:SI 2 "s_register_operand" "r,r"))
0f447ef2 2373 (match_operand:DI 1 "s_register_operand" "0,?r")))]
5b3e6663 2374 "TARGET_32BIT"
0f447ef2 2375 "@
3dafc5c3 2376 orr%?\\t%Q0, %Q1, %2
6ab589e0 2377 #"
cca0a211
RE
2378 [(set_attr "length" "4,8")
2379 (set_attr "predicable" "yes")]
d5b7b3ae 2380)
ff9940b0 2381
4cdb3ed4 2382(define_insn "*iordi_sesidi_di"
ff9940b0
RE
2383 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2384 (ior:DI (sign_extend:DI
2385 (match_operand:SI 2 "s_register_operand" "r,r"))
2386 (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 2387 "TARGET_32BIT"
6ab589e0 2388 "#"
cca0a211
RE
2389 [(set_attr "length" "8")
2390 (set_attr "predicable" "yes")]
d5b7b3ae 2391)
ff9940b0 2392
091426d3 2393(define_expand "iorsi3"
d5b7b3ae 2394 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
2395 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2396 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 2397 "TARGET_EITHER"
091426d3
RE
2398 "
2399 if (GET_CODE (operands[2]) == CONST_INT)
2400 {
5b3e6663 2401 if (TARGET_32BIT)
d5b7b3ae 2402 {
a406f566
MM
2403 arm_split_constant (IOR, SImode, NULL_RTX,
2404 INTVAL (operands[2]), operands[0], operands[1],
b3a13419 2405 optimize && can_create_pseudo_p ());
d5b7b3ae
RE
2406 DONE;
2407 }
5b3e6663 2408 else /* TARGET_THUMB1 */
d5b7b3ae 2409 operands [2] = force_reg (SImode, operands [2]);
091426d3 2410 }
d5b7b3ae
RE
2411 "
2412)
091426d3 2413
bb6ae783 2414(define_insn_and_split "*arm_iorsi3"
d5b7b3ae 2415 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
091426d3
RE
2416 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2417 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
5b3e6663 2418 "TARGET_32BIT"
091426d3
RE
2419 "@
2420 orr%?\\t%0, %1, %2
2421 #"
5b3e6663 2422 "TARGET_32BIT
bb6ae783
RE
2423 && GET_CODE (operands[2]) == CONST_INT
2424 && !const_ok_for_arm (INTVAL (operands[2]))"
2425 [(clobber (const_int 0))]
2426 "
a406f566
MM
2427 arm_split_constant (IOR, SImode, curr_insn,
2428 INTVAL (operands[2]), operands[0], operands[1], 0);
bb6ae783
RE
2429 DONE;
2430 "
cca0a211
RE
2431 [(set_attr "length" "4,16")
2432 (set_attr "predicable" "yes")]
d5b7b3ae
RE
2433)
2434
5b3e6663 2435(define_insn "*thumb1_iorsi3"
d5b7b3ae
RE
2436 [(set (match_operand:SI 0 "register_operand" "=l")
2437 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2438 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 2439 "TARGET_THUMB1"
d5b7b3ae
RE
2440 "orr\\t%0, %0, %2"
2441 [(set_attr "length" "2")]
2442)
ff9940b0 2443
bb6ae783
RE
2444(define_peephole2
2445 [(match_scratch:SI 3 "r")
3053b100
RE
2446 (set (match_operand:SI 0 "arm_general_register_operand" "")
2447 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
091426d3 2448 (match_operand:SI 2 "const_int_operand" "")))]
5b3e6663 2449 "TARGET_32BIT
bb6ae783
RE
2450 && !const_ok_for_arm (INTVAL (operands[2]))
2451 && const_ok_for_arm (~INTVAL (operands[2]))"
2452 [(set (match_dup 3) (match_dup 2))
2453 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2454 ""
5895f793 2455)
bb6ae783 2456
4cdb3ed4 2457(define_insn "*iorsi3_compare0"
48a08b9c 2458 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2459 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2460 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2461 (const_int 0)))
2462 (set (match_operand:SI 0 "s_register_operand" "=r")
2463 (ior:SI (match_dup 1) (match_dup 2)))]
5b3e6663
PB
2464 "TARGET_32BIT"
2465 "orr%.\\t%0, %1, %2"
d5b7b3ae
RE
2466 [(set_attr "conds" "set")]
2467)
ff9940b0 2468
4cdb3ed4 2469(define_insn "*iorsi3_compare0_scratch"
48a08b9c 2470 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2471 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2472 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2473 (const_int 0)))
2474 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
2475 "TARGET_32BIT"
2476 "orr%.\\t%0, %1, %2"
cca0a211
RE
2477 [(set_attr "conds" "set")]
2478)
ff9940b0
RE
2479
2480(define_insn "xordi3"
d5b7b3ae
RE
2481 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2482 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2483 (match_operand:DI 2 "s_register_operand" "r,r")))]
5b3e6663 2484 "TARGET_32BIT && !TARGET_IWMMXT"
6ab589e0 2485 "#"
cca0a211
RE
2486 [(set_attr "length" "8")
2487 (set_attr "predicable" "yes")]
d5b7b3ae 2488)
ff9940b0 2489
4cdb3ed4 2490(define_insn "*xordi_zesidi_di"
ff9940b0
RE
2491 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2492 (xor:DI (zero_extend:DI
2493 (match_operand:SI 2 "s_register_operand" "r,r"))
0f447ef2 2494 (match_operand:DI 1 "s_register_operand" "0,?r")))]
5b3e6663 2495 "TARGET_32BIT"
0f447ef2 2496 "@
3dafc5c3 2497 eor%?\\t%Q0, %Q1, %2
6ab589e0 2498 #"
cca0a211
RE
2499 [(set_attr "length" "4,8")
2500 (set_attr "predicable" "yes")]
d5b7b3ae 2501)
ff9940b0 2502
4cdb3ed4 2503(define_insn "*xordi_sesidi_di"
ff9940b0
RE
2504 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2505 (xor:DI (sign_extend:DI
2506 (match_operand:SI 2 "s_register_operand" "r,r"))
2507 (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 2508 "TARGET_32BIT"
6ab589e0 2509 "#"
cca0a211
RE
2510 [(set_attr "length" "8")
2511 (set_attr "predicable" "yes")]
d5b7b3ae 2512)
ff9940b0 2513
d5b7b3ae
RE
2514(define_expand "xorsi3"
2515 [(set (match_operand:SI 0 "s_register_operand" "")
2516 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2517 (match_operand:SI 2 "arm_rhs_operand" "")))]
2518 "TARGET_EITHER"
5b3e6663 2519 "if (TARGET_THUMB1)
d5b7b3ae
RE
2520 if (GET_CODE (operands[2]) == CONST_INT)
2521 operands[2] = force_reg (SImode, operands[2]);
2522 "
2523)
2524
2525(define_insn "*arm_xorsi3"
2526 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff9940b0
RE
2527 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2528 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
5b3e6663 2529 "TARGET_32BIT"
d5b7b3ae 2530 "eor%?\\t%0, %1, %2"
cca0a211 2531 [(set_attr "predicable" "yes")]
d5b7b3ae
RE
2532)
2533
5b3e6663 2534(define_insn "*thumb1_xorsi3"
d5b7b3ae
RE
2535 [(set (match_operand:SI 0 "register_operand" "=l")
2536 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2537 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 2538 "TARGET_THUMB1"
d5b7b3ae
RE
2539 "eor\\t%0, %0, %2"
2540 [(set_attr "length" "2")]
2541)
ff9940b0 2542
4cdb3ed4 2543(define_insn "*xorsi3_compare0"
48a08b9c 2544 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2545 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2546 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2547 (const_int 0)))
2548 (set (match_operand:SI 0 "s_register_operand" "=r")
2549 (xor:SI (match_dup 1) (match_dup 2)))]
5b3e6663
PB
2550 "TARGET_32BIT"
2551 "eor%.\\t%0, %1, %2"
cca0a211
RE
2552 [(set_attr "conds" "set")]
2553)
ff9940b0 2554
4cdb3ed4 2555(define_insn "*xorsi3_compare0_scratch"
48a08b9c 2556 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2557 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2558 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2559 (const_int 0)))]
5b3e6663 2560 "TARGET_32BIT"
c63165be 2561 "teq%?\\t%0, %1"
d5b7b3ae
RE
2562 [(set_attr "conds" "set")]
2563)
ff9940b0 2564
5895f793
RE
2565; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2566; (NOT D) we can sometimes merge the final NOT into one of the following
2567; insns.
ff9940b0
RE
2568
2569(define_split
12249385
RE
2570 [(set (match_operand:SI 0 "s_register_operand" "")
2571 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2572 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2573 (match_operand:SI 3 "arm_rhs_operand" "")))
2574 (clobber (match_operand:SI 4 "s_register_operand" ""))]
5b3e6663 2575 "TARGET_32BIT"
ff9940b0
RE
2576 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2577 (not:SI (match_dup 3))))
2578 (set (match_dup 0) (not:SI (match_dup 4)))]
2579 ""
2580)
2581
4cdb3ed4 2582(define_insn "*andsi_iorsi3_notsi"
ff9940b0
RE
2583 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2584 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2585 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2586 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
5b3e6663 2587 "TARGET_32BIT"
c63165be 2588 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
cca0a211 2589 [(set_attr "length" "8")
5b3e6663 2590 (set_attr "ce_count" "2")
cca0a211 2591 (set_attr "predicable" "yes")]
d5b7b3ae 2592)
ff9940b0 2593
5b3e6663
PB
2594; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2595; insns are available?
da5cafa7
RE
2596(define_split
2597 [(set (match_operand:SI 0 "s_register_operand" "")
2598 (match_operator:SI 1 "logical_binary_operator"
2599 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2600 (match_operand:SI 3 "const_int_operand" "")
2601 (match_operand:SI 4 "const_int_operand" ""))
2602 (match_operator:SI 9 "logical_binary_operator"
2603 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2604 (match_operand:SI 6 "const_int_operand" ""))
2605 (match_operand:SI 7 "s_register_operand" "")])]))
2606 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 2607 "TARGET_32BIT
da5cafa7
RE
2608 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2609 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2610 [(set (match_dup 8)
2611 (match_op_dup 1
2612 [(ashift:SI (match_dup 2) (match_dup 4))
2613 (match_dup 5)]))
2614 (set (match_dup 0)
2615 (match_op_dup 1
2616 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2617 (match_dup 7)]))]
2618 "
2619 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2620")
2621
2622(define_split
2623 [(set (match_operand:SI 0 "s_register_operand" "")
2624 (match_operator:SI 1 "logical_binary_operator"
2625 [(match_operator:SI 9 "logical_binary_operator"
2626 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2627 (match_operand:SI 6 "const_int_operand" ""))
2628 (match_operand:SI 7 "s_register_operand" "")])
2629 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2630 (match_operand:SI 3 "const_int_operand" "")
2631 (match_operand:SI 4 "const_int_operand" ""))]))
2632 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 2633 "TARGET_32BIT
da5cafa7
RE
2634 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2635 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2636 [(set (match_dup 8)
2637 (match_op_dup 1
2638 [(ashift:SI (match_dup 2) (match_dup 4))
2639 (match_dup 5)]))
2640 (set (match_dup 0)
2641 (match_op_dup 1
2642 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2643 (match_dup 7)]))]
2644 "
2645 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2646")
2647
2648(define_split
2649 [(set (match_operand:SI 0 "s_register_operand" "")
2650 (match_operator:SI 1 "logical_binary_operator"
2651 [(sign_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 [(ashiftrt: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" ""))]
5b3e6663 2659 "TARGET_32BIT
da5cafa7
RE
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 [(ashiftrt: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 [(ashiftrt: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 (sign_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" ""))]
5b3e6663 2685 "TARGET_32BIT
da5cafa7
RE
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 [(ashiftrt: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")
ff9940b0
RE
2699\f
2700
2701;; Minimum and maximum insns
2702
0a484e3e
RE
2703(define_expand "smaxsi3"
2704 [(parallel [
2705 (set (match_operand:SI 0 "s_register_operand" "")
2706 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2707 (match_operand:SI 2 "arm_rhs_operand" "")))
2708 (clobber (reg:CC CC_REGNUM))])]
5b3e6663 2709 "TARGET_32BIT"
0a484e3e 2710 "
0cb381f0 2711 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
0a484e3e
RE
2712 {
2713 /* No need for a clobber of the condition code register here. */
2714 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2715 gen_rtx_SMAX (SImode, operands[1],
2716 operands[2])));
2717 DONE;
2718 }
2719")
2720
2721(define_insn "*smax_0"
2722 [(set (match_operand:SI 0 "s_register_operand" "=r")
2723 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2724 (const_int 0)))]
5b3e6663 2725 "TARGET_32BIT"
0a484e3e
RE
2726 "bic%?\\t%0, %1, %1, asr #31"
2727 [(set_attr "predicable" "yes")]
2728)
2729
0cb381f0
NP
2730(define_insn "*smax_m1"
2731 [(set (match_operand:SI 0 "s_register_operand" "=r")
2732 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2733 (const_int -1)))]
5b3e6663 2734 "TARGET_32BIT"
0cb381f0
NP
2735 "orr%?\\t%0, %1, %1, asr #31"
2736 [(set_attr "predicable" "yes")]
2737)
2738
5b3e6663 2739(define_insn "*arm_smax_insn"
0a484e3e
RE
2740 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2741 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2742 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
48a08b9c 2743 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 2744 "TARGET_ARM"
0f447ef2
RE
2745 "@
2746 cmp\\t%1, %2\;movlt\\t%0, %2
0f447ef2 2747 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
d5b7b3ae 2748 [(set_attr "conds" "clob")
0a484e3e 2749 (set_attr "length" "8,12")]
d5b7b3ae 2750)
ff9940b0 2751
0a484e3e
RE
2752(define_expand "sminsi3"
2753 [(parallel [
2754 (set (match_operand:SI 0 "s_register_operand" "")
2755 (smin:SI (match_operand:SI 1 "s_register_operand" "")
2756 (match_operand:SI 2 "arm_rhs_operand" "")))
2757 (clobber (reg:CC CC_REGNUM))])]
5b3e6663 2758 "TARGET_32BIT"
0a484e3e
RE
2759 "
2760 if (operands[2] == const0_rtx)
2761 {
2762 /* No need for a clobber of the condition code register here. */
2763 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2764 gen_rtx_SMIN (SImode, operands[1],
2765 operands[2])));
2766 DONE;
2767 }
2768")
2769
2770(define_insn "*smin_0"
2771 [(set (match_operand:SI 0 "s_register_operand" "=r")
2772 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2773 (const_int 0)))]
5b3e6663 2774 "TARGET_32BIT"
0a484e3e
RE
2775 "and%?\\t%0, %1, %1, asr #31"
2776 [(set_attr "predicable" "yes")]
2777)
2778
5b3e6663 2779(define_insn "*arm_smin_insn"
0a484e3e
RE
2780 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2781 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2782 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
48a08b9c 2783 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 2784 "TARGET_ARM"
0f447ef2
RE
2785 "@
2786 cmp\\t%1, %2\;movge\\t%0, %2
0f447ef2 2787 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
cca0a211 2788 [(set_attr "conds" "clob")
0a484e3e 2789 (set_attr "length" "8,12")]
cca0a211 2790)
ff9940b0 2791
5b3e6663
PB
2792(define_expand "umaxsi3"
2793 [(parallel [
2794 (set (match_operand:SI 0 "s_register_operand" "")
2795 (umax:SI (match_operand:SI 1 "s_register_operand" "")
2796 (match_operand:SI 2 "arm_rhs_operand" "")))
2797 (clobber (reg:CC CC_REGNUM))])]
2798 "TARGET_32BIT"
2799 ""
2800)
2801
2802(define_insn "*arm_umaxsi3"
ff9940b0
RE
2803 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2804 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2805 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
48a08b9c 2806 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 2807 "TARGET_ARM"
0f447ef2
RE
2808 "@
2809 cmp\\t%1, %2\;movcc\\t%0, %2
2810 cmp\\t%1, %2\;movcs\\t%0, %1
2811 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
cca0a211
RE
2812 [(set_attr "conds" "clob")
2813 (set_attr "length" "8,8,12")]
2814)
ff9940b0 2815
5b3e6663
PB
2816(define_expand "uminsi3"
2817 [(parallel [
2818 (set (match_operand:SI 0 "s_register_operand" "")
2819 (umin:SI (match_operand:SI 1 "s_register_operand" "")
2820 (match_operand:SI 2 "arm_rhs_operand" "")))
2821 (clobber (reg:CC CC_REGNUM))])]
2822 "TARGET_32BIT"
2823 ""
2824)
2825
2826(define_insn "*arm_uminsi3"
ff9940b0
RE
2827 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2828 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2829 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
48a08b9c 2830 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 2831 "TARGET_ARM"
0f447ef2
RE
2832 "@
2833 cmp\\t%1, %2\;movcs\\t%0, %2
2834 cmp\\t%1, %2\;movcc\\t%0, %1
2835 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
cca0a211
RE
2836 [(set_attr "conds" "clob")
2837 (set_attr "length" "8,8,12")]
2838)
ff9940b0 2839
f54fd62e 2840(define_insn "*store_minmaxsi"
ff9940b0
RE
2841 [(set (match_operand:SI 0 "memory_operand" "=m")
2842 (match_operator:SI 3 "minmax_operator"
2843 [(match_operand:SI 1 "s_register_operand" "r")
2844 (match_operand:SI 2 "s_register_operand" "r")]))
48a08b9c 2845 (clobber (reg:CC CC_REGNUM))]
5b3e6663 2846 "TARGET_32BIT"
ff9940b0 2847 "*
0f4c242b
KH
2848 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2849 operands[1], operands[2]);
0f447ef2 2850 output_asm_insn (\"cmp\\t%1, %2\", operands);
5b3e6663
PB
2851 if (TARGET_THUMB2)
2852 output_asm_insn (\"ite\t%d3\", operands);
0f447ef2
RE
2853 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2854 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2855 return \"\";
cca0a211
RE
2856 "
2857 [(set_attr "conds" "clob")
5b3e6663
PB
2858 (set (attr "length")
2859 (if_then_else (eq_attr "is_thumb" "yes")
2860 (const_int 14)
2861 (const_int 12)))
cca0a211
RE
2862 (set_attr "type" "store1")]
2863)
ff9940b0 2864
f54fd62e
RE
2865; Reject the frame pointer in operand[1], since reloading this after
2866; it has been eliminated can cause carnage.
4cdb3ed4 2867(define_insn "*minmax_arithsi"
ff9940b0
RE
2868 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2869 (match_operator:SI 4 "shiftable_operator"
2870 [(match_operator:SI 5 "minmax_operator"
2871 [(match_operand:SI 2 "s_register_operand" "r,r")
2872 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2873 (match_operand:SI 1 "s_register_operand" "0,?r")]))
48a08b9c 2874 (clobber (reg:CC CC_REGNUM))]
5b3e6663 2875 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
ff9940b0 2876 "*
cca0a211
RE
2877 {
2878 enum rtx_code code = GET_CODE (operands[4]);
5b3e6663
PB
2879 bool need_else;
2880
2881 if (which_alternative != 0 || operands[3] != const0_rtx
2882 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2883 need_else = true;
2884 else
2885 need_else = false;
cca0a211 2886
0f4c242b
KH
2887 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2888 operands[2], operands[3]);
cca0a211 2889 output_asm_insn (\"cmp\\t%2, %3\", operands);
5b3e6663
PB
2890 if (TARGET_THUMB2)
2891 {
2892 if (need_else)
2893 output_asm_insn (\"ite\\t%d5\", operands);
2894 else
2895 output_asm_insn (\"it\\t%d5\", operands);
2896 }
cca0a211 2897 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
5b3e6663 2898 if (need_else)
cca0a211
RE
2899 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2900 return \"\";
5895f793 2901 }"
cca0a211 2902 [(set_attr "conds" "clob")
5b3e6663
PB
2903 (set (attr "length")
2904 (if_then_else (eq_attr "is_thumb" "yes")
2905 (const_int 14)
2906 (const_int 12)))]
cca0a211 2907)
ff9940b0 2908
3a33f76f
RK
2909\f
2910;; Shift and rotation insns
2911
9b66ebb1
PB
2912(define_expand "ashldi3"
2913 [(set (match_operand:DI 0 "s_register_operand" "")
2914 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2915 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 2916 "TARGET_32BIT"
9b66ebb1
PB
2917 "
2918 if (GET_CODE (operands[2]) == CONST_INT)
2919 {
2920 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2921 {
2922 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2923 DONE;
2924 }
2925 /* Ideally we shouldn't fail here if we could know that operands[1]
2926 ends up already living in an iwmmxt register. Otherwise it's
2927 cheaper to have the alternate code being generated than moving
ff482c8d 2928 values to iwmmxt regs and back. */
9b66ebb1
PB
2929 FAIL;
2930 }
2931 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2932 FAIL;
2933 "
2934)
2935
2936(define_insn "arm_ashldi3_1bit"
2937 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2938 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2939 (const_int 1)))
2940 (clobber (reg:CC CC_REGNUM))]
5b3e6663 2941 "TARGET_32BIT"
9b66ebb1
PB
2942 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2943 [(set_attr "conds" "clob")
2944 (set_attr "length" "8")]
2945)
2946
091426d3 2947(define_expand "ashlsi3"
d5b7b3ae 2948 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
2949 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2950 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 2951 "TARGET_EITHER"
091426d3
RE
2952 "
2953 if (GET_CODE (operands[2]) == CONST_INT
2954 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2955 {
2956 emit_insn (gen_movsi (operands[0], const0_rtx));
2957 DONE;
2958 }
d5b7b3ae
RE
2959 "
2960)
2961
5b3e6663 2962(define_insn "*thumb1_ashlsi3"
d5b7b3ae
RE
2963 [(set (match_operand:SI 0 "register_operand" "=l,l")
2964 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2965 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
5b3e6663 2966 "TARGET_THUMB1"
d5b7b3ae
RE
2967 "lsl\\t%0, %1, %2"
2968 [(set_attr "length" "2")]
2969)
3a33f76f 2970
9b66ebb1
PB
2971(define_expand "ashrdi3"
2972 [(set (match_operand:DI 0 "s_register_operand" "")
2973 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2974 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 2975 "TARGET_32BIT"
9b66ebb1
PB
2976 "
2977 if (GET_CODE (operands[2]) == CONST_INT)
2978 {
2979 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2980 {
2981 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2982 DONE;
2983 }
2984 /* Ideally we shouldn't fail here if we could know that operands[1]
2985 ends up already living in an iwmmxt register. Otherwise it's
2986 cheaper to have the alternate code being generated than moving
ff482c8d 2987 values to iwmmxt regs and back. */
9b66ebb1
PB
2988 FAIL;
2989 }
2990 else if (!TARGET_REALLY_IWMMXT)
2991 FAIL;
2992 "
2993)
2994
2995(define_insn "arm_ashrdi3_1bit"
2996 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2997 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2998 (const_int 1)))
2999 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3000 "TARGET_32BIT"
9b66ebb1
PB
3001 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3002 [(set_attr "conds" "clob")
3003 (set_attr "length" "8")]
3004)
3005
091426d3 3006(define_expand "ashrsi3"
d5b7b3ae 3007 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3008 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3009 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 3010 "TARGET_EITHER"
091426d3
RE
3011 "
3012 if (GET_CODE (operands[2]) == CONST_INT
3013 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3014 operands[2] = GEN_INT (31);
d5b7b3ae
RE
3015 "
3016)
3017
5b3e6663 3018(define_insn "*thumb1_ashrsi3"
d5b7b3ae
RE
3019 [(set (match_operand:SI 0 "register_operand" "=l,l")
3020 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3021 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
5b3e6663 3022 "TARGET_THUMB1"
d5b7b3ae
RE
3023 "asr\\t%0, %1, %2"
3024 [(set_attr "length" "2")]
3025)
3a33f76f 3026
9b66ebb1
PB
3027(define_expand "lshrdi3"
3028 [(set (match_operand:DI 0 "s_register_operand" "")
3029 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3030 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 3031 "TARGET_32BIT"
9b66ebb1
PB
3032 "
3033 if (GET_CODE (operands[2]) == CONST_INT)
3034 {
3035 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3036 {
3037 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3038 DONE;
3039 }
3040 /* Ideally we shouldn't fail here if we could know that operands[1]
3041 ends up already living in an iwmmxt register. Otherwise it's
3042 cheaper to have the alternate code being generated than moving
ff482c8d 3043 values to iwmmxt regs and back. */
9b66ebb1
PB
3044 FAIL;
3045 }
3046 else if (!TARGET_REALLY_IWMMXT)
3047 FAIL;
3048 "
3049)
3050
3051(define_insn "arm_lshrdi3_1bit"
3052 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3053 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3054 (const_int 1)))
3055 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3056 "TARGET_32BIT"
9b66ebb1
PB
3057 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3058 [(set_attr "conds" "clob")
3059 (set_attr "length" "8")]
3060)
3061
091426d3 3062(define_expand "lshrsi3"
d5b7b3ae 3063 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3064 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3065 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 3066 "TARGET_EITHER"
091426d3
RE
3067 "
3068 if (GET_CODE (operands[2]) == CONST_INT
3069 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3070 {
3071 emit_insn (gen_movsi (operands[0], const0_rtx));
3072 DONE;
3073 }
d5b7b3ae
RE
3074 "
3075)
3076
5b3e6663 3077(define_insn "*thumb1_lshrsi3"
d5b7b3ae
RE
3078 [(set (match_operand:SI 0 "register_operand" "=l,l")
3079 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3080 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
5b3e6663 3081 "TARGET_THUMB1"
d5b7b3ae
RE
3082 "lsr\\t%0, %1, %2"
3083 [(set_attr "length" "2")]
3084)
3a33f76f 3085
091426d3 3086(define_expand "rotlsi3"
d5b7b3ae 3087 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3088 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3089 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 3090 "TARGET_32BIT"
091426d3
RE
3091 "
3092 if (GET_CODE (operands[2]) == CONST_INT)
3093 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3094 else
3a33f76f 3095 {
091426d3
RE
3096 rtx reg = gen_reg_rtx (SImode);
3097 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3098 operands[2] = reg;
3a33f76f 3099 }
d5b7b3ae
RE
3100 "
3101)
ff9940b0 3102
091426d3 3103(define_expand "rotrsi3"
d5b7b3ae 3104 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3105 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3106 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 3107 "TARGET_EITHER"
091426d3 3108 "
5b3e6663 3109 if (TARGET_32BIT)
d5b7b3ae
RE
3110 {
3111 if (GET_CODE (operands[2]) == CONST_INT
3112 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3113 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3114 }
5b3e6663 3115 else /* TARGET_THUMB1 */
d5b7b3ae
RE
3116 {
3117 if (GET_CODE (operands [2]) == CONST_INT)
3118 operands [2] = force_reg (SImode, operands[2]);
3119 }
3120 "
3121)
091426d3 3122
5b3e6663 3123(define_insn "*thumb1_rotrsi3"
d5b7b3ae
RE
3124 [(set (match_operand:SI 0 "register_operand" "=l")
3125 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3126 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 3127 "TARGET_THUMB1"
d5b7b3ae
RE
3128 "ror\\t%0, %0, %2"
3129 [(set_attr "length" "2")]
3130)
3131
3132(define_insn "*arm_shiftsi3"
3133 [(set (match_operand:SI 0 "s_register_operand" "=r")
3134 (match_operator:SI 3 "shift_operator"
3135 [(match_operand:SI 1 "s_register_operand" "r")
091426d3 3136 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
5b3e6663
PB
3137 "TARGET_32BIT"
3138 "* return arm_output_shift(operands, 0);"
ca68ea18 3139 [(set_attr "predicable" "yes")
d19fb8e3 3140 (set_attr "shift" "1")
9b66ebb1
PB
3141 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3142 (const_string "alu_shift")
3143 (const_string "alu_shift_reg")))]
b020fd92 3144)
091426d3 3145
4cdb3ed4 3146(define_insn "*shiftsi3_compare0"
48a08b9c 3147 [(set (reg:CC_NOOV CC_REGNUM)
091426d3
RE
3148 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3149 [(match_operand:SI 1 "s_register_operand" "r")
3150 (match_operand:SI 2 "arm_rhs_operand" "rM")])
ff9940b0
RE
3151 (const_int 0)))
3152 (set (match_operand:SI 0 "s_register_operand" "=r")
091426d3 3153 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
5b3e6663
PB
3154 "TARGET_32BIT"
3155 "* return arm_output_shift(operands, 1);"
ca68ea18 3156 [(set_attr "conds" "set")
d19fb8e3 3157 (set_attr "shift" "1")
9b66ebb1
PB
3158 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3159 (const_string "alu_shift")
3160 (const_string "alu_shift_reg")))]
cca0a211 3161)
ff9940b0 3162
4cdb3ed4 3163(define_insn "*shiftsi3_compare0_scratch"
48a08b9c 3164 [(set (reg:CC_NOOV CC_REGNUM)
091426d3
RE
3165 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3166 [(match_operand:SI 1 "s_register_operand" "r")
3167 (match_operand:SI 2 "arm_rhs_operand" "rM")])
ff9940b0
RE
3168 (const_int 0)))
3169 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
3170 "TARGET_32BIT"
3171 "* return arm_output_shift(operands, 1);"
ca68ea18 3172 [(set_attr "conds" "set")
9b66ebb1 3173 (set_attr "shift" "1")]
cca0a211 3174)
ff9940b0 3175
5b3e6663 3176(define_insn "*arm_notsi_shiftsi"
ff9940b0 3177 [(set (match_operand:SI 0 "s_register_operand" "=r")
091426d3
RE
3178 (not:SI (match_operator:SI 3 "shift_operator"
3179 [(match_operand:SI 1 "s_register_operand" "r")
3180 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
d5b7b3ae 3181 "TARGET_ARM"
b020fd92 3182 "mvn%?\\t%0, %1%S3"
ca68ea18 3183 [(set_attr "predicable" "yes")
d19fb8e3 3184 (set_attr "shift" "1")
9b66ebb1
PB
3185 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3186 (const_string "alu_shift")
3187 (const_string "alu_shift_reg")))]
cca0a211 3188)
ff9940b0 3189
5b3e6663 3190(define_insn "*arm_notsi_shiftsi_compare0"
48a08b9c 3191 [(set (reg:CC_NOOV CC_REGNUM)
091426d3
RE
3192 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3193 [(match_operand:SI 1 "s_register_operand" "r")
3194 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
ff9940b0
RE
3195 (const_int 0)))
3196 (set (match_operand:SI 0 "s_register_operand" "=r")
091426d3 3197 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5b7b3ae 3198 "TARGET_ARM"
5b3e6663 3199 "mvn%.\\t%0, %1%S3"
ca68ea18 3200 [(set_attr "conds" "set")
d19fb8e3 3201 (set_attr "shift" "1")
9b66ebb1
PB
3202 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3203 (const_string "alu_shift")
3204 (const_string "alu_shift_reg")))]
cca0a211 3205)
ff9940b0 3206
5b3e6663 3207(define_insn "*arm_not_shiftsi_compare0_scratch"
48a08b9c 3208 [(set (reg:CC_NOOV CC_REGNUM)
091426d3
RE
3209 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3210 [(match_operand:SI 1 "s_register_operand" "r")
3211 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
ff9940b0
RE
3212 (const_int 0)))
3213 (clobber (match_scratch:SI 0 "=r"))]
d5b7b3ae 3214 "TARGET_ARM"
5b3e6663 3215 "mvn%.\\t%0, %1%S3"
ca68ea18 3216 [(set_attr "conds" "set")
d19fb8e3 3217 (set_attr "shift" "1")
9b66ebb1
PB
3218 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3219 (const_string "alu_shift")
3220 (const_string "alu_shift_reg")))]
cca0a211 3221)
ff9940b0 3222
d5b7b3ae
RE
3223;; We don't really have extzv, but defining this using shifts helps
3224;; to reduce register pressure later on.
3225
3226(define_expand "extzv"
3227 [(set (match_dup 4)
3228 (ashift:SI (match_operand:SI 1 "register_operand" "")
3229 (match_operand:SI 2 "const_int_operand" "")))
3230 (set (match_operand:SI 0 "register_operand" "")
3231 (lshiftrt:SI (match_dup 4)
5895f793 3232 (match_operand:SI 3 "const_int_operand" "")))]
5b3e6663 3233 "TARGET_THUMB1"
d5b7b3ae
RE
3234 "
3235 {
3236 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3237 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3238
3239 operands[3] = GEN_INT (rshift);
3240
3241 if (lshift == 0)
3242 {
3243 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3244 DONE;
3245 }
3246
3247 operands[2] = GEN_INT (lshift);
3248 operands[4] = gen_reg_rtx (SImode);
5895f793 3249 }"
d5b7b3ae
RE
3250)
3251
3a33f76f
RK
3252\f
3253;; Unary arithmetic insns
3254
d5b7b3ae
RE
3255(define_expand "negdi2"
3256 [(parallel
3257 [(set (match_operand:DI 0 "s_register_operand" "")
3258 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
48a08b9c 3259 (clobber (reg:CC CC_REGNUM))])]
d5b7b3ae
RE
3260 "TARGET_EITHER"
3261 "
5b3e6663 3262 if (TARGET_THUMB1)
d5b7b3ae
RE
3263 {
3264 if (GET_CODE (operands[1]) != REG)
3265 operands[1] = force_reg (SImode, operands[1]);
3266 }
5895f793 3267 "
d5b7b3ae
RE
3268)
3269
3270;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3271;; The second alternative is to allow the common case of a *full* overlap.
3272(define_insn "*arm_negdi2"
3273 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3274 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
48a08b9c 3275 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3276 "TARGET_ARM"
3dafc5c3 3277 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
d5b7b3ae
RE
3278 [(set_attr "conds" "clob")
3279 (set_attr "length" "8")]
3280)
3a33f76f 3281
5b3e6663 3282(define_insn "*thumb1_negdi2"
d5b7b3ae
RE
3283 [(set (match_operand:DI 0 "register_operand" "=&l")
3284 (neg:DI (match_operand:DI 1 "register_operand" "l")))
48a08b9c 3285 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3286 "TARGET_THUMB1"
d5b7b3ae
RE
3287 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3288 [(set_attr "length" "6")]
3289)
3290
3291(define_expand "negsi2"
3292 [(set (match_operand:SI 0 "s_register_operand" "")
3293 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3294 "TARGET_EITHER"
3a33f76f 3295 ""
d5b7b3ae
RE
3296)
3297
3298(define_insn "*arm_negsi2"
3299 [(set (match_operand:SI 0 "s_register_operand" "=r")
3300 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 3301 "TARGET_32BIT"
d5b7b3ae 3302 "rsb%?\\t%0, %1, #0"
cca0a211 3303 [(set_attr "predicable" "yes")]
d5b7b3ae
RE
3304)
3305
5b3e6663 3306(define_insn "*thumb1_negsi2"
d5b7b3ae
RE
3307 [(set (match_operand:SI 0 "register_operand" "=l")
3308 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
5b3e6663 3309 "TARGET_THUMB1"
d5b7b3ae
RE
3310 "neg\\t%0, %1"
3311 [(set_attr "length" "2")]
3312)
3a33f76f 3313
37f74dcf
RE
3314(define_expand "negsf2"
3315 [(set (match_operand:SF 0 "s_register_operand" "")
3316 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
5b3e6663 3317 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
37f74dcf
RE
3318 ""
3319)
3320
3321(define_expand "negdf2"
3322 [(set (match_operand:DF 0 "s_register_operand" "")
3323 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
5b3e6663 3324 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
37f74dcf
RE
3325 "")
3326
ff9940b0
RE
3327;; abssi2 doesn't really clobber the condition codes if a different register
3328;; is being set. To keep things simple, assume during rtl manipulations that
3329;; it does, but tell the final scan operator the truth. Similarly for
3330;; (neg (abs...))
3331
37f74dcf
RE
3332(define_expand "abssi2"
3333 [(parallel
3334 [(set (match_operand:SI 0 "s_register_operand" "")
3335 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ecaf6f07
RE
3336 (clobber (match_dup 2))])]
3337 "TARGET_EITHER"
3338 "
5b3e6663 3339 if (TARGET_THUMB1)
ecaf6f07
RE
3340 operands[2] = gen_rtx_SCRATCH (SImode);
3341 else
3342 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3343")
37f74dcf 3344
9b6b54e2 3345(define_insn "*arm_abssi2"
ecaf6f07 3346 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
ff9940b0 3347 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
48a08b9c 3348 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3349 "TARGET_ARM"
0f447ef2
RE
3350 "@
3351 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
c63165be 3352 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
d5b7b3ae 3353 [(set_attr "conds" "clob,*")
d19fb8e3 3354 (set_attr "shift" "1")
cca0a211 3355 ;; predicable can't be set based on the variant, so left as no
d5b7b3ae
RE
3356 (set_attr "length" "8")]
3357)
ff9940b0 3358
5b3e6663 3359(define_insn_and_split "*thumb1_abssi2"
ecaf6f07
RE
3360 [(set (match_operand:SI 0 "s_register_operand" "=l")
3361 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3362 (clobber (match_scratch:SI 2 "=&l"))]
5b3e6663 3363 "TARGET_THUMB1"
ecaf6f07 3364 "#"
5b3e6663 3365 "TARGET_THUMB1 && reload_completed"
ecaf6f07
RE
3366 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3367 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3368 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3369 ""
3370 [(set_attr "length" "6")]
3371)
3372
3373(define_insn "*arm_neg_abssi2"
ff9940b0
RE
3374 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3375 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
48a08b9c 3376 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3377 "TARGET_ARM"
0f447ef2
RE
3378 "@
3379 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
c63165be 3380 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
d5b7b3ae 3381 [(set_attr "conds" "clob,*")
d19fb8e3 3382 (set_attr "shift" "1")
cca0a211 3383 ;; predicable can't be set based on the variant, so left as no
d5b7b3ae
RE
3384 (set_attr "length" "8")]
3385)
3a33f76f 3386
5b3e6663 3387(define_insn_and_split "*thumb1_neg_abssi2"
ecaf6f07
RE
3388 [(set (match_operand:SI 0 "s_register_operand" "=l")
3389 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3390 (clobber (match_scratch:SI 2 "=&l"))]
5b3e6663 3391 "TARGET_THUMB1"
ecaf6f07 3392 "#"
5b3e6663 3393 "TARGET_THUMB1 && reload_completed"
ecaf6f07
RE
3394 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3395 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3396 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3397 ""
3398 [(set_attr "length" "6")]
3399)
3400
37f74dcf
RE
3401(define_expand "abssf2"
3402 [(set (match_operand:SF 0 "s_register_operand" "")
3403 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
5b3e6663 3404 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf
RE
3405 "")
3406
37f74dcf
RE
3407(define_expand "absdf2"
3408 [(set (match_operand:DF 0 "s_register_operand" "")
3409 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
5b3e6663 3410 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf
RE
3411 "")
3412
82955615
RE
3413(define_expand "sqrtsf2"
3414 [(set (match_operand:SF 0 "s_register_operand" "")
3415 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
5b3e6663 3416 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
82955615 3417 "")
ff9940b0 3418
82955615
RE
3419(define_expand "sqrtdf2"
3420 [(set (match_operand:DF 0 "s_register_operand" "")
3421 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
5b3e6663 3422 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
82955615 3423 "")
ff9940b0 3424
bb6ae783 3425(define_insn_and_split "one_cmpldi2"
ff9940b0
RE
3426 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3427 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
5b3e6663 3428 "TARGET_32BIT"
6ab589e0 3429 "#"
5b3e6663 3430 "TARGET_32BIT && reload_completed"
bb6ae783
RE
3431 [(set (match_dup 0) (not:SI (match_dup 1)))
3432 (set (match_dup 2) (not:SI (match_dup 3)))]
3433 "
3434 {
3435 operands[2] = gen_highpart (SImode, operands[0]);
3436 operands[0] = gen_lowpart (SImode, operands[0]);
3437 operands[3] = gen_highpart (SImode, operands[1]);
3438 operands[1] = gen_lowpart (SImode, operands[1]);
3439 }"
cca0a211
RE
3440 [(set_attr "length" "8")
3441 (set_attr "predicable" "yes")]
d5b7b3ae 3442)
3a33f76f 3443
d5b7b3ae
RE
3444(define_expand "one_cmplsi2"
3445 [(set (match_operand:SI 0 "s_register_operand" "")
3446 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3447 "TARGET_EITHER"
3a33f76f 3448 ""
d5b7b3ae
RE
3449)
3450
3451(define_insn "*arm_one_cmplsi2"
3452 [(set (match_operand:SI 0 "s_register_operand" "=r")
3453 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 3454 "TARGET_32BIT"
d5b7b3ae 3455 "mvn%?\\t%0, %1"
cca0a211 3456 [(set_attr "predicable" "yes")]
d5b7b3ae
RE
3457)
3458
5b3e6663 3459(define_insn "*thumb1_one_cmplsi2"
d5b7b3ae
RE
3460 [(set (match_operand:SI 0 "register_operand" "=l")
3461 (not:SI (match_operand:SI 1 "register_operand" "l")))]
5b3e6663 3462 "TARGET_THUMB1"
d5b7b3ae
RE
3463 "mvn\\t%0, %1"
3464 [(set_attr "length" "2")]
3465)
ff9940b0 3466
4cdb3ed4 3467(define_insn "*notsi_compare0"
48a08b9c 3468 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
3469 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3470 (const_int 0)))
3471 (set (match_operand:SI 0 "s_register_operand" "=r")
3472 (not:SI (match_dup 1)))]
5b3e6663
PB
3473 "TARGET_32BIT"
3474 "mvn%.\\t%0, %1"
d5b7b3ae
RE
3475 [(set_attr "conds" "set")]
3476)
ff9940b0 3477
4cdb3ed4 3478(define_insn "*notsi_compare0_scratch"
48a08b9c 3479 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
3480 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3481 (const_int 0)))
3482 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
3483 "TARGET_32BIT"
3484 "mvn%.\\t%0, %1"
d5b7b3ae
RE
3485 [(set_attr "conds" "set")]
3486)
3a33f76f
RK
3487\f
3488;; Fixed <--> Floating conversion insns
3489
37f74dcf
RE
3490(define_expand "floatsisf2"
3491 [(set (match_operand:SF 0 "s_register_operand" "")
3492 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
5b3e6663 3493 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 3494 "
9b66ebb1 3495 if (TARGET_MAVERICK)
37f74dcf
RE
3496 {
3497 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3498 DONE;
3499 }
3500")
3501
37f74dcf
RE
3502(define_expand "floatsidf2"
3503 [(set (match_operand:DF 0 "s_register_operand" "")
3504 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
5b3e6663 3505 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 3506 "
9b66ebb1 3507 if (TARGET_MAVERICK)
37f74dcf
RE
3508 {
3509 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3510 DONE;
3511 }
3512")
3513
37f74dcf
RE
3514(define_expand "fix_truncsfsi2"
3515 [(set (match_operand:SI 0 "s_register_operand" "")
17136dde 3516 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
5b3e6663 3517 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 3518 "
9b66ebb1 3519 if (TARGET_MAVERICK)
37f74dcf
RE
3520 {
3521 if (!cirrus_fp_register (operands[0], SImode))
3522 operands[0] = force_reg (SImode, operands[0]);
3523 if (!cirrus_fp_register (operands[1], SFmode))
3524 operands[1] = force_reg (SFmode, operands[0]);
3525 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3526 DONE;
3527 }
3528")
3529
37f74dcf
RE
3530(define_expand "fix_truncdfsi2"
3531 [(set (match_operand:SI 0 "s_register_operand" "")
17136dde 3532 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
5b3e6663 3533 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 3534 "
9b66ebb1 3535 if (TARGET_MAVERICK)
37f74dcf
RE
3536 {
3537 if (!cirrus_fp_register (operands[1], DFmode))
3538 operands[1] = force_reg (DFmode, operands[0]);
3539 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3540 DONE;
3541 }
3542")
3543
3a7a2719 3544;; Truncation insns
3a33f76f 3545
37f74dcf
RE
3546(define_expand "truncdfsf2"
3547 [(set (match_operand:SF 0 "s_register_operand" "")
3548 (float_truncate:SF
3549 (match_operand:DF 1 "s_register_operand" "")))]
5b3e6663 3550 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf
RE
3551 ""
3552)
3a33f76f 3553\f
ff9940b0 3554;; Zero and sign extension instructions.
3a33f76f 3555
5b3e6663
PB
3556(define_expand "zero_extendsidi2"
3557 [(set (match_operand:DI 0 "s_register_operand" "")
3558 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3559 "TARGET_32BIT"
3560 ""
3561)
3562
3563(define_insn "*arm_zero_extendsidi2"
ff9940b0
RE
3564 [(set (match_operand:DI 0 "s_register_operand" "=r")
3565 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
d5b7b3ae 3566 "TARGET_ARM"
ff9940b0 3567 "*
cca0a211
RE
3568 if (REGNO (operands[1])
3569 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3570 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3571 return \"mov%?\\t%R0, #0\";
3572 "
3573 [(set_attr "length" "8")
3574 (set_attr "predicable" "yes")]
3575)
ff9940b0 3576
5b3e6663
PB
3577(define_expand "zero_extendqidi2"
3578 [(set (match_operand:DI 0 "s_register_operand" "")
3579 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3580 "TARGET_32BIT"
3581 ""
3582)
3583
3584(define_insn "*arm_zero_extendqidi2"
d5b7b3ae 3585 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
ff9940b0 3586 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
d5b7b3ae 3587 "TARGET_ARM"
0f447ef2 3588 "@
3dafc5c3 3589 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
5b3e6663 3590 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
d5b7b3ae 3591 [(set_attr "length" "8")
cca0a211 3592 (set_attr "predicable" "yes")
9b66ebb1 3593 (set_attr "type" "*,load_byte")
d5b7b3ae
RE
3594 (set_attr "pool_range" "*,4092")
3595 (set_attr "neg_pool_range" "*,4084")]
3596)
ff9940b0 3597
5b3e6663
PB
3598(define_expand "extendsidi2"
3599 [(set (match_operand:DI 0 "s_register_operand" "")
3600 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3601 "TARGET_32BIT"
3602 ""
3603)
3604
3605(define_insn "*arm_extendsidi2"
ff9940b0
RE
3606 [(set (match_operand:DI 0 "s_register_operand" "=r")
3607 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
d5b7b3ae 3608 "TARGET_ARM"
ff9940b0 3609 "*
cca0a211
RE
3610 if (REGNO (operands[1])
3611 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3612 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3613 return \"mov%?\\t%R0, %Q0, asr #31\";
d5b7b3ae
RE
3614 "
3615 [(set_attr "length" "8")
d19fb8e3 3616 (set_attr "shift" "1")
cca0a211
RE
3617 (set_attr "predicable" "yes")]
3618)
ff9940b0
RE
3619
3620(define_expand "zero_extendhisi2"
d5b7b3ae 3621 [(set (match_dup 2)
cca0a211
RE
3622 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3623 (const_int 16)))
ff9940b0 3624 (set (match_operand:SI 0 "s_register_operand" "")
091426d3 3625 (lshiftrt:SI (match_dup 2) (const_int 16)))]
d5b7b3ae 3626 "TARGET_EITHER"
ff9940b0 3627 "
d5b7b3ae 3628 {
5b3e6663 3629 if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
d5b7b3ae 3630 {
9b66ebb1
PB
3631 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3632 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3633 DONE;
d5b7b3ae 3634 }
d5b7b3ae 3635
61f0ccff 3636 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
9b66ebb1
PB
3637 {
3638 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3639 DONE;
3640 }
d5b7b3ae 3641
9b66ebb1
PB
3642 if (!s_register_operand (operands[1], HImode))
3643 operands[1] = copy_to_mode_reg (HImode, operands[1]);
d5b7b3ae 3644
9b66ebb1
PB
3645 if (arm_arch6)
3646 {
3647 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3648 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3649 DONE;
d5b7b3ae 3650 }
9b66ebb1
PB
3651
3652 operands[1] = gen_lowpart (SImode, operands[1]);
3653 operands[2] = gen_reg_rtx (SImode);
d5b7b3ae
RE
3654 }"
3655)
3656
5b3e6663 3657(define_insn "*thumb1_zero_extendhisi2"
9b66ebb1
PB
3658 [(set (match_operand:SI 0 "register_operand" "=l")
3659 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
5b3e6663 3660 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
3661 "*
3662 rtx mem = XEXP (operands[1], 0);
3663
3664 if (GET_CODE (mem) == CONST)
3665 mem = XEXP (mem, 0);
3666
3667 if (GET_CODE (mem) == LABEL_REF)
3668 return \"ldr\\t%0, %1\";
3669
3670 if (GET_CODE (mem) == PLUS)
4cdb3ed4 3671 {
d5b7b3ae
RE
3672 rtx a = XEXP (mem, 0);
3673 rtx b = XEXP (mem, 1);
3674
3675 /* This can happen due to bugs in reload. */
3676 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3677 {
3678 rtx ops[2];
3679 ops[0] = operands[0];
3680 ops[1] = a;
3681
3682 output_asm_insn (\"mov %0, %1\", ops);
3683
3684 XEXP (mem, 0) = operands[0];
3685 }
3686
3687 else if ( GET_CODE (a) == LABEL_REF
3688 && GET_CODE (b) == CONST_INT)
3689 return \"ldr\\t%0, %1\";
988337ca 3690 }
d5b7b3ae
RE
3691
3692 return \"ldrh\\t%0, %1\";
3693 "
3694 [(set_attr "length" "4")
9b66ebb1 3695 (set_attr "type" "load_byte")
d5b7b3ae
RE
3696 (set_attr "pool_range" "60")]
3697)
ff9940b0 3698
5b3e6663 3699(define_insn "*thumb1_zero_extendhisi2_v6"
9b66ebb1
PB
3700 [(set (match_operand:SI 0 "register_operand" "=l,l")
3701 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
5b3e6663 3702 "TARGET_THUMB1 && arm_arch6"
9b66ebb1
PB
3703 "*
3704 rtx mem;
3705
3706 if (which_alternative == 0)
3707 return \"uxth\\t%0, %1\";
3708
3709 mem = XEXP (operands[1], 0);
3710
3711 if (GET_CODE (mem) == CONST)
3712 mem = XEXP (mem, 0);
3713
3714 if (GET_CODE (mem) == LABEL_REF)
3715 return \"ldr\\t%0, %1\";
3716
3717 if (GET_CODE (mem) == PLUS)
3718 {
3719 rtx a = XEXP (mem, 0);
3720 rtx b = XEXP (mem, 1);
3721
3722 /* This can happen due to bugs in reload. */
3723 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3724 {
3725 rtx ops[2];
3726 ops[0] = operands[0];
3727 ops[1] = a;
3728
3729 output_asm_insn (\"mov %0, %1\", ops);
3730
3731 XEXP (mem, 0) = operands[0];
3732 }
3733
3734 else if ( GET_CODE (a) == LABEL_REF
3735 && GET_CODE (b) == CONST_INT)
3736 return \"ldr\\t%0, %1\";
3737 }
3738
3739 return \"ldrh\\t%0, %1\";
3740 "
3741 [(set_attr "length" "2,4")
3742 (set_attr "type" "alu_shift,load_byte")
3743 (set_attr "pool_range" "*,60")]
3744)
3745
d5b7b3ae 3746(define_insn "*arm_zero_extendhisi2"
9b66ebb1
PB
3747 [(set (match_operand:SI 0 "s_register_operand" "=r")
3748 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3749 "TARGET_ARM && arm_arch4 && !arm_arch6"
5b3e6663 3750 "ldr%(h%)\\t%0, %1"
9b66ebb1 3751 [(set_attr "type" "load_byte")
cca0a211 3752 (set_attr "predicable" "yes")
d5b7b3ae
RE
3753 (set_attr "pool_range" "256")
3754 (set_attr "neg_pool_range" "244")]
3755)
4cdb3ed4 3756
9b66ebb1
PB
3757(define_insn "*arm_zero_extendhisi2_v6"
3758 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3759 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3760 "TARGET_ARM && arm_arch6"
3761 "@
3762 uxth%?\\t%0, %1
5b3e6663 3763 ldr%(h%)\\t%0, %1"
9b66ebb1
PB
3764 [(set_attr "type" "alu_shift,load_byte")
3765 (set_attr "predicable" "yes")
3766 (set_attr "pool_range" "*,256")
3767 (set_attr "neg_pool_range" "*,244")]
3768)
3769
3770(define_insn "*arm_zero_extendhisi2addsi"
3771 [(set (match_operand:SI 0 "s_register_operand" "=r")
3772 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3773 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 3774 "TARGET_INT_SIMD"
9b66ebb1
PB
3775 "uxtah%?\\t%0, %2, %1"
3776 [(set_attr "type" "alu_shift")
3777 (set_attr "predicable" "yes")]
3778)
3779
091426d3 3780(define_expand "zero_extendqisi2"
d5b7b3ae
RE
3781 [(set (match_operand:SI 0 "s_register_operand" "")
3782 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3783 "TARGET_EITHER"
091426d3 3784 "
9b66ebb1 3785 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
091426d3 3786 {
d5b7b3ae
RE
3787 if (TARGET_ARM)
3788 {
5895f793
RE
3789 emit_insn (gen_andsi3 (operands[0],
3790 gen_lowpart (SImode, operands[1]),
d5b7b3ae
RE
3791 GEN_INT (255)));
3792 }
3793 else /* TARGET_THUMB */
3794 {
3795 rtx temp = gen_reg_rtx (SImode);
3796 rtx ops[3];
3797
3798 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3799 operands[1] = gen_lowpart (SImode, operands[1]);
3800
3801 ops[0] = temp;
3802 ops[1] = operands[1];
3803 ops[2] = GEN_INT (24);
3804
5895f793
RE
3805 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3806 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
d5b7b3ae
RE
3807
3808 ops[0] = operands[0];
3809 ops[1] = temp;
3810 ops[2] = GEN_INT (24);
3811
5895f793
RE
3812 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3813 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
d5b7b3ae 3814 }
091426d3
RE
3815 DONE;
3816 }
5895f793
RE
3817 "
3818)
ff9940b0 3819
5b3e6663 3820(define_insn "*thumb1_zero_extendqisi2"
9b66ebb1
PB
3821 [(set (match_operand:SI 0 "register_operand" "=l")
3822 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
5b3e6663 3823 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
3824 "ldrb\\t%0, %1"
3825 [(set_attr "length" "2")
9b66ebb1 3826 (set_attr "type" "load_byte")
d5b7b3ae
RE
3827 (set_attr "pool_range" "32")]
3828)
3829
5b3e6663 3830(define_insn "*thumb1_zero_extendqisi2_v6"
9b66ebb1
PB
3831 [(set (match_operand:SI 0 "register_operand" "=l,l")
3832 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
5b3e6663 3833 "TARGET_THUMB1 && arm_arch6"
9b66ebb1
PB
3834 "@
3835 uxtb\\t%0, %1
3836 ldrb\\t%0, %1"
3837 [(set_attr "length" "2,2")
3838 (set_attr "type" "alu_shift,load_byte")
3839 (set_attr "pool_range" "*,32")]
3840)
3841
d5b7b3ae 3842(define_insn "*arm_zero_extendqisi2"
9b66ebb1
PB
3843 [(set (match_operand:SI 0 "s_register_operand" "=r")
3844 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3845 "TARGET_ARM && !arm_arch6"
5b3e6663 3846 "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
9b66ebb1 3847 [(set_attr "type" "load_byte")
cca0a211 3848 (set_attr "predicable" "yes")
d5b7b3ae
RE
3849 (set_attr "pool_range" "4096")
3850 (set_attr "neg_pool_range" "4084")]
3851)
091426d3 3852
9b66ebb1
PB
3853(define_insn "*arm_zero_extendqisi2_v6"
3854 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3855 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3856 "TARGET_ARM && arm_arch6"
3857 "@
5b3e6663
PB
3858 uxtb%(%)\\t%0, %1
3859 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
9b66ebb1
PB
3860 [(set_attr "type" "alu_shift,load_byte")
3861 (set_attr "predicable" "yes")
3862 (set_attr "pool_range" "*,4096")
3863 (set_attr "neg_pool_range" "*,4084")]
3864)
3865
3866(define_insn "*arm_zero_extendqisi2addsi"
3867 [(set (match_operand:SI 0 "s_register_operand" "=r")
3868 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3869 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 3870 "TARGET_INT_SIMD"
9b66ebb1
PB
3871 "uxtab%?\\t%0, %2, %1"
3872 [(set_attr "predicable" "yes")
c956e102 3873 (set_attr "insn" "xtab")
9b66ebb1
PB
3874 (set_attr "type" "alu_shift")]
3875)
3876
091426d3
RE
3877(define_split
3878 [(set (match_operand:SI 0 "s_register_operand" "")
3879 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3880 (clobber (match_operand:SI 2 "s_register_operand" ""))]
5b3e6663 3881 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
091426d3
RE
3882 [(set (match_dup 2) (match_dup 1))
3883 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
d5b7b3ae
RE
3884 ""
3885)
ff9940b0 3886
174ddc67
RS
3887(define_split
3888 [(set (match_operand:SI 0 "s_register_operand" "")
3889 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3890 (clobber (match_operand:SI 2 "s_register_operand" ""))]
5b3e6663 3891 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
174ddc67
RS
3892 [(set (match_dup 2) (match_dup 1))
3893 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3894 ""
3895)
3896
4cdb3ed4 3897(define_insn "*compareqi_eq0"
48a08b9c 3898 [(set (reg:CC_Z CC_REGNUM)
0502226c 3899 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
091426d3 3900 (const_int 0)))]
5b3e6663 3901 "TARGET_32BIT"
091426d3 3902 "tst\\t%0, #255"
d5b7b3ae
RE
3903 [(set_attr "conds" "set")]
3904)
3a33f76f 3905
3a33f76f 3906(define_expand "extendhisi2"
fd3f89a9 3907 [(set (match_dup 2)
988337ca 3908 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3a33f76f 3909 (const_int 16)))
ff9940b0 3910 (set (match_operand:SI 0 "s_register_operand" "")
fd3f89a9
TG
3911 (ashiftrt:SI (match_dup 2)
3912 (const_int 16)))]
d5b7b3ae 3913 "TARGET_EITHER"
3a33f76f 3914 "
d5b7b3ae 3915 {
9b66ebb1 3916 if (GET_CODE (operands[1]) == MEM)
d5b7b3ae 3917 {
5b3e6663 3918 if (TARGET_THUMB1)
9b66ebb1 3919 {
5b3e6663 3920 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
9b66ebb1
PB
3921 DONE;
3922 }
3923 else if (arm_arch4)
3924 {
9b66ebb1
PB
3925 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3926 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3927 DONE;
3928 }
d5b7b3ae 3929 }
6cc8c0b3 3930
61f0ccff 3931 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
d5b7b3ae
RE
3932 {
3933 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3934 DONE;
3935 }
9b66ebb1 3936
5895f793 3937 if (!s_register_operand (operands[1], HImode))
d5b7b3ae 3938 operands[1] = copy_to_mode_reg (HImode, operands[1]);
d5b7b3ae 3939
9b66ebb1 3940 if (arm_arch6)
d5b7b3ae 3941 {
5b3e6663
PB
3942 if (TARGET_THUMB1)
3943 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
9b66ebb1
PB
3944 else
3945 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3946 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3947
d5b7b3ae
RE
3948 DONE;
3949 }
9b66ebb1
PB
3950
3951 operands[1] = gen_lowpart (SImode, operands[1]);
3952 operands[2] = gen_reg_rtx (SImode);
d5b7b3ae
RE
3953 }"
3954)
3955
5b3e6663 3956(define_insn "thumb1_extendhisi2"
9b66ebb1
PB
3957 [(set (match_operand:SI 0 "register_operand" "=l")
3958 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3959 (clobber (match_scratch:SI 2 "=&l"))]
5b3e6663 3960 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
3961 "*
3962 {
3963 rtx ops[4];
3964 rtx mem = XEXP (operands[1], 0);
3965
3966 /* This code used to try to use 'V', and fix the address only if it was
3967 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3968 range of QImode offsets, and offsettable_address_p does a QImode
3969 address check. */
3970
3971 if (GET_CODE (mem) == CONST)
3972 mem = XEXP (mem, 0);
3973
3974 if (GET_CODE (mem) == LABEL_REF)
3975 return \"ldr\\t%0, %1\";
3976
3977 if (GET_CODE (mem) == PLUS)
3978 {
3979 rtx a = XEXP (mem, 0);
3980 rtx b = XEXP (mem, 1);
3981
3982 if (GET_CODE (a) == LABEL_REF
3983 && GET_CODE (b) == CONST_INT)
3984 return \"ldr\\t%0, %1\";
3985
3986 if (GET_CODE (b) == REG)
3987 return \"ldrsh\\t%0, %1\";
3988
3989 ops[1] = a;
3990 ops[2] = b;
3991 }
3992 else
3993 {
3994 ops[1] = mem;
3995 ops[2] = const0_rtx;
3996 }
e6d29d15
NS
3997
3998 gcc_assert (GET_CODE (ops[1]) == REG);
d5b7b3ae
RE
3999
4000 ops[0] = operands[0];
4001 ops[3] = operands[2];
4002 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4003 return \"\";
4004 }"
4005 [(set_attr "length" "4")
9b66ebb1 4006 (set_attr "type" "load_byte")
d5b7b3ae
RE
4007 (set_attr "pool_range" "1020")]
4008)
988337ca 4009
9b66ebb1
PB
4010;; We used to have an early-clobber on the scratch register here.
4011;; However, there's a bug somewhere in reload which means that this
4012;; can be partially ignored during spill allocation if the memory
e6d29d15 4013;; address also needs reloading; this causes us to die later on when
9b66ebb1
PB
4014;; we try to verify the operands. Fortunately, we don't really need
4015;; the early-clobber: we can always use operand 0 if operand 2
4016;; overlaps the address.
5b3e6663 4017(define_insn "*thumb1_extendhisi2_insn_v6"
9b66ebb1
PB
4018 [(set (match_operand:SI 0 "register_operand" "=l,l")
4019 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4020 (clobber (match_scratch:SI 2 "=X,l"))]
5b3e6663 4021 "TARGET_THUMB1 && arm_arch6"
9b66ebb1
PB
4022 "*
4023 {
4024 rtx ops[4];
4025 rtx mem;
4026
4027 if (which_alternative == 0)
4028 return \"sxth\\t%0, %1\";
4029
4030 mem = XEXP (operands[1], 0);
4031
4032 /* This code used to try to use 'V', and fix the address only if it was
4033 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4034 range of QImode offsets, and offsettable_address_p does a QImode
4035 address check. */
4036
4037 if (GET_CODE (mem) == CONST)
4038 mem = XEXP (mem, 0);
4039
4040 if (GET_CODE (mem) == LABEL_REF)
4041 return \"ldr\\t%0, %1\";
4042
4043 if (GET_CODE (mem) == PLUS)
4044 {
4045 rtx a = XEXP (mem, 0);
4046 rtx b = XEXP (mem, 1);
4047
4048 if (GET_CODE (a) == LABEL_REF
4049 && GET_CODE (b) == CONST_INT)
4050 return \"ldr\\t%0, %1\";
4051
4052 if (GET_CODE (b) == REG)
4053 return \"ldrsh\\t%0, %1\";
4054
4055 ops[1] = a;
4056 ops[2] = b;
4057 }
4058 else
4059 {
4060 ops[1] = mem;
4061 ops[2] = const0_rtx;
4062 }
4063
e6d29d15 4064 gcc_assert (GET_CODE (ops[1]) == REG);
9b66ebb1
PB
4065
4066 ops[0] = operands[0];
4067 if (reg_mentioned_p (operands[2], ops[1]))
4068 ops[3] = ops[0];
4069 else
4070 ops[3] = operands[2];
4071 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4072 return \"\";
4073 }"
4074 [(set_attr "length" "2,4")
4075 (set_attr "type" "alu_shift,load_byte")
4076 (set_attr "pool_range" "*,1020")]
4077)
4078
5b3e6663 4079;; This pattern will only be used when ldsh is not available
988337ca 4080(define_expand "extendhisi2_mem"
34757369 4081 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
988337ca 4082 (set (match_dup 3)
34757369 4083 (zero_extend:SI (match_dup 7)))
988337ca
RE
4084 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4085 (set (match_operand:SI 0 "" "")
4086 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
d5b7b3ae 4087 "TARGET_ARM"
988337ca 4088 "
5895f793
RE
4089 {
4090 rtx mem1, mem2;
4091 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4092
31fa16b6
RE
4093 mem1 = change_address (operands[1], QImode, addr);
4094 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5895f793
RE
4095 operands[0] = gen_lowpart (SImode, operands[0]);
4096 operands[1] = mem1;
4097 operands[2] = gen_reg_rtx (SImode);
4098 operands[3] = gen_reg_rtx (SImode);
4099 operands[6] = gen_reg_rtx (SImode);
4100 operands[7] = mem2;
988337ca 4101
5895f793
RE
4102 if (BYTES_BIG_ENDIAN)
4103 {
4104 operands[4] = operands[2];
4105 operands[5] = operands[3];
4106 }
4107 else
4108 {
4109 operands[4] = operands[3];
4110 operands[5] = operands[2];
4111 }
4112 }"
4113)
3a33f76f 4114
9b66ebb1
PB
4115(define_insn "*arm_extendhisi2"
4116 [(set (match_operand:SI 0 "s_register_operand" "=r")
4117 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4118 "TARGET_ARM && arm_arch4 && !arm_arch6"
5b3e6663 4119 "ldr%(sh%)\\t%0, %1"
9b66ebb1 4120 [(set_attr "type" "load_byte")
cca0a211 4121 (set_attr "predicable" "yes")
d5b7b3ae
RE
4122 (set_attr "pool_range" "256")
4123 (set_attr "neg_pool_range" "244")]
4124)
4cdb3ed4 4125
5b3e6663 4126;; ??? Check Thumb-2 pool range
9b66ebb1
PB
4127(define_insn "*arm_extendhisi2_v6"
4128 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4129 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5b3e6663 4130 "TARGET_32BIT && arm_arch6"
9b66ebb1
PB
4131 "@
4132 sxth%?\\t%0, %1
5b3e6663 4133 ldr%(sh%)\\t%0, %1"
9b66ebb1
PB
4134 [(set_attr "type" "alu_shift,load_byte")
4135 (set_attr "predicable" "yes")
4136 (set_attr "pool_range" "*,256")
4137 (set_attr "neg_pool_range" "*,244")]
4138)
4139
4140(define_insn "*arm_extendhisi2addsi"
4141 [(set (match_operand:SI 0 "s_register_operand" "=r")
4142 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4143 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 4144 "TARGET_INT_SIMD"
9b66ebb1
PB
4145 "sxtah%?\\t%0, %2, %1"
4146)
4147
fd3f89a9
TG
4148(define_expand "extendqihi2"
4149 [(set (match_dup 2)
4cdb3ed4 4150 (ashift:SI (match_operand:QI 1 "general_operand" "")
fd3f89a9 4151 (const_int 24)))
ff9940b0 4152 (set (match_operand:HI 0 "s_register_operand" "")
fd3f89a9
TG
4153 (ashiftrt:SI (match_dup 2)
4154 (const_int 24)))]
d5b7b3ae 4155 "TARGET_ARM"
fd3f89a9 4156 "
5895f793
RE
4157 {
4158 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4159 {
4160 emit_insn (gen_rtx_SET (VOIDmode,
4161 operands[0],
4162 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4163 DONE;
4164 }
4165 if (!s_register_operand (operands[1], QImode))
4166 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4167 operands[0] = gen_lowpart (SImode, operands[0]);
4168 operands[1] = gen_lowpart (SImode, operands[1]);
4169 operands[2] = gen_reg_rtx (SImode);
4170 }"
4171)
4cdb3ed4 4172
5b3e6663 4173(define_insn "*arm_extendqihi_insn"
1e1ab407
RE
4174 [(set (match_operand:HI 0 "s_register_operand" "=r")
4175 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
d5b7b3ae 4176 "TARGET_ARM && arm_arch4"
5b3e6663 4177 "ldr%(sb%)\\t%0, %1"
9b66ebb1 4178 [(set_attr "type" "load_byte")
cca0a211 4179 (set_attr "predicable" "yes")
d5b7b3ae
RE
4180 (set_attr "pool_range" "256")
4181 (set_attr "neg_pool_range" "244")]
4182)
4d818c85 4183
3a33f76f 4184(define_expand "extendqisi2"
fd3f89a9 4185 [(set (match_dup 2)
4d818c85 4186 (ashift:SI (match_operand:QI 1 "general_operand" "")
3a33f76f 4187 (const_int 24)))
ff9940b0 4188 (set (match_operand:SI 0 "s_register_operand" "")
fd3f89a9
TG
4189 (ashiftrt:SI (match_dup 2)
4190 (const_int 24)))]
d5b7b3ae 4191 "TARGET_EITHER"
3a33f76f 4192 "
d5b7b3ae 4193 {
9b66ebb1 4194 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
d5b7b3ae 4195 {
9b66ebb1 4196 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
d5b7b3ae
RE
4197 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4198 DONE;
4199 }
9b66ebb1 4200
5895f793 4201 if (!s_register_operand (operands[1], QImode))
d5b7b3ae 4202 operands[1] = copy_to_mode_reg (QImode, operands[1]);
d5b7b3ae 4203
9b66ebb1
PB
4204 if (arm_arch6)
4205 {
4206 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4207 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4208 DONE;
d5b7b3ae 4209 }
9b66ebb1
PB
4210
4211 operands[1] = gen_lowpart (SImode, operands[1]);
4212 operands[2] = gen_reg_rtx (SImode);
d5b7b3ae
RE
4213 }"
4214)
4cdb3ed4 4215
9b66ebb1
PB
4216(define_insn "*arm_extendqisi"
4217 [(set (match_operand:SI 0 "s_register_operand" "=r")
1e1ab407 4218 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
9b66ebb1 4219 "TARGET_ARM && arm_arch4 && !arm_arch6"
5b3e6663 4220 "ldr%(sb%)\\t%0, %1"
9b66ebb1 4221 [(set_attr "type" "load_byte")
cca0a211 4222 (set_attr "predicable" "yes")
d5b7b3ae
RE
4223 (set_attr "pool_range" "256")
4224 (set_attr "neg_pool_range" "244")]
4225)
4d818c85 4226
9b66ebb1
PB
4227(define_insn "*arm_extendqisi_v6"
4228 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1e1ab407 4229 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
9b66ebb1 4230 "TARGET_ARM && arm_arch6"
1e1ab407
RE
4231 "@
4232 sxtb%?\\t%0, %1
5b3e6663 4233 ldr%(sb%)\\t%0, %1"
9b66ebb1
PB
4234 [(set_attr "type" "alu_shift,load_byte")
4235 (set_attr "predicable" "yes")
9b66ebb1
PB
4236 (set_attr "pool_range" "*,256")
4237 (set_attr "neg_pool_range" "*,244")]
4238)
4239
4240(define_insn "*arm_extendqisi2addsi"
4241 [(set (match_operand:SI 0 "s_register_operand" "=r")
4242 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4243 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 4244 "TARGET_INT_SIMD"
9b66ebb1
PB
4245 "sxtab%?\\t%0, %2, %1"
4246 [(set_attr "type" "alu_shift")
c956e102 4247 (set_attr "insn" "xtab")
9b66ebb1
PB
4248 (set_attr "predicable" "yes")]
4249)
4250
5b3e6663 4251(define_insn "*thumb1_extendqisi2"
9b66ebb1
PB
4252 [(set (match_operand:SI 0 "register_operand" "=l,l")
4253 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
5b3e6663 4254 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
4255 "*
4256 {
4257 rtx ops[3];
4258 rtx mem = XEXP (operands[1], 0);
4259
4260 if (GET_CODE (mem) == CONST)
4261 mem = XEXP (mem, 0);
4262
4263 if (GET_CODE (mem) == LABEL_REF)
4264 return \"ldr\\t%0, %1\";
4265
4266 if (GET_CODE (mem) == PLUS
4267 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4268 return \"ldr\\t%0, %1\";
4269
4270 if (which_alternative == 0)
4271 return \"ldrsb\\t%0, %1\";
4272
4273 ops[0] = operands[0];
4274
4275 if (GET_CODE (mem) == PLUS)
4276 {
4277 rtx a = XEXP (mem, 0);
4278 rtx b = XEXP (mem, 1);
4279
4280 ops[1] = a;
4281 ops[2] = b;
4282
4283 if (GET_CODE (a) == REG)
4284 {
4285 if (GET_CODE (b) == REG)
4286 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4287 else if (REGNO (a) == REGNO (ops[0]))
5895f793
RE
4288 {
4289 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4290 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4291 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4292 }
d5b7b3ae
RE
4293 else
4294 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4295 }
d5b7b3ae
RE
4296 else
4297 {
e6d29d15 4298 gcc_assert (GET_CODE (b) == REG);
d5b7b3ae 4299 if (REGNO (b) == REGNO (ops[0]))
5895f793
RE
4300 {
4301 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4302 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4303 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4304 }
d5b7b3ae
RE
4305 else
4306 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4307 }
4308 }
4309 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4310 {
5895f793
RE
4311 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4312 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4313 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
d5b7b3ae
RE
4314 }
4315 else
4316 {
4317 ops[1] = mem;
4318 ops[2] = const0_rtx;
4319
4320 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4321 }
4322 return \"\";
4323 }"
4324 [(set_attr "length" "2,6")
9b66ebb1 4325 (set_attr "type" "load_byte,load_byte")
d5b7b3ae
RE
4326 (set_attr "pool_range" "32,32")]
4327)
4328
5b3e6663 4329(define_insn "*thumb1_extendqisi2_v6"
9b66ebb1
PB
4330 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4331 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
5b3e6663 4332 "TARGET_THUMB1 && arm_arch6"
9b66ebb1
PB
4333 "*
4334 {
4335 rtx ops[3];
4336 rtx mem;
4337
4338 if (which_alternative == 0)
4339 return \"sxtb\\t%0, %1\";
4340
4341 mem = XEXP (operands[1], 0);
4342
4343 if (GET_CODE (mem) == CONST)
4344 mem = XEXP (mem, 0);
4345
4346 if (GET_CODE (mem) == LABEL_REF)
4347 return \"ldr\\t%0, %1\";
4348
4349 if (GET_CODE (mem) == PLUS
4350 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4351 return \"ldr\\t%0, %1\";
4352
4353 if (which_alternative == 0)
4354 return \"ldrsb\\t%0, %1\";
4355
4356 ops[0] = operands[0];
4357
4358 if (GET_CODE (mem) == PLUS)
4359 {
4360 rtx a = XEXP (mem, 0);
4361 rtx b = XEXP (mem, 1);
4362
4363 ops[1] = a;
4364 ops[2] = b;
4365
4366 if (GET_CODE (a) == REG)
4367 {
4368 if (GET_CODE (b) == REG)
4369 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4370 else if (REGNO (a) == REGNO (ops[0]))
4371 {
4372 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4373 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4374 }
4375 else
4376 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4377 }
9b66ebb1
PB
4378 else
4379 {
e6d29d15 4380 gcc_assert (GET_CODE (b) == REG);
9b66ebb1
PB
4381 if (REGNO (b) == REGNO (ops[0]))
4382 {
4383 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4384 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4385 }
4386 else
4387 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4388 }
4389 }
4390 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4391 {
4392 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4393 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4394 }
4395 else
4396 {
4397 ops[1] = mem;
4398 ops[2] = const0_rtx;
4399
4400 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4401 }
4402 return \"\";
4403 }"
4404 [(set_attr "length" "2,2,4")
4405 (set_attr "type" "alu_shift,load_byte,load_byte")
4406 (set_attr "pool_range" "*,32,32")]
4407)
4408
1e3af7f6
NC
4409(define_expand "extendsfdf2"
4410 [(set (match_operand:DF 0 "s_register_operand" "")
4411 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
5b3e6663 4412 "TARGET_32BIT && TARGET_HARD_FLOAT"
1e3af7f6
NC
4413 ""
4414)
3a33f76f
RK
4415\f
4416;; Move insns (including loads and stores)
4417
4418;; XXX Just some ideas about movti.
ff9940b0
RE
4419;; I don't think these are a good idea on the arm, there just aren't enough
4420;; registers
3a33f76f 4421;;(define_expand "loadti"
ff9940b0 4422;; [(set (match_operand:TI 0 "s_register_operand" "")
3a33f76f
RK
4423;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4424;; "" "")
4425
4426;;(define_expand "storeti"
4427;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
ff9940b0 4428;; (match_operand:TI 1 "s_register_operand" ""))]
3a33f76f
RK
4429;; "" "")
4430
4431;;(define_expand "movti"
4432;; [(set (match_operand:TI 0 "general_operand" "")
4433;; (match_operand:TI 1 "general_operand" ""))]
4434;; ""
4435;; "
4436;;{
4437;; rtx insn;
4438;;
4439;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4440;; operands[1] = copy_to_reg (operands[1]);
4441;; if (GET_CODE (operands[0]) == MEM)
4442;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4443;; else if (GET_CODE (operands[1]) == MEM)
4444;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4445;; else
4446;; FAIL;
4447;;
4448;; emit_insn (insn);
4449;; DONE;
4450;;}")
4451
05713b80 4452;; Recognize garbage generated above.
3a33f76f
RK
4453
4454;;(define_insn ""
4455;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4456;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4457;; ""
4458;; "*
4459;; {
4460;; register mem = (which_alternative < 3);
cca0a211 4461;; register const char *template;
3a33f76f
RK
4462;;
4463;; operands[mem] = XEXP (operands[mem], 0);
4464;; switch (which_alternative)
4465;; {
4466;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4467;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4468;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4469;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4470;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4471;; case 5: template = \"stmia\\t%0, %M1\"; break;
4472;; }
0f447ef2
RE
4473;; output_asm_insn (template, operands);
4474;; return \"\";
3a33f76f
RK
4475;; }")
4476
d5b7b3ae
RE
4477(define_expand "movdi"
4478 [(set (match_operand:DI 0 "general_operand" "")
4479 (match_operand:DI 1 "general_operand" ""))]
4480 "TARGET_EITHER"
4481 "
b3a13419 4482 if (can_create_pseudo_p ())
d5b7b3ae 4483 {
d5b6e637
PB
4484 if (GET_CODE (operands[0]) != REG)
4485 operands[1] = force_reg (DImode, operands[1]);
d5b7b3ae
RE
4486 }
4487 "
4488)
3a33f76f 4489
d5b7b3ae 4490(define_insn "*arm_movdi"
9b901d50
RE
4491 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4492 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
9b66ebb1 4493 "TARGET_ARM
d5b6e637
PB
4494 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4495 && !TARGET_IWMMXT
4496 && ( register_operand (operands[0], DImode)
4497 || register_operand (operands[1], DImode))"
3a33f76f 4498 "*
9b901d50
RE
4499 switch (which_alternative)
4500 {
4501 case 0:
4502 case 1:
4503 case 2:
4504 return \"#\";
4505 default:
4506 return output_move_double (operands);
4507 }
d5b7b3ae 4508 "
2075b05d
RE
4509 [(set_attr "length" "8,12,16,8,8")
4510 (set_attr "type" "*,*,*,load2,store2")
4511 (set_attr "pool_range" "*,*,*,1020,*")
4512 (set_attr "neg_pool_range" "*,*,*,1008,*")]
d5b7b3ae
RE
4513)
4514
9b901d50
RE
4515(define_split
4516 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4517 (match_operand:ANY64 1 "const_double_operand" ""))]
5b3e6663 4518 "TARGET_32BIT
9b901d50
RE
4519 && reload_completed
4520 && (arm_const_double_inline_cost (operands[1])
4521 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4522 [(const_int 0)]
4523 "
4524 arm_split_constant (SET, SImode, curr_insn,
4525 INTVAL (gen_lowpart (SImode, operands[1])),
4526 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4527 arm_split_constant (SET, SImode, curr_insn,
4528 INTVAL (gen_highpart_mode (SImode,
4529 GET_MODE (operands[0]),
4530 operands[1])),
4531 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4532 DONE;
4533 "
4534)
4535
b4a58f80
RE
4536; If optimizing for size, or if we have load delay slots, then
4537; we want to split the constant into two separate operations.
4538; In both cases this may split a trivial part into a single data op
4539; leaving a single complex constant to load. We can also get longer
4540; offsets in a LDR which means we get better chances of sharing the pool
4541; entries. Finally, we can normally do a better job of scheduling
4542; LDR instructions than we can with LDM.
4543; This pattern will only match if the one above did not.
4544(define_split
4545 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4546 (match_operand:ANY64 1 "const_double_operand" ""))]
4547 "TARGET_ARM && reload_completed
4548 && arm_const_double_by_parts (operands[1])"
4549 [(set (match_dup 0) (match_dup 1))
4550 (set (match_dup 2) (match_dup 3))]
4551 "
4552 operands[2] = gen_highpart (SImode, operands[0]);
4553 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4554 operands[1]);
4555 operands[0] = gen_lowpart (SImode, operands[0]);
4556 operands[1] = gen_lowpart (SImode, operands[1]);
4557 "
4558)
4559
9b901d50
RE
4560(define_split
4561 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4562 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4563 "TARGET_EITHER && reload_completed"
4564 [(set (match_dup 0) (match_dup 1))
4565 (set (match_dup 2) (match_dup 3))]
4566 "
4567 operands[2] = gen_highpart (SImode, operands[0]);
4568 operands[3] = gen_highpart (SImode, operands[1]);
4569 operands[0] = gen_lowpart (SImode, operands[0]);
4570 operands[1] = gen_lowpart (SImode, operands[1]);
4571
4572 /* Handle a partial overlap. */
4573 if (rtx_equal_p (operands[0], operands[3]))
4574 {
4575 rtx tmp0 = operands[0];
4576 rtx tmp1 = operands[1];
4577
4578 operands[0] = operands[2];
4579 operands[1] = operands[3];
4580 operands[2] = tmp0;
4581 operands[3] = tmp1;
4582 }
4583 "
4584)
4585
fdd695fd
PB
4586;; We can't actually do base+index doubleword loads if the index and
4587;; destination overlap. Split here so that we at least have chance to
4588;; schedule.
4589(define_split
4590 [(set (match_operand:DI 0 "s_register_operand" "")
4591 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4592 (match_operand:SI 2 "s_register_operand" ""))))]
4593 "TARGET_LDRD
4594 && reg_overlap_mentioned_p (operands[0], operands[1])
4595 && reg_overlap_mentioned_p (operands[0], operands[2])"
4596 [(set (match_dup 4)
4597 (plus:SI (match_dup 1)
4598 (match_dup 2)))
4599 (set (match_dup 0)
4600 (mem:DI (match_dup 4)))]
4601 "
4602 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4603 "
4604)
4605
d5b7b3ae
RE
4606;;; ??? This should have alternatives for constants.
4607;;; ??? This was originally identical to the movdf_insn pattern.
4608;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4609;;; thumb_reorg with a memory reference.
5b3e6663 4610(define_insn "*thumb1_movdi_insn"
5895f793
RE
4611 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4612 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
5b3e6663 4613 "TARGET_THUMB1
9b66ebb1 4614 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
d5b7b3ae
RE
4615 && ( register_operand (operands[0], DImode)
4616 || register_operand (operands[1], DImode))"
4617 "*
4618 {
4619 switch (which_alternative)
4620 {
4621 default:
4622 case 0:
4623 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4624 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4625 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4626 case 1:
4627 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4628 case 2:
4629 operands[1] = GEN_INT (- INTVAL (operands[1]));
4630 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4631 case 3:
4632 return \"ldmia\\t%1, {%0, %H0}\";
4633 case 4:
4634 return \"stmia\\t%0, {%1, %H1}\";
4635 case 5:
4636 return thumb_load_double_from_address (operands);
4637 case 6:
f1c25d3b 4638 operands[2] = gen_rtx_MEM (SImode,
5895f793 4639 plus_constant (XEXP (operands[0], 0), 4));
d5b7b3ae
RE
4640 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4641 return \"\";
4642 case 7:
4643 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4644 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4645 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4646 }
4647 }"
4648 [(set_attr "length" "4,4,6,2,2,6,4,4")
9b66ebb1 4649 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d5b7b3ae
RE
4650 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4651)
3a33f76f 4652
ff9940b0
RE
4653(define_expand "movsi"
4654 [(set (match_operand:SI 0 "general_operand" "")
4655 (match_operand:SI 1 "general_operand" ""))]
d5b7b3ae 4656 "TARGET_EITHER"
ff9940b0 4657 "
8426b956
RS
4658 rtx base, offset, tmp;
4659
5b3e6663 4660 if (TARGET_32BIT)
ff9940b0 4661 {
d6b4baa4 4662 /* Everything except mem = const or mem = mem can be done easily. */
d5b7b3ae
RE
4663 if (GET_CODE (operands[0]) == MEM)
4664 operands[1] = force_reg (SImode, operands[1]);
9b66ebb1
PB
4665 if (arm_general_register_operand (operands[0], SImode)
4666 && GET_CODE (operands[1]) == CONST_INT
d5b7b3ae
RE
4667 && !(const_ok_for_arm (INTVAL (operands[1]))
4668 || const_ok_for_arm (~INTVAL (operands[1]))))
4669 {
a406f566
MM
4670 arm_split_constant (SET, SImode, NULL_RTX,
4671 INTVAL (operands[1]), operands[0], NULL_RTX,
b3a13419 4672 optimize && can_create_pseudo_p ());
d5b7b3ae
RE
4673 DONE;
4674 }
4675 }
5b3e6663 4676 else /* TARGET_THUMB1... */
d5b7b3ae 4677 {
b3a13419 4678 if (can_create_pseudo_p ())
d5b7b3ae
RE
4679 {
4680 if (GET_CODE (operands[0]) != REG)
4681 operands[1] = force_reg (SImode, operands[1]);
4682 }
ff9940b0 4683 }
d3585b76 4684
8426b956
RS
4685 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
4686 {
4687 split_const (operands[1], &base, &offset);
4688 if (GET_CODE (base) == SYMBOL_REF
4689 && !offset_within_block_p (base, INTVAL (offset)))
4690 {
08a576fb 4691 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
8426b956
RS
4692 emit_move_insn (tmp, base);
4693 emit_insn (gen_addsi3 (operands[0], tmp, offset));
4694 DONE;
4695 }
4696 }
4697
d3585b76
DJ
4698 /* Recognize the case where operand[1] is a reference to thread-local
4699 data and load its address to a register. */
4700 if (arm_tls_referenced_p (operands[1]))
4701 {
4702 rtx tmp = operands[1];
4703 rtx addend = NULL;
4704
4705 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4706 {
4707 addend = XEXP (XEXP (tmp, 0), 1);
4708 tmp = XEXP (XEXP (tmp, 0), 0);
4709 }
4710
4711 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4712 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4713
b3a13419
ILT
4714 tmp = legitimize_tls_address (tmp,
4715 !can_create_pseudo_p () ? operands[0] : 0);
d3585b76
DJ
4716 if (addend)
4717 {
4718 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4719 tmp = force_operand (tmp, operands[0]);
4720 }
4721 operands[1] = tmp;
4722 }
4723 else if (flag_pic
4724 && (CONSTANT_P (operands[1])
4725 || symbol_mentioned_p (operands[1])
4726 || label_mentioned_p (operands[1])))
4727 operands[1] = legitimize_pic_address (operands[1], SImode,
b3a13419
ILT
4728 (!can_create_pseudo_p ()
4729 ? operands[0]
4730 : 0));
5895f793
RE
4731 "
4732)
ff9940b0 4733
d5b7b3ae 4734(define_insn "*arm_movsi_insn"
5b3e6663
PB
4735 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r, m")
4736 (match_operand:SI 1 "general_operand" "rI,K,N,mi,r"))]
5a9335ef 4737 "TARGET_ARM && ! TARGET_IWMMXT
9b66ebb1 4738 && !(TARGET_HARD_FLOAT && TARGET_VFP)
d5b7b3ae
RE
4739 && ( register_operand (operands[0], SImode)
4740 || register_operand (operands[1], SImode))"
4cdb3ed4
RE
4741 "@
4742 mov%?\\t%0, %1
4743 mvn%?\\t%0, #%B1
5b3e6663 4744 movw%?\\t%0, %1
4cdb3ed4
RE
4745 ldr%?\\t%0, %1
4746 str%?\\t%1, %0"
5b3e6663 4747 [(set_attr "type" "*,*,*,load1,store1")
cca0a211 4748 (set_attr "predicable" "yes")
5b3e6663
PB
4749 (set_attr "pool_range" "*,*,*,4096,*")
4750 (set_attr "neg_pool_range" "*,*,*,4084,*")]
d5b7b3ae 4751)
091426d3
RE
4752
4753(define_split
9b66ebb1 4754 [(set (match_operand:SI 0 "arm_general_register_operand" "")
091426d3 4755 (match_operand:SI 1 "const_int_operand" ""))]
5b3e6663 4756 "TARGET_32BIT
5895f793
RE
4757 && (!(const_ok_for_arm (INTVAL (operands[1]))
4758 || const_ok_for_arm (~INTVAL (operands[1]))))"
091426d3
RE
4759 [(clobber (const_int 0))]
4760 "
a406f566
MM
4761 arm_split_constant (SET, SImode, NULL_RTX,
4762 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
091426d3 4763 DONE;
5895f793
RE
4764 "
4765)
ff9940b0 4766
5b3e6663 4767(define_insn "*thumb1_movsi_insn"
5895f793
RE
4768 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4769 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
5b3e6663 4770 "TARGET_THUMB1
d5b7b3ae
RE
4771 && ( register_operand (operands[0], SImode)
4772 || register_operand (operands[1], SImode))"
4773 "@
4774 mov %0, %1
4775 mov %0, %1
4776 #
4777 #
4778 ldmia\\t%1, {%0}
4779 stmia\\t%0, {%1}
4780 ldr\\t%0, %1
4781 str\\t%1, %0
4782 mov\\t%0, %1"
4783 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
9b66ebb1 4784 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
d5b7b3ae
RE
4785 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4786)
4787
4788(define_split
4789 [(set (match_operand:SI 0 "register_operand" "")
4790 (match_operand:SI 1 "const_int_operand" ""))]
5b3e6663 4791 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
d5b7b3ae
RE
4792 [(set (match_dup 0) (match_dup 1))
4793 (set (match_dup 0) (neg:SI (match_dup 0)))]
4794 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4795)
4796
4797(define_split
4798 [(set (match_operand:SI 0 "register_operand" "")
4799 (match_operand:SI 1 "const_int_operand" ""))]
5b3e6663 4800 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
d5b7b3ae
RE
4801 [(set (match_dup 0) (match_dup 1))
4802 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4803 "
4804 {
4805 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4806 unsigned HOST_WIDE_INT mask = 0xff;
4807 int i;
4808
4809 for (i = 0; i < 25; i++)
4810 if ((val & (mask << i)) == val)
4811 break;
4812
3a4edb44 4813 /* Shouldn't happen, but we don't want to split if the shift is zero. */
d5b7b3ae
RE
4814 if (i == 0)
4815 FAIL;
4816
4817 operands[1] = GEN_INT (val >> i);
4818 operands[2] = GEN_INT (i);
4819 }"
4820)
4821
f12c5ef3
RE
4822;; When generating pic, we need to load the symbol offset into a register.
4823;; So that the optimizer does not confuse this with a normal symbol load
4824;; we use an unspec. The offset will be loaded from a constant pool entry,
4825;; since that is the only type of relocation we can use.
4826
4827;; The rather odd constraints on the following are to force reload to leave
4828;; the insn alone, and to force the minipool generation pass to then move
4829;; the GOT symbol to memory.
fef37aaf 4830
4bec9f7d 4831(define_insn "pic_load_addr_arm"
fef37aaf 4832 [(set (match_operand:SI 0 "s_register_operand" "=r")
b15bca31 4833 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4bec9f7d 4834 "TARGET_ARM && flag_pic"
f12c5ef3 4835 "ldr%?\\t%0, %1"
9b66ebb1 4836 [(set_attr "type" "load1")
4bec9f7d
NC
4837 (set (attr "pool_range") (const_int 4096))
4838 (set (attr "neg_pool_range") (const_int 4084))]
4839)
4840
5b3e6663 4841(define_insn "pic_load_addr_thumb1"
4bec9f7d 4842 [(set (match_operand:SI 0 "s_register_operand" "=l")
b15bca31 4843 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5b3e6663 4844 "TARGET_THUMB1 && flag_pic"
4bec9f7d 4845 "ldr\\t%0, %1"
9b66ebb1 4846 [(set_attr "type" "load1")
4bec9f7d 4847 (set (attr "pool_range") (const_int 1024))]
d5b7b3ae 4848)
fef37aaf
RE
4849
4850;; This variant is used for AOF assembly, since it needs to mention the
4851;; pic register in the rtl.
4852(define_expand "pic_load_addr_based"
82955615 4853 [(set (match_operand:SI 0 "s_register_operand" "")
b15bca31 4854 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
d5b7b3ae 4855 "TARGET_ARM && flag_pic"
020a4035 4856 "operands[2] = cfun->machine->pic_reg;"
d5b7b3ae 4857)
fef37aaf
RE
4858
4859(define_insn "*pic_load_addr_based_insn"
4860 [(set (match_operand:SI 0 "s_register_operand" "=r")
4861 (unspec:SI [(match_operand 1 "" "")
b15bca31
RE
4862 (match_operand 2 "s_register_operand" "r")]
4863 UNSPEC_PIC_SYM))]
020a4035 4864 "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
fef37aaf
RE
4865 "*
4866#ifdef AOF_ASSEMBLER
4867 operands[1] = aof_pic_entry (operands[1]);
4868#endif
4869 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4870 return \"\";
d5b7b3ae 4871 "
9b66ebb1 4872 [(set_attr "type" "load1")
d5b7b3ae
RE
4873 (set (attr "pool_range")
4874 (if_then_else (eq_attr "is_thumb" "yes")
4875 (const_int 1024)
4876 (const_int 4096)))
4877 (set (attr "neg_pool_range")
4878 (if_then_else (eq_attr "is_thumb" "yes")
4879 (const_int 0)
4880 (const_int 4084)))]
4881)
4882
4883(define_insn "pic_add_dot_plus_four"
6137ba90
PB
4884 [(set (match_operand:SI 0 "register_operand" "=r")
4885 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
10ae7c7b
DJ
4886 (const (plus:SI (pc) (const_int 4))))
4887 (match_operand 2 "" "")]
4888 UNSPEC_PIC_BASE))]
5b3e6663 4889 "TARGET_THUMB1"
d5b7b3ae 4890 "*
f16fe45f
DJ
4891 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4892 INTVAL (operands[2]));
d5b7b3ae
RE
4893 return \"add\\t%0, %|pc\";
4894 "
4895 [(set_attr "length" "2")]
4896)
fef37aaf
RE
4897
4898(define_insn "pic_add_dot_plus_eight"
6137ba90
PB
4899 [(set (match_operand:SI 0 "register_operand" "=r")
4900 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
10ae7c7b
DJ
4901 (const (plus:SI (pc) (const_int 8))))
4902 (match_operand 2 "" "")]
4903 UNSPEC_PIC_BASE))]
d3585b76 4904 "TARGET_ARM"
dfa08768 4905 "*
f16fe45f
DJ
4906 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4907 INTVAL (operands[2]));
6137ba90 4908 return \"add%?\\t%0, %|pc, %1\";
d5b7b3ae 4909 "
cca0a211 4910 [(set_attr "predicable" "yes")]
d5b7b3ae 4911)
fef37aaf 4912
d3585b76
DJ
4913(define_insn "tls_load_dot_plus_eight"
4914 [(set (match_operand:SI 0 "register_operand" "+r")
4915 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
10ae7c7b
DJ
4916 (const (plus:SI (pc) (const_int 8))))
4917 (match_operand 2 "" "")]
4918 UNSPEC_PIC_BASE)))]
d3585b76
DJ
4919 "TARGET_ARM"
4920 "*
f16fe45f
DJ
4921 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4922 INTVAL (operands[2]));
d3585b76
DJ
4923 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4924 "
4925 [(set_attr "predicable" "yes")]
4926)
4927
4928;; PIC references to local variables can generate pic_add_dot_plus_eight
4929;; followed by a load. These sequences can be crunched down to
4930;; tls_load_dot_plus_eight by a peephole.
4931
4932(define_peephole2
4933 [(parallel [(set (match_operand:SI 0 "register_operand" "")
6137ba90 4934 (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
d3585b76
DJ
4935 (const (plus:SI (pc) (const_int 8))))]
4936 UNSPEC_PIC_BASE))
4937 (use (label_ref (match_operand 1 "" "")))])
4938 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4939 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
6137ba90
PB
4940 [(parallel [(set (match_dup 2)
4941 (mem:SI (unspec:SI [(plus:SI (match_dup 3)
d3585b76
DJ
4942 (const (plus:SI (pc) (const_int 8))))]
4943 UNSPEC_PIC_BASE)))
6137ba90 4944 (use (label_ref (match_dup 1)))])]
d3585b76
DJ
4945 ""
4946)
4947
9403b7f7
RS
4948(define_insn "pic_offset_arm"
4949 [(set (match_operand:SI 0 "register_operand" "=r")
4950 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
4951 (unspec:SI [(match_operand:SI 2 "" "X")]
4952 UNSPEC_PIC_OFFSET))))]
4953 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
4954 "ldr%?\\t%0, [%1,%2]"
4955 [(set_attr "type" "load1")]
4956)
4957
c1163e75
PB
4958(define_expand "builtin_setjmp_receiver"
4959 [(label_ref (match_operand 0 "" ""))]
4960 "flag_pic"
4961 "
4962{
fe013435
PB
4963 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4964 register. */
020a4035
RE
4965 if (arm_pic_register != INVALID_REGNUM)
4966 arm_load_pic_register (1UL << 3);
c1163e75
PB
4967 DONE;
4968}")
4969
ff9940b0
RE
4970;; If copying one reg to another we can set the condition codes according to
4971;; its value. Such a move is common after a return from subroutine and the
4972;; result is being tested against zero.
4973
4cdb3ed4 4974(define_insn "*movsi_compare0"
48a08b9c 4975 [(set (reg:CC CC_REGNUM)
d5b7b3ae
RE
4976 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4977 (const_int 0)))
4978 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4979 (match_dup 1))]
5b3e6663 4980 "TARGET_32BIT"
0f447ef2 4981 "@
c63165be 4982 cmp%?\\t%0, #0
5b3e6663 4983 sub%.\\t%0, %1, #0"
d5b7b3ae
RE
4984 [(set_attr "conds" "set")]
4985)
3a33f76f 4986
3a33f76f
RK
4987;; Subroutine to store a half word from a register into memory.
4988;; Operand 0 is the source register (HImode)
fd3f89a9 4989;; Operand 1 is the destination address in a register (SImode)
3a33f76f 4990
ff9940b0 4991;; In both this routine and the next, we must be careful not to spill
ddd5a7c1 4992;; a memory address of reg+large_const into a separate PLUS insn, since this
ff9940b0
RE
4993;; can generate unrecognizable rtl.
4994
3a33f76f 4995(define_expand "storehi"
fd3f89a9 4996 [;; store the low byte
7a0a1f09 4997 (set (match_operand 1 "" "") (match_dup 3))
3a33f76f 4998 ;; extract the high byte
fd3f89a9
TG
4999 (set (match_dup 2)
5000 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3a33f76f 5001 ;; store the high byte
c9389e79 5002 (set (match_dup 4) (match_dup 5))]
d5b7b3ae 5003 "TARGET_ARM"
3a33f76f 5004 "
5895f793 5005 {
792760b9
RK
5006 rtx op1 = operands[1];
5007 rtx addr = XEXP (op1, 0);
5895f793
RE
5008 enum rtx_code code = GET_CODE (addr);
5009
5010 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5011 || code == MINUS)
792760b9 5012 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5895f793 5013
792760b9 5014 operands[4] = adjust_address (op1, QImode, 1);
f4ef873c 5015 operands[1] = adjust_address (operands[1], QImode, 0);
5895f793
RE
5016 operands[3] = gen_lowpart (QImode, operands[0]);
5017 operands[0] = gen_lowpart (SImode, operands[0]);
c9389e79
RE
5018 operands[2] = gen_reg_rtx (SImode);
5019 operands[5] = gen_lowpart (QImode, operands[2]);
5895f793
RE
5020 }"
5021)
3a33f76f 5022
fe241a29 5023(define_expand "storehi_bigend"
7a0a1f09 5024 [(set (match_dup 4) (match_dup 3))
fe241a29
RE
5025 (set (match_dup 2)
5026 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
c9389e79 5027 (set (match_operand 1 "" "") (match_dup 5))]
d5b7b3ae 5028 "TARGET_ARM"
3a33f76f 5029 "
5895f793 5030 {
792760b9
RK
5031 rtx op1 = operands[1];
5032 rtx addr = XEXP (op1, 0);
5895f793
RE
5033 enum rtx_code code = GET_CODE (addr);
5034
5035 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5036 || code == MINUS)
792760b9 5037 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5895f793 5038
792760b9 5039 operands[4] = adjust_address (op1, QImode, 1);
f4ef873c 5040 operands[1] = adjust_address (operands[1], QImode, 0);
5895f793
RE
5041 operands[3] = gen_lowpart (QImode, operands[0]);
5042 operands[0] = gen_lowpart (SImode, operands[0]);
5043 operands[2] = gen_reg_rtx (SImode);
c9389e79 5044 operands[5] = gen_lowpart (QImode, operands[2]);
5895f793
RE
5045 }"
5046)
fe241a29
RE
5047
5048;; Subroutine to store a half word integer constant into memory.
5049(define_expand "storeinthi"
7a0a1f09 5050 [(set (match_operand 0 "" "")
c9389e79 5051 (match_operand 1 "" ""))
5d5603e2 5052 (set (match_dup 3) (match_dup 2))]
d5b7b3ae 5053 "TARGET_ARM"
fe241a29 5054 "
5895f793
RE
5055 {
5056 HOST_WIDE_INT value = INTVAL (operands[1]);
5057 rtx addr = XEXP (operands[0], 0);
792760b9 5058 rtx op0 = operands[0];
5895f793 5059 enum rtx_code code = GET_CODE (addr);
fe241a29 5060
5895f793
RE
5061 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5062 || code == MINUS)
792760b9 5063 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
fe241a29 5064
5895f793
RE
5065 operands[1] = gen_reg_rtx (SImode);
5066 if (BYTES_BIG_ENDIAN)
5067 {
5068 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5069 if ((value & 255) == ((value >> 8) & 255))
5070 operands[2] = operands[1];
5071 else
5072 {
5073 operands[2] = gen_reg_rtx (SImode);
5074 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5075 }
5076 }
5077 else
5078 {
5079 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5080 if ((value & 255) == ((value >> 8) & 255))
5081 operands[2] = operands[1];
5082 else
5083 {
5084 operands[2] = gen_reg_rtx (SImode);
5085 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5086 }
5087 }
fe241a29 5088
792760b9 5089 operands[3] = adjust_address (op0, QImode, 1);
f4ef873c 5090 operands[0] = adjust_address (operands[0], QImode, 0);
5d5603e2 5091 operands[2] = gen_lowpart (QImode, operands[2]);
c9389e79 5092 operands[1] = gen_lowpart (QImode, operands[1]);
5895f793
RE
5093 }"
5094)
3a33f76f 5095
4cdb3ed4
RE
5096(define_expand "storehi_single_op"
5097 [(set (match_operand:HI 0 "memory_operand" "")
5098 (match_operand:HI 1 "general_operand" ""))]
5b3e6663 5099 "TARGET_32BIT && arm_arch4"
4cdb3ed4 5100 "
5895f793 5101 if (!s_register_operand (operands[1], HImode))
4cdb3ed4 5102 operands[1] = copy_to_mode_reg (HImode, operands[1]);
5895f793
RE
5103 "
5104)
4cdb3ed4 5105
3a33f76f
RK
5106(define_expand "movhi"
5107 [(set (match_operand:HI 0 "general_operand" "")
fd3f89a9 5108 (match_operand:HI 1 "general_operand" ""))]
d5b7b3ae 5109 "TARGET_EITHER"
3a33f76f 5110 "
d5b7b3ae 5111 if (TARGET_ARM)
3a33f76f 5112 {
b3a13419 5113 if (can_create_pseudo_p ())
d5b7b3ae
RE
5114 {
5115 if (GET_CODE (operands[0]) == MEM)
3a33f76f 5116 {
d5b7b3ae
RE
5117 if (arm_arch4)
5118 {
5119 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5120 DONE;
5121 }
5122 if (GET_CODE (operands[1]) == CONST_INT)
5123 emit_insn (gen_storeinthi (operands[0], operands[1]));
fe241a29 5124 else
d5b7b3ae
RE
5125 {
5126 if (GET_CODE (operands[1]) == MEM)
5127 operands[1] = force_reg (HImode, operands[1]);
5128 if (BYTES_BIG_ENDIAN)
5129 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5130 else
5131 emit_insn (gen_storehi (operands[1], operands[0]));
5132 }
5133 DONE;
3a33f76f 5134 }
d5b7b3ae
RE
5135 /* Sign extend a constant, and keep it in an SImode reg. */
5136 else if (GET_CODE (operands[1]) == CONST_INT)
ff9940b0 5137 {
d5b7b3ae
RE
5138 rtx reg = gen_reg_rtx (SImode);
5139 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5140
5141 /* If the constant is already valid, leave it alone. */
5895f793 5142 if (!const_ok_for_arm (val))
d5b7b3ae
RE
5143 {
5144 /* If setting all the top bits will make the constant
5145 loadable in a single instruction, then set them.
5146 Otherwise, sign extend the number. */
5147
5895f793 5148 if (const_ok_for_arm (~(val | ~0xffff)))
d5b7b3ae
RE
5149 val |= ~0xffff;
5150 else if (val & 0x8000)
5151 val |= ~0xffff;
5152 }
5153
5154 emit_insn (gen_movsi (reg, GEN_INT (val)));
5d5603e2 5155 operands[1] = gen_lowpart (HImode, reg);
ff9940b0 5156 }
b3a13419 5157 else if (arm_arch4 && optimize && can_create_pseudo_p ()
b41caf7c
RE
5158 && GET_CODE (operands[1]) == MEM)
5159 {
5160 rtx reg = gen_reg_rtx (SImode);
5161
5162 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5163 operands[1] = gen_lowpart (HImode, reg);
5164 }
5895f793 5165 else if (!arm_arch4)
4cdb3ed4 5166 {
d5b7b3ae
RE
5167 if (GET_CODE (operands[1]) == MEM)
5168 {
61f0ccff
RE
5169 rtx base;
5170 rtx offset = const0_rtx;
5171 rtx reg = gen_reg_rtx (SImode);
5172
5173 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5174 || (GET_CODE (base) == PLUS
5175 && (GET_CODE (offset = XEXP (base, 1))
5176 == CONST_INT)
5177 && ((INTVAL(offset) & 1) != 1)
5178 && GET_CODE (base = XEXP (base, 0)) == REG))
5179 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
0502226c 5180 {
61f0ccff
RE
5181 rtx new;
5182
31fa16b6
RE
5183 new = widen_memory_access (operands[1], SImode,
5184 ((INTVAL (offset) & ~3)
5185 - INTVAL (offset)));
61f0ccff
RE
5186 emit_insn (gen_movsi (reg, new));
5187 if (((INTVAL (offset) & 2) != 0)
5188 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5189 {
5190 rtx reg2 = gen_reg_rtx (SImode);
5191
5192 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5193 reg = reg2;
5194 }
0502226c 5195 }
61f0ccff
RE
5196 else
5197 emit_insn (gen_movhi_bytes (reg, operands[1]));
5198
5199 operands[1] = gen_lowpart (HImode, reg);
d5b7b3ae
RE
5200 }
5201 }
5202 }
d6b4baa4 5203 /* Handle loading a large integer during reload. */
d5b7b3ae 5204 else if (GET_CODE (operands[1]) == CONST_INT
5895f793
RE
5205 && !const_ok_for_arm (INTVAL (operands[1]))
5206 && !const_ok_for_arm (~INTVAL (operands[1])))
d5b7b3ae
RE
5207 {
5208 /* Writing a constant to memory needs a scratch, which should
5209 be handled with SECONDARY_RELOADs. */
e6d29d15 5210 gcc_assert (GET_CODE (operands[0]) == REG);
d5b7b3ae
RE
5211
5212 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5213 emit_insn (gen_movsi (operands[0], operands[1]));
5214 DONE;
5215 }
5216 }
5b3e6663
PB
5217 else if (TARGET_THUMB2)
5218 {
5219 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
b3a13419 5220 if (can_create_pseudo_p ())
5b3e6663
PB
5221 {
5222 if (GET_CODE (operands[0]) != REG)
5223 operands[1] = force_reg (HImode, operands[1]);
5224 /* Zero extend a constant, and keep it in an SImode reg. */
5225 else if (GET_CODE (operands[1]) == CONST_INT)
5226 {
5227 rtx reg = gen_reg_rtx (SImode);
5228 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5229
5230 emit_insn (gen_movsi (reg, GEN_INT (val)));
5231 operands[1] = gen_lowpart (HImode, reg);
5232 }
5233 }
5234 }
5235 else /* TARGET_THUMB1 */
d5b7b3ae 5236 {
b3a13419 5237 if (can_create_pseudo_p ())
d5b7b3ae 5238 {
78a5d727
RE
5239 if (GET_CODE (operands[1]) == CONST_INT)
5240 {
5241 rtx reg = gen_reg_rtx (SImode);
5242
5243 emit_insn (gen_movsi (reg, operands[1]));
5244 operands[1] = gen_lowpart (HImode, reg);
5245 }
d5b7b3ae
RE
5246
5247 /* ??? We shouldn't really get invalid addresses here, but this can
5895f793
RE
5248 happen if we are passed a SP (never OK for HImode/QImode) or
5249 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5250 HImode/QImode) relative address. */
d5b7b3ae
RE
5251 /* ??? This should perhaps be fixed elsewhere, for instance, in
5252 fixup_stack_1, by checking for other kinds of invalid addresses,
5253 e.g. a bare reference to a virtual register. This may confuse the
5254 alpha though, which must handle this case differently. */
5255 if (GET_CODE (operands[0]) == MEM
5895f793
RE
5256 && !memory_address_p (GET_MODE (operands[0]),
5257 XEXP (operands[0], 0)))
792760b9
RK
5258 operands[0]
5259 = replace_equiv_address (operands[0],
5260 copy_to_reg (XEXP (operands[0], 0)));
d5b7b3ae
RE
5261
5262 if (GET_CODE (operands[1]) == MEM
5895f793
RE
5263 && !memory_address_p (GET_MODE (operands[1]),
5264 XEXP (operands[1], 0)))
792760b9
RK
5265 operands[1]
5266 = replace_equiv_address (operands[1],
5267 copy_to_reg (XEXP (operands[1], 0)));
78a5d727
RE
5268
5269 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5270 {
5271 rtx reg = gen_reg_rtx (SImode);
5272
5273 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5274 operands[1] = gen_lowpart (HImode, reg);
5275 }
5276
5277 if (GET_CODE (operands[0]) == MEM)
5278 operands[1] = force_reg (HImode, operands[1]);
d5b7b3ae 5279 }
d5b7b3ae 5280 else if (GET_CODE (operands[1]) == CONST_INT
ce92b223 5281 && !satisfies_constraint_I (operands[1]))
d5b7b3ae 5282 {
78a5d727
RE
5283 /* Handle loading a large integer during reload. */
5284
d5b7b3ae
RE
5285 /* Writing a constant to memory needs a scratch, which should
5286 be handled with SECONDARY_RELOADs. */
e6d29d15 5287 gcc_assert (GET_CODE (operands[0]) == REG);
d5b7b3ae 5288
f1c25d3b 5289 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
d5b7b3ae
RE
5290 emit_insn (gen_movsi (operands[0], operands[1]));
5291 DONE;
5292 }
3a33f76f 5293 }
d5b7b3ae
RE
5294 "
5295)
5296
5b3e6663 5297(define_insn "*thumb1_movhi_insn"
f954388e
RE
5298 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5299 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
5b3e6663 5300 "TARGET_THUMB1
d5b7b3ae
RE
5301 && ( register_operand (operands[0], HImode)
5302 || register_operand (operands[1], HImode))"
5303 "*
5304 switch (which_alternative)
f57b1ad3 5305 {
d5b7b3ae
RE
5306 case 0: return \"add %0, %1, #0\";
5307 case 2: return \"strh %1, %0\";
5308 case 3: return \"mov %0, %1\";
5309 case 4: return \"mov %0, %1\";
5310 case 5: return \"mov %0, %1\";
e6d29d15 5311 default: gcc_unreachable ();
d5b7b3ae
RE
5312 case 1:
5313 /* The stack pointer can end up being taken as an index register.
5314 Catch this case here and deal with it. */
5315 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5316 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5317 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5318 {
5319 rtx ops[2];
5320 ops[0] = operands[0];
5321 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5322
5323 output_asm_insn (\"mov %0, %1\", ops);
5324
5325 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5326
5327 }
5328 return \"ldrh %0, %1\";
5329 }"
5330 [(set_attr "length" "2,4,2,2,2,2")
9b66ebb1 5331 (set_attr "type" "*,load1,store1,*,*,*")]
d5b7b3ae 5332)
f57b1ad3 5333
3a33f76f 5334
988337ca 5335(define_expand "movhi_bytes"
34757369 5336 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
988337ca 5337 (set (match_dup 3)
34757369 5338 (zero_extend:SI (match_dup 6)))
988337ca
RE
5339 (set (match_operand:SI 0 "" "")
5340 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
d5b7b3ae 5341 "TARGET_ARM"
988337ca 5342 "
5895f793
RE
5343 {
5344 rtx mem1, mem2;
5345 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5346
31fa16b6
RE
5347 mem1 = change_address (operands[1], QImode, addr);
5348 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5895f793
RE
5349 operands[0] = gen_lowpart (SImode, operands[0]);
5350 operands[1] = mem1;
5351 operands[2] = gen_reg_rtx (SImode);
5352 operands[3] = gen_reg_rtx (SImode);
5353 operands[6] = mem2;
988337ca 5354
5895f793
RE
5355 if (BYTES_BIG_ENDIAN)
5356 {
5357 operands[4] = operands[2];
5358 operands[5] = operands[3];
5359 }
5360 else
5361 {
5362 operands[4] = operands[3];
5363 operands[5] = operands[2];
5364 }
5365 }"
5366)
988337ca 5367
fe241a29
RE
5368(define_expand "movhi_bigend"
5369 [(set (match_dup 2)
5370 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5371 (const_int 16)))
5372 (set (match_dup 3)
5373 (ashiftrt:SI (match_dup 2) (const_int 16)))
5374 (set (match_operand:HI 0 "s_register_operand" "")
c9389e79 5375 (match_dup 4))]
d5b7b3ae 5376 "TARGET_ARM"
fe241a29
RE
5377 "
5378 operands[2] = gen_reg_rtx (SImode);
5379 operands[3] = gen_reg_rtx (SImode);
c9389e79 5380 operands[4] = gen_lowpart (HImode, operands[3]);
5895f793
RE
5381 "
5382)
3a33f76f 5383
05713b80 5384;; Pattern to recognize insn generated default case above
4cdb3ed4 5385(define_insn "*movhi_insn_arch4"
d5b7b3ae 5386 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
5895f793 5387 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
d5b7b3ae
RE
5388 "TARGET_ARM
5389 && arm_arch4
4cdb3ed4
RE
5390 && (GET_CODE (operands[1]) != CONST_INT
5391 || const_ok_for_arm (INTVAL (operands[1]))
5392 || const_ok_for_arm (~INTVAL (operands[1])))"
5393 "@
5394 mov%?\\t%0, %1\\t%@ movhi
5395 mvn%?\\t%0, #%B1\\t%@ movhi
5b3e6663
PB
5396 str%(h%)\\t%1, %0\\t%@ movhi
5397 ldr%(h%)\\t%0, %1\\t%@ movhi"
9b66ebb1 5398 [(set_attr "type" "*,*,store1,load1")
cca0a211 5399 (set_attr "predicable" "yes")
d5b7b3ae
RE
5400 (set_attr "pool_range" "*,*,*,256")
5401 (set_attr "neg_pool_range" "*,*,*,244")]
5402)
4cdb3ed4 5403
4cdb3ed4 5404(define_insn "*movhi_bytes"
988337ca
RE
5405 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5406 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
61f0ccff 5407 "TARGET_ARM"
988337ca
RE
5408 "@
5409 mov%?\\t%0, %1\\t%@ movhi
cca0a211
RE
5410 mvn%?\\t%0, #%B1\\t%@ movhi"
5411 [(set_attr "predicable" "yes")]
5412)
988337ca 5413
2591db65
RE
5414(define_expand "thumb_movhi_clobber"
5415 [(set (match_operand:HI 0 "memory_operand" "")
5416 (match_operand:HI 1 "register_operand" ""))
5417 (clobber (match_operand:DI 2 "register_operand" ""))]
5b3e6663 5418 "TARGET_THUMB1"
2591db65
RE
5419 "
5420 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5421 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5422 {
5423 emit_insn (gen_movhi (operands[0], operands[1]));
5424 DONE;
5425 }
5426 /* XXX Fixme, need to handle other cases here as well. */
5427 gcc_unreachable ();
5428 "
d5b7b3ae
RE
5429)
5430
f9cc092a
RE
5431;; We use a DImode scratch because we may occasionally need an additional
5432;; temporary if the address isn't offsettable -- push_reload doesn't seem
5433;; to take any notice of the "o" constraints on reload_memory_operand operand.
c1d5bfb9 5434(define_expand "reload_outhi"
d5b7b3ae 5435 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5895f793
RE
5436 (match_operand:HI 1 "s_register_operand" "r")
5437 (match_operand:DI 2 "s_register_operand" "=&l")])]
d5b7b3ae
RE
5438 "TARGET_EITHER"
5439 "if (TARGET_ARM)
5440 arm_reload_out_hi (operands);
5441 else
5442 thumb_reload_out_hi (operands);
c1d5bfb9 5443 DONE;
d5b7b3ae
RE
5444 "
5445)
c1d5bfb9 5446
988337ca
RE
5447(define_expand "reload_inhi"
5448 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
d5b7b3ae 5449 (match_operand:HI 1 "arm_reload_memory_operand" "o")
f9cc092a 5450 (match_operand:DI 2 "s_register_operand" "=&r")])]
61f0ccff 5451 "TARGET_EITHER"
988337ca 5452 "
d5b7b3ae
RE
5453 if (TARGET_ARM)
5454 arm_reload_in_hi (operands);
5455 else
5456 thumb_reload_out_hi (operands);
988337ca
RE
5457 DONE;
5458")
5459
ff9940b0
RE
5460(define_expand "movqi"
5461 [(set (match_operand:QI 0 "general_operand" "")
5462 (match_operand:QI 1 "general_operand" ""))]
d5b7b3ae 5463 "TARGET_EITHER"
ff9940b0 5464 "
78a5d727 5465 /* Everything except mem = const or mem = mem can be done easily */
b41caf7c 5466
b3a13419 5467 if (can_create_pseudo_p ())
d5b7b3ae 5468 {
78a5d727
RE
5469 if (GET_CODE (operands[1]) == CONST_INT)
5470 {
5471 rtx reg = gen_reg_rtx (SImode);
5472
5473 emit_insn (gen_movsi (reg, operands[1]));
5474 operands[1] = gen_lowpart (QImode, reg);
5475 }
d5b7b3ae 5476
78a5d727
RE
5477 if (TARGET_THUMB)
5478 {
d5b7b3ae 5479 /* ??? We shouldn't really get invalid addresses here, but this can
5895f793
RE
5480 happen if we are passed a SP (never OK for HImode/QImode) or
5481 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5482 HImode/QImode) relative address. */
d5b7b3ae
RE
5483 /* ??? This should perhaps be fixed elsewhere, for instance, in
5484 fixup_stack_1, by checking for other kinds of invalid addresses,
5485 e.g. a bare reference to a virtual register. This may confuse the
5486 alpha though, which must handle this case differently. */
5487 if (GET_CODE (operands[0]) == MEM
5895f793 5488 && !memory_address_p (GET_MODE (operands[0]),
d5b7b3ae 5489 XEXP (operands[0], 0)))
792760b9
RK
5490 operands[0]
5491 = replace_equiv_address (operands[0],
5492 copy_to_reg (XEXP (operands[0], 0)));
5895f793
RE
5493 if (GET_CODE (operands[1]) == MEM
5494 && !memory_address_p (GET_MODE (operands[1]),
d5b7b3ae 5495 XEXP (operands[1], 0)))
792760b9
RK
5496 operands[1]
5497 = replace_equiv_address (operands[1],
5498 copy_to_reg (XEXP (operands[1], 0)));
78a5d727
RE
5499 }
5500
5501 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5502 {
5503 rtx reg = gen_reg_rtx (SImode);
5504
5505 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5506 operands[1] = gen_lowpart (QImode, reg);
5507 }
5508
5509 if (GET_CODE (operands[0]) == MEM)
5510 operands[1] = force_reg (QImode, operands[1]);
5511 }
5512 else if (TARGET_THUMB
5513 && GET_CODE (operands[1]) == CONST_INT
ce92b223 5514 && !satisfies_constraint_I (operands[1]))
78a5d727 5515 {
d6b4baa4 5516 /* Handle loading a large integer during reload. */
d5b7b3ae 5517
78a5d727
RE
5518 /* Writing a constant to memory needs a scratch, which should
5519 be handled with SECONDARY_RELOADs. */
5520 gcc_assert (GET_CODE (operands[0]) == REG);
5521
5522 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5523 emit_insn (gen_movsi (operands[0], operands[1]));
5524 DONE;
d5b7b3ae
RE
5525 }
5526 "
5527)
3a33f76f 5528
ff9940b0 5529
d5b7b3ae
RE
5530(define_insn "*arm_movqi_insn"
5531 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
68df59d3 5532 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5b3e6663 5533 "TARGET_32BIT
d5b7b3ae
RE
5534 && ( register_operand (operands[0], QImode)
5535 || register_operand (operands[1], QImode))"
68df59d3
RE
5536 "@
5537 mov%?\\t%0, %1
5538 mvn%?\\t%0, #%B1
5b3e6663
PB
5539 ldr%(b%)\\t%0, %1
5540 str%(b%)\\t%1, %0"
9b66ebb1 5541 [(set_attr "type" "*,*,load1,store1")
cca0a211 5542 (set_attr "predicable" "yes")]
d5b7b3ae
RE
5543)
5544
5b3e6663 5545(define_insn "*thumb1_movqi_insn"
d5b7b3ae 5546 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5895f793 5547 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5b3e6663 5548 "TARGET_THUMB1
d5b7b3ae
RE
5549 && ( register_operand (operands[0], QImode)
5550 || register_operand (operands[1], QImode))"
5551 "@
5552 add\\t%0, %1, #0
5553 ldrb\\t%0, %1
5554 strb\\t%1, %0
5555 mov\\t%0, %1
5556 mov\\t%0, %1
5557 mov\\t%0, %1"
5558 [(set_attr "length" "2")
9b66ebb1 5559 (set_attr "type" "*,load1,store1,*,*,*")
d5b7b3ae
RE
5560 (set_attr "pool_range" "*,32,*,*,*,*")]
5561)
3a33f76f 5562
091426d3
RE
5563(define_expand "movsf"
5564 [(set (match_operand:SF 0 "general_operand" "")
5565 (match_operand:SF 1 "general_operand" ""))]
d5b7b3ae 5566 "TARGET_EITHER"
091426d3 5567 "
5b3e6663 5568 if (TARGET_32BIT)
d5b7b3ae
RE
5569 {
5570 if (GET_CODE (operands[0]) == MEM)
5571 operands[1] = force_reg (SFmode, operands[1]);
5572 }
5b3e6663 5573 else /* TARGET_THUMB1 */
d5b7b3ae 5574 {
b3a13419 5575 if (can_create_pseudo_p ())
d5b7b3ae
RE
5576 {
5577 if (GET_CODE (operands[0]) != REG)
5578 operands[1] = force_reg (SFmode, operands[1]);
5579 }
5580 }
5581 "
5582)
5583
f7657ed3
RE
5584;; Transform a floating-point move of a constant into a core register into
5585;; an SImode operation.
d5b7b3ae 5586(define_split
f7657ed3 5587 [(set (match_operand:SF 0 "arm_general_register_operand" "")
d5b7b3ae 5588 (match_operand:SF 1 "immediate_operand" ""))]
5b3e6663 5589 "TARGET_32BIT
d5b7b3ae
RE
5590 && reload_completed
5591 && GET_CODE (operands[1]) == CONST_DOUBLE"
5592 [(set (match_dup 2) (match_dup 3))]
5593 "
5594 operands[2] = gen_lowpart (SImode, operands[0]);
5595 operands[3] = gen_lowpart (SImode, operands[1]);
5596 if (operands[2] == 0 || operands[3] == 0)
5597 FAIL;
5895f793
RE
5598 "
5599)
091426d3 5600
d5b7b3ae
RE
5601(define_insn "*arm_movsf_soft_insn"
5602 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5603 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5604 "TARGET_ARM
5605 && TARGET_SOFT_FLOAT
5895f793
RE
5606 && (GET_CODE (operands[0]) != MEM
5607 || register_operand (operands[1], SFmode))"
39c0ef95
DE
5608 "@
5609 mov%?\\t%0, %1
5610 ldr%?\\t%0, %1\\t%@ float
5611 str%?\\t%1, %0\\t%@ float"
d5b7b3ae 5612 [(set_attr "length" "4,4,4")
cca0a211 5613 (set_attr "predicable" "yes")
9b66ebb1 5614 (set_attr "type" "*,load1,store1")
d5b7b3ae
RE
5615 (set_attr "pool_range" "*,4096,*")
5616 (set_attr "neg_pool_range" "*,4084,*")]
5617)
5618
5619;;; ??? This should have alternatives for constants.
5b3e6663 5620(define_insn "*thumb1_movsf_insn"
5895f793
RE
5621 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5622 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5b3e6663 5623 "TARGET_THUMB1
d5b7b3ae
RE
5624 && ( register_operand (operands[0], SFmode)
5625 || register_operand (operands[1], SFmode))"
5626 "@
5627 add\\t%0, %1, #0
5628 ldmia\\t%1, {%0}
5629 stmia\\t%0, {%1}
5630 ldr\\t%0, %1
5631 str\\t%1, %0
5632 mov\\t%0, %1
5633 mov\\t%0, %1"
5634 [(set_attr "length" "2")
9b66ebb1 5635 (set_attr "type" "*,load1,store1,load1,store1,*,*")
d5b7b3ae
RE
5636 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5637)
39c0ef95 5638
ff9940b0 5639(define_expand "movdf"
091426d3
RE
5640 [(set (match_operand:DF 0 "general_operand" "")
5641 (match_operand:DF 1 "general_operand" ""))]
d5b7b3ae 5642 "TARGET_EITHER"
ff9940b0 5643 "
5b3e6663 5644 if (TARGET_32BIT)
d5b7b3ae
RE
5645 {
5646 if (GET_CODE (operands[0]) == MEM)
5647 operands[1] = force_reg (DFmode, operands[1]);
5648 }
5649 else /* TARGET_THUMB */
5650 {
b3a13419 5651 if (can_create_pseudo_p ())
d5b7b3ae
RE
5652 {
5653 if (GET_CODE (operands[0]) != REG)
5654 operands[1] = force_reg (DFmode, operands[1]);
5655 }
5656 }
5657 "
5658)
3a33f76f 5659
ff9940b0
RE
5660;; Reloading a df mode value stored in integer regs to memory can require a
5661;; scratch reg.
5662(define_expand "reload_outdf"
d5b7b3ae 5663 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
091426d3
RE
5664 (match_operand:DF 1 "s_register_operand" "r")
5665 (match_operand:SI 2 "s_register_operand" "=&r")]
5b3e6663 5666 "TARGET_32BIT"
091426d3 5667 "
5895f793
RE
5668 {
5669 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4cdb3ed4 5670
5895f793
RE
5671 if (code == REG)
5672 operands[2] = XEXP (operands[0], 0);
5673 else if (code == POST_INC || code == PRE_DEC)
5674 {
5675 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5676 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5677 emit_insn (gen_movdi (operands[0], operands[1]));
5678 DONE;
5679 }
5680 else if (code == PRE_INC)
5681 {
5682 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4cdb3ed4 5683
5895f793
RE
5684 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5685 operands[2] = reg;
5686 }
5687 else if (code == POST_DEC)
5688 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5689 else
5690 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5691 XEXP (XEXP (operands[0], 0), 1)));
4cdb3ed4 5692
31fa16b6
RE
5693 emit_insn (gen_rtx_SET (VOIDmode,
5694 replace_equiv_address (operands[0], operands[2]),
5895f793 5695 operands[1]));
4cdb3ed4 5696
5895f793
RE
5697 if (code == POST_DEC)
5698 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5699
5700 DONE;
5701 }"
5702)
ff9940b0 5703
39c0ef95 5704(define_insn "*movdf_soft_insn"
2075b05d
RE
5705 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5706 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
ca68ea18 5707 "TARGET_ARM && TARGET_SOFT_FLOAT
d5b6e637
PB
5708 && ( register_operand (operands[0], DFmode)
5709 || register_operand (operands[1], DFmode))"
9b901d50
RE
5710 "*
5711 switch (which_alternative)
5712 {
5713 case 0:
5714 case 1:
5715 case 2:
5716 return \"#\";
5717 default:
5718 return output_move_double (operands);
5719 }
5720 "
2075b05d
RE
5721 [(set_attr "length" "8,12,16,8,8")
5722 (set_attr "type" "*,*,*,load2,store2")
0be5cf85
RE
5723 (set_attr "pool_range" "1020")
5724 (set_attr "neg_pool_range" "1008")]
d5b7b3ae
RE
5725)
5726
5727;;; ??? This should have alternatives for constants.
5728;;; ??? This was originally identical to the movdi_insn pattern.
5729;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5730;;; thumb_reorg with a memory reference.
5731(define_insn "*thumb_movdf_insn"
5895f793
RE
5732 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5733 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5b3e6663 5734 "TARGET_THUMB1
d5b7b3ae
RE
5735 && ( register_operand (operands[0], DFmode)
5736 || register_operand (operands[1], DFmode))"
5737 "*
5738 switch (which_alternative)
5739 {
5740 default:
5741 case 0:
5742 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5743 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5744 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5745 case 1:
5746 return \"ldmia\\t%1, {%0, %H0}\";
5747 case 2:
5748 return \"stmia\\t%0, {%1, %H1}\";
5749 case 3:
5750 return thumb_load_double_from_address (operands);
5751 case 4:
f1c25d3b
KH
5752 operands[2] = gen_rtx_MEM (SImode,
5753 plus_constant (XEXP (operands[0], 0), 4));
d5b7b3ae
RE
5754 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5755 return \"\";
5756 case 5:
5757 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5758 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5759 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5760 }
5761 "
5762 [(set_attr "length" "4,2,2,6,4,4")
9b66ebb1 5763 (set_attr "type" "*,load2,store2,load2,store2,*")
d5b7b3ae
RE
5764 (set_attr "pool_range" "*,*,*,1020,*,*")]
5765)
5a9335ef 5766
9f7bf991
RE
5767(define_expand "movxf"
5768 [(set (match_operand:XF 0 "general_operand" "")
5769 (match_operand:XF 1 "general_operand" ""))]
5b3e6663 5770 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
9f7bf991
RE
5771 "
5772 if (GET_CODE (operands[0]) == MEM)
5773 operands[1] = force_reg (XFmode, operands[1]);
5774 "
5775)
5776
3a33f76f 5777\f
3a33f76f 5778
ff9940b0
RE
5779;; load- and store-multiple insns
5780;; The arm can load/store any set of registers, provided that they are in
5781;; ascending order; but that is beyond GCC so stick with what it knows.
3a33f76f 5782
ff9940b0
RE
5783(define_expand "load_multiple"
5784 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5785 (match_operand:SI 1 "" ""))
5786 (use (match_operand:SI 2 "" ""))])]
5b3e6663 5787 "TARGET_32BIT"
50ed9cea
RH
5788{
5789 HOST_WIDE_INT offset = 0;
5790
48a08b9c 5791 /* Support only fixed point registers. */
ff9940b0
RE
5792 if (GET_CODE (operands[2]) != CONST_INT
5793 || INTVAL (operands[2]) > 14
5794 || INTVAL (operands[2]) < 2
5795 || GET_CODE (operands[1]) != MEM
5796 || GET_CODE (operands[0]) != REG
48a08b9c
NC
5797 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5798 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
ff9940b0
RE
5799 FAIL;
5800
5801 operands[3]
7a0a1f09
RE
5802 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5803 force_reg (SImode, XEXP (operands[1], 0)),
50ed9cea
RH
5804 TRUE, FALSE, operands[1], &offset);
5805})
3a33f76f 5806
ff9940b0
RE
5807;; Load multiple with write-back
5808
d6c5a763 5809(define_insn "*ldmsi_postinc4"
ff9940b0 5810 [(match_parallel 0 "load_multiple_operation"
24cdff34 5811 [(set (match_operand:SI 1 "s_register_operand" "=r")
b0888988 5812 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
d6c5a763
RE
5813 (const_int 16)))
5814 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5815 (mem:SI (match_dup 2)))
b0888988 5816 (set (match_operand:SI 4 "arm_hard_register_operand" "")
d6c5a763
RE
5817 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5818 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5819 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5820 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5821 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5b3e6663
PB
5822 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5823 "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
9b66ebb1 5824 [(set_attr "type" "load4")
d6c5a763
RE
5825 (set_attr "predicable" "yes")]
5826)
3a33f76f 5827
5b3e6663 5828(define_insn "*ldmsi_postinc4_thumb1"
9f7bf991
RE
5829 [(match_parallel 0 "load_multiple_operation"
5830 [(set (match_operand:SI 1 "s_register_operand" "=l")
5831 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5832 (const_int 16)))
5833 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5834 (mem:SI (match_dup 2)))
5835 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5836 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5837 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5838 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5839 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5840 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5b3e6663 5841 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
9f7bf991
RE
5842 "ldmia\\t%1!, {%3, %4, %5, %6}"
5843 [(set_attr "type" "load4")]
5844)
5845
d6c5a763
RE
5846(define_insn "*ldmsi_postinc3"
5847 [(match_parallel 0 "load_multiple_operation"
24cdff34 5848 [(set (match_operand:SI 1 "s_register_operand" "=r")
d6c5a763
RE
5849 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5850 (const_int 12)))
5851 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5852 (mem:SI (match_dup 2)))
5853 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5854 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5855 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5856 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5b3e6663
PB
5857 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5858 "ldm%(ia%)\\t%1!, {%3, %4, %5}"
9b66ebb1 5859 [(set_attr "type" "load3")
d6c5a763
RE
5860 (set_attr "predicable" "yes")]
5861)
3a33f76f 5862
d6c5a763
RE
5863(define_insn "*ldmsi_postinc2"
5864 [(match_parallel 0 "load_multiple_operation"
24cdff34 5865 [(set (match_operand:SI 1 "s_register_operand" "=r")
d6c5a763
RE
5866 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5867 (const_int 8)))
5868 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5869 (mem:SI (match_dup 2)))
5870 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5871 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5b3e6663
PB
5872 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5873 "ldm%(ia%)\\t%1!, {%3, %4}"
9b66ebb1 5874 [(set_attr "type" "load2")
cca0a211
RE
5875 (set_attr "predicable" "yes")]
5876)
3a33f76f 5877
ff9940b0 5878;; Ordinary load multiple
3a33f76f 5879
d6c5a763 5880(define_insn "*ldmsi4"
ff9940b0 5881 [(match_parallel 0 "load_multiple_operation"
d6c5a763
RE
5882 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5883 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5884 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5885 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5886 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5887 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5888 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5889 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5b3e6663
PB
5890 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5891 "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
9b66ebb1 5892 [(set_attr "type" "load4")
d6c5a763
RE
5893 (set_attr "predicable" "yes")]
5894)
ff9940b0 5895
d6c5a763
RE
5896(define_insn "*ldmsi3"
5897 [(match_parallel 0 "load_multiple_operation"
5898 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5899 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5900 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5901 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5902 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5903 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5b3e6663
PB
5904 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5905 "ldm%(ia%)\\t%1, {%2, %3, %4}"
9b66ebb1 5906 [(set_attr "type" "load3")
d6c5a763
RE
5907 (set_attr "predicable" "yes")]
5908)
ff9940b0 5909
d6c5a763
RE
5910(define_insn "*ldmsi2"
5911 [(match_parallel 0 "load_multiple_operation"
5912 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5913 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5914 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5915 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5b3e6663
PB
5916 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
5917 "ldm%(ia%)\\t%1, {%2, %3}"
9b66ebb1 5918 [(set_attr "type" "load2")
cca0a211
RE
5919 (set_attr "predicable" "yes")]
5920)
ff9940b0
RE
5921
5922(define_expand "store_multiple"
5923 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5924 (match_operand:SI 1 "" ""))
5925 (use (match_operand:SI 2 "" ""))])]
5b3e6663 5926 "TARGET_32BIT"
50ed9cea
RH
5927{
5928 HOST_WIDE_INT offset = 0;
5929
d6b4baa4 5930 /* Support only fixed point registers. */
ff9940b0
RE
5931 if (GET_CODE (operands[2]) != CONST_INT
5932 || INTVAL (operands[2]) > 14
5933 || INTVAL (operands[2]) < 2
5934 || GET_CODE (operands[1]) != REG
5935 || GET_CODE (operands[0]) != MEM
48a08b9c
NC
5936 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5937 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
ff9940b0
RE
5938 FAIL;
5939
5940 operands[3]
7a0a1f09
RE
5941 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5942 force_reg (SImode, XEXP (operands[0], 0)),
50ed9cea
RH
5943 TRUE, FALSE, operands[0], &offset);
5944})
3a33f76f 5945
ff9940b0
RE
5946;; Store multiple with write-back
5947
d6c5a763 5948(define_insn "*stmsi_postinc4"
ff9940b0 5949 [(match_parallel 0 "store_multiple_operation"
24cdff34 5950 [(set (match_operand:SI 1 "s_register_operand" "=r")
b0888988 5951 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
d6c5a763 5952 (const_int 16)))
b0888988 5953 (set (mem:SI (match_dup 2))
d6c5a763
RE
5954 (match_operand:SI 3 "arm_hard_register_operand" ""))
5955 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5956 (match_operand:SI 4 "arm_hard_register_operand" ""))
5957 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5958 (match_operand:SI 5 "arm_hard_register_operand" ""))
5959 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5960 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5b3e6663
PB
5961 "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5962 "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
d6c5a763
RE
5963 [(set_attr "predicable" "yes")
5964 (set_attr "type" "store4")]
5965)
3a33f76f 5966
5b3e6663 5967(define_insn "*stmsi_postinc4_thumb1"
9f7bf991
RE
5968 [(match_parallel 0 "store_multiple_operation"
5969 [(set (match_operand:SI 1 "s_register_operand" "=l")
5970 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5971 (const_int 16)))
5972 (set (mem:SI (match_dup 2))
5973 (match_operand:SI 3 "arm_hard_register_operand" ""))
5974 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5975 (match_operand:SI 4 "arm_hard_register_operand" ""))
5976 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5977 (match_operand:SI 5 "arm_hard_register_operand" ""))
5978 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5979 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5b3e6663 5980 "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
9f7bf991
RE
5981 "stmia\\t%1!, {%3, %4, %5, %6}"
5982 [(set_attr "type" "store4")]
5983)
5984
d6c5a763
RE
5985(define_insn "*stmsi_postinc3"
5986 [(match_parallel 0 "store_multiple_operation"
24cdff34 5987 [(set (match_operand:SI 1 "s_register_operand" "=r")
d6c5a763
RE
5988 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5989 (const_int 12)))
5990 (set (mem:SI (match_dup 2))
5991 (match_operand:SI 3 "arm_hard_register_operand" ""))
5992 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5993 (match_operand:SI 4 "arm_hard_register_operand" ""))
5994 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5995 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5b3e6663
PB
5996 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5997 "stm%(ia%)\\t%1!, {%3, %4, %5}"
d6c5a763
RE
5998 [(set_attr "predicable" "yes")
5999 (set_attr "type" "store3")]
6000)
ff9940b0 6001
d6c5a763
RE
6002(define_insn "*stmsi_postinc2"
6003 [(match_parallel 0 "store_multiple_operation"
24cdff34 6004 [(set (match_operand:SI 1 "s_register_operand" "=r")
d6c5a763
RE
6005 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6006 (const_int 8)))
6007 (set (mem:SI (match_dup 2))
6008 (match_operand:SI 3 "arm_hard_register_operand" ""))
6009 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6010 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6011 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6012 "stm%(ia%)\\t%1!, {%3, %4}"
cca0a211 6013 [(set_attr "predicable" "yes")
d6c5a763 6014 (set_attr "type" "store2")]
d5b7b3ae 6015)
ff9940b0
RE
6016
6017;; Ordinary store multiple
6018
d6c5a763 6019(define_insn "*stmsi4"
ff9940b0 6020 [(match_parallel 0 "store_multiple_operation"
b0888988 6021 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
d6c5a763
RE
6022 (match_operand:SI 2 "arm_hard_register_operand" ""))
6023 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6024 (match_operand:SI 3 "arm_hard_register_operand" ""))
6025 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6026 (match_operand:SI 4 "arm_hard_register_operand" ""))
6027 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6028 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6029 "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6030 "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
d6c5a763
RE
6031 [(set_attr "predicable" "yes")
6032 (set_attr "type" "store4")]
6033)
ff9940b0 6034
d6c5a763
RE
6035(define_insn "*stmsi3"
6036 [(match_parallel 0 "store_multiple_operation"
6037 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6038 (match_operand:SI 2 "arm_hard_register_operand" ""))
6039 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6040 (match_operand:SI 3 "arm_hard_register_operand" ""))
6041 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6042 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6043 "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6044 "stm%(ia%)\\t%1, {%2, %3, %4}"
d6c5a763
RE
6045 [(set_attr "predicable" "yes")
6046 (set_attr "type" "store3")]
6047)
ff9940b0 6048
d6c5a763
RE
6049(define_insn "*stmsi2"
6050 [(match_parallel 0 "store_multiple_operation"
6051 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6052 (match_operand:SI 2 "arm_hard_register_operand" ""))
6053 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6054 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5b3e6663
PB
6055 "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6056 "stm%(ia%)\\t%1, {%2, %3}"
cca0a211 6057 [(set_attr "predicable" "yes")
d6c5a763 6058 (set_attr "type" "store2")]
d5b7b3ae 6059)
ff9940b0
RE
6060
6061;; Move a block of memory if it is word aligned and MORE than 2 words long.
6062;; We could let this apply for blocks of less than this, but it clobbers so
6063;; many registers that there is then probably a better way.
6064
70128ad9 6065(define_expand "movmemqi"
0bdece8a
RE
6066 [(match_operand:BLK 0 "general_operand" "")
6067 (match_operand:BLK 1 "general_operand" "")
6068 (match_operand:SI 2 "const_int_operand" "")
6069 (match_operand:SI 3 "const_int_operand" "")]
d5b7b3ae 6070 "TARGET_EITHER"
ff9940b0 6071 "
5b3e6663 6072 if (TARGET_32BIT)
d5b7b3ae 6073 {
70128ad9 6074 if (arm_gen_movmemqi (operands))
d5b7b3ae
RE
6075 DONE;
6076 FAIL;
6077 }
5b3e6663 6078 else /* TARGET_THUMB1 */
d5b7b3ae
RE
6079 {
6080 if ( INTVAL (operands[3]) != 4
6081 || INTVAL (operands[2]) > 48)
6082 FAIL;
6083
70128ad9 6084 thumb_expand_movmemqi (operands);
d5b7b3ae
RE
6085 DONE;
6086 }
6087 "
6088)
6089
d6c5a763 6090;; Thumb block-move insns
d5b7b3ae
RE
6091
6092(define_insn "movmem12b"
ca356f3a
RE
6093 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6094 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6095 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6096 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6097 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6098 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6099 (set (match_operand:SI 0 "register_operand" "=l")
6100 (plus:SI (match_dup 2) (const_int 12)))
6101 (set (match_operand:SI 1 "register_operand" "=l")
6102 (plus:SI (match_dup 3) (const_int 12)))
6103 (clobber (match_scratch:SI 4 "=&l"))
6104 (clobber (match_scratch:SI 5 "=&l"))
6105 (clobber (match_scratch:SI 6 "=&l"))]
5b3e6663 6106 "TARGET_THUMB1"
d5b7b3ae
RE
6107 "* return thumb_output_move_mem_multiple (3, operands);"
6108 [(set_attr "length" "4")
5895f793
RE
6109 ; This isn't entirely accurate... It loads as well, but in terms of
6110 ; scheduling the following insn it is better to consider it as a store
d5b7b3ae
RE
6111 (set_attr "type" "store3")]
6112)
6113
6114(define_insn "movmem8b"
ca356f3a
RE
6115 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6116 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6117 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6118 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6119 (set (match_operand:SI 0 "register_operand" "=l")
6120 (plus:SI (match_dup 2) (const_int 8)))
6121 (set (match_operand:SI 1 "register_operand" "=l")
6122 (plus:SI (match_dup 3) (const_int 8)))
6123 (clobber (match_scratch:SI 4 "=&l"))
6124 (clobber (match_scratch:SI 5 "=&l"))]
5b3e6663 6125 "TARGET_THUMB1"
d5b7b3ae
RE
6126 "* return thumb_output_move_mem_multiple (2, operands);"
6127 [(set_attr "length" "4")
5895f793
RE
6128 ; This isn't entirely accurate... It loads as well, but in terms of
6129 ; scheduling the following insn it is better to consider it as a store
d5b7b3ae
RE
6130 (set_attr "type" "store2")]
6131)
6132
ff9940b0 6133\f
3a33f76f 6134
6c98269c 6135;; Compare & branch insns
9a9f7594 6136;; The range calculations are based as follows:
6c98269c
RE
6137;; For forward branches, the address calculation returns the address of
6138;; the next instruction. This is 2 beyond the branch instruction.
6139;; For backward branches, the address calculation returns the address of
6140;; the first instruction in this pattern (cmp). This is 2 before the branch
6141;; instruction for the shortest sequence, and 4 before the branch instruction
6142;; if we have to jump around an unconditional branch.
6143;; To the basic branch range the PC offset must be added (this is +4).
6144;; So for forward branches we have
6145;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6146;; And for backward branches we have
6147;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6148;;
6149;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6150;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
d5b7b3ae 6151
c769a35d
RE
6152(define_expand "cbranchsi4"
6153 [(set (pc) (if_then_else
6154 (match_operator 0 "arm_comparison_operator"
6155 [(match_operand:SI 1 "s_register_operand" "")
6156 (match_operand:SI 2 "nonmemory_operand" "")])
6157 (label_ref (match_operand 3 "" ""))
6158 (pc)))]
5b3e6663 6159 "TARGET_THUMB1"
c769a35d 6160 "
5b3e6663 6161 if (thumb1_cmpneg_operand (operands[2], SImode))
c769a35d
RE
6162 {
6163 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6164 operands[3], operands[0]));
6165 DONE;
6166 }
5b3e6663 6167 if (!thumb1_cmp_operand (operands[2], SImode))
c769a35d
RE
6168 operands[2] = force_reg (SImode, operands[2]);
6169 ")
6170
6171(define_insn "*cbranchsi4_insn"
6172 [(set (pc) (if_then_else
6173 (match_operator 0 "arm_comparison_operator"
6174 [(match_operand:SI 1 "s_register_operand" "l,*h")
5b3e6663 6175 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
c769a35d
RE
6176 (label_ref (match_operand 3 "" ""))
6177 (pc)))]
5b3e6663 6178 "TARGET_THUMB1"
d5b7b3ae
RE
6179 "*
6180 output_asm_insn (\"cmp\\t%1, %2\", operands);
c769a35d 6181
d5b7b3ae
RE
6182 switch (get_attr_length (insn))
6183 {
6184 case 4: return \"b%d0\\t%l3\";
6185 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6186 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6187 }
6188 "
6189 [(set (attr "far_jump")
6190 (if_then_else
6191 (eq_attr "length" "8")
6192 (const_string "yes")
6193 (const_string "no")))
6194 (set (attr "length")
6195 (if_then_else
6196 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6197 (le (minus (match_dup 3) (pc)) (const_int 256)))
6198 (const_int 4)
6199 (if_then_else
6200 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6c98269c 6201 (le (minus (match_dup 3) (pc)) (const_int 2048)))
d5b7b3ae
RE
6202 (const_int 6)
6203 (const_int 8))))]
6204)
6205
c769a35d
RE
6206(define_insn "cbranchsi4_scratch"
6207 [(set (pc) (if_then_else
6208 (match_operator 4 "arm_comparison_operator"
6209 [(match_operand:SI 1 "s_register_operand" "l,0")
5b3e6663 6210 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
c769a35d
RE
6211 (label_ref (match_operand 3 "" ""))
6212 (pc)))
6213 (clobber (match_scratch:SI 0 "=l,l"))]
5b3e6663 6214 "TARGET_THUMB1"
c769a35d
RE
6215 "*
6216 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6217
6218 switch (get_attr_length (insn))
6219 {
6220 case 4: return \"b%d4\\t%l3\";
6221 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6222 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6223 }
6224 "
6225 [(set (attr "far_jump")
6226 (if_then_else
6227 (eq_attr "length" "8")
6228 (const_string "yes")
6229 (const_string "no")))
6230 (set (attr "length")
6231 (if_then_else
6232 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6233 (le (minus (match_dup 3) (pc)) (const_int 256)))
6234 (const_int 4)
6235 (if_then_else
6236 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6237 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6238 (const_int 6)
6239 (const_int 8))))]
6240)
6241(define_insn "*movsi_cbranchsi4"
6242 [(set (pc)
6243 (if_then_else
6244 (match_operator 3 "arm_comparison_operator"
6245 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6246 (const_int 0)])
6247 (label_ref (match_operand 2 "" ""))
6248 (pc)))
6249 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6250 (match_dup 1))]
5b3e6663 6251 "TARGET_THUMB1"
c769a35d
RE
6252 "*{
6253 if (which_alternative == 0)
6254 output_asm_insn (\"cmp\t%0, #0\", operands);
6255 else if (which_alternative == 1)
6256 output_asm_insn (\"sub\t%0, %1, #0\", operands);
6257 else
6258 {
6259 output_asm_insn (\"cmp\t%1, #0\", operands);
6260 if (which_alternative == 2)
6261 output_asm_insn (\"mov\t%0, %1\", operands);
6262 else
6263 output_asm_insn (\"str\t%1, %0\", operands);
6264 }
6265 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6266 {
6267 case 4: return \"b%d3\\t%l2\";
6268 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6269 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6270 }
6271 }"
6272 [(set (attr "far_jump")
6273 (if_then_else
6274 (ior (and (gt (symbol_ref ("which_alternative"))
6275 (const_int 1))
6276 (eq_attr "length" "8"))
6277 (eq_attr "length" "10"))
6278 (const_string "yes")
6279 (const_string "no")))
6280 (set (attr "length")
6281 (if_then_else
6282 (le (symbol_ref ("which_alternative"))
6283 (const_int 1))
6284 (if_then_else
6285 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6286 (le (minus (match_dup 2) (pc)) (const_int 256)))
6287 (const_int 4)
6288 (if_then_else
6289 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6290 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6291 (const_int 6)
6292 (const_int 8)))
6293 (if_then_else
6294 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6295 (le (minus (match_dup 2) (pc)) (const_int 256)))
6296 (const_int 6)
6297 (if_then_else
6298 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6299 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6300 (const_int 8)
6301 (const_int 10)))))]
6302)
6303
d5b7b3ae
RE
6304(define_insn "*negated_cbranchsi4"
6305 [(set (pc)
6306 (if_then_else
1ac3e311 6307 (match_operator 0 "equality_operator"
c769a35d
RE
6308 [(match_operand:SI 1 "s_register_operand" "l")
6309 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6310 (label_ref (match_operand 3 "" ""))
5895f793 6311 (pc)))]
5b3e6663 6312 "TARGET_THUMB1"
d5b7b3ae
RE
6313 "*
6314 output_asm_insn (\"cmn\\t%1, %2\", operands);
6315 switch (get_attr_length (insn))
6316 {
6317 case 4: return \"b%d0\\t%l3\";
6318 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6319 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6320 }
6321 "
6322 [(set (attr "far_jump")
6323 (if_then_else
6324 (eq_attr "length" "8")
6325 (const_string "yes")
6326 (const_string "no")))
6327 (set (attr "length")
6328 (if_then_else
6329 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6c98269c 6330 (le (minus (match_dup 3) (pc)) (const_int 256)))
d5b7b3ae
RE
6331 (const_int 4)
6332 (if_then_else
6c98269c
RE
6333 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6334 (le (minus (match_dup 3) (pc)) (const_int 2048)))
d5b7b3ae
RE
6335 (const_int 6)
6336 (const_int 8))))]
6337)
6338
defc0463
RE
6339(define_insn "*tbit_cbranch"
6340 [(set (pc)
6341 (if_then_else
6342 (match_operator 0 "equality_operator"
6343 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6344 (const_int 1)
6345 (match_operand:SI 2 "const_int_operand" "i"))
6346 (const_int 0)])
6347 (label_ref (match_operand 3 "" ""))
6348 (pc)))
6349 (clobber (match_scratch:SI 4 "=l"))]
5b3e6663 6350 "TARGET_THUMB1"
defc0463
RE
6351 "*
6352 {
6353 rtx op[3];
6354 op[0] = operands[4];
6355 op[1] = operands[1];
6356 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6357
f9fa4363
RE
6358 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6359 switch (get_attr_length (insn))
6360 {
6361 case 4: return \"b%d0\\t%l3\";
6362 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6363 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6364 }
6365 }"
6366 [(set (attr "far_jump")
6367 (if_then_else
6368 (eq_attr "length" "8")
6369 (const_string "yes")
6370 (const_string "no")))
6371 (set (attr "length")
6372 (if_then_else
6373 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6374 (le (minus (match_dup 3) (pc)) (const_int 256)))
6375 (const_int 4)
6376 (if_then_else
6377 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6378 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6379 (const_int 6)
6380 (const_int 8))))]
6381)
6382
6383(define_insn "*tlobits_cbranch"
6384 [(set (pc)
6385 (if_then_else
6386 (match_operator 0 "equality_operator"
6387 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6388 (match_operand:SI 2 "const_int_operand" "i")
6389 (const_int 0))
6390 (const_int 0)])
6391 (label_ref (match_operand 3 "" ""))
6392 (pc)))
6393 (clobber (match_scratch:SI 4 "=l"))]
5b3e6663 6394 "TARGET_THUMB1"
f9fa4363
RE
6395 "*
6396 {
6397 rtx op[3];
6398 op[0] = operands[4];
6399 op[1] = operands[1];
6400 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6401
defc0463
RE
6402 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6403 switch (get_attr_length (insn))
6404 {
6405 case 4: return \"b%d0\\t%l3\";
6406 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6407 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6408 }
6409 }"
6410 [(set (attr "far_jump")
6411 (if_then_else
6412 (eq_attr "length" "8")
6413 (const_string "yes")
6414 (const_string "no")))
6415 (set (attr "length")
6416 (if_then_else
6417 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6418 (le (minus (match_dup 3) (pc)) (const_int 256)))
6419 (const_int 4)
6420 (if_then_else
6421 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6422 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6423 (const_int 6)
6424 (const_int 8))))]
6425)
6426
c769a35d 6427(define_insn "*tstsi3_cbranch"
defc0463
RE
6428 [(set (pc)
6429 (if_then_else
c769a35d
RE
6430 (match_operator 3 "equality_operator"
6431 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6432 (match_operand:SI 1 "s_register_operand" "l"))
defc0463 6433 (const_int 0)])
c769a35d
RE
6434 (label_ref (match_operand 2 "" ""))
6435 (pc)))]
5b3e6663 6436 "TARGET_THUMB1"
defc0463
RE
6437 "*
6438 {
c769a35d 6439 output_asm_insn (\"tst\\t%0, %1\", operands);
defc0463
RE
6440 switch (get_attr_length (insn))
6441 {
c769a35d
RE
6442 case 4: return \"b%d3\\t%l2\";
6443 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6444 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
defc0463
RE
6445 }
6446 }"
6447 [(set (attr "far_jump")
6448 (if_then_else
6449 (eq_attr "length" "8")
6450 (const_string "yes")
6451 (const_string "no")))
6452 (set (attr "length")
6453 (if_then_else
c769a35d
RE
6454 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6455 (le (minus (match_dup 2) (pc)) (const_int 256)))
defc0463
RE
6456 (const_int 4)
6457 (if_then_else
c769a35d
RE
6458 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6459 (le (minus (match_dup 2) (pc)) (const_int 2048)))
defc0463
RE
6460 (const_int 6)
6461 (const_int 8))))]
6462)
6463
6464(define_insn "*andsi3_cbranch"
6465 [(set (pc)
6466 (if_then_else
6467 (match_operator 5 "equality_operator"
6468 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6469 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6470 (const_int 0)])
6471 (label_ref (match_operand 4 "" ""))
6472 (pc)))
c769a35d 6473 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
defc0463
RE
6474 (and:SI (match_dup 2) (match_dup 3)))
6475 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 6476 "TARGET_THUMB1"
defc0463
RE
6477 "*
6478 {
6479 if (which_alternative == 0)
6480 output_asm_insn (\"and\\t%0, %3\", operands);
6481 else if (which_alternative == 1)
6482 {
6483 output_asm_insn (\"and\\t%1, %3\", operands);
6484 output_asm_insn (\"mov\\t%0, %1\", operands);
6485 }
6486 else
6487 {
6488 output_asm_insn (\"and\\t%1, %3\", operands);
6489 output_asm_insn (\"str\\t%1, %0\", operands);
6490 }
6491
6492 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6493 {
6494 case 4: return \"b%d5\\t%l4\";
6495 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6496 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6497 }
6498 }"
6499 [(set (attr "far_jump")
6500 (if_then_else
6501 (ior (and (eq (symbol_ref ("which_alternative"))
6502 (const_int 0))
6503 (eq_attr "length" "8"))
6504 (eq_attr "length" "10"))
6505 (const_string "yes")
6506 (const_string "no")))
6507 (set (attr "length")
6508 (if_then_else
6509 (eq (symbol_ref ("which_alternative"))
6510 (const_int 0))
6511 (if_then_else
6512 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6513 (le (minus (match_dup 4) (pc)) (const_int 256)))
6514 (const_int 4)
6515 (if_then_else
6516 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6517 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6518 (const_int 6)
6519 (const_int 8)))
6520 (if_then_else
6521 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6522 (le (minus (match_dup 4) (pc)) (const_int 256)))
6523 (const_int 6)
6524 (if_then_else
6525 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6526 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6527 (const_int 8)
6528 (const_int 10)))))]
6529)
6530
6531(define_insn "*orrsi3_cbranch_scratch"
6532 [(set (pc)
6533 (if_then_else
6534 (match_operator 4 "equality_operator"
6535 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6536 (match_operand:SI 2 "s_register_operand" "l"))
6537 (const_int 0)])
6538 (label_ref (match_operand 3 "" ""))
6539 (pc)))
6540 (clobber (match_scratch:SI 0 "=l"))]
5b3e6663 6541 "TARGET_THUMB1"
defc0463
RE
6542 "*
6543 {
6544 output_asm_insn (\"orr\\t%0, %2\", operands);
6545 switch (get_attr_length (insn))
6546 {
6547 case 4: return \"b%d4\\t%l3\";
6548 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6549 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6550 }
6551 }"
6552 [(set (attr "far_jump")
6553 (if_then_else
6554 (eq_attr "length" "8")
6555 (const_string "yes")
6556 (const_string "no")))
6557 (set (attr "length")
6558 (if_then_else
6559 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6560 (le (minus (match_dup 3) (pc)) (const_int 256)))
6561 (const_int 4)
6562 (if_then_else
6563 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6564 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6565 (const_int 6)
6566 (const_int 8))))]
6567)
6568
6569(define_insn "*orrsi3_cbranch"
6570 [(set (pc)
6571 (if_then_else
6572 (match_operator 5 "equality_operator"
6573 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6574 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6575 (const_int 0)])
6576 (label_ref (match_operand 4 "" ""))
6577 (pc)))
c769a35d 6578 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
defc0463
RE
6579 (ior:SI (match_dup 2) (match_dup 3)))
6580 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 6581 "TARGET_THUMB1"
defc0463
RE
6582 "*
6583 {
6584 if (which_alternative == 0)
6585 output_asm_insn (\"orr\\t%0, %3\", operands);
6586 else if (which_alternative == 1)
6587 {
6588 output_asm_insn (\"orr\\t%1, %3\", operands);
6589 output_asm_insn (\"mov\\t%0, %1\", operands);
6590 }
6591 else
6592 {
6593 output_asm_insn (\"orr\\t%1, %3\", operands);
6594 output_asm_insn (\"str\\t%1, %0\", operands);
6595 }
6596
6597 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6598 {
6599 case 4: return \"b%d5\\t%l4\";
6600 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6601 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6602 }
6603 }"
6604 [(set (attr "far_jump")
6605 (if_then_else
6606 (ior (and (eq (symbol_ref ("which_alternative"))
6607 (const_int 0))
6608 (eq_attr "length" "8"))
6609 (eq_attr "length" "10"))
6610 (const_string "yes")
6611 (const_string "no")))
6612 (set (attr "length")
6613 (if_then_else
6614 (eq (symbol_ref ("which_alternative"))
6615 (const_int 0))
6616 (if_then_else
6617 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6618 (le (minus (match_dup 4) (pc)) (const_int 256)))
6619 (const_int 4)
6620 (if_then_else
6621 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6622 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6623 (const_int 6)
6624 (const_int 8)))
6625 (if_then_else
6626 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6627 (le (minus (match_dup 4) (pc)) (const_int 256)))
6628 (const_int 6)
6629 (if_then_else
6630 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6631 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6632 (const_int 8)
6633 (const_int 10)))))]
6634)
6635
6636(define_insn "*xorsi3_cbranch_scratch"
6637 [(set (pc)
6638 (if_then_else
6639 (match_operator 4 "equality_operator"
6640 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6641 (match_operand:SI 2 "s_register_operand" "l"))
6642 (const_int 0)])
6643 (label_ref (match_operand 3 "" ""))
6644 (pc)))
6645 (clobber (match_scratch:SI 0 "=l"))]
5b3e6663 6646 "TARGET_THUMB1"
defc0463
RE
6647 "*
6648 {
6649 output_asm_insn (\"eor\\t%0, %2\", operands);
6650 switch (get_attr_length (insn))
6651 {
6652 case 4: return \"b%d4\\t%l3\";
6653 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6654 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6655 }
6656 }"
6657 [(set (attr "far_jump")
6658 (if_then_else
6659 (eq_attr "length" "8")
6660 (const_string "yes")
6661 (const_string "no")))
6662 (set (attr "length")
6663 (if_then_else
6664 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6665 (le (minus (match_dup 3) (pc)) (const_int 256)))
6666 (const_int 4)
6667 (if_then_else
6668 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6669 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6670 (const_int 6)
6671 (const_int 8))))]
6672)
6673
6674(define_insn "*xorsi3_cbranch"
6675 [(set (pc)
6676 (if_then_else
6677 (match_operator 5 "equality_operator"
6678 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6679 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6680 (const_int 0)])
6681 (label_ref (match_operand 4 "" ""))
6682 (pc)))
c769a35d 6683 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
defc0463
RE
6684 (xor:SI (match_dup 2) (match_dup 3)))
6685 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 6686 "TARGET_THUMB1"
defc0463
RE
6687 "*
6688 {
6689 if (which_alternative == 0)
6690 output_asm_insn (\"eor\\t%0, %3\", operands);
6691 else if (which_alternative == 1)
6692 {
6693 output_asm_insn (\"eor\\t%1, %3\", operands);
6694 output_asm_insn (\"mov\\t%0, %1\", operands);
6695 }
6696 else
6697 {
6698 output_asm_insn (\"eor\\t%1, %3\", operands);
6699 output_asm_insn (\"str\\t%1, %0\", operands);
6700 }
6701
6702 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6703 {
6704 case 4: return \"b%d5\\t%l4\";
6705 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6706 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6707 }
6708 }"
6709 [(set (attr "far_jump")
6710 (if_then_else
6711 (ior (and (eq (symbol_ref ("which_alternative"))
6712 (const_int 0))
6713 (eq_attr "length" "8"))
6714 (eq_attr "length" "10"))
6715 (const_string "yes")
6716 (const_string "no")))
6717 (set (attr "length")
6718 (if_then_else
6719 (eq (symbol_ref ("which_alternative"))
6720 (const_int 0))
6721 (if_then_else
6722 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6723 (le (minus (match_dup 4) (pc)) (const_int 256)))
6724 (const_int 4)
6725 (if_then_else
6726 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6727 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6728 (const_int 6)
6729 (const_int 8)))
6730 (if_then_else
6731 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6732 (le (minus (match_dup 4) (pc)) (const_int 256)))
6733 (const_int 6)
6734 (if_then_else
6735 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6736 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6737 (const_int 8)
6738 (const_int 10)))))]
6739)
6740
c769a35d
RE
6741(define_insn "*bicsi3_cbranch_scratch"
6742 [(set (pc)
6743 (if_then_else
6744 (match_operator 4 "equality_operator"
6745 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6746 (match_operand:SI 1 "s_register_operand" "0"))
6747 (const_int 0)])
6748 (label_ref (match_operand 3 "" ""))
6749 (pc)))
6750 (clobber (match_scratch:SI 0 "=l"))]
5b3e6663 6751 "TARGET_THUMB1"
c769a35d
RE
6752 "*
6753 {
6754 output_asm_insn (\"bic\\t%0, %2\", operands);
6755 switch (get_attr_length (insn))
6756 {
6757 case 4: return \"b%d4\\t%l3\";
6758 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6759 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6760 }
6761 }"
6762 [(set (attr "far_jump")
6763 (if_then_else
6764 (eq_attr "length" "8")
6765 (const_string "yes")
6766 (const_string "no")))
6767 (set (attr "length")
6768 (if_then_else
6769 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6770 (le (minus (match_dup 3) (pc)) (const_int 256)))
6771 (const_int 4)
6772 (if_then_else
6773 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6774 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6775 (const_int 6)
6776 (const_int 8))))]
6777)
6778
6779(define_insn "*bicsi3_cbranch"
6780 [(set (pc)
6781 (if_then_else
6782 (match_operator 5 "equality_operator"
e1d2bd1e
RE
6783 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6784 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
c769a35d
RE
6785 (const_int 0)])
6786 (label_ref (match_operand 4 "" ""))
6787 (pc)))
e1d2bd1e 6788 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
c769a35d 6789 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
e1d2bd1e 6790 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
5b3e6663 6791 "TARGET_THUMB1"
c769a35d
RE
6792 "*
6793 {
6794 if (which_alternative == 0)
6795 output_asm_insn (\"bic\\t%0, %3\", operands);
e1d2bd1e 6796 else if (which_alternative <= 2)
c769a35d
RE
6797 {
6798 output_asm_insn (\"bic\\t%1, %3\", operands);
e1d2bd1e
RE
6799 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6800 conditions again, since we're only testing for equality. */
c769a35d
RE
6801 output_asm_insn (\"mov\\t%0, %1\", operands);
6802 }
6803 else
6804 {
6805 output_asm_insn (\"bic\\t%1, %3\", operands);
6806 output_asm_insn (\"str\\t%1, %0\", operands);
6807 }
6808
6809 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6810 {
6811 case 4: return \"b%d5\\t%l4\";
6812 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6813 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6814 }
6815 }"
6816 [(set (attr "far_jump")
6817 (if_then_else
6818 (ior (and (eq (symbol_ref ("which_alternative"))
6819 (const_int 0))
6820 (eq_attr "length" "8"))
6821 (eq_attr "length" "10"))
6822 (const_string "yes")
6823 (const_string "no")))
6824 (set (attr "length")
6825 (if_then_else
6826 (eq (symbol_ref ("which_alternative"))
6827 (const_int 0))
6828 (if_then_else
6829 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6830 (le (minus (match_dup 4) (pc)) (const_int 256)))
6831 (const_int 4)
6832 (if_then_else
6833 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6834 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6835 (const_int 6)
6836 (const_int 8)))
6837 (if_then_else
6838 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6839 (le (minus (match_dup 4) (pc)) (const_int 256)))
6840 (const_int 6)
6841 (if_then_else
6842 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6843 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6844 (const_int 8)
6845 (const_int 10)))))]
6846)
6847
f9b9980e
RE
6848(define_insn "*cbranchne_decr1"
6849 [(set (pc)
6850 (if_then_else (match_operator 3 "equality_operator"
6851 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6852 (const_int 0)])
6853 (label_ref (match_operand 4 "" ""))
6854 (pc)))
c769a35d 6855 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
f9b9980e
RE
6856 (plus:SI (match_dup 2) (const_int -1)))
6857 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 6858 "TARGET_THUMB1"
f9b9980e
RE
6859 "*
6860 {
6861 rtx cond[2];
6862 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6863 ? GEU : LTU),
defc0463 6864 VOIDmode, operands[2], const1_rtx);
f9b9980e
RE
6865 cond[1] = operands[4];
6866
6867 if (which_alternative == 0)
6868 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6869 else if (which_alternative == 1)
6870 {
6871 /* We must provide an alternative for a hi reg because reload
6872 cannot handle output reloads on a jump instruction, but we
6873 can't subtract into that. Fortunately a mov from lo to hi
6874 does not clobber the condition codes. */
6875 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6876 output_asm_insn (\"mov\\t%0, %1\", operands);
6877 }
6878 else
6879 {
6880 /* Similarly, but the target is memory. */
6881 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6882 output_asm_insn (\"str\\t%1, %0\", operands);
6883 }
6884
6885 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6886 {
6887 case 4:
91de08c3 6888 output_asm_insn (\"b%d0\\t%l1\", cond);
f9b9980e
RE
6889 return \"\";
6890 case 6:
91de08c3 6891 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
f9b9980e
RE
6892 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6893 default:
91de08c3 6894 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
f9b9980e
RE
6895 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6896 }
6897 }
6898 "
6899 [(set (attr "far_jump")
6900 (if_then_else
6901 (ior (and (eq (symbol_ref ("which_alternative"))
6902 (const_int 0))
6903 (eq_attr "length" "8"))
6904 (eq_attr "length" "10"))
6905 (const_string "yes")
6906 (const_string "no")))
6907 (set_attr_alternative "length"
6908 [
6909 ;; Alternative 0
6910 (if_then_else
6911 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6912 (le (minus (match_dup 4) (pc)) (const_int 256)))
6913 (const_int 4)
6914 (if_then_else
6915 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6916 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6917 (const_int 6)
6918 (const_int 8)))
6919 ;; Alternative 1
6920 (if_then_else
6921 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6922 (le (minus (match_dup 4) (pc)) (const_int 256)))
6923 (const_int 6)
6924 (if_then_else
6925 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6926 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6927 (const_int 8)
6928 (const_int 10)))
6929 ;; Alternative 2
6930 (if_then_else
6931 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6932 (le (minus (match_dup 4) (pc)) (const_int 256)))
6933 (const_int 6)
6934 (if_then_else
6935 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6936 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6937 (const_int 8)
6938 (const_int 10)))
6939 ;; Alternative 3
6940 (if_then_else
6941 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6942 (le (minus (match_dup 4) (pc)) (const_int 256)))
6943 (const_int 6)
6944 (if_then_else
6945 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6946 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6947 (const_int 8)
6948 (const_int 10)))])]
6949)
d5b7b3ae 6950
defc0463
RE
6951(define_insn "*addsi3_cbranch"
6952 [(set (pc)
6953 (if_then_else
6954 (match_operator 4 "comparison_operator"
6955 [(plus:SI
6956 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6957 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6958 (const_int 0)])
6959 (label_ref (match_operand 5 "" ""))
6960 (pc)))
c769a35d
RE
6961 (set
6962 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6963 (plus:SI (match_dup 2) (match_dup 3)))
defc0463 6964 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
5b3e6663 6965 "TARGET_THUMB1
defc0463
RE
6966 && (GET_CODE (operands[4]) == EQ
6967 || GET_CODE (operands[4]) == NE
6968 || GET_CODE (operands[4]) == GE
6969 || GET_CODE (operands[4]) == LT)"
6970 "*
6971 {
6972 rtx cond[3];
6973
6974
6975 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6976 cond[1] = operands[2];
6977 cond[2] = operands[3];
6978
6979 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6980 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6981 else
6982 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6983
6984 if (which_alternative >= 3
6985 && which_alternative < 4)
6986 output_asm_insn (\"mov\\t%0, %1\", operands);
6987 else if (which_alternative >= 4)
6988 output_asm_insn (\"str\\t%1, %0\", operands);
6989
6990 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6991 {
6992 case 4:
6993 return \"b%d4\\t%l5\";
6994 case 6:
6995 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6996 default:
6997 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6998 }
6999 }
7000 "
7001 [(set (attr "far_jump")
7002 (if_then_else
7003 (ior (and (lt (symbol_ref ("which_alternative"))
7004 (const_int 3))
7005 (eq_attr "length" "8"))
7006 (eq_attr "length" "10"))
7007 (const_string "yes")
7008 (const_string "no")))
7009 (set (attr "length")
7010 (if_then_else
7011 (lt (symbol_ref ("which_alternative"))
7012 (const_int 3))
7013 (if_then_else
7014 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7015 (le (minus (match_dup 5) (pc)) (const_int 256)))
7016 (const_int 4)
7017 (if_then_else
7018 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7019 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7020 (const_int 6)
7021 (const_int 8)))
7022 (if_then_else
7023 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7024 (le (minus (match_dup 5) (pc)) (const_int 256)))
7025 (const_int 6)
7026 (if_then_else
7027 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7028 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7029 (const_int 8)
7030 (const_int 10)))))]
7031)
7032
7033(define_insn "*addsi3_cbranch_scratch"
7034 [(set (pc)
7035 (if_then_else
7036 (match_operator 3 "comparison_operator"
7037 [(plus:SI
7038 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
b49e92fe 7039 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
defc0463
RE
7040 (const_int 0)])
7041 (label_ref (match_operand 4 "" ""))
7042 (pc)))
7043 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
5b3e6663 7044 "TARGET_THUMB1
defc0463
RE
7045 && (GET_CODE (operands[3]) == EQ
7046 || GET_CODE (operands[3]) == NE
7047 || GET_CODE (operands[3]) == GE
7048 || GET_CODE (operands[3]) == LT)"
7049 "*
7050 {
7051 switch (which_alternative)
7052 {
7053 case 0:
7054 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7055 break;
7056 case 1:
7057 output_asm_insn (\"cmn\t%1, %2\", operands);
7058 break;
108a579c 7059 case 2:
b49e92fe
PB
7060 if (INTVAL (operands[2]) < 0)
7061 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7062 else
7063 output_asm_insn (\"add\t%0, %1, %2\", operands);
defc0463 7064 break;
108a579c 7065 case 3:
b49e92fe
PB
7066 if (INTVAL (operands[2]) < 0)
7067 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7068 else
7069 output_asm_insn (\"add\t%0, %0, %2\", operands);
defc0463
RE
7070 break;
7071 }
7072
7073 switch (get_attr_length (insn))
7074 {
7075 case 4:
7076 return \"b%d3\\t%l4\";
7077 case 6:
7078 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7079 default:
7080 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7081 }
7082 }
7083 "
7084 [(set (attr "far_jump")
7085 (if_then_else
7086 (eq_attr "length" "8")
7087 (const_string "yes")
7088 (const_string "no")))
7089 (set (attr "length")
7090 (if_then_else
7091 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7092 (le (minus (match_dup 4) (pc)) (const_int 256)))
7093 (const_int 4)
7094 (if_then_else
7095 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7096 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7097 (const_int 6)
7098 (const_int 8))))]
7099)
7100
7101(define_insn "*subsi3_cbranch"
7102 [(set (pc)
7103 (if_then_else
7104 (match_operator 4 "comparison_operator"
7105 [(minus:SI
7106 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7107 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7108 (const_int 0)])
7109 (label_ref (match_operand 5 "" ""))
7110 (pc)))
c769a35d 7111 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
defc0463
RE
7112 (minus:SI (match_dup 2) (match_dup 3)))
7113 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 7114 "TARGET_THUMB1
defc0463
RE
7115 && (GET_CODE (operands[4]) == EQ
7116 || GET_CODE (operands[4]) == NE
7117 || GET_CODE (operands[4]) == GE
7118 || GET_CODE (operands[4]) == LT)"
7119 "*
7120 {
7121 if (which_alternative == 0)
7122 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7123 else if (which_alternative == 1)
7124 {
7125 /* We must provide an alternative for a hi reg because reload
7126 cannot handle output reloads on a jump instruction, but we
7127 can't subtract into that. Fortunately a mov from lo to hi
7128 does not clobber the condition codes. */
7129 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7130 output_asm_insn (\"mov\\t%0, %1\", operands);
7131 }
7132 else
7133 {
7134 /* Similarly, but the target is memory. */
7135 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7136 output_asm_insn (\"str\\t%1, %0\", operands);
7137 }
7138
7139 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7140 {
7141 case 4:
7142 return \"b%d4\\t%l5\";
7143 case 6:
7144 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7145 default:
7146 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7147 }
7148 }
7149 "
7150 [(set (attr "far_jump")
7151 (if_then_else
7152 (ior (and (eq (symbol_ref ("which_alternative"))
7153 (const_int 0))
7154 (eq_attr "length" "8"))
7155 (eq_attr "length" "10"))
7156 (const_string "yes")
7157 (const_string "no")))
7158 (set (attr "length")
7159 (if_then_else
7160 (eq (symbol_ref ("which_alternative"))
7161 (const_int 0))
7162 (if_then_else
7163 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7164 (le (minus (match_dup 5) (pc)) (const_int 256)))
7165 (const_int 4)
7166 (if_then_else
7167 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7168 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7169 (const_int 6)
7170 (const_int 8)))
7171 (if_then_else
7172 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7173 (le (minus (match_dup 5) (pc)) (const_int 256)))
7174 (const_int 6)
7175 (if_then_else
7176 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7177 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7178 (const_int 8)
7179 (const_int 10)))))]
7180)
7181
7182(define_insn "*subsi3_cbranch_scratch"
7183 [(set (pc)
7184 (if_then_else
7185 (match_operator 0 "arm_comparison_operator"
7186 [(minus:SI (match_operand:SI 1 "register_operand" "l")
7187 (match_operand:SI 2 "nonmemory_operand" "l"))
7188 (const_int 0)])
7189 (label_ref (match_operand 3 "" ""))
7190 (pc)))]
5b3e6663 7191 "TARGET_THUMB1
defc0463
RE
7192 && (GET_CODE (operands[0]) == EQ
7193 || GET_CODE (operands[0]) == NE
7194 || GET_CODE (operands[0]) == GE
7195 || GET_CODE (operands[0]) == LT)"
7196 "*
7197 output_asm_insn (\"cmp\\t%1, %2\", operands);
7198 switch (get_attr_length (insn))
7199 {
7200 case 4: return \"b%d0\\t%l3\";
7201 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7202 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7203 }
7204 "
7205 [(set (attr "far_jump")
7206 (if_then_else
7207 (eq_attr "length" "8")
7208 (const_string "yes")
7209 (const_string "no")))
7210 (set (attr "length")
7211 (if_then_else
7212 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7213 (le (minus (match_dup 3) (pc)) (const_int 256)))
7214 (const_int 4)
7215 (if_then_else
7216 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7217 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7218 (const_int 6)
7219 (const_int 8))))]
7220)
7221
ff9940b0
RE
7222;; Comparison and test insns
7223
7224(define_expand "cmpsi"
589fe0fc
RE
7225 [(match_operand:SI 0 "s_register_operand" "")
7226 (match_operand:SI 1 "arm_add_operand" "")]
5b3e6663 7227 "TARGET_32BIT"
d5b7b3ae
RE
7228 "{
7229 arm_compare_op0 = operands[0];
7230 arm_compare_op1 = operands[1];
7231 DONE;
7232 }"
7233)
3a33f76f 7234
ff9940b0 7235(define_expand "cmpsf"
589fe0fc 7236 [(match_operand:SF 0 "s_register_operand" "")
9b66ebb1 7237 (match_operand:SF 1 "arm_float_compare_operand" "")]
5b3e6663 7238 "TARGET_32BIT && TARGET_HARD_FLOAT"
ff9940b0 7239 "
ff9940b0
RE
7240 arm_compare_op0 = operands[0];
7241 arm_compare_op1 = operands[1];
ff9940b0 7242 DONE;
5895f793
RE
7243 "
7244)
3a33f76f 7245
ff9940b0 7246(define_expand "cmpdf"
589fe0fc 7247 [(match_operand:DF 0 "s_register_operand" "")
9b66ebb1 7248 (match_operand:DF 1 "arm_float_compare_operand" "")]
5b3e6663 7249 "TARGET_32BIT && TARGET_HARD_FLOAT"
ff9940b0 7250 "
ff9940b0
RE
7251 arm_compare_op0 = operands[0];
7252 arm_compare_op1 = operands[1];
ff9940b0 7253 DONE;
5895f793
RE
7254 "
7255)
3a33f76f 7256
d5b7b3ae 7257(define_insn "*arm_cmpsi_insn"
48a08b9c 7258 [(set (reg:CC CC_REGNUM)
589fe0fc 7259 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
d5b7b3ae 7260 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5b3e6663 7261 "TARGET_32BIT"
68df59d3 7262 "@
589fe0fc
RE
7263 cmp%?\\t%0, %1
7264 cmn%?\\t%0, #%n1"
d5b7b3ae
RE
7265 [(set_attr "conds" "set")]
7266)
3a33f76f 7267
5b3e6663 7268(define_insn "*arm_cmpsi_shiftsi"
48a08b9c 7269 [(set (reg:CC CC_REGNUM)
d5b7b3ae
RE
7270 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
7271 (match_operator:SI 3 "shift_operator"
589fe0fc 7272 [(match_operand:SI 1 "s_register_operand" "r")
d5b7b3ae
RE
7273 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
7274 "TARGET_ARM"
589fe0fc 7275 "cmp%?\\t%0, %1%S3"
ca68ea18 7276 [(set_attr "conds" "set")
d19fb8e3 7277 (set_attr "shift" "1")
9b66ebb1
PB
7278 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7279 (const_string "alu_shift")
7280 (const_string "alu_shift_reg")))]
cca0a211 7281)
3a33f76f 7282
5b3e6663 7283(define_insn "*arm_cmpsi_shiftsi_swp"
48a08b9c 7284 [(set (reg:CC_SWP CC_REGNUM)
589fe0fc
RE
7285 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7286 [(match_operand:SI 1 "s_register_operand" "r")
7287 (match_operand:SI 2 "reg_or_int_operand" "rM")])
7288 (match_operand:SI 0 "s_register_operand" "r")))]
d5b7b3ae 7289 "TARGET_ARM"
589fe0fc 7290 "cmp%?\\t%0, %1%S3"
ca68ea18 7291 [(set_attr "conds" "set")
d19fb8e3 7292 (set_attr "shift" "1")
9b66ebb1
PB
7293 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7294 (const_string "alu_shift")
7295 (const_string "alu_shift_reg")))]
cca0a211 7296)
3a33f76f 7297
5b3e6663 7298(define_insn "*arm_cmpsi_negshiftsi_si"
1ac3e311
RE
7299 [(set (reg:CC_Z CC_REGNUM)
7300 (compare:CC_Z
7301 (neg:SI (match_operator:SI 1 "shift_operator"
7302 [(match_operand:SI 2 "s_register_operand" "r")
7303 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7304 (match_operand:SI 0 "s_register_operand" "r")))]
d5b7b3ae 7305 "TARGET_ARM"
1ac3e311 7306 "cmn%?\\t%0, %2%S1"
ca68ea18 7307 [(set_attr "conds" "set")
1ac3e311
RE
7308 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7309 (const_string "alu_shift")
7310 (const_string "alu_shift_reg")))]
cca0a211 7311)
3a33f76f 7312
9b6b54e2
NC
7313;; Cirrus SF compare instruction
7314(define_insn "*cirrus_cmpsf"
7315 [(set (reg:CCFP CC_REGNUM)
7316 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7317 (match_operand:SF 1 "cirrus_fp_register" "v")))]
9b66ebb1 7318 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
9b6b54e2 7319 "cfcmps%?\\tr15, %V0, %V1"
f0375c66 7320 [(set_attr "type" "mav_farith")
9b6b54e2
NC
7321 (set_attr "cirrus" "compare")]
7322)
7323
7324;; Cirrus DF compare instruction
7325(define_insn "*cirrus_cmpdf"
7326 [(set (reg:CCFP CC_REGNUM)
7327 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7328 (match_operand:DF 1 "cirrus_fp_register" "v")))]
9b66ebb1 7329 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
9b6b54e2 7330 "cfcmpd%?\\tr15, %V0, %V1"
f0375c66 7331 [(set_attr "type" "mav_farith")
9b6b54e2
NC
7332 (set_attr "cirrus" "compare")]
7333)
7334
7335;; Cirrus DI compare instruction
7336(define_expand "cmpdi"
7337 [(match_operand:DI 0 "cirrus_fp_register" "")
7338 (match_operand:DI 1 "cirrus_fp_register" "")]
9b66ebb1 7339 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
9b6b54e2
NC
7340 "{
7341 arm_compare_op0 = operands[0];
7342 arm_compare_op1 = operands[1];
7343 DONE;
7344 }")
7345
7346(define_insn "*cirrus_cmpdi"
7347 [(set (reg:CC CC_REGNUM)
7348 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7349 (match_operand:DI 1 "cirrus_fp_register" "v")))]
9b66ebb1 7350 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
9b6b54e2 7351 "cfcmp64%?\\tr15, %V0, %V1"
f0375c66 7352 [(set_attr "type" "mav_farith")
9b6b54e2
NC
7353 (set_attr "cirrus" "compare")]
7354)
7355
ff9940b0
RE
7356; This insn allows redundant compares to be removed by cse, nothing should
7357; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7358; is deleted later on. The match_dup will match the mode here, so that
7359; mode changes of the condition codes aren't lost by this even though we don't
7360; specify what they are.
7361
f54fd62e 7362(define_insn "*deleted_compare"
ff9940b0 7363 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5b3e6663 7364 "TARGET_32BIT"
c63165be 7365 "\\t%@ deleted compare"
d5b7b3ae
RE
7366 [(set_attr "conds" "set")
7367 (set_attr "length" "0")]
7368)
ff9940b0
RE
7369
7370\f
7371;; Conditional branch insns
7372
7373(define_expand "beq"
7374 [(set (pc)
7375 (if_then_else (eq (match_dup 1) (const_int 0))
7376 (label_ref (match_operand 0 "" ""))
7377 (pc)))]
5b3e6663 7378 "TARGET_32BIT"
d5b7b3ae
RE
7379 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7380)
9f072981 7381
ff9940b0
RE
7382(define_expand "bne"
7383 [(set (pc)
7384 (if_then_else (ne (match_dup 1) (const_int 0))
7385 (label_ref (match_operand 0 "" ""))
7386 (pc)))]
5b3e6663 7387 "TARGET_32BIT"
d5b7b3ae
RE
7388 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7389)
9f072981 7390
ff9940b0
RE
7391(define_expand "bgt"
7392 [(set (pc)
7393 (if_then_else (gt (match_dup 1) (const_int 0))
7394 (label_ref (match_operand 0 "" ""))
7395 (pc)))]
5b3e6663 7396 "TARGET_32BIT"
d5b7b3ae
RE
7397 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7398)
9f072981 7399
ff9940b0
RE
7400(define_expand "ble"
7401 [(set (pc)
7402 (if_then_else (le (match_dup 1) (const_int 0))
7403 (label_ref (match_operand 0 "" ""))
7404 (pc)))]
5b3e6663 7405 "TARGET_32BIT"
d5b7b3ae
RE
7406 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7407)
9f072981 7408
ff9940b0
RE
7409(define_expand "bge"
7410 [(set (pc)
7411 (if_then_else (ge (match_dup 1) (const_int 0))
7412 (label_ref (match_operand 0 "" ""))
7413 (pc)))]
5b3e6663 7414 "TARGET_32BIT"
d5b7b3ae
RE
7415 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7416)
9f072981 7417
ff9940b0
RE
7418(define_expand "blt"
7419 [(set (pc)
7420 (if_then_else (lt (match_dup 1) (const_int 0))
7421 (label_ref (match_operand 0 "" ""))
7422 (pc)))]
5b3e6663 7423 "TARGET_32BIT"
d5b7b3ae
RE
7424 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7425)
9f072981 7426
ff9940b0
RE
7427(define_expand "bgtu"
7428 [(set (pc)
7429 (if_then_else (gtu (match_dup 1) (const_int 0))
7430 (label_ref (match_operand 0 "" ""))
7431 (pc)))]
5b3e6663 7432 "TARGET_32BIT"
d5b7b3ae
RE
7433 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7434)
9f072981 7435
ff9940b0 7436(define_expand "bleu"
3a33f76f 7437 [(set (pc)
ff9940b0
RE
7438 (if_then_else (leu (match_dup 1) (const_int 0))
7439 (label_ref (match_operand 0 "" ""))
7440 (pc)))]
5b3e6663 7441 "TARGET_32BIT"
d5b7b3ae
RE
7442 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7443)
3a33f76f 7444
ff9940b0 7445(define_expand "bgeu"
3a33f76f 7446 [(set (pc)
ff9940b0
RE
7447 (if_then_else (geu (match_dup 1) (const_int 0))
7448 (label_ref (match_operand 0 "" ""))
7449 (pc)))]
5b3e6663 7450 "TARGET_32BIT"
d5b7b3ae
RE
7451 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7452)
3a33f76f 7453
ff9940b0
RE
7454(define_expand "bltu"
7455 [(set (pc)
7456 (if_then_else (ltu (match_dup 1) (const_int 0))
7457 (label_ref (match_operand 0 "" ""))
7458 (pc)))]
5b3e6663 7459 "TARGET_32BIT"
d5b7b3ae
RE
7460 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7461)
3a33f76f 7462
05ed98a1
RE
7463(define_expand "bunordered"
7464 [(set (pc)
7465 (if_then_else (unordered (match_dup 1) (const_int 0))
7466 (label_ref (match_operand 0 "" ""))
7467 (pc)))]
5b3e6663 7468 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7469 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7470 arm_compare_op1);"
7471)
7472
7473(define_expand "bordered"
7474 [(set (pc)
7475 (if_then_else (ordered (match_dup 1) (const_int 0))
7476 (label_ref (match_operand 0 "" ""))
7477 (pc)))]
5b3e6663 7478 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7479 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7480 arm_compare_op1);"
7481)
7482
7483(define_expand "bungt"
7484 [(set (pc)
7485 (if_then_else (ungt (match_dup 1) (const_int 0))
7486 (label_ref (match_operand 0 "" ""))
7487 (pc)))]
5b3e6663 7488 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7489 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7490)
7491
7492(define_expand "bunlt"
7493 [(set (pc)
7494 (if_then_else (unlt (match_dup 1) (const_int 0))
7495 (label_ref (match_operand 0 "" ""))
7496 (pc)))]
5b3e6663 7497 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7498 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7499)
7500
7501(define_expand "bunge"
7502 [(set (pc)
7503 (if_then_else (unge (match_dup 1) (const_int 0))
7504 (label_ref (match_operand 0 "" ""))
7505 (pc)))]
5b3e6663 7506 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7507 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7508)
7509
7510(define_expand "bunle"
7511 [(set (pc)
7512 (if_then_else (unle (match_dup 1) (const_int 0))
7513 (label_ref (match_operand 0 "" ""))
7514 (pc)))]
5b3e6663 7515 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7516 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7517)
7518
7519;; The following two patterns need two branch instructions, since there is
7520;; no single instruction that will handle all cases.
7521(define_expand "buneq"
7522 [(set (pc)
7523 (if_then_else (uneq (match_dup 1) (const_int 0))
7524 (label_ref (match_operand 0 "" ""))
7525 (pc)))]
5b3e6663 7526 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7527 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7528)
7529
7530(define_expand "bltgt"
7531 [(set (pc)
7532 (if_then_else (ltgt (match_dup 1) (const_int 0))
7533 (label_ref (match_operand 0 "" ""))
7534 (pc)))]
5b3e6663 7535 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7536 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7537)
7538
7539;;
7540;; Patterns to match conditional branch insns.
7541;;
7542
7543; Special pattern to match UNEQ.
7544(define_insn "*arm_buneq"
7545 [(set (pc)
7546 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7547 (label_ref (match_operand 0 "" ""))
7548 (pc)))]
5b3e6663 7549 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1 7550 "*
e6d29d15 7551 gcc_assert (!arm_ccfsm_state);
05ed98a1 7552
3ade30ea 7553 return \"bvs\\t%l0\;beq\\t%l0\";
05ed98a1
RE
7554 "
7555 [(set_attr "conds" "jump_clob")
7556 (set_attr "length" "8")]
7557)
7558
7559; Special pattern to match LTGT.
7560(define_insn "*arm_bltgt"
7561 [(set (pc)
7562 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7563 (label_ref (match_operand 0 "" ""))
7564 (pc)))]
5b3e6663 7565 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1 7566 "*
e6d29d15 7567 gcc_assert (!arm_ccfsm_state);
05ed98a1 7568
3ade30ea 7569 return \"bmi\\t%l0\;bgt\\t%l0\";
05ed98a1
RE
7570 "
7571 [(set_attr "conds" "jump_clob")
7572 (set_attr "length" "8")]
7573)
ff9940b0 7574
d5b7b3ae 7575(define_insn "*arm_cond_branch"
ff9940b0 7576 [(set (pc)
05ed98a1 7577 (if_then_else (match_operator 1 "arm_comparison_operator"
f54fd62e 7578 [(match_operand 2 "cc_register" "") (const_int 0)])
ff9940b0
RE
7579 (label_ref (match_operand 0 "" ""))
7580 (pc)))]
5b3e6663 7581 "TARGET_32BIT"
6d5363fa 7582 "*
ff9940b0 7583 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
d5b7b3ae
RE
7584 {
7585 arm_ccfsm_state += 2;
7586 return \"\";
7587 }
0f447ef2 7588 return \"b%d1\\t%l0\";
d5b7b3ae 7589 "
9b66ebb1
PB
7590 [(set_attr "conds" "use")
7591 (set_attr "type" "branch")]
d5b7b3ae 7592)
6d5363fa 7593
05ed98a1
RE
7594; Special pattern to match reversed UNEQ.
7595(define_insn "*arm_buneq_reversed"
7596 [(set (pc)
7597 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7598 (pc)
7599 (label_ref (match_operand 0 "" ""))))]
75fe7b2f 7600 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1 7601 "*
e6d29d15 7602 gcc_assert (!arm_ccfsm_state);
05ed98a1 7603
3ade30ea 7604 return \"bmi\\t%l0\;bgt\\t%l0\";
05ed98a1
RE
7605 "
7606 [(set_attr "conds" "jump_clob")
7607 (set_attr "length" "8")]
7608)
7609
7610; Special pattern to match reversed LTGT.
7611(define_insn "*arm_bltgt_reversed"
7612 [(set (pc)
7613 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7614 (pc)
7615 (label_ref (match_operand 0 "" ""))))]
75fe7b2f 7616 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1 7617 "*
e6d29d15 7618 gcc_assert (!arm_ccfsm_state);
05ed98a1 7619
3ade30ea 7620 return \"bvs\\t%l0\;beq\\t%l0\";
05ed98a1
RE
7621 "
7622 [(set_attr "conds" "jump_clob")
7623 (set_attr "length" "8")]
7624)
7625
d5b7b3ae 7626(define_insn "*arm_cond_branch_reversed"
ff9940b0 7627 [(set (pc)
05ed98a1 7628 (if_then_else (match_operator 1 "arm_comparison_operator"
f54fd62e 7629 [(match_operand 2 "cc_register" "") (const_int 0)])
ff9940b0
RE
7630 (pc)
7631 (label_ref (match_operand 0 "" ""))))]
5b3e6663 7632 "TARGET_32BIT"
6d5363fa 7633 "*
ff9940b0 7634 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
d5b7b3ae
RE
7635 {
7636 arm_ccfsm_state += 2;
7637 return \"\";
7638 }
0f447ef2 7639 return \"b%D1\\t%l0\";
d5b7b3ae 7640 "
9b66ebb1
PB
7641 [(set_attr "conds" "use")
7642 (set_attr "type" "branch")]
d5b7b3ae
RE
7643)
7644
3a33f76f 7645\f
ff9940b0
RE
7646
7647; scc insns
7648
7649(define_expand "seq"
82955615 7650 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7651 (eq:SI (match_dup 1) (const_int 0)))]
5b3e6663 7652 "TARGET_32BIT"
d5b7b3ae
RE
7653 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7654)
ff9940b0
RE
7655
7656(define_expand "sne"
82955615 7657 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7658 (ne:SI (match_dup 1) (const_int 0)))]
5b3e6663 7659 "TARGET_32BIT"
d5b7b3ae
RE
7660 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7661)
ff9940b0
RE
7662
7663(define_expand "sgt"
82955615 7664 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7665 (gt:SI (match_dup 1) (const_int 0)))]
5b3e6663 7666 "TARGET_32BIT"
d5b7b3ae
RE
7667 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7668)
ff9940b0
RE
7669
7670(define_expand "sle"
82955615 7671 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7672 (le:SI (match_dup 1) (const_int 0)))]
5b3e6663 7673 "TARGET_32BIT"
d5b7b3ae
RE
7674 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7675)
ff9940b0
RE
7676
7677(define_expand "sge"
82955615 7678 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7679 (ge:SI (match_dup 1) (const_int 0)))]
5b3e6663 7680 "TARGET_32BIT"
d5b7b3ae
RE
7681 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7682)
ff9940b0
RE
7683
7684(define_expand "slt"
82955615 7685 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7686 (lt:SI (match_dup 1) (const_int 0)))]
5b3e6663 7687 "TARGET_32BIT"
d5b7b3ae
RE
7688 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7689)
ff9940b0
RE
7690
7691(define_expand "sgtu"
82955615 7692 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7693 (gtu:SI (match_dup 1) (const_int 0)))]
5b3e6663 7694 "TARGET_32BIT"
d5b7b3ae
RE
7695 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7696)
ff9940b0
RE
7697
7698(define_expand "sleu"
82955615 7699 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7700 (leu:SI (match_dup 1) (const_int 0)))]
5b3e6663 7701 "TARGET_32BIT"
d5b7b3ae
RE
7702 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7703)
ff9940b0
RE
7704
7705(define_expand "sgeu"
82955615 7706 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7707 (geu:SI (match_dup 1) (const_int 0)))]
5b3e6663 7708 "TARGET_32BIT"
d5b7b3ae
RE
7709 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7710)
ff9940b0
RE
7711
7712(define_expand "sltu"
82955615 7713 [(set (match_operand:SI 0 "s_register_operand" "")
ff9940b0 7714 (ltu:SI (match_dup 1) (const_int 0)))]
5b3e6663 7715 "TARGET_32BIT"
d5b7b3ae
RE
7716 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7717)
ff9940b0 7718
05ed98a1 7719(define_expand "sunordered"
82955615 7720 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 7721 (unordered:SI (match_dup 1) (const_int 0)))]
5b3e6663 7722 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7723 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7724 arm_compare_op1);"
7725)
7726
7727(define_expand "sordered"
82955615 7728 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 7729 (ordered:SI (match_dup 1) (const_int 0)))]
5b3e6663 7730 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7731 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7732 arm_compare_op1);"
7733)
7734
7735(define_expand "sungt"
82955615 7736 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 7737 (ungt:SI (match_dup 1) (const_int 0)))]
5b3e6663 7738 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7739 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7740 arm_compare_op1);"
7741)
7742
7743(define_expand "sunge"
82955615 7744 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 7745 (unge:SI (match_dup 1) (const_int 0)))]
5b3e6663 7746 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7747 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7748 arm_compare_op1);"
7749)
7750
7751(define_expand "sunlt"
82955615 7752 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 7753 (unlt:SI (match_dup 1) (const_int 0)))]
5b3e6663 7754 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7755 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7756 arm_compare_op1);"
7757)
7758
7759(define_expand "sunle"
82955615 7760 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 7761 (unle:SI (match_dup 1) (const_int 0)))]
5b3e6663 7762 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
05ed98a1
RE
7763 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7764 arm_compare_op1);"
7765)
7766
7767;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7768;;; simple ARM instructions.
7769;
7770; (define_expand "suneq"
82955615 7771; [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 7772; (uneq:SI (match_dup 1) (const_int 0)))]
5b3e6663 7773; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
e6d29d15 7774; "gcc_unreachable ();"
05ed98a1
RE
7775; )
7776;
7777; (define_expand "sltgt"
82955615 7778; [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 7779; (ltgt:SI (match_dup 1) (const_int 0)))]
5b3e6663 7780; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
e6d29d15 7781; "gcc_unreachable ();"
05ed98a1
RE
7782; )
7783
4cdb3ed4 7784(define_insn "*mov_scc"
ff9940b0 7785 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 7786 (match_operator:SI 1 "arm_comparison_operator"
f54fd62e 7787 [(match_operand 2 "cc_register" "") (const_int 0)]))]
d5b7b3ae 7788 "TARGET_ARM"
cce4322b 7789 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
d5b7b3ae
RE
7790 [(set_attr "conds" "use")
7791 (set_attr "length" "8")]
7792)
ff9940b0 7793
4cdb3ed4 7794(define_insn "*mov_negscc"
ff9940b0 7795 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 7796 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
f54fd62e 7797 [(match_operand 2 "cc_register" "") (const_int 0)])))]
d5b7b3ae 7798 "TARGET_ARM"
cce4322b 7799 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
d5b7b3ae
RE
7800 [(set_attr "conds" "use")
7801 (set_attr "length" "8")]
7802)
ff9940b0 7803
4cdb3ed4 7804(define_insn "*mov_notscc"
ff9940b0 7805 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 7806 (not:SI (match_operator:SI 1 "arm_comparison_operator"
f54fd62e 7807 [(match_operand 2 "cc_register" "") (const_int 0)])))]
d5b7b3ae 7808 "TARGET_ARM"
cce4322b 7809 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
d5b7b3ae
RE
7810 [(set_attr "conds" "use")
7811 (set_attr "length" "8")]
7812)
ff9940b0 7813
a41a56b6
RE
7814(define_expand "cstoresi4"
7815 [(set (match_operand:SI 0 "s_register_operand" "")
7816 (match_operator:SI 1 "arm_comparison_operator"
7817 [(match_operand:SI 2 "s_register_operand" "")
7818 (match_operand:SI 3 "reg_or_int_operand" "")]))]
5b3e6663 7819 "TARGET_THUMB1"
a41a56b6
RE
7820 "{
7821 rtx op3, scratch, scratch2;
7822
7823 if (operands[3] == const0_rtx)
7824 {
7825 switch (GET_CODE (operands[1]))
7826 {
7827 case EQ:
5b3e6663 7828 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
a41a56b6
RE
7829 break;
7830
7831 case NE:
5b3e6663 7832 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
a41a56b6
RE
7833 break;
7834
7835 case LE:
7836 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7837 NULL_RTX, 0, OPTAB_WIDEN);
7838 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7839 NULL_RTX, 0, OPTAB_WIDEN);
7840 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7841 operands[0], 1, OPTAB_WIDEN);
7842 break;
7843
7844 case GE:
7845 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7846 NULL_RTX, 1);
7847 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7848 NULL_RTX, 1, OPTAB_WIDEN);
7849 break;
7850
7851 case GT:
7852 scratch = expand_binop (SImode, ashr_optab, operands[2],
7853 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7854 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7855 NULL_RTX, 0, OPTAB_WIDEN);
7856 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7857 0, OPTAB_WIDEN);
7858 break;
7859
7860 /* LT is handled by generic code. No need for unsigned with 0. */
7861 default:
7862 FAIL;
7863 }
7864 DONE;
7865 }
7866
7867 switch (GET_CODE (operands[1]))
7868 {
7869 case EQ:
7870 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7871 NULL_RTX, 0, OPTAB_WIDEN);
5b3e6663 7872 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
a41a56b6
RE
7873 break;
7874
7875 case NE:
7876 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7877 NULL_RTX, 0, OPTAB_WIDEN);
5b3e6663 7878 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
a41a56b6
RE
7879 break;
7880
7881 case LE:
7882 op3 = force_reg (SImode, operands[3]);
7883
7884 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7885 NULL_RTX, 1, OPTAB_WIDEN);
7886 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7887 NULL_RTX, 0, OPTAB_WIDEN);
5b3e6663 7888 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
a41a56b6
RE
7889 op3, operands[2]));
7890 break;
7891
7892 case GE:
7893 op3 = operands[3];
5b3e6663 7894 if (!thumb1_cmp_operand (op3, SImode))
a41a56b6
RE
7895 op3 = force_reg (SImode, op3);
7896 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7897 NULL_RTX, 0, OPTAB_WIDEN);
7898 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7899 NULL_RTX, 1, OPTAB_WIDEN);
5b3e6663 7900 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
a41a56b6
RE
7901 operands[2], op3));
7902 break;
7903
7904 case LEU:
7905 op3 = force_reg (SImode, operands[3]);
7906 scratch = force_reg (SImode, const0_rtx);
5b3e6663 7907 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
a41a56b6
RE
7908 op3, operands[2]));
7909 break;
7910
7911 case GEU:
7912 op3 = operands[3];
5b3e6663 7913 if (!thumb1_cmp_operand (op3, SImode))
a41a56b6
RE
7914 op3 = force_reg (SImode, op3);
7915 scratch = force_reg (SImode, const0_rtx);
5b3e6663 7916 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
a41a56b6
RE
7917 operands[2], op3));
7918 break;
7919
7920 case LTU:
7921 op3 = operands[3];
5b3e6663 7922 if (!thumb1_cmp_operand (op3, SImode))
a41a56b6
RE
7923 op3 = force_reg (SImode, op3);
7924 scratch = gen_reg_rtx (SImode);
5b3e6663 7925 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
a41a56b6
RE
7926 emit_insn (gen_negsi2 (operands[0], scratch));
7927 break;
7928
7929 case GTU:
7930 op3 = force_reg (SImode, operands[3]);
7931 scratch = gen_reg_rtx (SImode);
5b3e6663 7932 emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
a41a56b6
RE
7933 emit_insn (gen_negsi2 (operands[0], scratch));
7934 break;
7935
7936 /* No good sequences for GT, LT. */
7937 default:
7938 FAIL;
7939 }
7940 DONE;
7941}")
7942
5b3e6663 7943(define_expand "cstoresi_eq0_thumb1"
a41a56b6
RE
7944 [(parallel
7945 [(set (match_operand:SI 0 "s_register_operand" "")
7946 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7947 (const_int 0)))
7948 (clobber (match_dup:SI 2))])]
5b3e6663 7949 "TARGET_THUMB1"
a41a56b6
RE
7950 "operands[2] = gen_reg_rtx (SImode);"
7951)
7952
5b3e6663 7953(define_expand "cstoresi_ne0_thumb1"
a41a56b6
RE
7954 [(parallel
7955 [(set (match_operand:SI 0 "s_register_operand" "")
7956 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7957 (const_int 0)))
7958 (clobber (match_dup:SI 2))])]
5b3e6663 7959 "TARGET_THUMB1"
a41a56b6
RE
7960 "operands[2] = gen_reg_rtx (SImode);"
7961)
7962
5b3e6663 7963(define_insn "*cstoresi_eq0_thumb1_insn"
a41a56b6
RE
7964 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7965 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7966 (const_int 0)))
7967 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
5b3e6663 7968 "TARGET_THUMB1"
a41a56b6
RE
7969 "@
7970 neg\\t%0, %1\;adc\\t%0, %0, %1
7971 neg\\t%2, %1\;adc\\t%0, %1, %2"
7972 [(set_attr "length" "4")]
7973)
7974
5b3e6663 7975(define_insn "*cstoresi_ne0_thumb1_insn"
a41a56b6
RE
7976 [(set (match_operand:SI 0 "s_register_operand" "=l")
7977 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7978 (const_int 0)))
7979 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
5b3e6663 7980 "TARGET_THUMB1"
a41a56b6
RE
7981 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7982 [(set_attr "length" "4")]
7983)
7984
5b3e6663 7985(define_insn "cstoresi_nltu_thumb1"
a41a56b6
RE
7986 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7987 (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
5b3e6663
PB
7988 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7989 "TARGET_THUMB1"
a41a56b6
RE
7990 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7991 [(set_attr "length" "4")]
7992)
7993
7994;; Used as part of the expansion of thumb les sequence.
5b3e6663 7995(define_insn "thumb1_addsi3_addgeu"
a41a56b6
RE
7996 [(set (match_operand:SI 0 "s_register_operand" "=l")
7997 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7998 (match_operand:SI 2 "s_register_operand" "l"))
7999 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
5b3e6663
PB
8000 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8001 "TARGET_THUMB1"
a41a56b6
RE
8002 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8003 [(set_attr "length" "4")]
8004)
8005
ff9940b0 8006\f
e7c3cc84
DE
8007;; Conditional move insns
8008
8009(define_expand "movsicc"
f54fd62e 8010 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 8011 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
589fe0fc 8012 (match_operand:SI 2 "arm_not_operand" "")
f54fd62e 8013 (match_operand:SI 3 "arm_not_operand" "")))]
5b3e6663 8014 "TARGET_32BIT"
e7c3cc84 8015 "
5895f793
RE
8016 {
8017 enum rtx_code code = GET_CODE (operands[1]);
3ade30ea
RE
8018 rtx ccreg;
8019
8020 if (code == UNEQ || code == LTGT)
8021 FAIL;
e7c3cc84 8022
3ade30ea 8023 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
1c563bed 8024 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5895f793
RE
8025 }"
8026)
e7c3cc84
DE
8027
8028(define_expand "movsfcc"
f54fd62e 8029 [(set (match_operand:SF 0 "s_register_operand" "")
05ed98a1 8030 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
f54fd62e
RE
8031 (match_operand:SF 2 "s_register_operand" "")
8032 (match_operand:SF 3 "nonmemory_operand" "")))]
5b3e6663 8033 "TARGET_32BIT"
e7c3cc84 8034 "
5895f793
RE
8035 {
8036 enum rtx_code code = GET_CODE (operands[1]);
8037 rtx ccreg;
7a0a1f09 8038
3ade30ea
RE
8039 if (code == UNEQ || code == LTGT)
8040 FAIL;
8041
5895f793 8042 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
9b66ebb1
PB
8043 Otherwise, ensure it is a valid FP add operand */
8044 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8045 || (!arm_float_add_operand (operands[3], SFmode)))
5895f793 8046 operands[3] = force_reg (SFmode, operands[3]);
e7c3cc84 8047
5895f793 8048 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
1c563bed 8049 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5895f793
RE
8050 }"
8051)
e7c3cc84
DE
8052
8053(define_expand "movdfcc"
f54fd62e 8054 [(set (match_operand:DF 0 "s_register_operand" "")
05ed98a1 8055 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
f54fd62e 8056 (match_operand:DF 2 "s_register_operand" "")
9b66ebb1 8057 (match_operand:DF 3 "arm_float_add_operand" "")))]
5b3e6663 8058 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
e7c3cc84 8059 "
5895f793
RE
8060 {
8061 enum rtx_code code = GET_CODE (operands[1]);
3ade30ea 8062 rtx ccreg;
e7c3cc84 8063
3ade30ea
RE
8064 if (code == UNEQ || code == LTGT)
8065 FAIL;
8066
8067 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
1c563bed 8068 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5895f793
RE
8069 }"
8070)
e7c3cc84
DE
8071
8072(define_insn "*movsicc_insn"
7a0a1f09 8073 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
f54fd62e 8074 (if_then_else:SI
05ed98a1 8075 (match_operator 3 "arm_comparison_operator"
f54fd62e 8076 [(match_operand 4 "cc_register" "") (const_int 0)])
7a0a1f09
RE
8077 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8078 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
d5b7b3ae 8079 "TARGET_ARM"
e7c3cc84 8080 "@
f54fd62e
RE
8081 mov%D3\\t%0, %2
8082 mvn%D3\\t%0, #%B2
7a0a1f09
RE
8083 mov%d3\\t%0, %1
8084 mvn%d3\\t%0, #%B1
f54fd62e
RE
8085 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8086 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8087 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8088 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7a0a1f09 8089 [(set_attr "length" "4,4,4,4,8,8,8,8")
5895f793
RE
8090 (set_attr "conds" "use")]
8091)
e7c3cc84 8092
e7c3cc84 8093(define_insn "*movsfcc_soft_insn"
7a0a1f09 8094 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
05ed98a1 8095 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
f54fd62e 8096 [(match_operand 4 "cc_register" "") (const_int 0)])
7a0a1f09
RE
8097 (match_operand:SF 1 "s_register_operand" "0,r")
8098 (match_operand:SF 2 "s_register_operand" "r,0")))]
d5b7b3ae 8099 "TARGET_ARM && TARGET_SOFT_FLOAT"
7a0a1f09
RE
8100 "@
8101 mov%D3\\t%0, %2
8102 mov%d3\\t%0, %1"
05ed98a1
RE
8103 [(set_attr "conds" "use")]
8104)
e7c3cc84 8105
e7c3cc84 8106\f
ff9940b0
RE
8107;; Jump and linkage insns
8108
d5b7b3ae 8109(define_expand "jump"
ff9940b0
RE
8110 [(set (pc)
8111 (label_ref (match_operand 0 "" "")))]
d5b7b3ae 8112 "TARGET_EITHER"
ff9940b0 8113 ""
d5b7b3ae
RE
8114)
8115
8116(define_insn "*arm_jump"
8117 [(set (pc)
8118 (label_ref (match_operand 0 "" "")))]
5b3e6663 8119 "TARGET_32BIT"
ff9940b0 8120 "*
cca0a211
RE
8121 {
8122 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8123 {
8124 arm_ccfsm_state += 2;
8125 return \"\";
8126 }
8127 return \"b%?\\t%l0\";
8128 }
8129 "
8130 [(set_attr "predicable" "yes")]
8131)
ff9940b0 8132
d5b7b3ae
RE
8133(define_insn "*thumb_jump"
8134 [(set (pc)
8135 (label_ref (match_operand 0 "" "")))]
5b3e6663 8136 "TARGET_THUMB1"
d5b7b3ae
RE
8137 "*
8138 if (get_attr_length (insn) == 2)
8139 return \"b\\t%l0\";
8140 return \"bl\\t%l0\\t%@ far jump\";
8141 "
8142 [(set (attr "far_jump")
8143 (if_then_else
8144 (eq_attr "length" "4")
8145 (const_string "yes")
8146 (const_string "no")))
8147 (set (attr "length")
8148 (if_then_else
a2246edc
NC
8149 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8150 (le (minus (match_dup 0) (pc)) (const_int 2048)))
d5b7b3ae
RE
8151 (const_int 2)
8152 (const_int 4)))]
8153)
8154
c1d5bfb9
RK
8155(define_expand "call"
8156 [(parallel [(call (match_operand 0 "memory_operand" "")
8157 (match_operand 1 "general_operand" ""))
d5b7b3ae 8158 (use (match_operand 2 "" ""))
48a08b9c 8159 (clobber (reg:SI LR_REGNUM))])]
d5b7b3ae 8160 "TARGET_EITHER"
b020fd92
NC
8161 "
8162 {
9403b7f7 8163 rtx callee, pat;
81ee8129 8164
81ee8129
SB
8165 /* In an untyped call, we can get NULL for operand 2. */
8166 if (operands[2] == NULL_RTX)
8167 operands[2] = const0_rtx;
8168
25a65198 8169 /* Decide if we should generate indirect calls by loading the
a50aa827 8170 32-bit address of the callee into a register before performing the
25a65198
RS
8171 branch and link. */
8172 callee = XEXP (operands[0], 0);
8173 if (GET_CODE (callee) == SYMBOL_REF
8174 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8175 : !REG_P (callee))
81ee8129 8176 XEXP (operands[0], 0) = force_reg (Pmode, callee);
9403b7f7
RS
8177
8178 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8179 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8180 DONE;
b020fd92
NC
8181 }"
8182)
c1d5bfb9 8183
9403b7f7
RS
8184(define_expand "call_internal"
8185 [(parallel [(call (match_operand 0 "memory_operand" "")
8186 (match_operand 1 "general_operand" ""))
8187 (use (match_operand 2 "" ""))
8188 (clobber (reg:SI LR_REGNUM))])])
8189
68d560d4 8190(define_insn "*call_reg_armv5"
c1d5bfb9 8191 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
d5b7b3ae
RE
8192 (match_operand 1 "" ""))
8193 (use (match_operand 2 "" ""))
48a08b9c 8194 (clobber (reg:SI LR_REGNUM))]
68d560d4
RE
8195 "TARGET_ARM && arm_arch5"
8196 "blx%?\\t%0"
8197 [(set_attr "type" "call")]
8198)
8199
8200(define_insn "*call_reg_arm"
8201 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8202 (match_operand 1 "" ""))
8203 (use (match_operand 2 "" ""))
8204 (clobber (reg:SI LR_REGNUM))]
8205 "TARGET_ARM && !arm_arch5"
ff9940b0 8206 "*
68df59d3 8207 return output_call (operands);
d5b7b3ae
RE
8208 "
8209 ;; length is worst case, normally it is only two
8210 [(set_attr "length" "12")
8211 (set_attr "type" "call")]
8212)
ff9940b0 8213
4cdb3ed4 8214(define_insn "*call_mem"
e6add59b 8215 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
d5b7b3ae
RE
8216 (match_operand 1 "" ""))
8217 (use (match_operand 2 "" ""))
48a08b9c 8218 (clobber (reg:SI LR_REGNUM))]
d5b7b3ae 8219 "TARGET_ARM"
ff9940b0 8220 "*
68df59d3 8221 return output_call_mem (operands);
d5b7b3ae
RE
8222 "
8223 [(set_attr "length" "12")
8224 (set_attr "type" "call")]
8225)
8226
5b3e6663 8227(define_insn "*call_reg_thumb1_v5"
d5b7b3ae
RE
8228 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8229 (match_operand 1 "" ""))
8230 (use (match_operand 2 "" ""))
48a08b9c 8231 (clobber (reg:SI LR_REGNUM))]
5b3e6663 8232 "TARGET_THUMB1 && arm_arch5"
68d560d4
RE
8233 "blx\\t%0"
8234 [(set_attr "length" "2")
8235 (set_attr "type" "call")]
d5b7b3ae
RE
8236)
8237
5b3e6663 8238(define_insn "*call_reg_thumb1"
68d560d4
RE
8239 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8240 (match_operand 1 "" ""))
8241 (use (match_operand 2 "" ""))
48a08b9c 8242 (clobber (reg:SI LR_REGNUM))]
5b3e6663 8243 "TARGET_THUMB1 && !arm_arch5"
d5b7b3ae
RE
8244 "*
8245 {
a2503645 8246 if (!TARGET_CALLER_INTERWORKING)
b12a00f1 8247 return thumb_call_via_reg (operands[0]);
a2503645 8248 else if (operands[1] == const0_rtx)
68d560d4 8249 return \"bl\\t%__interwork_call_via_%0\";
a2503645
RS
8250 else if (frame_pointer_needed)
8251 return \"bl\\t%__interwork_r7_call_via_%0\";
d5b7b3ae 8252 else
a2503645 8253 return \"bl\\t%__interwork_r11_call_via_%0\";
d5b7b3ae
RE
8254 }"
8255 [(set_attr "type" "call")]
8256)
ff9940b0 8257
c1d5bfb9 8258(define_expand "call_value"
60dd1b7b
AH
8259 [(parallel [(set (match_operand 0 "" "")
8260 (call (match_operand 1 "memory_operand" "")
8261 (match_operand 2 "general_operand" "")))
d5b7b3ae 8262 (use (match_operand 3 "" ""))
48a08b9c 8263 (clobber (reg:SI LR_REGNUM))])]
d5b7b3ae 8264 "TARGET_EITHER"
b020fd92
NC
8265 "
8266 {
9403b7f7 8267 rtx pat, callee;
81ee8129
SB
8268
8269 /* In an untyped call, we can get NULL for operand 2. */
8270 if (operands[3] == 0)
8271 operands[3] = const0_rtx;
8272
25a65198
RS
8273 /* Decide if we should generate indirect calls by loading the
8274 32-bit address of the callee into a register before performing the
8275 branch and link. */
8276 callee = XEXP (operands[1], 0);
8277 if (GET_CODE (callee) == SYMBOL_REF
8278 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8279 : !REG_P (callee))
c27ba912 8280 XEXP (operands[1], 0) = force_reg (Pmode, callee);
9403b7f7
RS
8281
8282 pat = gen_call_value_internal (operands[0], operands[1],
8283 operands[2], operands[3]);
8284 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8285 DONE;
b020fd92
NC
8286 }"
8287)
c1d5bfb9 8288
9403b7f7
RS
8289(define_expand "call_value_internal"
8290 [(parallel [(set (match_operand 0 "" "")
8291 (call (match_operand 1 "memory_operand" "")
8292 (match_operand 2 "general_operand" "")))
8293 (use (match_operand 3 "" ""))
8294 (clobber (reg:SI LR_REGNUM))])])
8295
68d560d4 8296(define_insn "*call_value_reg_armv5"
24391720 8297 [(set (match_operand 0 "" "")
5a9335ef 8298 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
d5b7b3ae 8299 (match_operand 2 "" "")))
81ee8129 8300 (use (match_operand 3 "" ""))
48a08b9c 8301 (clobber (reg:SI LR_REGNUM))]
68d560d4
RE
8302 "TARGET_ARM && arm_arch5"
8303 "blx%?\\t%1"
8304 [(set_attr "type" "call")]
8305)
8306
8307(define_insn "*call_value_reg_arm"
8308 [(set (match_operand 0 "" "")
8309 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8310 (match_operand 2 "" "")))
8311 (use (match_operand 3 "" ""))
8312 (clobber (reg:SI LR_REGNUM))]
8313 "TARGET_ARM && !arm_arch5"
ff9940b0 8314 "*
5895f793 8315 return output_call (&operands[1]);
d5b7b3ae
RE
8316 "
8317 [(set_attr "length" "12")
8318 (set_attr "type" "call")]
8319)
ff9940b0 8320
4cdb3ed4 8321(define_insn "*call_value_mem"
24391720 8322 [(set (match_operand 0 "" "")
e6add59b 8323 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
d5b7b3ae 8324 (match_operand 2 "" "")))
81ee8129 8325 (use (match_operand 3 "" ""))
48a08b9c 8326 (clobber (reg:SI LR_REGNUM))]
5895f793 8327 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
ff9940b0 8328 "*
5895f793 8329 return output_call_mem (&operands[1]);
d5b7b3ae
RE
8330 "
8331 [(set_attr "length" "12")
8332 (set_attr "type" "call")]
8333)
ff9940b0 8334
5b3e6663 8335(define_insn "*call_value_reg_thumb1_v5"
68d560d4
RE
8336 [(set (match_operand 0 "" "")
8337 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8338 (match_operand 2 "" "")))
8339 (use (match_operand 3 "" ""))
8340 (clobber (reg:SI LR_REGNUM))]
5b3e6663 8341 "TARGET_THUMB1 && arm_arch5"
68d560d4
RE
8342 "blx\\t%1"
8343 [(set_attr "length" "2")
8344 (set_attr "type" "call")]
8345)
8346
5b3e6663 8347(define_insn "*call_value_reg_thumb1"
68d560d4
RE
8348 [(set (match_operand 0 "" "")
8349 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8350 (match_operand 2 "" "")))
8351 (use (match_operand 3 "" ""))
8352 (clobber (reg:SI LR_REGNUM))]
5b3e6663 8353 "TARGET_THUMB1 && !arm_arch5"
68d560d4
RE
8354 "*
8355 {
a2503645 8356 if (!TARGET_CALLER_INTERWORKING)
b12a00f1 8357 return thumb_call_via_reg (operands[1]);
a2503645 8358 else if (operands[2] == const0_rtx)
68d560d4 8359 return \"bl\\t%__interwork_call_via_%1\";
a2503645
RS
8360 else if (frame_pointer_needed)
8361 return \"bl\\t%__interwork_r7_call_via_%1\";
68d560d4 8362 else
a2503645 8363 return \"bl\\t%__interwork_r11_call_via_%1\";
68d560d4
RE
8364 }"
8365 [(set_attr "type" "call")]
8366)
8367
ff9940b0
RE
8368;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8369;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8370
4cdb3ed4 8371(define_insn "*call_symbol"
24391720 8372 [(call (mem:SI (match_operand:SI 0 "" ""))
d5b7b3ae 8373 (match_operand 1 "" ""))
81ee8129 8374 (use (match_operand 2 "" ""))
48a08b9c 8375 (clobber (reg:SI LR_REGNUM))]
d5b7b3ae
RE
8376 "TARGET_ARM
8377 && (GET_CODE (operands[0]) == SYMBOL_REF)
25a65198 8378 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
86efdc8e
PB
8379 "*
8380 {
ed0e6530 8381 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
86efdc8e 8382 }"
d5b7b3ae
RE
8383 [(set_attr "type" "call")]
8384)
ff9940b0 8385
4cdb3ed4 8386(define_insn "*call_value_symbol"
9f7bf991 8387 [(set (match_operand 0 "" "")
24391720 8388 (call (mem:SI (match_operand:SI 1 "" ""))
41e3f998 8389 (match_operand:SI 2 "" "")))
81ee8129 8390 (use (match_operand 3 "" ""))
48a08b9c 8391 (clobber (reg:SI LR_REGNUM))]
d5b7b3ae
RE
8392 "TARGET_ARM
8393 && (GET_CODE (operands[1]) == SYMBOL_REF)
25a65198 8394 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
86efdc8e
PB
8395 "*
8396 {
ed0e6530 8397 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
86efdc8e 8398 }"
d5b7b3ae
RE
8399 [(set_attr "type" "call")]
8400)
8401
8402(define_insn "*call_insn"
24391720 8403 [(call (mem:SI (match_operand:SI 0 "" ""))
d5b7b3ae
RE
8404 (match_operand:SI 1 "" ""))
8405 (use (match_operand 2 "" ""))
48a08b9c 8406 (clobber (reg:SI LR_REGNUM))]
0616531f 8407 "TARGET_THUMB
7b8781c8 8408 && GET_CODE (operands[0]) == SYMBOL_REF
25a65198 8409 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
d5b7b3ae
RE
8410 "bl\\t%a0"
8411 [(set_attr "length" "4")
8412 (set_attr "type" "call")]
8413)
8414
8415(define_insn "*call_value_insn"
9f7bf991 8416 [(set (match_operand 0 "" "")
24391720 8417 (call (mem:SI (match_operand 1 "" ""))
d5b7b3ae
RE
8418 (match_operand 2 "" "")))
8419 (use (match_operand 3 "" ""))
48a08b9c 8420 (clobber (reg:SI LR_REGNUM))]
0616531f 8421 "TARGET_THUMB
7b8781c8 8422 && GET_CODE (operands[1]) == SYMBOL_REF
25a65198 8423 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
d5b7b3ae
RE
8424 "bl\\t%a1"
8425 [(set_attr "length" "4")
8426 (set_attr "type" "call")]
8427)
ff9940b0 8428
0616531f
RE
8429;; We may also be able to do sibcalls for Thumb, but it's much harder...
8430(define_expand "sibcall"
8431 [(parallel [(call (match_operand 0 "memory_operand" "")
8432 (match_operand 1 "general_operand" ""))
72b075d1
RE
8433 (return)
8434 (use (match_operand 2 "" ""))])]
0616531f
RE
8435 "TARGET_ARM"
8436 "
8437 {
8438 if (operands[2] == NULL_RTX)
8439 operands[2] = const0_rtx;
0616531f
RE
8440 }"
8441)
8442
8443(define_expand "sibcall_value"
9f7bf991 8444 [(parallel [(set (match_operand 0 "" "")
0616531f
RE
8445 (call (match_operand 1 "memory_operand" "")
8446 (match_operand 2 "general_operand" "")))
72b075d1
RE
8447 (return)
8448 (use (match_operand 3 "" ""))])]
0616531f
RE
8449 "TARGET_ARM"
8450 "
8451 {
8452 if (operands[3] == NULL_RTX)
8453 operands[3] = const0_rtx;
0616531f
RE
8454 }"
8455)
8456
8457(define_insn "*sibcall_insn"
8458 [(call (mem:SI (match_operand:SI 0 "" "X"))
8459 (match_operand 1 "" ""))
72b075d1
RE
8460 (return)
8461 (use (match_operand 2 "" ""))]
0616531f
RE
8462 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8463 "*
8464 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8465 "
8466 [(set_attr "type" "call")]
8467)
8468
8469(define_insn "*sibcall_value_insn"
9f7bf991 8470 [(set (match_operand 0 "" "")
5a9335ef 8471 (call (mem:SI (match_operand:SI 1 "" "X"))
0616531f 8472 (match_operand 2 "" "")))
72b075d1
RE
8473 (return)
8474 (use (match_operand 3 "" ""))]
0616531f
RE
8475 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8476 "*
8477 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8478 "
8479 [(set_attr "type" "call")]
8480)
8481
ff9940b0
RE
8482;; Often the return insn will be the same as loading from memory, so set attr
8483(define_insn "return"
8484 [(return)]
d5b7b3ae 8485 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
ff9940b0 8486 "*
ff9940b0 8487 {
d5b7b3ae
RE
8488 if (arm_ccfsm_state == 2)
8489 {
8490 arm_ccfsm_state += 2;
8491 return \"\";
8492 }
64e92a26 8493 return output_return_instruction (const_true_rtx, TRUE, FALSE);
d5b7b3ae 8494 }"
9b66ebb1 8495 [(set_attr "type" "load1")
5a9335ef 8496 (set_attr "length" "12")
cca0a211 8497 (set_attr "predicable" "yes")]
d5b7b3ae 8498)
ff9940b0 8499
4cdb3ed4 8500(define_insn "*cond_return"
ff9940b0 8501 [(set (pc)
05ed98a1 8502 (if_then_else (match_operator 0 "arm_comparison_operator"
f54fd62e 8503 [(match_operand 1 "cc_register" "") (const_int 0)])
ff9940b0
RE
8504 (return)
8505 (pc)))]
d5b7b3ae 8506 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
ff9940b0 8507 "*
05ed98a1
RE
8508 {
8509 if (arm_ccfsm_state == 2)
8510 {
8511 arm_ccfsm_state += 2;
8512 return \"\";
8513 }
8514 return output_return_instruction (operands[0], TRUE, FALSE);
8515 }"
8516 [(set_attr "conds" "use")
5a9335ef 8517 (set_attr "length" "12")
9b66ebb1 8518 (set_attr "type" "load1")]
05ed98a1 8519)
ff9940b0 8520
4cdb3ed4 8521(define_insn "*cond_return_inverted"
ff9940b0 8522 [(set (pc)
05ed98a1 8523 (if_then_else (match_operator 0 "arm_comparison_operator"
f54fd62e 8524 [(match_operand 1 "cc_register" "") (const_int 0)])
ff9940b0
RE
8525 (pc)
8526 (return)))]
d5b7b3ae 8527 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
ff9940b0 8528 "*
05ed98a1
RE
8529 {
8530 if (arm_ccfsm_state == 2)
8531 {
8532 arm_ccfsm_state += 2;
8533 return \"\";
8534 }
8535 return output_return_instruction (operands[0], TRUE, TRUE);
8536 }"
8537 [(set_attr "conds" "use")
3e1b8dc0 8538 (set_attr "length" "12")
9b66ebb1 8539 (set_attr "type" "load1")]
05ed98a1 8540)
ff9940b0 8541
fcd53748
JT
8542;; Generate a sequence of instructions to determine if the processor is
8543;; in 26-bit or 32-bit mode, and return the appropriate return address
8544;; mask.
8545
8546(define_expand "return_addr_mask"
8547 [(set (match_dup 1)
8548 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8549 (const_int 0)))
8550 (set (match_operand:SI 0 "s_register_operand" "")
8551 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8552 (const_int -1)
8553 (const_int 67108860)))] ; 0x03fffffc
8554 "TARGET_ARM"
8555 "
20ae4500 8556 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
fcd53748
JT
8557 ")
8558
8559(define_insn "*check_arch2"
8560 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8561 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8562 (const_int 0)))]
8563 "TARGET_ARM"
8564 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8565 [(set_attr "length" "8")
8566 (set_attr "conds" "set")]
8567)
8568
ff9940b0
RE
8569;; Call subroutine returning any type.
8570
8571(define_expand "untyped_call"
8572 [(parallel [(call (match_operand 0 "" "")
8573 (const_int 0))
8574 (match_operand 1 "" "")
8575 (match_operand 2 "" "")])]
9f7bf991 8576 "TARGET_EITHER"
ff9940b0 8577 "
5895f793
RE
8578 {
8579 int i;
9f7bf991
RE
8580 rtx par = gen_rtx_PARALLEL (VOIDmode,
8581 rtvec_alloc (XVECLEN (operands[2], 0)));
8582 rtx addr = gen_reg_rtx (Pmode);
8583 rtx mem;
8584 int size = 0;
ff9940b0 8585
9f7bf991
RE
8586 emit_move_insn (addr, XEXP (operands[1], 0));
8587 mem = change_address (operands[1], BLKmode, addr);
ff9940b0 8588
5895f793
RE
8589 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8590 {
9f7bf991 8591 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
ff9940b0 8592
9f7bf991
RE
8593 /* Default code only uses r0 as a return value, but we could
8594 be using anything up to 4 registers. */
8595 if (REGNO (src) == R0_REGNUM)
8596 src = gen_rtx_REG (TImode, R0_REGNUM);
8597
8598 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8599 GEN_INT (size));
8600 size += GET_MODE_SIZE (GET_MODE (src));
8601 }
8602
8603 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8604 const0_rtx));
8605
8606 size = 0;
8607
8608 for (i = 0; i < XVECLEN (par, 0); i++)
8609 {
8610 HOST_WIDE_INT offset = 0;
8611 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8612
8613 if (size != 0)
8614 emit_move_insn (addr, plus_constant (addr, size));
8615
8616 mem = change_address (mem, GET_MODE (reg), NULL);
8617 if (REGNO (reg) == R0_REGNUM)
8618 {
8619 /* On thumb we have to use a write-back instruction. */
8620 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8621 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8622 size = TARGET_ARM ? 16 : 0;
8623 }
8624 else
8625 {
8626 emit_move_insn (mem, reg);
8627 size = GET_MODE_SIZE (GET_MODE (reg));
8628 }
5895f793 8629 }
ff9940b0 8630
5895f793
RE
8631 /* The optimizer does not know that the call sets the function value
8632 registers we stored in the result block. We avoid problems by
8633 claiming that all hard registers are used and clobbered at this
8634 point. */
8635 emit_insn (gen_blockage ());
8636
8637 DONE;
8638 }"
8639)
ff9940b0 8640
9f7bf991
RE
8641(define_expand "untyped_return"
8642 [(match_operand:BLK 0 "memory_operand" "")
8643 (match_operand 1 "" "")]
8644 "TARGET_EITHER"
8645 "
8646 {
8647 int i;
8648 rtx addr = gen_reg_rtx (Pmode);
8649 rtx mem;
8650 int size = 0;
8651
8652 emit_move_insn (addr, XEXP (operands[0], 0));
8653 mem = change_address (operands[0], BLKmode, addr);
8654
8655 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8656 {
8657 HOST_WIDE_INT offset = 0;
8658 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8659
8660 if (size != 0)
8661 emit_move_insn (addr, plus_constant (addr, size));
8662
8663 mem = change_address (mem, GET_MODE (reg), NULL);
8664 if (REGNO (reg) == R0_REGNUM)
8665 {
8666 /* On thumb we have to use a write-back instruction. */
8667 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8668 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8669 size = TARGET_ARM ? 16 : 0;
8670 }
8671 else
8672 {
8673 emit_move_insn (reg, mem);
8674 size = GET_MODE_SIZE (GET_MODE (reg));
8675 }
8676 }
8677
8678 /* Emit USE insns before the return. */
8679 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8680 emit_insn (gen_rtx_USE (VOIDmode,
8681 SET_DEST (XVECEXP (operands[1], 0, i))));
8682
8683 /* Construct the return. */
8684 expand_naked_return ();
8685
8686 DONE;
8687 }"
8688)
8689
ff9940b0
RE
8690;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8691;; all of memory. This blocks insns from being moved across this point.
8692
8693(define_insn "blockage"
b15bca31 8694 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
d5b7b3ae 8695 "TARGET_EITHER"
ff9940b0 8696 ""
d5b7b3ae
RE
8697 [(set_attr "length" "0")
8698 (set_attr "type" "block")]
8699)
ff9940b0 8700
4cdb3ed4
RE
8701(define_expand "casesi"
8702 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
589fe0fc
RE
8703 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8704 (match_operand:SI 2 "const_int_operand" "") ; total range
4cdb3ed4
RE
8705 (match_operand:SI 3 "" "") ; table label
8706 (match_operand:SI 4 "" "")] ; Out of range label
5b3e6663 8707 "TARGET_32BIT"
4cdb3ed4 8708 "
5895f793
RE
8709 {
8710 rtx reg;
8711 if (operands[1] != const0_rtx)
8712 {
8713 reg = gen_reg_rtx (SImode);
4cdb3ed4 8714
5895f793
RE
8715 emit_insn (gen_addsi3 (reg, operands[0],
8716 GEN_INT (-INTVAL (operands[1]))));
8717 operands[0] = reg;
8718 }
ff9940b0 8719
5895f793
RE
8720 if (!const_ok_for_arm (INTVAL (operands[2])))
8721 operands[2] = force_reg (SImode, operands[2]);
8722
5b3e6663
PB
8723 if (TARGET_ARM)
8724 {
8725 emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
8726 operands[3], operands[4]));
8727 }
8728 else if (flag_pic)
8729 {
8730 emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
8731 operands[2], operands[3], operands[4]));
8732 }
8733 else
8734 {
8735 emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
8736 operands[3], operands[4]));
8737 }
5895f793
RE
8738 DONE;
8739 }"
8740)
4cdb3ed4 8741
7a0a1f09
RE
8742;; The USE in this pattern is needed to tell flow analysis that this is
8743;; a CASESI insn. It has no other purpose.
5b3e6663 8744(define_insn "arm_casesi_internal"
7a0a1f09
RE
8745 [(parallel [(set (pc)
8746 (if_then_else
8747 (leu (match_operand:SI 0 "s_register_operand" "r")
8748 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8749 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8750 (label_ref (match_operand 2 "" ""))))
8751 (label_ref (match_operand 3 "" ""))))
48a08b9c 8752 (clobber (reg:CC CC_REGNUM))
7a0a1f09 8753 (use (label_ref (match_dup 2)))])]
d5b7b3ae 8754 "TARGET_ARM"
4cdb3ed4 8755 "*
cca0a211
RE
8756 if (flag_pic)
8757 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8758 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8759 "
8760 [(set_attr "conds" "clob")
8761 (set_attr "length" "12")]
8762)
ff9940b0 8763
d5b7b3ae 8764(define_expand "indirect_jump"
ff9940b0 8765 [(set (pc)
d5b7b3ae
RE
8766 (match_operand:SI 0 "s_register_operand" ""))]
8767 "TARGET_EITHER"
5b3e6663
PB
8768 "
8769 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8770 address and use bx. */
8771 if (TARGET_THUMB2)
8772 {
8773 rtx tmp;
8774 tmp = gen_reg_rtx (SImode);
8775 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8776 operands[0] = tmp;
8777 }
8778 "
d5b7b3ae
RE
8779)
8780
68d560d4 8781;; NB Never uses BX.
d5b7b3ae
RE
8782(define_insn "*arm_indirect_jump"
8783 [(set (pc)
8784 (match_operand:SI 0 "s_register_operand" "r"))]
8785 "TARGET_ARM"
8786 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
cca0a211 8787 [(set_attr "predicable" "yes")]
d5b7b3ae 8788)
ff9940b0 8789
4cdb3ed4 8790(define_insn "*load_indirect_jump"
ff9940b0
RE
8791 [(set (pc)
8792 (match_operand:SI 0 "memory_operand" "m"))]
d5b7b3ae
RE
8793 "TARGET_ARM"
8794 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9b66ebb1 8795 [(set_attr "type" "load1")
859230d4
NC
8796 (set_attr "pool_range" "4096")
8797 (set_attr "neg_pool_range" "4084")
cca0a211 8798 (set_attr "predicable" "yes")]
d5b7b3ae
RE
8799)
8800
68d560d4 8801;; NB Never uses BX.
5b3e6663 8802(define_insn "*thumb1_indirect_jump"
d5b7b3ae
RE
8803 [(set (pc)
8804 (match_operand:SI 0 "register_operand" "l*r"))]
5b3e6663 8805 "TARGET_THUMB1"
d5b7b3ae
RE
8806 "mov\\tpc, %0"
8807 [(set_attr "conds" "clob")
8808 (set_attr "length" "2")]
8809)
8810
ff9940b0
RE
8811\f
8812;; Misc insns
8813
8814(define_insn "nop"
8815 [(const_int 0)]
d5b7b3ae
RE
8816 "TARGET_EITHER"
8817 "*
5b3e6663
PB
8818 if (TARGET_UNIFIED_ASM)
8819 return \"nop\";
d5b7b3ae
RE
8820 if (TARGET_ARM)
8821 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8822 return \"mov\\tr8, r8\";
8823 "
8824 [(set (attr "length")
8825 (if_then_else (eq_attr "is_thumb" "yes")
8826 (const_int 2)
8827 (const_int 4)))]
8828)
8829
ff9940b0
RE
8830\f
8831;; Patterns to allow combination of arithmetic, cond code and shifts
8832
4cdb3ed4 8833(define_insn "*arith_shiftsi"
ff9940b0
RE
8834 [(set (match_operand:SI 0 "s_register_operand" "=r")
8835 (match_operator:SI 1 "shiftable_operator"
8836 [(match_operator:SI 3 "shift_operator"
8837 [(match_operand:SI 4 "s_register_operand" "r")
091426d3 8838 (match_operand:SI 5 "reg_or_int_operand" "rI")])
ff9940b0 8839 (match_operand:SI 2 "s_register_operand" "r")]))]
d5b7b3ae 8840 "TARGET_ARM"
b020fd92 8841 "%i1%?\\t%0, %2, %4%S3"
ca68ea18 8842 [(set_attr "predicable" "yes")
d19fb8e3 8843 (set_attr "shift" "4")
9b66ebb1
PB
8844 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8845 (const_string "alu_shift")
8846 (const_string "alu_shift_reg")))]
b020fd92 8847)
ff9940b0 8848
da5cafa7
RE
8849(define_split
8850 [(set (match_operand:SI 0 "s_register_operand" "")
8851 (match_operator:SI 1 "shiftable_operator"
8852 [(match_operator:SI 2 "shiftable_operator"
8853 [(match_operator:SI 3 "shift_operator"
8854 [(match_operand:SI 4 "s_register_operand" "")
8855 (match_operand:SI 5 "reg_or_int_operand" "")])
8856 (match_operand:SI 6 "s_register_operand" "")])
8857 (match_operand:SI 7 "arm_rhs_operand" "")]))
8858 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8859 "TARGET_ARM"
8860 [(set (match_dup 8)
8861 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8862 (match_dup 6)]))
8863 (set (match_dup 0)
8864 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8865 "")
8866
4cdb3ed4 8867(define_insn "*arith_shiftsi_compare0"
48a08b9c 8868 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
8869 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8870 [(match_operator:SI 3 "shift_operator"
8871 [(match_operand:SI 4 "s_register_operand" "r")
091426d3 8872 (match_operand:SI 5 "reg_or_int_operand" "rI")])
ff9940b0
RE
8873 (match_operand:SI 2 "s_register_operand" "r")])
8874 (const_int 0)))
8875 (set (match_operand:SI 0 "s_register_operand" "=r")
8876 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8877 (match_dup 2)]))]
d5b7b3ae 8878 "TARGET_ARM"
5b3e6663 8879 "%i1%.\\t%0, %2, %4%S3"
ca68ea18 8880 [(set_attr "conds" "set")
d19fb8e3 8881 (set_attr "shift" "4")
9b66ebb1
PB
8882 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8883 (const_string "alu_shift")
8884 (const_string "alu_shift_reg")))]
cca0a211 8885)
ff9940b0 8886
4cdb3ed4 8887(define_insn "*arith_shiftsi_compare0_scratch"
48a08b9c 8888 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
8889 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8890 [(match_operator:SI 3 "shift_operator"
8891 [(match_operand:SI 4 "s_register_operand" "r")
091426d3 8892 (match_operand:SI 5 "reg_or_int_operand" "rI")])
ff9940b0
RE
8893 (match_operand:SI 2 "s_register_operand" "r")])
8894 (const_int 0)))
8895 (clobber (match_scratch:SI 0 "=r"))]
d5b7b3ae 8896 "TARGET_ARM"
5b3e6663 8897 "%i1%.\\t%0, %2, %4%S3"
ca68ea18 8898 [(set_attr "conds" "set")
d19fb8e3 8899 (set_attr "shift" "4")
9b66ebb1
PB
8900 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8901 (const_string "alu_shift")
8902 (const_string "alu_shift_reg")))]
cca0a211 8903)
ff9940b0 8904
4cdb3ed4 8905(define_insn "*sub_shiftsi"
ff9940b0
RE
8906 [(set (match_operand:SI 0 "s_register_operand" "=r")
8907 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8908 (match_operator:SI 2 "shift_operator"
8909 [(match_operand:SI 3 "s_register_operand" "r")
091426d3 8910 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
d5b7b3ae 8911 "TARGET_ARM"
b020fd92 8912 "sub%?\\t%0, %1, %3%S2"
ca68ea18 8913 [(set_attr "predicable" "yes")
d19fb8e3 8914 (set_attr "shift" "3")
9b66ebb1
PB
8915 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8916 (const_string "alu_shift")
8917 (const_string "alu_shift_reg")))]
b020fd92 8918)
ff9940b0 8919
4cdb3ed4 8920(define_insn "*sub_shiftsi_compare0"
48a08b9c 8921 [(set (reg:CC_NOOV CC_REGNUM)
c63165be
RE
8922 (compare:CC_NOOV
8923 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8924 (match_operator:SI 2 "shift_operator"
8925 [(match_operand:SI 3 "s_register_operand" "r")
091426d3 8926 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
c63165be 8927 (const_int 0)))
ff9940b0
RE
8928 (set (match_operand:SI 0 "s_register_operand" "=r")
8929 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8930 (match_dup 4)])))]
d5b7b3ae 8931 "TARGET_ARM"
5b3e6663 8932 "sub%.\\t%0, %1, %3%S2"
ca68ea18 8933 [(set_attr "conds" "set")
9b66ebb1
PB
8934 (set_attr "shift" "3")
8935 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8936 (const_string "alu_shift")
8937 (const_string "alu_shift_reg")))]
cca0a211 8938)
ff9940b0 8939
4cdb3ed4 8940(define_insn "*sub_shiftsi_compare0_scratch"
48a08b9c 8941 [(set (reg:CC_NOOV CC_REGNUM)
c63165be
RE
8942 (compare:CC_NOOV
8943 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8944 (match_operator:SI 2 "shift_operator"
8945 [(match_operand:SI 3 "s_register_operand" "r")
091426d3 8946 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
c63165be 8947 (const_int 0)))
ff9940b0 8948 (clobber (match_scratch:SI 0 "=r"))]
d5b7b3ae 8949 "TARGET_ARM"
5b3e6663 8950 "sub%.\\t%0, %1, %3%S2"
ca68ea18 8951 [(set_attr "conds" "set")
9b66ebb1
PB
8952 (set_attr "shift" "3")
8953 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8954 (const_string "alu_shift")
8955 (const_string "alu_shift_reg")))]
cca0a211 8956)
ff9940b0 8957
ff9940b0
RE
8958\f
8959
4cdb3ed4 8960(define_insn "*and_scc"
ff9940b0 8961 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 8962 (and:SI (match_operator:SI 1 "arm_comparison_operator"
589fe0fc 8963 [(match_operand 3 "cc_register" "") (const_int 0)])
ff9940b0 8964 (match_operand:SI 2 "s_register_operand" "r")))]
d5b7b3ae 8965 "TARGET_ARM"
0f447ef2 8966 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
05ed98a1
RE
8967 [(set_attr "conds" "use")
8968 (set_attr "length" "8")]
8969)
ff9940b0 8970
4cdb3ed4 8971(define_insn "*ior_scc"
ff9940b0 8972 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 8973 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
f54fd62e 8974 [(match_operand 3 "cc_register" "") (const_int 0)])
ff9940b0 8975 (match_operand:SI 1 "s_register_operand" "0,?r")))]
d5b7b3ae 8976 "TARGET_ARM"
0f447ef2 8977 "@
916cc8c5
RE
8978 orr%d2\\t%0, %1, #1
8979 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
05ed98a1
RE
8980 [(set_attr "conds" "use")
8981 (set_attr "length" "4,8")]
8982)
ff9940b0 8983
4cdb3ed4 8984(define_insn "*compare_scc"
68df59d3 8985 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 8986 (match_operator:SI 1 "arm_comparison_operator"
68df59d3
RE
8987 [(match_operand:SI 2 "s_register_operand" "r,r")
8988 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
48a08b9c 8989 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 8990 "TARGET_ARM"
ff9940b0 8991 "*
9af66e58
RE
8992 if (operands[3] == const0_rtx)
8993 {
8994 if (GET_CODE (operands[1]) == LT)
8995 return \"mov\\t%0, %2, lsr #31\";
8996
8997 if (GET_CODE (operands[1]) == GE)
8998 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
0f447ef2 8999
9af66e58
RE
9000 if (GET_CODE (operands[1]) == EQ)
9001 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9002 }
0f447ef2 9003
05ed98a1
RE
9004 if (GET_CODE (operands[1]) == NE)
9005 {
9006 if (which_alternative == 1)
9007 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9008 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9009 }
9010 if (which_alternative == 1)
9011 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9012 else
9013 output_asm_insn (\"cmp\\t%2, %3\", operands);
9014 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9015 "
9016 [(set_attr "conds" "clob")
9017 (set_attr "length" "12")]
9018)
ff9940b0 9019
4cdb3ed4 9020(define_insn "*cond_move"
ff9940b0 9021 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
589fe0fc 9022 (if_then_else:SI (match_operator 3 "equality_operator"
05ed98a1 9023 [(match_operator 4 "arm_comparison_operator"
f54fd62e 9024 [(match_operand 5 "cc_register" "") (const_int 0)])
589fe0fc
RE
9025 (const_int 0)])
9026 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9027 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
d5b7b3ae 9028 "TARGET_ARM"
ff9940b0 9029 "*
05ed98a1
RE
9030 if (GET_CODE (operands[3]) == NE)
9031 {
9032 if (which_alternative != 1)
9033 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9034 if (which_alternative != 0)
9035 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9036 return \"\";
9037 }
9038 if (which_alternative != 0)
9039 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9040 if (which_alternative != 1)
9041 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9042 return \"\";
9043 "
9044 [(set_attr "conds" "use")
9045 (set_attr "length" "4,4,8")]
9046)
ff9940b0 9047
4cdb3ed4 9048(define_insn "*cond_arith"
ff9940b0
RE
9049 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9050 (match_operator:SI 5 "shiftable_operator"
05ed98a1 9051 [(match_operator:SI 4 "arm_comparison_operator"
ff9940b0
RE
9052 [(match_operand:SI 2 "s_register_operand" "r,r")
9053 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9054 (match_operand:SI 1 "s_register_operand" "0,?r")]))
48a08b9c 9055 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9056 "TARGET_ARM"
ff9940b0 9057 "*
05ed98a1
RE
9058 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9059 return \"%i5\\t%0, %1, %2, lsr #31\";
c63165be 9060
05ed98a1
RE
9061 output_asm_insn (\"cmp\\t%2, %3\", operands);
9062 if (GET_CODE (operands[5]) == AND)
9063 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9064 else if (GET_CODE (operands[5]) == MINUS)
9065 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9066 else if (which_alternative != 0)
9067 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9068 return \"%i5%d4\\t%0, %1, #1\";
9069 "
9070 [(set_attr "conds" "clob")
9071 (set_attr "length" "12")]
9072)
ff9940b0 9073
4cdb3ed4 9074(define_insn "*cond_sub"
ff9940b0
RE
9075 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9076 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
05ed98a1 9077 (match_operator:SI 4 "arm_comparison_operator"
ff9940b0
RE
9078 [(match_operand:SI 2 "s_register_operand" "r,r")
9079 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
48a08b9c 9080 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9081 "TARGET_ARM"
ff9940b0 9082 "*
05ed98a1
RE
9083 output_asm_insn (\"cmp\\t%2, %3\", operands);
9084 if (which_alternative != 0)
9085 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9086 return \"sub%d4\\t%0, %1, #1\";
9087 "
9088 [(set_attr "conds" "clob")
9089 (set_attr "length" "8,12")]
9090)
ff9940b0 9091
5b3e6663 9092;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
589fe0fc 9093(define_insn "*cmp_ite0"
d5b7b3ae 9094 [(set (match_operand 6 "dominant_cc_register" "")
589fe0fc
RE
9095 (compare
9096 (if_then_else:SI
05ed98a1 9097 (match_operator 4 "arm_comparison_operator"
589fe0fc
RE
9098 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9099 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
05ed98a1 9100 (match_operator:SI 5 "arm_comparison_operator"
589fe0fc
RE
9101 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9102 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9103 (const_int 0))
9104 (const_int 0)))]
d5b7b3ae 9105 "TARGET_ARM"
ff9940b0 9106 "*
589fe0fc 9107 {
05ed98a1
RE
9108 static const char * const opcodes[4][2] =
9109 {
9110 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9111 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9112 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9113 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9114 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9115 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9116 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9117 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9118 };
9119 int swap =
9120 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9121
9122 return opcodes[which_alternative][swap];
9123 }"
9124 [(set_attr "conds" "set")
9125 (set_attr "length" "8")]
9126)
ff9940b0 9127
589fe0fc 9128(define_insn "*cmp_ite1"
d5b7b3ae 9129 [(set (match_operand 6 "dominant_cc_register" "")
589fe0fc
RE
9130 (compare
9131 (if_then_else:SI
05ed98a1 9132 (match_operator 4 "arm_comparison_operator"
589fe0fc 9133 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
a0b632ec 9134 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
05ed98a1 9135 (match_operator:SI 5 "arm_comparison_operator"
589fe0fc 9136 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
a0b632ec 9137 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
589fe0fc
RE
9138 (const_int 1))
9139 (const_int 0)))]
d5b7b3ae 9140 "TARGET_ARM"
ff9940b0 9141 "*
ff9940b0 9142 {
5895f793
RE
9143 static const char * const opcodes[4][2] =
9144 {
9145 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9146 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9147 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9148 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9149 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9150 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9151 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9152 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9153 };
9154 int swap =
9155 comparison_dominates_p (GET_CODE (operands[5]),
9156 reverse_condition (GET_CODE (operands[4])));
9157
9158 return opcodes[which_alternative][swap];
9159 }"
05ed98a1
RE
9160 [(set_attr "conds" "set")
9161 (set_attr "length" "8")]
9162)
ff9940b0 9163
1646cf41
RE
9164(define_insn "*cmp_and"
9165 [(set (match_operand 6 "dominant_cc_register" "")
9166 (compare
9167 (and:SI
9168 (match_operator 4 "arm_comparison_operator"
9169 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9170 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9171 (match_operator:SI 5 "arm_comparison_operator"
9172 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9173 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9174 (const_int 0)))]
9175 "TARGET_ARM"
9176 "*
9177 {
27c38fbe 9178 static const char *const opcodes[4][2] =
1646cf41
RE
9179 {
9180 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9181 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9182 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9183 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9184 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9185 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9186 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9187 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9188 };
9189 int swap =
9190 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9191
9192 return opcodes[which_alternative][swap];
9193 }"
9194 [(set_attr "conds" "set")
9195 (set_attr "predicable" "no")
9196 (set_attr "length" "8")]
9197)
9198
9199(define_insn "*cmp_ior"
9200 [(set (match_operand 6 "dominant_cc_register" "")
9201 (compare
9202 (ior:SI
9203 (match_operator 4 "arm_comparison_operator"
9204 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9205 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9206 (match_operator:SI 5 "arm_comparison_operator"
9207 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9208 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9209 (const_int 0)))]
9210 "TARGET_ARM"
9211 "*
9212{
27c38fbe 9213 static const char *const opcodes[4][2] =
1646cf41
RE
9214 {
9215 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9216 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9217 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9218 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9219 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9220 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9221 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9222 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9223 };
9224 int swap =
9225 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9226
9227 return opcodes[which_alternative][swap];
9228}
9229"
9230 [(set_attr "conds" "set")
9231 (set_attr "length" "8")]
9232)
9233
03f1640c
RE
9234(define_insn_and_split "*ior_scc_scc"
9235 [(set (match_operand:SI 0 "s_register_operand" "=r")
9236 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9237 [(match_operand:SI 1 "s_register_operand" "r")
9238 (match_operand:SI 2 "arm_add_operand" "rIL")])
9239 (match_operator:SI 6 "arm_comparison_operator"
9240 [(match_operand:SI 4 "s_register_operand" "r")
9241 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9242 (clobber (reg:CC CC_REGNUM))]
9243 "TARGET_ARM
9244 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9245 != CCmode)"
9246 "#"
9247 "TARGET_ARM && reload_completed"
9248 [(set (match_dup 7)
9249 (compare
9250 (ior:SI
9251 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9252 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9253 (const_int 0)))
9254 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9255 "operands[7]
9256 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9257 DOM_CC_X_OR_Y),
9af66e58
RE
9258 CC_REGNUM);"
9259 [(set_attr "conds" "clob")
9260 (set_attr "length" "16")])
9261
9262; If the above pattern is followed by a CMP insn, then the compare is
9263; redundant, since we can rework the conditional instruction that follows.
9264(define_insn_and_split "*ior_scc_scc_cmp"
9265 [(set (match_operand 0 "dominant_cc_register" "")
9266 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9267 [(match_operand:SI 1 "s_register_operand" "r")
9268 (match_operand:SI 2 "arm_add_operand" "rIL")])
9269 (match_operator:SI 6 "arm_comparison_operator"
9270 [(match_operand:SI 4 "s_register_operand" "r")
9271 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9272 (const_int 0)))
9273 (set (match_operand:SI 7 "s_register_operand" "=r")
9274 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9275 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9276 "TARGET_ARM"
9277 "#"
9278 "TARGET_ARM && reload_completed"
9279 [(set (match_dup 0)
9280 (compare
9281 (ior:SI
9282 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9283 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9284 (const_int 0)))
9285 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9286 ""
9287 [(set_attr "conds" "set")
9288 (set_attr "length" "16")])
03f1640c
RE
9289
9290(define_insn_and_split "*and_scc_scc"
9291 [(set (match_operand:SI 0 "s_register_operand" "=r")
9292 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9293 [(match_operand:SI 1 "s_register_operand" "r")
9294 (match_operand:SI 2 "arm_add_operand" "rIL")])
9295 (match_operator:SI 6 "arm_comparison_operator"
9296 [(match_operand:SI 4 "s_register_operand" "r")
9297 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9298 (clobber (reg:CC CC_REGNUM))]
9299 "TARGET_ARM
9300 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9301 != CCmode)"
9302 "#"
9af66e58
RE
9303 "TARGET_ARM && reload_completed
9304 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9305 != CCmode)"
03f1640c
RE
9306 [(set (match_dup 7)
9307 (compare
9308 (and:SI
9309 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9310 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9311 (const_int 0)))
9312 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9313 "operands[7]
9314 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9315 DOM_CC_X_AND_Y),
9af66e58
RE
9316 CC_REGNUM);"
9317 [(set_attr "conds" "clob")
9318 (set_attr "length" "16")])
9319
9320; If the above pattern is followed by a CMP insn, then the compare is
9321; redundant, since we can rework the conditional instruction that follows.
9322(define_insn_and_split "*and_scc_scc_cmp"
9323 [(set (match_operand 0 "dominant_cc_register" "")
9324 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9325 [(match_operand:SI 1 "s_register_operand" "r")
9326 (match_operand:SI 2 "arm_add_operand" "rIL")])
9327 (match_operator:SI 6 "arm_comparison_operator"
9328 [(match_operand:SI 4 "s_register_operand" "r")
9329 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9330 (const_int 0)))
9331 (set (match_operand:SI 7 "s_register_operand" "=r")
9332 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9333 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9334 "TARGET_ARM"
9335 "#"
9336 "TARGET_ARM && reload_completed"
9337 [(set (match_dup 0)
9338 (compare
9339 (and:SI
9340 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9341 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9342 (const_int 0)))
9343 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9344 ""
9345 [(set_attr "conds" "set")
9346 (set_attr "length" "16")])
9347
9348;; If there is no dominance in the comparison, then we can still save an
9349;; instruction in the AND case, since we can know that the second compare
9350;; need only zero the value if false (if true, then the value is already
9351;; correct).
9352(define_insn_and_split "*and_scc_scc_nodom"
9353 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9354 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9355 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9356 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9357 (match_operator:SI 6 "arm_comparison_operator"
9358 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9359 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9360 (clobber (reg:CC CC_REGNUM))]
9361 "TARGET_ARM
9362 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9363 == CCmode)"
9364 "#"
9365 "TARGET_ARM && reload_completed"
9366 [(parallel [(set (match_dup 0)
9367 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9368 (clobber (reg:CC CC_REGNUM))])
9369 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9370 (set (match_dup 0)
9371 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9372 (match_dup 0)
9373 (const_int 0)))]
9374 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9375 operands[4], operands[5]),
9376 CC_REGNUM);
9377 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9378 operands[5]);"
9379 [(set_attr "conds" "clob")
9380 (set_attr "length" "20")])
03f1640c 9381
e25c906a
RE
9382(define_split
9383 [(set (reg:CC_NOOV CC_REGNUM)
9384 (compare:CC_NOOV (ior:SI
9385 (and:SI (match_operand:SI 0 "s_register_operand" "")
9386 (const_int 1))
9387 (match_operator:SI 1 "comparison_operator"
9388 [(match_operand:SI 2 "s_register_operand" "")
9389 (match_operand:SI 3 "arm_add_operand" "")]))
9390 (const_int 0)))
9391 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9392 "TARGET_ARM"
9393 [(set (match_dup 4)
9394 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9395 (match_dup 0)))
9396 (set (reg:CC_NOOV CC_REGNUM)
9397 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9398 (const_int 0)))]
9399 "")
9400
9401(define_split
9402 [(set (reg:CC_NOOV CC_REGNUM)
9403 (compare:CC_NOOV (ior:SI
9404 (match_operator:SI 1 "comparison_operator"
9405 [(match_operand:SI 2 "s_register_operand" "")
9406 (match_operand:SI 3 "arm_add_operand" "")])
9407 (and:SI (match_operand:SI 0 "s_register_operand" "")
9408 (const_int 1)))
9409 (const_int 0)))
9410 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9411 "TARGET_ARM"
9412 [(set (match_dup 4)
9413 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9414 (match_dup 0)))
9415 (set (reg:CC_NOOV CC_REGNUM)
9416 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9417 (const_int 0)))]
9418 "")
5b3e6663 9419;; ??? The conditional patterns above need checking for Thumb-2 usefulness
e25c906a 9420
4cdb3ed4 9421(define_insn "*negscc"
ff9940b0 9422 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 9423 (neg:SI (match_operator 3 "arm_comparison_operator"
ff9940b0
RE
9424 [(match_operand:SI 1 "s_register_operand" "r")
9425 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
48a08b9c 9426 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9427 "TARGET_ARM"
ff9940b0 9428 "*
630ef467 9429 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
0f447ef2
RE
9430 return \"mov\\t%0, %1, asr #31\";
9431
ff9940b0 9432 if (GET_CODE (operands[3]) == NE)
0f447ef2
RE
9433 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9434
0f447ef2
RE
9435 output_asm_insn (\"cmp\\t%1, %2\", operands);
9436 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9437 return \"mvn%d3\\t%0, #0\";
5895f793 9438 "
05ed98a1
RE
9439 [(set_attr "conds" "clob")
9440 (set_attr "length" "12")]
9441)
ff9940b0
RE
9442
9443(define_insn "movcond"
9444 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
68df59d3 9445 (if_then_else:SI
05ed98a1 9446 (match_operator 5 "arm_comparison_operator"
68df59d3
RE
9447 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9448 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9449 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9450 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
48a08b9c 9451 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9452 "TARGET_ARM"
ff9940b0
RE
9453 "*
9454 if (GET_CODE (operands[5]) == LT
9455 && (operands[4] == const0_rtx))
9456 {
68df59d3 9457 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
ff9940b0 9458 {
ff9940b0 9459 if (operands[2] == const0_rtx)
0f447ef2
RE
9460 return \"and\\t%0, %1, %3, asr #31\";
9461 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
ff9940b0
RE
9462 }
9463 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9464 {
ff9940b0 9465 if (operands[1] == const0_rtx)
0f447ef2
RE
9466 return \"bic\\t%0, %2, %3, asr #31\";
9467 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
ff9940b0
RE
9468 }
9469 /* The only case that falls through to here is when both ops 1 & 2
d6b4baa4 9470 are constants. */
ff9940b0 9471 }
0f447ef2 9472
ff9940b0
RE
9473 if (GET_CODE (operands[5]) == GE
9474 && (operands[4] == const0_rtx))
9475 {
9476 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9477 {
ff9940b0 9478 if (operands[2] == const0_rtx)
0f447ef2
RE
9479 return \"bic\\t%0, %1, %3, asr #31\";
9480 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
ff9940b0
RE
9481 }
9482 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9483 {
ff9940b0 9484 if (operands[1] == const0_rtx)
0f447ef2
RE
9485 return \"and\\t%0, %2, %3, asr #31\";
9486 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
ff9940b0
RE
9487 }
9488 /* The only case that falls through to here is when both ops 1 & 2
d6b4baa4 9489 are constants. */
ff9940b0
RE
9490 }
9491 if (GET_CODE (operands[4]) == CONST_INT
9492 && !const_ok_for_arm (INTVAL (operands[4])))
0f447ef2 9493 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
ff9940b0 9494 else
0f447ef2 9495 output_asm_insn (\"cmp\\t%3, %4\", operands);
ff9940b0 9496 if (which_alternative != 0)
0f447ef2 9497 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
ff9940b0 9498 if (which_alternative != 1)
0f447ef2 9499 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
ff9940b0 9500 return \"\";
5895f793 9501 "
05ed98a1
RE
9502 [(set_attr "conds" "clob")
9503 (set_attr "length" "8,8,12")]
9504)
ff9940b0 9505
5b3e6663
PB
9506;; ??? The patterns below need checking for Thumb-2 usefulness.
9507
f54fd62e
RE
9508(define_insn "*ifcompare_plus_move"
9509 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9510 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9511 [(match_operand:SI 4 "s_register_operand" "r,r")
9512 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9513 (plus:SI
9514 (match_operand:SI 2 "s_register_operand" "r,r")
9515 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
b36ba79f 9516 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
48a08b9c 9517 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9518 "TARGET_ARM"
f54fd62e 9519 "#"
05ed98a1
RE
9520 [(set_attr "conds" "clob")
9521 (set_attr "length" "8,12")]
9522)
f54fd62e
RE
9523
9524(define_insn "*if_plus_move"
b36ba79f 9525 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
f54fd62e 9526 (if_then_else:SI
05ed98a1 9527 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9528 [(match_operand 5 "cc_register" "") (const_int 0)])
9529 (plus:SI
b36ba79f
RE
9530 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9531 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9532 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
d5b7b3ae 9533 "TARGET_ARM"
f54fd62e
RE
9534 "@
9535 add%d4\\t%0, %2, %3
9536 sub%d4\\t%0, %2, #%n3
9537 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
b36ba79f 9538 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
05ed98a1
RE
9539 [(set_attr "conds" "use")
9540 (set_attr "length" "4,4,8,8")
9541 (set_attr "type" "*,*,*,*")]
9542)
f54fd62e
RE
9543
9544(define_insn "*ifcompare_move_plus"
68df59d3 9545 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9546 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9547 [(match_operand:SI 4 "s_register_operand" "r,r")
9548 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
b36ba79f 9549 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
f54fd62e
RE
9550 (plus:SI
9551 (match_operand:SI 2 "s_register_operand" "r,r")
9552 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
48a08b9c 9553 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9554 "TARGET_ARM"
f54fd62e 9555 "#"
05ed98a1
RE
9556 [(set_attr "conds" "clob")
9557 (set_attr "length" "8,12")]
9558)
f54fd62e
RE
9559
9560(define_insn "*if_move_plus"
b36ba79f 9561 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
f54fd62e 9562 (if_then_else:SI
05ed98a1 9563 (match_operator 4 "arm_comparison_operator"
f54fd62e 9564 [(match_operand 5 "cc_register" "") (const_int 0)])
b36ba79f 9565 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
f54fd62e 9566 (plus:SI
b36ba79f
RE
9567 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9568 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
d5b7b3ae 9569 "TARGET_ARM"
f54fd62e
RE
9570 "@
9571 add%D4\\t%0, %2, %3
9572 sub%D4\\t%0, %2, #%n3
9573 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
b36ba79f 9574 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
05ed98a1
RE
9575 [(set_attr "conds" "use")
9576 (set_attr "length" "4,4,8,8")
9577 (set_attr "type" "*,*,*,*")]
9578)
f54fd62e
RE
9579
9580(define_insn "*ifcompare_arith_arith"
9581 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 9582 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
f54fd62e
RE
9583 [(match_operand:SI 5 "s_register_operand" "r")
9584 (match_operand:SI 6 "arm_add_operand" "rIL")])
ff9940b0 9585 (match_operator:SI 8 "shiftable_operator"
f54fd62e
RE
9586 [(match_operand:SI 1 "s_register_operand" "r")
9587 (match_operand:SI 2 "arm_rhs_operand" "rI")])
ff9940b0 9588 (match_operator:SI 7 "shiftable_operator"
f54fd62e
RE
9589 [(match_operand:SI 3 "s_register_operand" "r")
9590 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
48a08b9c 9591 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9592 "TARGET_ARM"
f54fd62e 9593 "#"
05ed98a1
RE
9594 [(set_attr "conds" "clob")
9595 (set_attr "length" "12")]
9596)
ff9940b0 9597
f54fd62e
RE
9598(define_insn "*if_arith_arith"
9599 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 9600 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9601 [(match_operand 8 "cc_register" "") (const_int 0)])
9602 (match_operator:SI 6 "shiftable_operator"
9603 [(match_operand:SI 1 "s_register_operand" "r")
9604 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9605 (match_operator:SI 7 "shiftable_operator"
9606 [(match_operand:SI 3 "s_register_operand" "r")
9607 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
d5b7b3ae 9608 "TARGET_ARM"
f54fd62e 9609 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
05ed98a1
RE
9610 [(set_attr "conds" "use")
9611 (set_attr "length" "8")]
9612)
f54fd62e 9613
4cdb3ed4 9614(define_insn "*ifcompare_arith_move"
ff9940b0 9615 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9616 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
ff9940b0 9617 [(match_operand:SI 2 "s_register_operand" "r,r")
68df59d3 9618 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
ff9940b0
RE
9619 (match_operator:SI 7 "shiftable_operator"
9620 [(match_operand:SI 4 "s_register_operand" "r,r")
9621 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
b36ba79f 9622 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
48a08b9c 9623 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9624 "TARGET_ARM"
ff9940b0 9625 "*
ff9940b0 9626 /* If we have an operation where (op x 0) is the identity operation and
ddd5a7c1 9627 the conditional operator is LT or GE and we are comparing against zero and
d6b4baa4 9628 everything is in registers then we can do this in two instructions. */
ff9940b0
RE
9629 if (operands[3] == const0_rtx
9630 && GET_CODE (operands[7]) != AND
9631 && GET_CODE (operands[5]) == REG
9632 && GET_CODE (operands[1]) == REG
9633 && REGNO (operands[1]) == REGNO (operands[4])
9634 && REGNO (operands[4]) != REGNO (operands[0]))
9635 {
9636 if (GET_CODE (operands[6]) == LT)
c63165be 9637 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
ff9940b0 9638 else if (GET_CODE (operands[6]) == GE)
c63165be 9639 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
ff9940b0
RE
9640 }
9641 if (GET_CODE (operands[3]) == CONST_INT
9642 && !const_ok_for_arm (INTVAL (operands[3])))
0f447ef2 9643 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
ff9940b0 9644 else
0f447ef2 9645 output_asm_insn (\"cmp\\t%2, %3\", operands);
c63165be 9646 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
ff9940b0 9647 if (which_alternative != 0)
b36ba79f 9648 return \"mov%D6\\t%0, %1\";
ff9940b0 9649 return \"\";
5895f793 9650 "
05ed98a1
RE
9651 [(set_attr "conds" "clob")
9652 (set_attr "length" "8,12")]
9653)
ff9940b0 9654
f54fd62e 9655(define_insn "*if_arith_move"
b36ba79f 9656 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9657 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9658 [(match_operand 6 "cc_register" "") (const_int 0)])
9659 (match_operator:SI 5 "shiftable_operator"
b36ba79f
RE
9660 [(match_operand:SI 2 "s_register_operand" "r,r")
9661 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9662 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
d5b7b3ae 9663 "TARGET_ARM"
f54fd62e
RE
9664 "@
9665 %I5%d4\\t%0, %2, %3
b36ba79f 9666 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
05ed98a1
RE
9667 [(set_attr "conds" "use")
9668 (set_attr "length" "4,8")
9669 (set_attr "type" "*,*")]
9670)
f54fd62e 9671
4cdb3ed4 9672(define_insn "*ifcompare_move_arith"
ff9940b0 9673 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 9674 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
ff9940b0 9675 [(match_operand:SI 4 "s_register_operand" "r,r")
68df59d3 9676 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
b36ba79f 9677 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
ff9940b0
RE
9678 (match_operator:SI 7 "shiftable_operator"
9679 [(match_operand:SI 2 "s_register_operand" "r,r")
9680 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
48a08b9c 9681 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9682 "TARGET_ARM"
ff9940b0 9683 "*
ff9940b0 9684 /* If we have an operation where (op x 0) is the identity operation and
ddd5a7c1 9685 the conditional operator is LT or GE and we are comparing against zero and
ff9940b0
RE
9686 everything is in registers then we can do this in two instructions */
9687 if (operands[5] == const0_rtx
9688 && GET_CODE (operands[7]) != AND
9689 && GET_CODE (operands[3]) == REG
9690 && GET_CODE (operands[1]) == REG
9691 && REGNO (operands[1]) == REGNO (operands[2])
9692 && REGNO (operands[2]) != REGNO (operands[0]))
9693 {
9694 if (GET_CODE (operands[6]) == GE)
c63165be 9695 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
ff9940b0 9696 else if (GET_CODE (operands[6]) == LT)
c63165be 9697 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
ff9940b0 9698 }
c63165be 9699
ff9940b0
RE
9700 if (GET_CODE (operands[5]) == CONST_INT
9701 && !const_ok_for_arm (INTVAL (operands[5])))
0f447ef2 9702 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
ff9940b0 9703 else
0f447ef2 9704 output_asm_insn (\"cmp\\t%4, %5\", operands);
c63165be 9705
ff9940b0 9706 if (which_alternative != 0)
b36ba79f 9707 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
c63165be 9708 return \"%I7%D6\\t%0, %2, %3\";
5895f793 9709 "
05ed98a1
RE
9710 [(set_attr "conds" "clob")
9711 (set_attr "length" "8,12")]
9712)
ff9940b0 9713
f54fd62e 9714(define_insn "*if_move_arith"
b36ba79f 9715 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 9716 (if_then_else:SI
05ed98a1 9717 (match_operator 4 "arm_comparison_operator"
f54fd62e 9718 [(match_operand 6 "cc_register" "") (const_int 0)])
b36ba79f 9719 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
f54fd62e 9720 (match_operator:SI 5 "shiftable_operator"
b36ba79f
RE
9721 [(match_operand:SI 2 "s_register_operand" "r,r")
9722 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
d5b7b3ae 9723 "TARGET_ARM"
f54fd62e
RE
9724 "@
9725 %I5%D4\\t%0, %2, %3
b36ba79f 9726 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
05ed98a1
RE
9727 [(set_attr "conds" "use")
9728 (set_attr "length" "4,8")
9729 (set_attr "type" "*,*")]
9730)
f54fd62e
RE
9731
9732(define_insn "*ifcompare_move_not"
ff9940b0 9733 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 9734 (if_then_else:SI
05ed98a1 9735 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9736 [(match_operand:SI 3 "s_register_operand" "r,r")
9737 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9738 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9739 (not:SI
9740 (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 9741 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9742 "TARGET_ARM"
f54fd62e 9743 "#"
05ed98a1
RE
9744 [(set_attr "conds" "clob")
9745 (set_attr "length" "8,12")]
9746)
ff9940b0 9747
f54fd62e
RE
9748(define_insn "*if_move_not"
9749 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9750 (if_then_else:SI
05ed98a1 9751 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9752 [(match_operand 3 "cc_register" "") (const_int 0)])
9753 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9754 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
d5b7b3ae 9755 "TARGET_ARM"
f54fd62e
RE
9756 "@
9757 mvn%D4\\t%0, %2
9758 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9759 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
05ed98a1
RE
9760 [(set_attr "conds" "use")
9761 (set_attr "length" "4,8,8")]
9762)
f54fd62e
RE
9763
9764(define_insn "*ifcompare_not_move"
ff9940b0 9765 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 9766 (if_then_else:SI
05ed98a1 9767 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9768 [(match_operand:SI 3 "s_register_operand" "r,r")
9769 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9770 (not:SI
9771 (match_operand:SI 2 "s_register_operand" "r,r"))
9772 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
48a08b9c 9773 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9774 "TARGET_ARM"
f54fd62e 9775 "#"
05ed98a1
RE
9776 [(set_attr "conds" "clob")
9777 (set_attr "length" "8,12")]
9778)
ff9940b0 9779
f54fd62e
RE
9780(define_insn "*if_not_move"
9781 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9782 (if_then_else:SI
05ed98a1 9783 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9784 [(match_operand 3 "cc_register" "") (const_int 0)])
9785 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9786 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
d5b7b3ae 9787 "TARGET_ARM"
f54fd62e
RE
9788 "@
9789 mvn%d4\\t%0, %2
9790 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9791 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
05ed98a1
RE
9792 [(set_attr "conds" "use")
9793 (set_attr "length" "4,8,8")]
9794)
f54fd62e
RE
9795
9796(define_insn "*ifcompare_shift_move"
ff9940b0 9797 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 9798 (if_then_else:SI
05ed98a1 9799 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9800 [(match_operand:SI 4 "s_register_operand" "r,r")
9801 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9802 (match_operator:SI 7 "shift_operator"
9803 [(match_operand:SI 2 "s_register_operand" "r,r")
9804 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9805 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
48a08b9c 9806 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9807 "TARGET_ARM"
ff9940b0 9808 "#"
05ed98a1
RE
9809 [(set_attr "conds" "clob")
9810 (set_attr "length" "8,12")]
9811)
ff9940b0 9812
f54fd62e
RE
9813(define_insn "*if_shift_move"
9814 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9815 (if_then_else:SI
05ed98a1 9816 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9817 [(match_operand 6 "cc_register" "") (const_int 0)])
9818 (match_operator:SI 4 "shift_operator"
9819 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9820 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9821 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
d5b7b3ae 9822 "TARGET_ARM"
68df59d3 9823 "@
f54fd62e
RE
9824 mov%d5\\t%0, %2%S4
9825 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9826 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
05ed98a1 9827 [(set_attr "conds" "use")
d19fb8e3 9828 (set_attr "shift" "2")
9b66ebb1
PB
9829 (set_attr "length" "4,8,8")
9830 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9831 (const_string "alu_shift")
9832 (const_string "alu_shift_reg")))]
05ed98a1 9833)
68df59d3 9834
f54fd62e
RE
9835(define_insn "*ifcompare_move_shift"
9836 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
68df59d3 9837 (if_then_else:SI
05ed98a1 9838 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9839 [(match_operand:SI 4 "s_register_operand" "r,r")
9840 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9841 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
68df59d3 9842 (match_operator:SI 7 "shift_operator"
f54fd62e
RE
9843 [(match_operand:SI 2 "s_register_operand" "r,r")
9844 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
48a08b9c 9845 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9846 "TARGET_ARM"
f54fd62e 9847 "#"
05ed98a1
RE
9848 [(set_attr "conds" "clob")
9849 (set_attr "length" "8,12")]
9850)
68df59d3 9851
f54fd62e
RE
9852(define_insn "*if_move_shift"
9853 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
68df59d3 9854 (if_then_else:SI
05ed98a1 9855 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9856 [(match_operand 6 "cc_register" "") (const_int 0)])
9857 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9858 (match_operator:SI 4 "shift_operator"
9859 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9860 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
d5b7b3ae 9861 "TARGET_ARM"
68df59d3 9862 "@
f54fd62e
RE
9863 mov%D5\\t%0, %2%S4
9864 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9865 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
05ed98a1 9866 [(set_attr "conds" "use")
d19fb8e3 9867 (set_attr "shift" "2")
9b66ebb1
PB
9868 (set_attr "length" "4,8,8")
9869 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9870 (const_string "alu_shift")
9871 (const_string "alu_shift_reg")))]
05ed98a1 9872)
ff9940b0 9873
4cdb3ed4 9874(define_insn "*ifcompare_shift_shift"
f54fd62e 9875 [(set (match_operand:SI 0 "s_register_operand" "=r")
68df59d3 9876 (if_then_else:SI
05ed98a1 9877 (match_operator 7 "arm_comparison_operator"
f54fd62e
RE
9878 [(match_operand:SI 5 "s_register_operand" "r")
9879 (match_operand:SI 6 "arm_add_operand" "rIL")])
68df59d3 9880 (match_operator:SI 8 "shift_operator"
f54fd62e
RE
9881 [(match_operand:SI 1 "s_register_operand" "r")
9882 (match_operand:SI 2 "arm_rhs_operand" "rM")])
68df59d3 9883 (match_operator:SI 9 "shift_operator"
f54fd62e
RE
9884 [(match_operand:SI 3 "s_register_operand" "r")
9885 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
48a08b9c 9886 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9887 "TARGET_ARM"
f54fd62e 9888 "#"
05ed98a1
RE
9889 [(set_attr "conds" "clob")
9890 (set_attr "length" "12")]
9891)
ff9940b0 9892
f54fd62e
RE
9893(define_insn "*if_shift_shift"
9894 [(set (match_operand:SI 0 "s_register_operand" "=r")
9895 (if_then_else:SI
05ed98a1 9896 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9897 [(match_operand 8 "cc_register" "") (const_int 0)])
9898 (match_operator:SI 6 "shift_operator"
9899 [(match_operand:SI 1 "s_register_operand" "r")
9900 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9901 (match_operator:SI 7 "shift_operator"
9902 [(match_operand:SI 3 "s_register_operand" "r")
9903 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
d5b7b3ae 9904 "TARGET_ARM"
f54fd62e 9905 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
05ed98a1 9906 [(set_attr "conds" "use")
d19fb8e3 9907 (set_attr "shift" "1")
9b66ebb1
PB
9908 (set_attr "length" "8")
9909 (set (attr "type") (if_then_else
9910 (and (match_operand 2 "const_int_operand" "")
9911 (match_operand 4 "const_int_operand" ""))
9912 (const_string "alu_shift")
9913 (const_string "alu_shift_reg")))]
05ed98a1 9914)
f54fd62e 9915
4cdb3ed4 9916(define_insn "*ifcompare_not_arith"
f54fd62e 9917 [(set (match_operand:SI 0 "s_register_operand" "=r")
68df59d3 9918 (if_then_else:SI
05ed98a1 9919 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9920 [(match_operand:SI 4 "s_register_operand" "r")
9921 (match_operand:SI 5 "arm_add_operand" "rIL")])
9922 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
68df59d3 9923 (match_operator:SI 7 "shiftable_operator"
f54fd62e
RE
9924 [(match_operand:SI 2 "s_register_operand" "r")
9925 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
48a08b9c 9926 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9927 "TARGET_ARM"
f54fd62e 9928 "#"
05ed98a1
RE
9929 [(set_attr "conds" "clob")
9930 (set_attr "length" "12")]
9931)
ff9940b0 9932
f54fd62e
RE
9933(define_insn "*if_not_arith"
9934 [(set (match_operand:SI 0 "s_register_operand" "=r")
9935 (if_then_else:SI
05ed98a1 9936 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9937 [(match_operand 4 "cc_register" "") (const_int 0)])
9938 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9939 (match_operator:SI 6 "shiftable_operator"
9940 [(match_operand:SI 2 "s_register_operand" "r")
9941 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
d5b7b3ae 9942 "TARGET_ARM"
f54fd62e 9943 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
05ed98a1
RE
9944 [(set_attr "conds" "use")
9945 (set_attr "length" "8")]
9946)
f54fd62e
RE
9947
9948(define_insn "*ifcompare_arith_not"
9949 [(set (match_operand:SI 0 "s_register_operand" "=r")
68df59d3 9950 (if_then_else:SI
05ed98a1 9951 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
9952 [(match_operand:SI 4 "s_register_operand" "r")
9953 (match_operand:SI 5 "arm_add_operand" "rIL")])
68df59d3 9954 (match_operator:SI 7 "shiftable_operator"
f54fd62e
RE
9955 [(match_operand:SI 2 "s_register_operand" "r")
9956 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9957 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
48a08b9c 9958 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9959 "TARGET_ARM"
f54fd62e 9960 "#"
05ed98a1
RE
9961 [(set_attr "conds" "clob")
9962 (set_attr "length" "12")]
9963)
ff9940b0 9964
f54fd62e
RE
9965(define_insn "*if_arith_not"
9966 [(set (match_operand:SI 0 "s_register_operand" "=r")
9967 (if_then_else:SI
05ed98a1 9968 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9969 [(match_operand 4 "cc_register" "") (const_int 0)])
9970 (match_operator:SI 6 "shiftable_operator"
9971 [(match_operand:SI 2 "s_register_operand" "r")
9972 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9973 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
d5b7b3ae 9974 "TARGET_ARM"
f54fd62e 9975 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
05ed98a1
RE
9976 [(set_attr "conds" "use")
9977 (set_attr "length" "8")]
9978)
f54fd62e 9979
4cdb3ed4 9980(define_insn "*ifcompare_neg_move"
f54fd62e 9981 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
68df59d3 9982 (if_then_else:SI
05ed98a1 9983 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
9984 [(match_operand:SI 3 "s_register_operand" "r,r")
9985 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9986 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9987 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
48a08b9c 9988 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 9989 "TARGET_ARM"
f54fd62e 9990 "#"
05ed98a1
RE
9991 [(set_attr "conds" "clob")
9992 (set_attr "length" "8,12")]
9993)
f54fd62e
RE
9994
9995(define_insn "*if_neg_move"
9996 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9997 (if_then_else:SI
05ed98a1 9998 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
9999 [(match_operand 3 "cc_register" "") (const_int 0)])
10000 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10001 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
d5b7b3ae 10002 "TARGET_ARM"
f54fd62e
RE
10003 "@
10004 rsb%d4\\t%0, %2, #0
10005 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10006 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
05ed98a1
RE
10007 [(set_attr "conds" "use")
10008 (set_attr "length" "4,8,8")]
10009)
ff9940b0 10010
4cdb3ed4 10011(define_insn "*ifcompare_move_neg"
f54fd62e 10012 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
68df59d3 10013 (if_then_else:SI
05ed98a1 10014 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
10015 [(match_operand:SI 3 "s_register_operand" "r,r")
10016 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10017 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10018 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 10019 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 10020 "TARGET_ARM"
f54fd62e 10021 "#"
05ed98a1
RE
10022 [(set_attr "conds" "clob")
10023 (set_attr "length" "8,12")]
10024)
f54fd62e
RE
10025
10026(define_insn "*if_move_neg"
10027 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10028 (if_then_else:SI
05ed98a1 10029 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
10030 [(match_operand 3 "cc_register" "") (const_int 0)])
10031 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10032 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
d5b7b3ae 10033 "TARGET_ARM"
f54fd62e
RE
10034 "@
10035 rsb%D4\\t%0, %2, #0
10036 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10037 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
cca0a211
RE
10038 [(set_attr "conds" "use")
10039 (set_attr "length" "4,8,8")]
10040)
ff9940b0 10041
4cdb3ed4 10042(define_insn "*arith_adjacentmem"
ff9940b0
RE
10043 [(set (match_operand:SI 0 "s_register_operand" "=r")
10044 (match_operator:SI 1 "shiftable_operator"
10045 [(match_operand:SI 2 "memory_operand" "m")
10046 (match_operand:SI 3 "memory_operand" "m")]))
10047 (clobber (match_scratch:SI 4 "=r"))]
d5b7b3ae 10048 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
ff9940b0 10049 "*
5895f793
RE
10050 {
10051 rtx ldm[3];
10052 rtx arith[4];
15b5c4c1
RE
10053 rtx base_reg;
10054 HOST_WIDE_INT val1 = 0, val2 = 0;
ff9940b0 10055
5895f793
RE
10056 if (REGNO (operands[0]) > REGNO (operands[4]))
10057 {
10058 ldm[1] = operands[4];
10059 ldm[2] = operands[0];
10060 }
10061 else
10062 {
10063 ldm[1] = operands[0];
10064 ldm[2] = operands[4];
10065 }
15b5c4c1
RE
10066
10067 base_reg = XEXP (operands[2], 0);
10068
10069 if (!REG_P (base_reg))
10070 {
10071 val1 = INTVAL (XEXP (base_reg, 1));
10072 base_reg = XEXP (base_reg, 0);
10073 }
10074
10075 if (!REG_P (XEXP (operands[3], 0)))
5895f793 10076 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
15b5c4c1 10077
5895f793
RE
10078 arith[0] = operands[0];
10079 arith[3] = operands[1];
15b5c4c1 10080
5895f793
RE
10081 if (val1 < val2)
10082 {
10083 arith[1] = ldm[1];
10084 arith[2] = ldm[2];
10085 }
10086 else
10087 {
10088 arith[1] = ldm[2];
10089 arith[2] = ldm[1];
10090 }
15b5c4c1
RE
10091
10092 ldm[0] = base_reg;
10093 if (val1 !=0 && val2 != 0)
5895f793 10094 {
bcf640f7
PB
10095 rtx ops[3];
10096
15b5c4c1
RE
10097 if (val1 == 4 || val2 == 4)
10098 /* Other val must be 8, since we know they are adjacent and neither
10099 is zero. */
5b3e6663 10100 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
bcf640f7 10101 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
15b5c4c1 10102 {
15b5c4c1
RE
10103 ldm[0] = ops[0] = operands[4];
10104 ops[1] = base_reg;
10105 ops[2] = GEN_INT (val1);
10106 output_add_immediate (ops);
10107 if (val1 < val2)
5b3e6663 10108 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
15b5c4c1 10109 else
5b3e6663 10110 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
15b5c4c1 10111 }
bcf640f7
PB
10112 else
10113 {
10114 /* Offset is out of range for a single add, so use two ldr. */
10115 ops[0] = ldm[1];
10116 ops[1] = base_reg;
10117 ops[2] = GEN_INT (val1);
10118 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10119 ops[0] = ldm[2];
10120 ops[2] = GEN_INT (val2);
10121 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10122 }
5895f793 10123 }
15b5c4c1 10124 else if (val1 != 0)
5895f793 10125 {
5895f793 10126 if (val1 < val2)
5b3e6663 10127 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
5895f793 10128 else
5b3e6663 10129 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
5895f793
RE
10130 }
10131 else
10132 {
5895f793 10133 if (val1 < val2)
5b3e6663 10134 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
5895f793 10135 else
5b3e6663 10136 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
5895f793
RE
10137 }
10138 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10139 return \"\";
10140 }"
10141 [(set_attr "length" "12")
10142 (set_attr "predicable" "yes")
9b66ebb1 10143 (set_attr "type" "load1")]
5895f793 10144)
ff9940b0 10145
ff9940b0
RE
10146; This pattern is never tried by combine, so do it as a peephole
10147
bb6ae783 10148(define_peephole2
3053b100
RE
10149 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10150 (match_operand:SI 1 "arm_general_register_operand" ""))
48a08b9c 10151 (set (reg:CC CC_REGNUM)
589fe0fc 10152 (compare:CC (match_dup 1) (const_int 0)))]
3053b100 10153 "TARGET_ARM"
bb6ae783
RE
10154 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10155 (set (match_dup 0) (match_dup 1))])]
10156 ""
cca0a211 10157)
ff9940b0 10158
25b1c156
NC
10159; Peepholes to spot possible load- and store-multiples, if the ordering is
10160; reversed, check that the memory references aren't volatile.
ff9940b0
RE
10161
10162(define_peephole
10163 [(set (match_operand:SI 0 "s_register_operand" "=r")
589fe0fc
RE
10164 (match_operand:SI 4 "memory_operand" "m"))
10165 (set (match_operand:SI 1 "s_register_operand" "=r")
10166 (match_operand:SI 5 "memory_operand" "m"))
ff9940b0 10167 (set (match_operand:SI 2 "s_register_operand" "=r")
589fe0fc 10168 (match_operand:SI 6 "memory_operand" "m"))
ff9940b0 10169 (set (match_operand:SI 3 "s_register_operand" "=r")
589fe0fc 10170 (match_operand:SI 7 "memory_operand" "m"))]
d5b7b3ae 10171 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
589fe0fc
RE
10172 "*
10173 return emit_ldm_seq (operands, 4);
5895f793
RE
10174 "
10175)
ff9940b0
RE
10176
10177(define_peephole
10178 [(set (match_operand:SI 0 "s_register_operand" "=r")
589fe0fc
RE
10179 (match_operand:SI 3 "memory_operand" "m"))
10180 (set (match_operand:SI 1 "s_register_operand" "=r")
10181 (match_operand:SI 4 "memory_operand" "m"))
ff9940b0 10182 (set (match_operand:SI 2 "s_register_operand" "=r")
589fe0fc 10183 (match_operand:SI 5 "memory_operand" "m"))]
d5b7b3ae 10184 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
589fe0fc
RE
10185 "*
10186 return emit_ldm_seq (operands, 3);
5895f793
RE
10187 "
10188)
ff9940b0
RE
10189
10190(define_peephole
10191 [(set (match_operand:SI 0 "s_register_operand" "=r")
589fe0fc
RE
10192 (match_operand:SI 2 "memory_operand" "m"))
10193 (set (match_operand:SI 1 "s_register_operand" "=r")
10194 (match_operand:SI 3 "memory_operand" "m"))]
d5b7b3ae 10195 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
589fe0fc
RE
10196 "*
10197 return emit_ldm_seq (operands, 2);
5895f793
RE
10198 "
10199)
ff9940b0
RE
10200
10201(define_peephole
589fe0fc 10202 [(set (match_operand:SI 4 "memory_operand" "=m")
ff9940b0 10203 (match_operand:SI 0 "s_register_operand" "r"))
589fe0fc
RE
10204 (set (match_operand:SI 5 "memory_operand" "=m")
10205 (match_operand:SI 1 "s_register_operand" "r"))
10206 (set (match_operand:SI 6 "memory_operand" "=m")
ff9940b0 10207 (match_operand:SI 2 "s_register_operand" "r"))
589fe0fc
RE
10208 (set (match_operand:SI 7 "memory_operand" "=m")
10209 (match_operand:SI 3 "s_register_operand" "r"))]
d5b7b3ae 10210 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
589fe0fc
RE
10211 "*
10212 return emit_stm_seq (operands, 4);
5895f793
RE
10213 "
10214)
ff9940b0
RE
10215
10216(define_peephole
589fe0fc 10217 [(set (match_operand:SI 3 "memory_operand" "=m")
ff9940b0 10218 (match_operand:SI 0 "s_register_operand" "r"))
589fe0fc
RE
10219 (set (match_operand:SI 4 "memory_operand" "=m")
10220 (match_operand:SI 1 "s_register_operand" "r"))
10221 (set (match_operand:SI 5 "memory_operand" "=m")
10222 (match_operand:SI 2 "s_register_operand" "r"))]
d5b7b3ae 10223 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
589fe0fc
RE
10224 "*
10225 return emit_stm_seq (operands, 3);
5895f793
RE
10226 "
10227)
ff9940b0
RE
10228
10229(define_peephole
589fe0fc 10230 [(set (match_operand:SI 2 "memory_operand" "=m")
ff9940b0 10231 (match_operand:SI 0 "s_register_operand" "r"))
589fe0fc
RE
10232 (set (match_operand:SI 3 "memory_operand" "=m")
10233 (match_operand:SI 1 "s_register_operand" "r"))]
d5b7b3ae 10234 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
589fe0fc
RE
10235 "*
10236 return emit_stm_seq (operands, 2);
5895f793
RE
10237 "
10238)
ff9940b0 10239
ff9940b0
RE
10240(define_split
10241 [(set (match_operand:SI 0 "s_register_operand" "")
10242 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10243 (const_int 0))
05ed98a1 10244 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
ff9940b0
RE
10245 [(match_operand:SI 3 "s_register_operand" "")
10246 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10247 (clobber (match_operand:SI 5 "s_register_operand" ""))]
d5b7b3ae 10248 "TARGET_ARM"
ff9940b0
RE
10249 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10250 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10251 (match_dup 5)))]
5895f793
RE
10252 ""
10253)
ff9940b0 10254
589fe0fc
RE
10255;; This split can be used because CC_Z mode implies that the following
10256;; branch will be an equality, or an unsigned inequality, so the sign
10257;; extension is not needed.
ff9940b0 10258
589fe0fc 10259(define_split
48a08b9c 10260 [(set (reg:CC_Z CC_REGNUM)
589fe0fc
RE
10261 (compare:CC_Z
10262 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
ff9940b0 10263 (const_int 24))
589fe0fc
RE
10264 (match_operand 1 "const_int_operand" "")))
10265 (clobber (match_scratch:SI 2 ""))]
d5b7b3ae
RE
10266 "TARGET_ARM
10267 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10268 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
589fe0fc 10269 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
48a08b9c 10270 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
589fe0fc 10271 "
ff9940b0 10272 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5895f793
RE
10273 "
10274)
5b3e6663 10275;; ??? Check the patterns above for Thumb-2 usefulness
ff9940b0 10276
091426d3
RE
10277(define_expand "prologue"
10278 [(clobber (const_int 0))]
d5b7b3ae 10279 "TARGET_EITHER"
5b3e6663 10280 "if (TARGET_32BIT)
d5b7b3ae
RE
10281 arm_expand_prologue ();
10282 else
5b3e6663 10283 thumb1_expand_prologue ();
091426d3 10284 DONE;
d5b7b3ae
RE
10285 "
10286)
091426d3 10287
949d79eb 10288(define_expand "epilogue"
c9ca9b88 10289 [(clobber (const_int 0))]
d5b7b3ae 10290 "TARGET_EITHER"
949d79eb 10291 "
c9ca9b88
PB
10292 if (current_function_calls_eh_return)
10293 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
5b3e6663
PB
10294 if (TARGET_THUMB1)
10295 thumb1_expand_epilogue ();
d5b7b3ae 10296 else if (USE_RETURN_INSN (FALSE))
949d79eb
RE
10297 {
10298 emit_jump_insn (gen_return ());
10299 DONE;
10300 }
d5b7b3ae
RE
10301 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10302 gen_rtvec (1,
10303 gen_rtx_RETURN (VOIDmode)),
b15bca31 10304 VUNSPEC_EPILOGUE));
d5b7b3ae
RE
10305 DONE;
10306 "
10307)
949d79eb 10308
e3289412
NC
10309;; Note - although unspec_volatile's USE all hard registers,
10310;; USEs are ignored after relaod has completed. Thus we need
10311;; to add an unspec of the link register to ensure that flow
10312;; does not think that it is unused by the sibcall branch that
10313;; will replace the standard function epilogue.
0616531f 10314(define_insn "sibcall_epilogue"
e3289412
NC
10315 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10316 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
5b3e6663 10317 "TARGET_32BIT"
0616531f 10318 "*
a72d4945 10319 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
64e92a26 10320 return output_return_instruction (const_true_rtx, FALSE, FALSE);
a72d4945 10321 return arm_output_epilogue (next_nonnote_insn (insn));
0616531f
RE
10322 "
10323;; Length is absolute worst case
10324 [(set_attr "length" "44")
0732a089
RE
10325 (set_attr "type" "block")
10326 ;; We don't clobber the conditions, but the potential length of this
10327 ;; operation is sufficient to make conditionalizing the sequence
10328 ;; unlikely to be profitable.
10329 (set_attr "conds" "clob")]
0616531f
RE
10330)
10331
d5b7b3ae 10332(define_insn "*epilogue_insns"
b15bca31 10333 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
d5b7b3ae 10334 "TARGET_EITHER"
949d79eb 10335 "*
5b3e6663 10336 if (TARGET_32BIT)
a72d4945 10337 return arm_output_epilogue (NULL);
5b3e6663 10338 else /* TARGET_THUMB1 */
d5b7b3ae
RE
10339 return thumb_unexpanded_epilogue ();
10340 "
5895f793 10341 ; Length is absolute worst case
d5b7b3ae 10342 [(set_attr "length" "44")
0732a089
RE
10343 (set_attr "type" "block")
10344 ;; We don't clobber the conditions, but the potential length of this
10345 ;; operation is sufficient to make conditionalizing the sequence
10346 ;; unlikely to be profitable.
10347 (set_attr "conds" "clob")]
d5b7b3ae
RE
10348)
10349
10350(define_expand "eh_epilogue"
82955615
RE
10351 [(use (match_operand:SI 0 "register_operand" ""))
10352 (use (match_operand:SI 1 "register_operand" ""))
10353 (use (match_operand:SI 2 "register_operand" ""))]
d5b7b3ae
RE
10354 "TARGET_EITHER"
10355 "
5895f793
RE
10356 {
10357 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10358 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10359 {
10360 rtx ra = gen_rtx_REG (Pmode, 2);
10361
10362 emit_move_insn (ra, operands[2]);
10363 operands[2] = ra;
10364 }
9b598fa0
RE
10365 /* This is a hack -- we may have crystalized the function type too
10366 early. */
10367 cfun->machine->func_type = 0;
5895f793
RE
10368 }"
10369)
949d79eb 10370
ff9940b0
RE
10371;; This split is only used during output to reduce the number of patterns
10372;; that need assembler instructions adding to them. We allowed the setting
10373;; of the conditions to be implicit during rtl generation so that
10374;; the conditional compare patterns would work. However this conflicts to
f54fd62e 10375;; some extent with the conditional data operations, so we have to split them
ff9940b0
RE
10376;; up again here.
10377
5b3e6663
PB
10378;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10379;; conditional execution sufficient?
10380
ff9940b0
RE
10381(define_split
10382 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1
RE
10383 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10384 [(match_operand 2 "" "") (match_operand 3 "" "")])
10385 (match_dup 0)
10386 (match_operand 4 "" "")))
48a08b9c 10387 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 10388 "TARGET_ARM && reload_completed"
05ed98a1
RE
10389 [(set (match_dup 5) (match_dup 6))
10390 (cond_exec (match_dup 7)
10391 (set (match_dup 0) (match_dup 4)))]
10392 "
10393 {
10394 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10395 operands[2], operands[3]);
10396 enum rtx_code rc = GET_CODE (operands[1]);
10397
48a08b9c 10398 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
05ed98a1
RE
10399 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10400 if (mode == CCFPmode || mode == CCFPEmode)
10401 rc = reverse_condition_maybe_unordered (rc);
10402 else
10403 rc = reverse_condition (rc);
10404
10405 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10406 }"
10407)
10408
10409(define_split
10410 [(set (match_operand:SI 0 "s_register_operand" "")
10411 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10412 [(match_operand 2 "" "") (match_operand 3 "" "")])
10413 (match_operand 4 "" "")
10414 (match_dup 0)))
48a08b9c 10415 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 10416 "TARGET_ARM && reload_completed"
05ed98a1
RE
10417 [(set (match_dup 5) (match_dup 6))
10418 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10419 (set (match_dup 0) (match_dup 4)))]
10420 "
10421 {
10422 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10423 operands[2], operands[3]);
10424
48a08b9c 10425 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
05ed98a1
RE
10426 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
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"
ff9940b0
RE
10433 [(match_operand 2 "" "") (match_operand 3 "" "")])
10434 (match_operand 4 "" "")
10435 (match_operand 5 "" "")))
48a08b9c 10436 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 10437 "TARGET_ARM && reload_completed"
05ed98a1
RE
10438 [(set (match_dup 6) (match_dup 7))
10439 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10440 (set (match_dup 0) (match_dup 4)))
10441 (cond_exec (match_dup 8)
10442 (set (match_dup 0) (match_dup 5)))]
10443 "
10444 {
10445 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10446 operands[2], operands[3]);
10447 enum rtx_code rc = GET_CODE (operands[1]);
10448
48a08b9c 10449 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
05ed98a1
RE
10450 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10451 if (mode == CCFPmode || mode == CCFPEmode)
10452 rc = reverse_condition_maybe_unordered (rc);
10453 else
10454 rc = reverse_condition (rc);
10455
10456 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10457 }"
10458)
10459
d5b7b3ae
RE
10460(define_split
10461 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 10462 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
d5b7b3ae
RE
10463 [(match_operand:SI 2 "s_register_operand" "")
10464 (match_operand:SI 3 "arm_add_operand" "")])
10465 (match_operand:SI 4 "arm_rhs_operand" "")
10466 (not:SI
10467 (match_operand:SI 5 "s_register_operand" ""))))
48a08b9c 10468 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 10469 "TARGET_ARM && reload_completed"
d5b7b3ae 10470 [(set (match_dup 6) (match_dup 7))
1646cf41
RE
10471 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10472 (set (match_dup 0) (match_dup 4)))
10473 (cond_exec (match_dup 8)
10474 (set (match_dup 0) (not:SI (match_dup 5))))]
d5b7b3ae 10475 "
5895f793
RE
10476 {
10477 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10478 operands[2], operands[3]);
1646cf41 10479 enum rtx_code rc = GET_CODE (operands[1]);
d5b7b3ae 10480
48a08b9c 10481 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
f1c25d3b 10482 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
1646cf41
RE
10483 if (mode == CCFPmode || mode == CCFPEmode)
10484 rc = reverse_condition_maybe_unordered (rc);
10485 else
10486 rc = reverse_condition (rc);
10487
10488 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
5895f793
RE
10489 }"
10490)
d5b7b3ae
RE
10491
10492(define_insn "*cond_move_not"
10493 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 10494 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
d5b7b3ae
RE
10495 [(match_operand 3 "cc_register" "") (const_int 0)])
10496 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10497 (not:SI
10498 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10499 "TARGET_ARM"
10500 "@
10501 mvn%D4\\t%0, %2
10502 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
cca0a211
RE
10503 [(set_attr "conds" "use")
10504 (set_attr "length" "4,8")]
10505)
d5b7b3ae 10506
ff9940b0
RE
10507;; The next two patterns occur when an AND operation is followed by a
10508;; scc insn sequence
10509
4cdb3ed4 10510(define_insn "*sign_extract_onebit"
ff9940b0
RE
10511 [(set (match_operand:SI 0 "s_register_operand" "=r")
10512 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10513 (const_int 1)
c1ff6200
JD
10514 (match_operand:SI 2 "const_int_operand" "n")))
10515 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 10516 "TARGET_ARM"
ff9940b0 10517 "*
cca0a211
RE
10518 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10519 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10520 return \"mvnne\\t%0, #0\";
10521 "
10522 [(set_attr "conds" "clob")
10523 (set_attr "length" "8")]
10524)
ff9940b0 10525
4cdb3ed4 10526(define_insn "*not_signextract_onebit"
ff9940b0
RE
10527 [(set (match_operand:SI 0 "s_register_operand" "=r")
10528 (not:SI
10529 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10530 (const_int 1)
c1ff6200
JD
10531 (match_operand:SI 2 "const_int_operand" "n"))))
10532 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 10533 "TARGET_ARM"
ff9940b0 10534 "*
cca0a211
RE
10535 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10536 output_asm_insn (\"tst\\t%1, %2\", operands);
10537 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10538 return \"movne\\t%0, #0\";
10539 "
10540 [(set_attr "conds" "clob")
10541 (set_attr "length" "12")]
10542)
5b3e6663 10543;; ??? The above patterns need auditing for Thumb-2
091426d3 10544
cca0a211
RE
10545;; Push multiple registers to the stack. Registers are in parallel (use ...)
10546;; expressions. For simplicity, the first register is also in the unspec
10547;; part.
4cdb3ed4 10548(define_insn "*push_multi"
091426d3
RE
10549 [(match_parallel 2 "multi_register_push"
10550 [(set (match_operand:BLK 0 "memory_operand" "=m")
b15bca31
RE
10551 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10552 UNSPEC_PUSH_MULT))])]
5b3e6663 10553 "TARGET_32BIT"
091426d3 10554 "*
5895f793
RE
10555 {
10556 int num_saves = XVECLEN (operands[2], 0);
3a5a4282 10557
5895f793 10558 /* For the StrongARM at least it is faster to
5b3e6663 10559 use STR to store only a single register.
7a085dce
KH
10560 In Thumb mode always use push, and the assembler will pick
10561 something appropriate. */
5b3e6663 10562 if (num_saves == 1 && TARGET_ARM)
5895f793
RE
10563 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10564 else
10565 {
10566 int i;
10567 char pattern[100];
3a5a4282 10568
5b3e6663
PB
10569 if (TARGET_ARM)
10570 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10571 else
10572 strcpy (pattern, \"push\\t{%1\");
5895f793 10573
880c4dcb 10574 for (i = 1; i < num_saves; i++)
5895f793
RE
10575 {
10576 strcat (pattern, \", %|\");
10577 strcat (pattern,
10578 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10579 }
10580
10581 strcat (pattern, \"}\");
10582 output_asm_insn (pattern, operands);
10583 }
10584
10585 return \"\";
10586 }"
10587 [(set_attr "type" "store4")]
10588)
4cdb3ed4 10589
3894f59e
RE
10590(define_insn "stack_tie"
10591 [(set (mem:BLK (scratch))
10592 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10593 (match_operand:SI 1 "s_register_operand" "r")]
10594 UNSPEC_PRLG_STK))]
10595 ""
10596 ""
10597 [(set_attr "length" "0")]
10598)
10599
38e01259 10600;; Similarly for the floating point registers
e9335bb6
RE
10601(define_insn "*push_fp_multi"
10602 [(match_parallel 2 "multi_register_push"
10603 [(set (match_operand:BLK 0 "memory_operand" "=m")
b15bca31
RE
10604 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10605 UNSPEC_PUSH_MULT))])]
5b3e6663 10606 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
e9335bb6 10607 "*
5895f793
RE
10608 {
10609 char pattern[100];
e9335bb6 10610
5895f793
RE
10611 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10612 output_asm_insn (pattern, operands);
10613 return \"\";
10614 }"
10615 [(set_attr "type" "f_store")]
10616)
e9335bb6 10617
4cdb3ed4
RE
10618;; Special patterns for dealing with the constant pool
10619
d5b7b3ae 10620(define_insn "align_4"
b15bca31 10621 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
d5b7b3ae 10622 "TARGET_EITHER"
4cdb3ed4 10623 "*
d5b7b3ae 10624 assemble_align (32);
4cdb3ed4 10625 return \"\";
d5b7b3ae
RE
10626 "
10627)
4cdb3ed4 10628
5a9335ef
NC
10629(define_insn "align_8"
10630 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
5848830f 10631 "TARGET_EITHER"
5a9335ef
NC
10632 "*
10633 assemble_align (64);
10634 return \"\";
10635 "
10636)
10637
d5b7b3ae 10638(define_insn "consttable_end"
b15bca31 10639 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
d5b7b3ae 10640 "TARGET_EITHER"
4cdb3ed4 10641 "*
d5b7b3ae 10642 making_const_table = FALSE;
4cdb3ed4 10643 return \"\";
d5b7b3ae
RE
10644 "
10645)
4cdb3ed4 10646
d5b7b3ae 10647(define_insn "consttable_1"
b15bca31 10648 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
5b3e6663 10649 "TARGET_THUMB1"
4cdb3ed4 10650 "*
d5b7b3ae 10651 making_const_table = TRUE;
c8af3574 10652 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
d5b7b3ae 10653 assemble_zeros (3);
4cdb3ed4 10654 return \"\";
d5b7b3ae
RE
10655 "
10656 [(set_attr "length" "4")]
10657)
4cdb3ed4 10658
d5b7b3ae 10659(define_insn "consttable_2"
b15bca31 10660 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
5b3e6663 10661 "TARGET_THUMB1"
4cdb3ed4 10662 "*
d5b7b3ae 10663 making_const_table = TRUE;
c8af3574 10664 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
d5b7b3ae 10665 assemble_zeros (2);
4cdb3ed4 10666 return \"\";
d5b7b3ae
RE
10667 "
10668 [(set_attr "length" "4")]
10669)
10670
10671(define_insn "consttable_4"
b15bca31 10672 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
d5b7b3ae
RE
10673 "TARGET_EITHER"
10674 "*
10675 {
10676 making_const_table = TRUE;
10677 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10678 {
10679 case MODE_FLOAT:
10680 {
b216cd4a
ZW
10681 REAL_VALUE_TYPE r;
10682 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10683 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
d5b7b3ae
RE
10684 break;
10685 }
10686 default:
c8af3574 10687 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
d5b7b3ae
RE
10688 break;
10689 }
10690 return \"\";
10691 }"
10692 [(set_attr "length" "4")]
10693)
10694
10695(define_insn "consttable_8"
b15bca31 10696 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
d5b7b3ae
RE
10697 "TARGET_EITHER"
10698 "*
10699 {
10700 making_const_table = TRUE;
10701 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10702 {
10703 case MODE_FLOAT:
10704 {
b216cd4a
ZW
10705 REAL_VALUE_TYPE r;
10706 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10707 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
d5b7b3ae
RE
10708 break;
10709 }
10710 default:
c8af3574 10711 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
d5b7b3ae
RE
10712 break;
10713 }
10714 return \"\";
10715 }"
10716 [(set_attr "length" "8")]
10717)
10718
88f77cba
JB
10719(define_insn "consttable_16"
10720 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10721 "TARGET_EITHER"
10722 "*
10723 {
10724 making_const_table = TRUE;
10725 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10726 {
10727 case MODE_FLOAT:
10728 {
10729 REAL_VALUE_TYPE r;
10730 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10731 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10732 break;
10733 }
10734 default:
10735 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10736 break;
10737 }
10738 return \"\";
10739 }"
10740 [(set_attr "length" "16")]
10741)
10742
d5b7b3ae
RE
10743;; Miscellaneous Thumb patterns
10744
657d9449 10745(define_expand "tablejump"
82955615 10746 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
657d9449 10747 (use (label_ref (match_operand 1 "" "")))])]
5b3e6663 10748 "TARGET_THUMB1"
657d9449
RE
10749 "
10750 if (flag_pic)
10751 {
10752 /* Hopefully, CSE will eliminate this copy. */
10753 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10754 rtx reg2 = gen_reg_rtx (SImode);
10755
10756 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10757 operands[0] = reg2;
10758 }
10759 "
10760)
10761
68d560d4 10762;; NB never uses BX.
5b3e6663 10763(define_insn "*thumb1_tablejump"
d5b7b3ae
RE
10764 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10765 (use (label_ref (match_operand 1 "" "")))]
5b3e6663 10766 "TARGET_THUMB1"
657d9449 10767 "mov\\t%|pc, %0"
d5b7b3ae
RE
10768 [(set_attr "length" "2")]
10769)
cca0a211 10770
d19fb8e3
NC
10771;; V5 Instructions,
10772
7dba8395
RH
10773(define_insn "clzsi2"
10774 [(set (match_operand:SI 0 "s_register_operand" "=r")
10775 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 10776 "TARGET_32BIT && arm_arch5"
e912eadf 10777 "clz%?\\t%0, %1"
c956e102
MS
10778 [(set_attr "predicable" "yes")
10779 (set_attr "insn" "clz")])
d19fb8e3 10780
b15bca31
RE
10781(define_expand "ffssi2"
10782 [(set (match_operand:SI 0 "s_register_operand" "")
10783 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
5b3e6663 10784 "TARGET_32BIT && arm_arch5"
b15bca31
RE
10785 "
10786 {
10787 rtx t1, t2, t3;
10788
10789 t1 = gen_reg_rtx (SImode);
10790 t2 = gen_reg_rtx (SImode);
10791 t3 = gen_reg_rtx (SImode);
10792
10793 emit_insn (gen_negsi2 (t1, operands[1]));
10794 emit_insn (gen_andsi3 (t2, operands[1], t1));
7dba8395 10795 emit_insn (gen_clzsi2 (t3, t2));
b15bca31
RE
10796 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10797 DONE;
10798 }"
10799)
10800
7dba8395
RH
10801(define_expand "ctzsi2"
10802 [(set (match_operand:SI 0 "s_register_operand" "")
10803 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
5b3e6663 10804 "TARGET_32BIT && arm_arch5"
7dba8395
RH
10805 "
10806 {
10807 rtx t1, t2, t3;
10808
10809 t1 = gen_reg_rtx (SImode);
10810 t2 = gen_reg_rtx (SImode);
10811 t3 = gen_reg_rtx (SImode);
10812
10813 emit_insn (gen_negsi2 (t1, operands[1]));
10814 emit_insn (gen_andsi3 (t2, operands[1], t1));
10815 emit_insn (gen_clzsi2 (t3, t2));
10816 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10817 DONE;
10818 }"
10819)
10820
b15bca31 10821;; V5E instructions.
d19fb8e3
NC
10822
10823(define_insn "prefetch"
fa980e6b
RE
10824 [(prefetch (match_operand:SI 0 "address_operand" "p")
10825 (match_operand:SI 1 "" "")
10826 (match_operand:SI 2 "" ""))]
5b3e6663 10827 "TARGET_32BIT && arm_arch5e"
a00b07c5 10828 "pld\\t%a0")
d19fb8e3 10829
cca0a211
RE
10830;; General predication pattern
10831
10832(define_cond_exec
10833 [(match_operator 0 "arm_comparison_operator"
10834 [(match_operand 1 "cc_register" "")
10835 (const_int 0)])]
5b3e6663 10836 "TARGET_32BIT"
cca0a211
RE
10837 ""
10838)
10839
6bacc7b0
NC
10840(define_insn "prologue_use"
10841 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10842 ""
10843 "%@ %0 needed for prologue"
10844)
82955615 10845
c9ca9b88
PB
10846
10847;; Patterns for exception handling
10848
10849(define_expand "eh_return"
10850 [(use (match_operand 0 "general_operand" ""))]
10851 "TARGET_EITHER"
10852 "
10853 {
5b3e6663 10854 if (TARGET_32BIT)
c9ca9b88
PB
10855 emit_insn (gen_arm_eh_return (operands[0]));
10856 else
10857 emit_insn (gen_thumb_eh_return (operands[0]));
10858 DONE;
10859 }"
10860)
10861
10862;; We can't expand this before we know where the link register is stored.
10863(define_insn_and_split "arm_eh_return"
10864 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10865 VUNSPEC_EH_RETURN)
10866 (clobber (match_scratch:SI 1 "=&r"))]
10867 "TARGET_ARM"
10868 "#"
10869 "&& reload_completed"
10870 [(const_int 0)]
10871 "
10872 {
10873 arm_set_return_address (operands[0], operands[1]);
10874 DONE;
10875 }"
10876)
10877
10878(define_insn_and_split "thumb_eh_return"
10879 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10880 VUNSPEC_EH_RETURN)
10881 (clobber (match_scratch:SI 1 "=&l"))]
5b3e6663 10882 "TARGET_THUMB1"
c9ca9b88
PB
10883 "#"
10884 "&& reload_completed"
10885 [(const_int 0)]
10886 "
10887 {
10888 thumb_set_return_address (operands[0], operands[1]);
10889 DONE;
10890 }"
10891)
10892
d3585b76
DJ
10893\f
10894;; TLS support
10895
10896(define_insn "load_tp_hard"
10897 [(set (match_operand:SI 0 "register_operand" "=r")
10898 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10899 "TARGET_HARD_TP"
10900 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10901 [(set_attr "predicable" "yes")]
10902)
10903
10904;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10905(define_insn "load_tp_soft"
10906 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10907 (clobber (reg:SI LR_REGNUM))
10908 (clobber (reg:SI IP_REGNUM))
10909 (clobber (reg:CC CC_REGNUM))]
10910 "TARGET_SOFT_TP"
10911 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10912 [(set_attr "conds" "clob")]
10913)
10914
82955615
RE
10915;; Load the FPA co-processor patterns
10916(include "fpa.md")
10917;; Load the Maverick co-processor patterns
10918(include "cirrus.md")
88f77cba
JB
10919;; Vector bits common to IWMMXT and Neon
10920(include "vec-common.md")
5a9335ef
NC
10921;; Load the Intel Wireless Multimedia Extension patterns
10922(include "iwmmxt.md")
9b66ebb1
PB
10923;; Load the VFP co-processor patterns
10924(include "vfp.md")
5b3e6663
PB
10925;; Thumb-2 patterns
10926(include "thumb2.md")
88f77cba
JB
10927;; Neon patterns
10928(include "neon.md")
9b66ebb1 10929